<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[41376] trunk: Editor: Add CodeMirror-powered code editor with syntax highlighting, linting, and auto-completion.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/41376">41376</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/41376","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>westonruter</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2017-09-13 06:07:48 +0000 (Wed, 13 Sep 2017)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Editor: Add CodeMirror-powered code editor with syntax highlighting, linting, and auto-completion.

* Code editor is integrated into the Theme/Plugin Editor, Additional CSS in Customizer, and Custom HTML widget. Code editor is not yet integrated into the post editor, and it may not be until accessibility concerns are addressed.
* The CodeMirror component in the Custom HTML widget is integrated in a similar way to TinyMCE being integrated into the Text widget, adopting the same approach for integrating dynamic JavaScript-initialized fields.
* Linting is performed for JS, CSS, HTML, and JSON via JSHint, CSSLint, HTMLHint, and JSONLint respectively. Linting is not yet supported for PHP.
* When user lacks `unfiltered_html` the capability, the Custom HTML widget will report any Kses-invalid elements and attributes as errors via a custom Kses rule for HTMLHint.
* When linting errors are detected, the user will be prevented from saving the code until the errors are fixed, reducing instances of broken websites.
* The placeholder value is removed from Custom CSS in favor of a fleshed-out section description which now auto-expands when the CSS field is empty. See <a href="https://core.trac.wordpress.org/ticket/39892">#39892</a>.
* The CodeMirror library is included as `wp.CodeMirror` to prevent conflicts with any existing `CodeMirror` global.
* An `wp.codeEditor.initialize()` API in JS is provided to convert a `textarea` into CodeMirror, with a `wp_enqueue_code_editor()` function in PHP to manage enqueueing the assets and settings needed to edit a given type of code.
* A user preference is added to manage whether or not "syntax highlighting" is enabled. The feature is opt-out, being enabled by default.
* Allowed file extensions in the theme and plugin editors have been updated to include formats which CodeMirror has modes for: `conf`, `css`, `diff`, `patch`, `html`, `htm`, `http`, `js`, `json`, `jsx`, `less`, `md`, `php`, `phtml`, `php3`, `php4`, `php5`, `php7`, `phps`, `scss`, `sass`, `sh`, `bash`, `sql`, `svg`, `xml`, `yml`, `yaml`, `txt`.

Props westonruter, georgestephanis, obenland, melchoyce, pixolin, mizejewski, michelleweber, afercia, grahamarmfield, samikeijonen, rianrietveld, iseulde.
See <a href="https://core.trac.wordpress.org/ticket/38707">#38707</a>.
Fixes <a href="https://core.trac.wordpress.org/ticket/12423">#12423</a>, <a href="https://core.trac.wordpress.org/ticket/39892">#39892</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkGruntfilejs">trunk/Gruntfile.js</a></li>
<li><a href="#trunksrcwpadmincsscommoncss">trunk/src/wp-admin/css/common.css</a></li>
<li><a href="#trunksrcwpadmincsscustomizecontrolscss">trunk/src/wp-admin/css/customize-controls.css</a></li>
<li><a href="#trunksrcwpadmincsswidgetscss">trunk/src/wp-admin/css/widgets.css</a></li>
<li><a href="#trunksrcwpadminincludesuserphp">trunk/src/wp-admin/includes/user.php</a></li>
<li><a href="#trunksrcwpadminjscustomizecontrolsjs">trunk/src/wp-admin/js/customize-controls.js</a></li>
<li><a href="#trunksrcwpadminplugineditorphp">trunk/src/wp-admin/plugin-editor.php</a></li>
<li><a href="#trunksrcwpadminthemeeditorphp">trunk/src/wp-admin/theme-editor.php</a></li>
<li><a href="#trunksrcwpadminusereditphp">trunk/src/wp-admin/user-edit.php</a></li>
<li><a href="#trunksrcwpincludesauthortemplatephp">trunk/src/wp-includes/author-template.php</a></li>
<li><a href="#trunksrcwpincludesclasswpcustomizemanagerphp">trunk/src/wp-includes/class-wp-customize-manager.php</a></li>
<li><a href="#trunksrcwpincludesclasswpuserphp">trunk/src/wp-includes/class-wp-user.php</a></li>
<li><a href="#trunksrcwpincludescustomizeclasswpcustomizecustomcsssettingphp">trunk/src/wp-includes/customize/class-wp-customize-custom-css-setting.php</a></li>
<li><a href="#trunksrcwpincludesgeneraltemplatephp">trunk/src/wp-includes/general-template.php</a></li>
<li><a href="#trunksrcwpincludesscriptloaderphp">trunk/src/wp-includes/script-loader.php</a></li>
<li><a href="#trunksrcwpincludesuserphp">trunk/src/wp-includes/user.php</a></li>
<li><a href="#trunksrcwpincludeswidgetsclasswpwidgetcustomhtmlphp">trunk/src/wp-includes/widgets/class-wp-widget-custom-html.php</a></li>
<li><a href="#trunksrcwpincludeswidgetsclasswpwidgettextphp">trunk/src/wp-includes/widgets/class-wp-widget-text.php</a></li>
<li><a href="#trunktestsphpunittestscustomizecustomcsssettingphp">trunk/tests/phpunit/tests/customize/custom-css-setting.php</a></li>
<li><a href="#trunktestsphpunittestscustomizemanagerphp">trunk/tests/phpunit/tests/customize/manager.php</a></li>
<li><a href="#trunktestsphpunittestsuserphp">trunk/tests/phpunit/tests/user.php</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunksrcwpadmincsscodeeditorcss">trunk/src/wp-admin/css/code-editor.css</a></li>
<li><a href="#trunksrcwpadminjscodeeditorjs">trunk/src/wp-admin/js/code-editor.js</a></li>
<li><a href="#trunksrcwpadminjsthemeplugineditorjs">trunk/src/wp-admin/js/theme-plugin-editor.js</a></li>
<li><a href="#trunksrcwpadminjswidgetscustomhtmlwidgetsjs">trunk/src/wp-admin/js/widgets/custom-html-widgets.js</a></li>
<li>trunk/src/wp-includes/js/codemirror/</li>
<li><a href="#trunksrcwpincludesjscodemirrorcodemirrormincss">trunk/src/wp-includes/js/codemirror/codemirror.min.css</a></li>
<li><a href="#trunksrcwpincludesjscodemirrorcodemirrorminjs">trunk/src/wp-includes/js/codemirror/codemirror.min.js</a></li>
<li><a href="#trunksrcwpincludesjscodemirrorcsslintjs">trunk/src/wp-includes/js/codemirror/csslint.js</a></li>
<li><a href="#trunksrcwpincludesjscodemirrorhtmlhintksesjs">trunk/src/wp-includes/js/codemirror/htmlhint-kses.js</a></li>
<li><a href="#trunksrcwpincludesjscodemirrorhtmlhintjs">trunk/src/wp-includes/js/codemirror/htmlhint.js</a></li>
<li><a href="#trunksrcwpincludesjscodemirrorjshintjs">trunk/src/wp-includes/js/codemirror/jshint.js</a></li>
<li><a href="#trunksrcwpincludesjscodemirrorjsonlintjs">trunk/src/wp-includes/js/codemirror/jsonlint.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkGruntfilejs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/Gruntfile.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/Gruntfile.js        2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/Gruntfile.js  2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -360,6 +360,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                        'wp-includes/js/tinymce/plugins/wordpress/plugin.js',
</span><span class="cx" style="display: block; padding: 0 10px">                                        'wp-includes/js/tinymce/plugins/wp*/plugin.js',
</span><span class="cx" style="display: block; padding: 0 10px">                                        // Third party scripts
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                        '!wp-includes/js/codemirror/*.js',
</ins><span class="cx" style="display: block; padding: 0 10px">                                         '!wp-admin/js/farbtastic.js',
</span><span class="cx" style="display: block; padding: 0 10px">                                        '!wp-includes/js/backbone*.js',
</span><span class="cx" style="display: block; padding: 0 10px">                                        '!wp-includes/js/swfobject.js',
</span></span></pre></div>
<a id="trunksrcwpadmincsscodeeditorcss"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/src/wp-admin/css/code-editor.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/css/code-editor.css                            (rev 0)
+++ trunk/src/wp-admin/css/code-editor.css      2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,62 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.wrap [class*="CodeMirror-lint-marker"],
+.wp-core-ui [class*="CodeMirror-lint-message"],
+.wrap .CodeMirror-lint-marker-multiple {
+       background-image: none;
+}
+
+.wrap [class*="CodeMirror-lint-marker"]:before {
+       font: normal 18px/1 dashicons;
+       position: relative;
+       top: -2px;
+}
+
+.wp-core-ui [class*="CodeMirror-lint-message"]:before {
+       font: normal 16px/1 dashicons;
+       left: 16px;
+       position: absolute;
+}
+
+.wp-core-ui .CodeMirror-lint-message-error,
+.wp-core-ui .CodeMirror-lint-message-warning {
+       box-shadow: 0 1px 1px 0 rgba( 0, 0, 0, 0.1 );
+       margin: 5px 0 2px;
+       padding: 3px 12px 3px 28px;
+}
+
+.wp-core-ui .CodeMirror-lint-message-warning {
+       background-color: #fff8e5;
+       border-left: 4px solid #ffb900;
+}
+
+.wrap .CodeMirror-lint-marker-warning:before,
+.wp-core-ui .CodeMirror-lint-message-warning:before {
+       content: "\f534";
+       color: #f6a306;
+}
+
+.wp-core-ui .CodeMirror-lint-message-error {
+       background-color: #fbeaea;
+       border-left: 4px solid #dc3232;
+}
+
+.wrap .CodeMirror-lint-marker-error:before,
+.wp-core-ui .CodeMirror-lint-message-error:before {
+       content: "\f153";
+       color: #dc3232;
+}
+
+.wp-core-ui .CodeMirror-lint-tooltip {
+       background: none;
+       border: none;
+       border-radius: 0;
+       direction: ltr;
+}
+
+.wrap .CodeMirror .CodeMirror-matchingbracket {
+       background: rgba(255, 150, 0, .3);
+       color: inherit;
+}
+
+.CodeMirror {
+       text-align: left;
+}
</ins></span></pre></div>
<a id="trunksrcwpadmincsscommoncss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/css/common.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/css/common.css 2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/src/wp-admin/css/common.css   2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2200,7 +2200,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">        visibility: visible;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-#template div {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+#template > div {
</ins><span class="cx" style="display: block; padding: 0 10px">         margin-right: 190px;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3015,13 +3015,18 @@
</span><span class="cx" style="display: block; padding: 0 10px"> #template textarea {
</span><span class="cx" style="display: block; padding: 0 10px">        font-family: Consolas, Monaco, monospace;
</span><span class="cx" style="display: block; padding: 0 10px">        font-size: 13px;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        width: 97%;
</del><span class="cx" style="display: block; padding: 0 10px">         background: #f9f9f9;
</span><span class="cx" style="display: block; padding: 0 10px">        -moz-tab-size: 4;
</span><span class="cx" style="display: block; padding: 0 10px">        -o-tab-size: 4;
</span><span class="cx" style="display: block; padding: 0 10px">        tab-size: 4;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+#template textarea,
+#template .CodeMirror {
+       width: 97%;
+       height: calc( 100vh - 220px );
+}
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /* rtl:ignore */
</span><span class="cx" style="display: block; padding: 0 10px"> #template textarea,
</span><span class="cx" style="display: block; padding: 0 10px"> #docs-list {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3032,6 +3037,25 @@
</span><span class="cx" style="display: block; padding: 0 10px">        width: 97%;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+#file-editor-linting-error {
+       margin-top: 1em;
+       margin-bottom: 1em;
+}
+#file-editor-linting-error > .notice {
+       margin: 0;
+       display: inline-block;
+}
+#file-editor-linting-error > .notice > p {
+       width: auto;
+}
+#template .submit {
+       margin-top: 1em;
+       padding: 0;
+}
+
+#template .submit input[type=submit][disabled] {
+       cursor: not-allowed;
+}
</ins><span class="cx" style="display: block; padding: 0 10px"> #templateside {
</span><span class="cx" style="display: block; padding: 0 10px">        float: right;
</span><span class="cx" style="display: block; padding: 0 10px">        width: 190px;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3585,12 +3609,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                margin-top: -5px;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        #template div {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ #template > div {
</ins><span class="cx" style="display: block; padding: 0 10px">                 float: none;
</span><span class="cx" style="display: block; padding: 0 10px">                margin: 0;
</span><span class="cx" style="display: block; padding: 0 10px">                width: auto;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        #template .CodeMirror,
</ins><span class="cx" style="display: block; padding: 0 10px">         #template textarea {
</span><span class="cx" style="display: block; padding: 0 10px">                width: 100%;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span></span></pre></div>
<a id="trunksrcwpadmincsscustomizecontrolscss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/css/customize-controls.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/css/customize-controls.css     2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/src/wp-admin/css/customize-controls.css       2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -550,7 +550,21 @@
</span><span class="cx" style="display: block; padding: 0 10px">        margin-top: 22px;
</span><span class="cx" style="display: block; padding: 0 10px">        margin-bottom: 0;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.customize-section-description ul {
+       margin-left: 1em;
+}
+.customize-section-description ul > li {
+       list-style: disc;
+}
+.section-description-buttons {
+       text-align: right;
+}
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.section-description-buttons button.button-link {
+       color: #0073aa;
+       text-decoration: underline;
+}
+
</ins><span class="cx" style="display: block; padding: 0 10px"> .customize-control {
</span><span class="cx" style="display: block; padding: 0 10px">        width: 100%;
</span><span class="cx" style="display: block; padding: 0 10px">        float: left;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1154,6 +1168,19 @@
</span><span class="cx" style="display: block; padding: 0 10px">        margin-bottom: -12px;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.customize-section-description-container + #customize-control-custom_css:last-child .CodeMirror {
+       height: calc( 100vh - 185px );
+}
+.CodeMirror-lint-tooltip,
+.CodeMirror-hints {
+       z-index: 500000 !important;
+}
+
+.customize-section-description-container + #customize-control-custom_css:last-child .customize-control-notifications-container {
+       margin-left: 12px;
+       margin-right: 12px;
+}
+
</ins><span class="cx" style="display: block; padding: 0 10px"> @media screen and ( max-width: 640px ) {
</span><span class="cx" style="display: block; padding: 0 10px">        .customize-section-description-container + #customize-control-custom_css:last-child {
</span><span class="cx" style="display: block; padding: 0 10px">                margin-right: 0;
</span></span></pre></div>
<a id="trunksrcwpadmincsswidgetscss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/css/widgets.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/css/widgets.css        2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/src/wp-admin/css/widgets.css  2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -645,6 +645,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">        line-height: 1.4em;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.custom-html-widget-fields > p > .CodeMirror {
+       border: 1px solid #e5e5e5;
+}
+.custom-html-widget-fields code {
+       padding-top: 1px;
+       padding-bottom: 1px;
+}
+ul.CodeMirror-hints {
+       z-index: 101; /* Due to z-index 100 set on .widget.open */
+}
+.widget-control-actions .custom-html-widget-save-button.button.validation-blocked {
+       cursor: not-allowed;
+}
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /* =Media Queries
</span><span class="cx" style="display: block; padding: 0 10px"> -------------------------------------------------------------- */
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre></div>
<a id="trunksrcwpadminincludesuserphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/includes/user.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/includes/user.php      2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/src/wp-admin/includes/user.php        2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -91,7 +91,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        if ( $update ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $user->rich_editing = isset( $_POST['rich_editing'] ) && 'false' == $_POST['rich_editing'] ? 'false' : 'true';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $user->rich_editing = isset( $_POST['rich_editing'] ) && 'false' === $_POST['rich_editing'] ? 'false' : 'true';
+               $user->syntax_highlighting = isset( $_POST['syntax_highlighting'] ) && 'false' === $_POST['syntax_highlighting'] ? 'false' : 'true';
</ins><span class="cx" style="display: block; padding: 0 10px">                 $user->admin_color = isset( $_POST['admin_color'] ) ? sanitize_text_field( $_POST['admin_color'] ) : 'fresh';
</span><span class="cx" style="display: block; padding: 0 10px">                $user->show_admin_bar_front = isset( $_POST['admin_bar_front'] ) ? 'true' : 'false';
</span><span class="cx" style="display: block; padding: 0 10px">                $user->locale = '';
</span></span></pre></div>
<a id="trunksrcwpadminjscodeeditorjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/src/wp-admin/js/code-editor.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/js/code-editor.js                              (rev 0)
+++ trunk/src/wp-admin/js/code-editor.js        2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,309 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+if ( 'undefined' === typeof window.wp ) {
+       window.wp = {};
+}
+if ( 'undefined' === typeof window.wp.codeEditor ) {
+       window.wp.codeEditor = {};
+}
+
+( function( $, wp ) {
+       'use strict';
+
+       /**
+        * Default settings for code editor.
+        *
+        * @since 4.9.0
+        * @type {object}
+        */
+       wp.codeEditor.defaultSettings = {
+               codemirror: {},
+               csslint: {},
+               htmlhint: {},
+               jshint: {},
+               onTabNext: function() {},
+               onTabPrevious: function() {},
+               onChangeLintingErrors: function() {},
+               onUpdateErrorNotice: function() {}
+       };
+
+       /**
+        * All instances of code editors.
+        *
+        * @since 4.9.0
+        * @type {Array.<CodeEditorInstance>}
+        */
+       wp.codeEditor.instances = [];
+
+       /**
+        * Configure linting.
+        *
+        * @param {CodeMirror} editor - Editor.
+        * @param {object}     settings - Code editor settings.
+        * @param {object}     settings.codeMirror - Settings for CodeMirror.
+        * @param {Function}   settings.onChangeLintingErrors - Callback for when there are changes to linting errors.
+        * @param {Function}   settings.onUpdateErrorNotice - Callback to update error notice.
+        * @returns {void}
+        */
+       function configureLinting( editor, settings ) { // eslint-disable-line complexity
+               var lintOptions = editor.getOption( 'lint' ), currentErrorAnnotations = [], updateErrorNotice, previouslyShownErrorAnnotations = [];
+               if ( ! lintOptions ) {
+                       return;
+               }
+
+               if ( true === lintOptions ) {
+                       lintOptions = {};
+               } else {
+                       lintOptions = $.extend( {}, lintOptions );
+               }
+
+               // Note that rules must be sent in the "deprecated" lint.options property to prevent linter from complaining about unrecognized options. See <https://github.com/codemirror/CodeMirror/pull/4944>.
+               if ( ! lintOptions.options ) {
+                       lintOptions.options = {};
+               }
+
+               // Configure JSHint.
+               if ( 'javascript' === settings.codemirror.mode && settings.jshint ) {
+                       $.extend( lintOptions.options, settings.jshint );
+               }
+
+               // Configure CSSLint.
+               if ( 'css' === settings.codemirror.mode && settings.csslint ) {
+                       $.extend( lintOptions.options, settings.csslint );
+               }
+
+               // Configure HTMLHint.
+               if ( 'htmlmixed' === settings.codemirror.mode && settings.htmlhint ) {
+                       lintOptions.options.rules = $.extend( {}, settings.htmlhint );
+
+                       if ( settings.jshint ) {
+                               lintOptions.options.rules.jshint = settings.jshint;
+                       }
+                       if ( settings.csslint ) {
+                               lintOptions.options.rules.csslint = settings.csslint;
+                       }
+               }
+
+               /**
+                * Call the onUpdateErrorNotice if there are new errors to show.
+                *
+                * @returns {void}
+                */
+               updateErrorNotice = function() {
+                       if ( settings.onUpdateErrorNotice && ! _.isEqual( currentErrorAnnotations, previouslyShownErrorAnnotations ) ) {
+                               settings.onUpdateErrorNotice( currentErrorAnnotations, editor );
+                               previouslyShownErrorAnnotations = currentErrorAnnotations;
+                       }
+               };
+
+               // Wrap the onUpdateLinting CodeMirror event to route to onChangeLintingErrors and onUpdateErrorNotice.
+               lintOptions.onUpdateLinting = (function( onUpdateLintingOverridden ) {
+                       return function( annotations, annotationsSorted, cm ) {
+                               var errorAnnotations = _.filter( annotations, function( annotation ) {
+                                       return 'error' === annotation.severity;
+                               } );
+
+                               if ( onUpdateLintingOverridden ) {
+                                       onUpdateLintingOverridden.apply( annotations, annotationsSorted, cm );
+                               }
+
+                               // Skip if there are no changes to the errors.
+                               if ( _.isEqual( errorAnnotations, currentErrorAnnotations ) ) {
+                                       return;
+                               }
+
+                               currentErrorAnnotations = errorAnnotations;
+
+                               if ( settings.onChangeLintingErrors ) {
+                                       settings.onChangeLintingErrors( errorAnnotations, annotations, annotationsSorted, cm );
+                               }
+
+                               /*
+                                * Update notifications when the editor is not focused to prevent error message
+                                * from overwhelming the user during input, unless there are now no errors or there
+                                * were previously errors shown. In these cases, update immediately so they can know
+                                * that they fixed the errors.
+                                */
+                               if ( ! cm.state.focused || 0 === currentErrorAnnotations.length || previouslyShownErrorAnnotations.length > 0 ) {
+                                       updateErrorNotice();
+                               }
+                       };
+               })( lintOptions.onUpdateLinting );
+
+               editor.setOption( 'lint', lintOptions );
+
+               // Update error notice when leaving the editor.
+               editor.on( 'blur', updateErrorNotice );
+
+               // Work around hint selection with mouse causing focus to leave editor.
+               editor.on( 'startCompletion', function() {
+                       editor.off( 'blur', updateErrorNotice );
+               } );
+               editor.on( 'endCompletion', function() {
+                       var editorRefocusWait = 500;
+                       editor.on( 'blur', updateErrorNotice );
+
+                       // Wait for editor to possibly get re-focused after selection.
+                       _.delay( function() {
+                               if ( ! editor.state.focused ) {
+                                       updateErrorNotice();
+                               }
+                       }, editorRefocusWait );
+               });
+
+               /*
+                * Make sure setting validities are set if the user tries to click Publish
+                * while an autocomplete dropdown is still open. The Customizer will block
+                * saving when a setting has an error notifications on it. This is only
+                * necessary for mouse interactions because keyboards will have already
+                * blurred the field and cause onUpdateErrorNotice to have already been
+                * called.
+                */
+               $( document.body ).on( 'mousedown', function( event ) {
+                       if ( editor.state.focused && ! $.contains( editor.display.wrapper, event.target ) && ! $( event.target ).hasClass( 'CodeMirror-hint' ) ) {
+                               updateErrorNotice();
+                       }
+               });
+       }
+
+       /**
+        * Configure tabbing.
+        *
+        * @param {CodeMirror} codemirror - Editor.
+        * @param {object}     settings - Code editor settings.
+        * @param {object}     settings.codeMirror - Settings for CodeMirror.
+        * @param {Function}   settings.onTabNext - Callback to handle tabbing to the next tabbable element.
+        * @param {Function}   settings.onTabPrevious - Callback to handle tabbing to the previous tabbable element.
+        * @returns {void}
+        */
+       function configureTabbing( codemirror, settings ) {
+               var $textarea = $( codemirror.getTextArea() );
+
+               codemirror.on( 'blur', function() {
+                       $textarea.data( 'next-tab-blurs', false );
+               });
+               codemirror.on( 'focus', function() {
+                       if ( codemirror.display.wrapper.scrollIntoViewIfNeeded ) {
+                               codemirror.display.wrapper.scrollIntoViewIfNeeded();
+                       } else {
+                               codemirror.display.wrapper.scrollIntoView();
+                       }
+               });
+               codemirror.on( 'keydown', function onKeydown( editor, event ) {
+                       var tabKeyCode = 9, escKeyCode = 27;
+
+                       // Take note of the ESC keypress so that the next TAB can focus outside the editor.
+                       if ( escKeyCode === event.keyCode ) {
+                               $textarea.data( 'next-tab-blurs', true );
+                               return;
+                       }
+
+                       // Short-circuit if tab key is not being pressed or the tab key press should move focus.
+                       if ( tabKeyCode !== event.keyCode || ! $textarea.data( 'next-tab-blurs' ) ) {
+                               return;
+                       }
+
+                       // Focus on previous or next focusable item.
+                       if ( event.shiftKey ) {
+                               settings.onTabPrevious( codemirror, event );
+                       } else {
+                               settings.onTabNext( codemirror, event );
+                       }
+
+                       // Reset tab state.
+                       $textarea.data( 'next-tab-blurs', false );
+
+                       // Prevent tab character from being added.
+                       event.preventDefault();
+               });
+       }
+
+       /**
+        * @typedef {object} CodeEditorInstance
+        * @property {object} settings - The code editor settings.
+        * @property {CodeMirror} codemirror - The CodeMirror instance.
+        */
+
+       /**
+        * Initialize Code Editor (CodeMirror) for an existing textarea.
+        *
+        * @since 4.9.0
+        *
+        * @param {string|jQuery|Element} textarea - The HTML id, jQuery object, or DOM Element for the textarea that is used for the editor.
+        * @param {object}                [settings] - Settings to override defaults.
+        * @param {Function}              [settings.onChangeLintingErrors] - Callback for when the linting errors have changed.
+        * @param {Function}              [settings.onUpdateErrorNotice] - Callback for when error notice should be displayed.
+        * @param {Function}              [settings.onTabPrevious] - Callback to handle tabbing to the previous tabbable element.
+        * @param {Function}              [settings.onTabNext] - Callback to handle tabbing to the next tabbable element.
+        * @param {object}                [settings.codemirror] - Options for CodeMirror.
+        * @param {object}                [settings.csslint] - Rules for CSSLint.
+        * @param {object}                [settings.htmlhint] - Rules for HTMLHint.
+        * @param {object}                [settings.jshint] - Rules for JSHint.
+        * @returns {CodeEditorInstance} Instance.
+        */
+       wp.codeEditor.initialize = function initialize( textarea, settings ) {
+               var $textarea, codemirror, instanceSettings, instance;
+               if ( 'string' === typeof textarea ) {
+                       $textarea = $( '#' + textarea );
+               } else {
+                       $textarea = $( textarea );
+               }
+
+               instanceSettings = $.extend( {}, wp.codeEditor.defaultSettings, settings );
+               instanceSettings.codemirror = $.extend( {}, instanceSettings.codemirror );
+
+               codemirror = wp.CodeMirror.fromTextArea( $textarea[0], instanceSettings.codemirror );
+
+               configureLinting( codemirror, instanceSettings );
+
+               instance = {
+                       settings: instanceSettings,
+                       codemirror: codemirror
+               };
+
+               // Keep track of the instances that have been created.
+               wp.codeEditor.instances.push( instance );
+
+               if ( codemirror.showHint ) {
+                       codemirror.on( 'keyup', function( editor, event ) { // eslint-disable-line complexity
+                               var shouldAutocomplete, isAlphaKey = /^[a-zA-Z]$/.test( event.key ), lineBeforeCursor, innerMode, token;
+                               if ( codemirror.state.completionActive && isAlphaKey ) {
+                                       return;
+                               }
+
+                               // Prevent autocompletion in string literals or comments.
+                               token = codemirror.getTokenAt( codemirror.getCursor() );
+                               if ( 'string' === token.type || 'comment' === token.type ) {
+                                       return;
+                               }
+
+                               innerMode = wp.CodeMirror.innerMode( codemirror.getMode(), token.state ).mode.name;
+                               lineBeforeCursor = codemirror.doc.getLine( codemirror.doc.getCursor().line ).substr( 0, codemirror.doc.getCursor().ch );
+                               if ( 'html' === innerMode || 'xml' === innerMode ) {
+                                       shouldAutocomplete =
+                                               '<' === event.key ||
+                                               '/' === event.key && 'tag' === token.type ||
+                                               isAlphaKey && 'tag' === token.type ||
+                                               isAlphaKey && 'attribute' === token.type ||
+                                               '=' === token.string && token.state.htmlState && token.state.htmlState.tagName;
+                               } else if ( 'css' === innerMode ) {
+                                       shouldAutocomplete =
+                                               isAlphaKey ||
+                                               ':' === event.key ||
+                                               ' ' === event.key && /:\s+$/.test( lineBeforeCursor );
+                               } else if ( 'javascript' === innerMode ) {
+                                       shouldAutocomplete = isAlphaKey || '.' === event.key;
+                               } else if ( 'clike' === innerMode && 'application/x-httpd-php' === codemirror.options.mode ) {
+                                       shouldAutocomplete = 'keyword' === token.type || 'variable' === token.type;
+                               }
+                               if ( shouldAutocomplete ) {
+                                       codemirror.showHint( { completeSingle: false } );
+                               }
+                       });
+               }
+
+               // Facilitate tabbing out of the editor.
+               configureTabbing( codemirror, settings );
+
+               return instance;
+       };
+
+})( window.jQuery, window.wp );
</ins></span></pre></div>
<a id="trunksrcwpadminjscustomizecontrolsjs"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/js/customize-controls.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/js/customize-controls.js       2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/src/wp-admin/js/customize-controls.js 2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -5631,51 +5631,213 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        });
</span><span class="cx" style="display: block; padding: 0 10px">                });
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // Allow tabs to be entered in Custom CSS textarea.
-               api.control( 'custom_css', function setupCustomCssControl( control ) {
-                       control.deferred.embedded.done( function allowTabs() {
-                               var $textarea = control.container.find( 'textarea' ), textarea = $textarea[0];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // Add code editor for Custom CSS.
+               (function() {
+                       var ready, sectionReady = $.Deferred(), controlReady = $.Deferred();
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $textarea.on( 'blur', function onBlur() {
-                                       $textarea.data( 'next-tab-blurs', false );
-                               } );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 api.section( 'custom_css', function( section ) {
+                               section.deferred.embedded.done( function() {
+                                       if ( section.expanded() ) {
+                                               sectionReady.resolve( section );
+                                       } else {
+                                               section.expanded.bind( function( isExpanded ) {
+                                                       if ( isExpanded ) {
+                                                               sectionReady.resolve( section );
+                                                       }
+                                               } );
+                                       }
+                               });
+                       });
+                       api.control( 'custom_css', function( control ) {
+                               control.deferred.embedded.done( function() {
+                                       controlReady.resolve( control );
+                               });
+                       });
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $textarea.on( 'keydown', function onKeydown( event ) {
-                                       var selectionStart, selectionEnd, value, tabKeyCode = 9, escKeyCode = 27;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 ready = $.when( sectionReady, controlReady );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        if ( escKeyCode === event.keyCode ) {
-                                               if ( ! $textarea.data( 'next-tab-blurs' ) ) {
-                                                       $textarea.data( 'next-tab-blurs', true );
-                                                       event.stopPropagation(); // Prevent collapsing the section.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 // Set up the section desription behaviors.
+                       ready.done( function setupSectionDescription( section, control ) {
+
+                               // Close the section description when clicking the close button.
+                               section.container.find( '.section-description-buttons .section-description-close' ).on( 'click', function() {
+                                       section.container.find( '.section-meta .customize-section-description:first' )
+                                               .removeClass( 'open' )
+                                               .slideUp()
+                                               .attr( 'aria-expanded', 'false' );
+                               });
+
+                               // Reveal help text if setting is empty.
+                               if ( ! control.setting.get() ) {
+                                       section.container.find( '.section-meta .customize-section-description:first' )
+                                               .addClass( 'open' )
+                                               .show()
+                                               .attr( 'aria-expanded', 'true' );
+                               }
+                       });
+
+                       // Set up the code editor itself.
+                       if ( api.settings.customCss && api.settings.customCss.codeEditor ) {
+
+                               // Set up the syntax highlighting editor.
+                               ready.done( function setupSyntaxHighlightingEditor( section, control ) {
+                                       var $textarea = control.container.find( 'textarea' ), settings, suspendEditorUpdate = false;
+
+                                       // Make sure editor gets focused when control is focused.
+                                       control.focus = (function( originalFocus ) { // eslint-disable-line max-nested-callbacks
+                                               return function( params ) { // eslint-disable-line max-nested-callbacks
+                                                       var extendedParams = _.extend( {}, params ), originalCompleteCallback;
+                                                       originalCompleteCallback = extendedParams.completeCallback;
+                                                       extendedParams.completeCallback = function() {
+                                                               if ( originalCompleteCallback ) {
+                                                                       originalCompleteCallback();
+                                                               }
+                                                               if ( control.editor ) {
+                                                                       control.editor.codemirror.focus();
+                                                               }
+                                                       };
+                                                       originalFocus.call( this, extendedParams );
+                                               };
+                                       })( control.focus );
+
+                                       settings = _.extend( {}, api.settings.customCss.codeEditor, {
+
+                                               /**
+                                                * Handle tabbing to the field after the editor.
+                                                *
+                                                * @returns {void}
+                                                */
+                                               onTabNext: function onTabNext() {
+                                                       var controls, controlIndex;
+                                                       controls = section.controls();
+                                                       controlIndex = controls.indexOf( control );
+                                                       if ( controls.length === controlIndex + 1 ) {
+                                                               $( '#customize-footer-actions .collapse-sidebar' ).focus();
+                                                       } else {
+                                                               controls[ controlIndex + 1 ].container.find( ':focusable:first' ).focus();
+                                                       }
+                                               },
+
+                                               /**
+                                                * Handle tabbing to the field before the editor.
+                                                *
+                                                * @returns {void}
+                                                */
+                                               onTabPrevious: function onTabPrevious() {
+                                                       var controls, controlIndex;
+                                                       controls = section.controls();
+                                                       controlIndex = controls.indexOf( control );
+                                                       if ( 0 === controlIndex ) {
+                                                               section.contentContainer.find( '.customize-section-title .customize-help-toggle, .customize-section-title .customize-section-description.open .section-description-close' ).last().focus();
+                                                       } else {
+                                                               controls[ controlIndex - 1 ].contentContainer.find( ':focusable:first' ).focus();
+                                                       }
+                                               },
+
+                                               /**
+                                                * Update error notice.
+                                                *
+                                                * @param {Array} errorAnnotations - Error annotations.
+                                                * @returns {void}
+                                                */
+                                               onUpdateErrorNotice: function onUpdateErrorNotice( errorAnnotations ) {
+                                                       var message;
+                                                       control.setting.notifications.remove( 'csslint_error' );
+
+                                                       if ( 0 !== errorAnnotations.length ) {
+                                                               if ( 1 === errorAnnotations.length ) {
+                                                                       message = api.l10n.customCssError.singular.replace( '%d', '1' );
+                                                               } else {
+                                                                       message = api.l10n.customCssError.plural.replace( '%d', String( errorAnnotations.length ) );
+                                                               }
+                                                               control.setting.notifications.add( 'csslint_error', new api.Notification( 'csslint_error', {
+                                                                       message: message,
+                                                                       type: 'error'
+                                                               } ) );
+                                                       }
</ins><span class="cx" style="display: block; padding: 0 10px">                                                 }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                                return;
-                                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 });
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        // Short-circuit if tab key is not being pressed or if a modifier key *is* being pressed.
-                                       if ( tabKeyCode !== event.keyCode || event.ctrlKey || event.altKey || event.shiftKey ) {
-                                               return;
-                                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 control.editor = wp.codeEditor.initialize( $textarea, settings );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        // Prevent capturing Tab characters if Esc was pressed.
-                                       if ( $textarea.data( 'next-tab-blurs' ) ) {
-                                               return;
-                                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 // Refresh when receiving focus.
+                                       control.editor.codemirror.on( 'focus', function( codemirror ) {
+                                               codemirror.refresh();
+                                       });
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        selectionStart = textarea.selectionStart;
-                                       selectionEnd = textarea.selectionEnd;
-                                       value = textarea.value;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 /*
+                                        * When the CodeMirror instance changes, mirror to the textarea,
+                                        * where we have our "true" change event handler bound.
+                                        */
+                                       control.editor.codemirror.on( 'change', function( codemirror ) {
+                                               suspendEditorUpdate = true;
+                                               $textarea.val( codemirror.getValue() ).trigger( 'change' );
+                                               suspendEditorUpdate = false;
+                                       });
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        if ( selectionStart >= 0 ) {
-                                               textarea.value = value.substring( 0, selectionStart ).concat( '\t', value.substring( selectionEnd ) );
-                                               $textarea.selectionStart = textarea.selectionEnd = selectionStart + 1;
-                                       }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 // Update CodeMirror when the setting is changed by another plugin.
+                                       control.setting.bind( function( value ) {
+                                               if ( ! suspendEditorUpdate ) {
+                                                       control.editor.codemirror.setValue( value );
+                                               }
+                                       });
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                        event.stopPropagation();
-                                       event.preventDefault();
-                               } );
-                       } );
-               } );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                 // Prevent collapsing section when hitting Esc to tab out of editor.
+                                       control.editor.codemirror.on( 'keydown', function onKeydown( codemirror, event ) {
+                                               var escKeyCode = 27;
+                                               if ( escKeyCode === event.keyCode ) {
+                                                       event.stopPropagation();
+                                               }
+                                       });
+                               });
+                       } else {
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                                // Allow tabs to be entered in Custom CSS textarea.
+                               ready.done( function allowTabs( section, control ) {
+
+                                       var $textarea = control.container.find( 'textarea' ), textarea = $textarea[0];
+
+                                       $textarea.on( 'blur', function onBlur() {
+                                               $textarea.data( 'next-tab-blurs', false );
+                                       } );
+
+                                       $textarea.on( 'keydown', function onKeydown( event ) {
+                                               var selectionStart, selectionEnd, value, tabKeyCode = 9, escKeyCode = 27;
+
+                                               if ( escKeyCode === event.keyCode ) {
+                                                       if ( ! $textarea.data( 'next-tab-blurs' ) ) {
+                                                               $textarea.data( 'next-tab-blurs', true );
+                                                               event.stopPropagation(); // Prevent collapsing the section.
+                                                       }
+                                                       return;
+                                               }
+
+                                               // Short-circuit if tab key is not being pressed or if a modifier key *is* being pressed.
+                                               if ( tabKeyCode !== event.keyCode || event.ctrlKey || event.altKey || event.shiftKey ) {
+                                                       return;
+                                               }
+
+                                               // Prevent capturing Tab characters if Esc was pressed.
+                                               if ( $textarea.data( 'next-tab-blurs' ) ) {
+                                                       return;
+                                               }
+
+                                               selectionStart = textarea.selectionStart;
+                                               selectionEnd = textarea.selectionEnd;
+                                               value = textarea.value;
+
+                                               if ( selectionStart >= 0 ) {
+                                                       textarea.value = value.substring( 0, selectionStart ).concat( '\t', value.substring( selectionEnd ) );
+                                                       $textarea.selectionStart = textarea.selectionEnd = selectionStart + 1;
+                                               }
+
+                                               event.stopPropagation();
+                                               event.preventDefault();
+                                       });
+                               });
+                       }
+               })();
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 // Toggle visibility of Header Video notice when active state change.
</span><span class="cx" style="display: block; padding: 0 10px">                api.control( 'header_video', function( headerVideoControl ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        headerVideoControl.deferred.embedded.done( function() {
</span></span></pre></div>
<a id="trunksrcwpadminjsthemeplugineditorjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/src/wp-admin/js/theme-plugin-editor.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/js/theme-plugin-editor.js                              (rev 0)
+++ trunk/src/wp-admin/js/theme-plugin-editor.js        2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,90 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/* eslint no-magic-numbers: ["error", { "ignore": [-1, 0, 1] }] */
+
+if ( ! window.wp ) {
+       window.wp = {};
+}
+
+wp.themePluginEditor = (function( $ ) {
+       'use strict';
+
+       var component = {
+               l10n: {
+                       lintError: {
+                               singular: '',
+                               plural: ''
+                       }
+               },
+               instance: null
+       };
+
+       /**
+        * Initialize component.
+        *
+        * @param {object} settings Settings.
+        * @returns {void}
+        */
+       component.init = function( settings ) {
+               var codeEditorSettings, noticeContainer, errorNotice = [], editor;
+
+               codeEditorSettings = $.extend( {}, settings );
+
+               /**
+                * Handle tabbing to the field before the editor.
+                *
+                * @returns {void}
+                */
+               codeEditorSettings.onTabPrevious = function() {
+                       $( '#templateside' ).find( ':tabbable' ).last().focus();
+               };
+
+               /**
+                * Handle tabbing to the field after the editor.
+                *
+                * @returns {void}
+                */
+               codeEditorSettings.onTabNext = function() {
+                       $( '#template' ).find( ':tabbable:not(.CodeMirror-code)' ).first().focus();
+               };
+
+               // Create the error notice container.
+               noticeContainer = $( '<div id="file-editor-linting-error"></div>' );
+               errorNotice = $( '<div class="inline notice notice-error"></div>' );
+               noticeContainer.append( errorNotice );
+               noticeContainer.hide();
+               $( 'p.submit' ).before( noticeContainer );
+
+               /**
+                * Update error notice.
+                *
+                * @param {Array} errorAnnotations - Error annotations.
+                * @returns {void}
+                */
+               codeEditorSettings.onUpdateErrorNotice = function onUpdateErrorNotice( errorAnnotations ) {
+                       var message;
+
+                       $( '#submit' ).prop( 'disabled', 0 !== errorAnnotations.length );
+
+                       if ( 0 !== errorAnnotations.length ) {
+                               errorNotice.empty();
+                               if ( 1 === errorAnnotations.length ) {
+                                       message = component.l10n.singular.replace( '%d', '1' );
+                               } else {
+                                       message = component.l10n.plural.replace( '%d', String( errorAnnotations.length ) );
+                               }
+                               errorNotice.append( $( '<p></p>', {
+                                       text: message
+                               } ) );
+                               noticeContainer.slideDown( 'fast' );
+                               wp.a11y.speak( message );
+                       } else {
+                               noticeContainer.slideUp( 'fast' );
+                       }
+               };
+
+               editor = wp.codeEditor.initialize( $( '#newcontent' ), codeEditorSettings );
+
+               component.instance = editor;
+       };
+
+       return component;
+})( jQuery );
</ins></span></pre></div>
<a id="trunksrcwpadminjswidgetscustomhtmlwidgetsjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/src/wp-admin/js/widgets/custom-html-widgets.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/js/widgets/custom-html-widgets.js                              (rev 0)
+++ trunk/src/wp-admin/js/widgets/custom-html-widgets.js        2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,414 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/* global wp */
+/* eslint consistent-this: [ "error", "control" ] */
+/* eslint no-magic-numbers: ["error", { "ignore": [0,1,-1] }] */
+wp.customHtmlWidgets = ( function( $ ) {
+       'use strict';
+
+       var component = {
+               idBases: [ 'custom_html' ],
+               codeEditorSettings: {},
+               l10n: {
+                       errorNotice: {
+                               singular: '',
+                               plural: ''
+                       }
+               }
+       };
+
+       /**
+        * Text widget control.
+        *
+        * @class CustomHtmlWidgetControl
+        * @constructor
+        * @abstract
+        */
+       component.CustomHtmlWidgetControl = Backbone.View.extend({
+
+               /**
+                * View events.
+                *
+                * @type {Object}
+                */
+               events: {},
+
+               /**
+                * Initialize.
+                *
+                * @param {Object} options - Options.
+                * @param {jQuery} options.el - Control field container element.
+                * @param {jQuery} options.syncContainer - Container element where fields are synced for the server.
+                * @returns {void}
+                */
+               initialize: function initialize( options ) {
+                       var control = this;
+
+                       if ( ! options.el ) {
+                               throw new Error( 'Missing options.el' );
+                       }
+                       if ( ! options.syncContainer ) {
+                               throw new Error( 'Missing options.syncContainer' );
+                       }
+
+                       Backbone.View.prototype.initialize.call( control, options );
+                       control.syncContainer = options.syncContainer;
+                       control.widgetIdBase = control.syncContainer.parent().find( '.id_base' ).val();
+                       control.widgetNumber = control.syncContainer.parent().find( '.widget_number' ).val();
+                       control.customizeSettingId = 'widget_' + control.widgetIdBase + '[' + String( control.widgetNumber ) + ']';
+
+                       control.$el.addClass( 'custom-html-widget-fields' );
+                       control.$el.html( wp.template( 'widget-custom-html-control-fields' )( { codeEditorDisabled: component.codeEditorSettings.disabled } ) );
+
+                       control.errorNoticeContainer = control.$el.find( '.code-editor-error-container' );
+                       control.currentErrorAnnotations = [];
+                       control.saveButton = control.syncContainer.add( control.syncContainer.parent().find( '.widget-control-actions' ) ).find( '.widget-control-save, #savewidget' );
+                       control.saveButton.addClass( 'custom-html-widget-save-button' ); // To facilitate style targeting.
+
+                       control.fields = {
+                               title: control.$el.find( '.title' ),
+                               content: control.$el.find( '.content' )
+                       };
+
+                       // Sync input fields to hidden sync fields which actually get sent to the server.
+                       _.each( control.fields, function( fieldInput, fieldName ) {
+                               fieldInput.on( 'input change', function updateSyncField() {
+                                       var syncInput = control.syncContainer.find( '.sync-input.' + fieldName );
+                                       if ( syncInput.val() !== fieldInput.val() ) {
+                                               syncInput.val( fieldInput.val() );
+                                               syncInput.trigger( 'change' );
+                                       }
+                               });
+
+                               // Note that syncInput cannot be re-used because it will be destroyed with each widget-updated event.
+                               fieldInput.val( control.syncContainer.find( '.sync-input.' + fieldName ).val() );
+                       });
+               },
+
+               /**
+                * Update input fields from the sync fields.
+                *
+                * This function is called at the widget-updated and widget-synced events.
+                * A field will only be updated if it is not currently focused, to avoid
+                * overwriting content that the user is entering.
+                *
+                * @returns {void}
+                */
+               updateFields: function updateFields() {
+                       var control = this, syncInput;
+
+                       if ( ! control.fields.title.is( document.activeElement ) ) {
+                               syncInput = control.syncContainer.find( '.sync-input.title' );
+                               control.fields.title.val( syncInput.val() );
+                       }
+
+                       /*
+                        * Prevent updating content when the editor is focused or if there are current error annotations,
+                        * to prevent the editor's contents from getting sanitized as soon as a user removes focus from
+                        * the editor. This is particularly important for users who cannot unfiltered_html.
+                        */
+                       control.contentUpdateBypassed = control.fields.content.is( document.activeElement ) || control.editor && control.editor.codemirror.state.focused || 0 !== control.currentErrorAnnotations;
+                       if ( ! control.contentUpdateBypassed ) {
+                               syncInput = control.syncContainer.find( '.sync-input.content' );
+                               control.fields.content.val( syncInput.val() ).trigger( 'change' );
+                       }
+               },
+
+               /**
+                * Show linting error notice.
+                *
+                * @param {Array} errorAnnotations - Error annotations.
+                * @returns {void}
+                */
+               updateErrorNotice: function( errorAnnotations ) {
+                       var control = this, errorNotice, message = '', customizeSetting;
+
+                       if ( 1 === errorAnnotations.length ) {
+                               message = component.l10n.errorNotice.singular.replace( '%d', '1' );
+                       } else if ( errorAnnotations.length > 1 ) {
+                               message = component.l10n.errorNotice.plural.replace( '%d', String( errorAnnotations.length ) );
+                       }
+
+                       if ( control.fields.content[0].setCustomValidity ) {
+                               control.fields.content[0].setCustomValidity( message );
+                       }
+
+                       if ( wp.customize && wp.customize.has( control.customizeSettingId ) ) {
+                               customizeSetting = wp.customize( control.customizeSettingId );
+                               customizeSetting.notifications.remove( 'htmlhint_error' );
+                               if ( 0 !== errorAnnotations.length ) {
+                                       customizeSetting.notifications.add( 'htmlhint_error', new wp.customize.Notification( 'htmlhint_error', {
+                                               message: message,
+                                               type: 'error'
+                                       } ) );
+                               }
+                       } else if ( 0 !== errorAnnotations.length ) {
+                               errorNotice = $( '<div class="inline notice notice-error notice-alt"></div>' );
+                               errorNotice.append( $( '<p></p>', {
+                                       text: message
+                               } ) );
+                               control.errorNoticeContainer.empty();
+                               control.errorNoticeContainer.append( errorNotice );
+                               control.errorNoticeContainer.slideDown( 'fast' );
+                               wp.a11y.speak( message );
+                       } else {
+                               control.errorNoticeContainer.slideUp( 'fast' );
+                       }
+               },
+
+               /**
+                * Initialize editor.
+                *
+                * @returns {void}
+                */
+               initializeEditor: function initializeEditor() {
+                       var control = this, settings;
+
+                       if ( component.codeEditorSettings.disabled ) {
+                               return;
+                       }
+
+                       settings = _.extend( {}, component.codeEditorSettings, {
+
+                               /**
+                                * Handle tabbing to the field before the editor.
+                                *
+                                * @returns {void}
+                                */
+                               onTabPrevious: function onTabPrevious() {
+                                       control.fields.title.focus();
+                               },
+
+                               /**
+                                * Handle tabbing to the field after the editor.
+                                *
+                                * @returns {void}
+                                */
+                               onTabNext: function onTabNext() {
+                                       var tabbables = control.syncContainer.add( control.syncContainer.parent().find( '.widget-position, .widget-control-actions' ) ).find( ':tabbable' );
+                                       tabbables.first().focus();
+                               },
+
+                               /**
+                                * Disable save button and store linting errors for use in updateFields.
+                                *
+                                * @param {Array} errorAnnotations - Error notifications.
+                                * @returns {void}
+                                */
+                               onChangeLintingErrors: function onChangeLintingErrors( errorAnnotations ) {
+                                       control.currentErrorAnnotations = errorAnnotations;
+                               },
+
+                               /**
+                                * Update error notice.
+                                *
+                                * @param {Array} errorAnnotations - Error annotations.
+                                * @returns {void}
+                                */
+                               onUpdateErrorNotice: function onUpdateErrorNotice( errorAnnotations ) {
+                                       control.saveButton.toggleClass( 'validation-blocked', errorAnnotations.length );
+                                       control.updateErrorNotice( errorAnnotations );
+                               }
+                       });
+
+                       control.editor = wp.codeEditor.initialize( control.fields.content, settings );
+                       control.fields.content.on( 'change', function() {
+                               if ( this.value !== control.editor.codemirror.getValue() ) {
+                                       control.editor.codemirror.setValue( this.value );
+                               }
+                       });
+                       control.editor.codemirror.on( 'change', function() {
+                               var value = control.editor.codemirror.getValue();
+                               if ( value !== control.fields.content.val() ) {
+                                       control.fields.content.val( value ).trigger( 'change' );
+                               }
+                       });
+
+                       // Make sure the editor gets updated if the content was updated on the server (sanitization) but not updated in the editor since it was focused.
+                       control.editor.codemirror.on( 'blur', function() {
+                               if ( control.contentUpdateBypassed ) {
+                                       control.syncContainer.find( '.sync-input.content' ).trigger( 'change' );
+                               }
+                       });
+
+                       // Prevent hitting Esc from collapsing the widget control.
+                       if ( wp.customize ) {
+                               control.editor.codemirror.on( 'keydown', function onKeydown( codemirror, event ) {
+                                       var escKeyCode = 27;
+                                       if ( escKeyCode === event.keyCode ) {
+                                               event.stopPropagation();
+                                       }
+                               });
+                       }
+               }
+       });
+
+       /**
+        * Mapping of widget ID to instances of CustomHtmlWidgetControl subclasses.
+        *
+        * @type {Object.<string, wp.textWidgets.CustomHtmlWidgetControl>}
+        */
+       component.widgetControls = {};
+
+       /**
+        * Handle widget being added or initialized for the first time at the widget-added event.
+        *
+        * @param {jQuery.Event} event - Event.
+        * @param {jQuery}       widgetContainer - Widget container element.
+        * @returns {void}
+        */
+       component.handleWidgetAdded = function handleWidgetAdded( event, widgetContainer ) {
+               var widgetForm, idBase, widgetControl, widgetId, animatedCheckDelay = 50, renderWhenAnimationDone, fieldContainer, syncContainer;
+               widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); // Note: '.form' appears in the customizer, whereas 'form' on the widgets admin screen.
+
+               idBase = widgetForm.find( '> .id_base' ).val();
+               if ( -1 === component.idBases.indexOf( idBase ) ) {
+                       return;
+               }
+
+               // Prevent initializing already-added widgets.
+               widgetId = widgetForm.find( '.widget-id' ).val();
+               if ( component.widgetControls[ widgetId ] ) {
+                       return;
+               }
+
+               /*
+                * Create a container element for the widget control fields.
+                * This is inserted into the DOM immediately before the the .widget-content
+                * element because the contents of this element are essentially "managed"
+                * by PHP, where each widget update cause the entire element to be emptied
+                * and replaced with the rendered output of WP_Widget::form() which is
+                * sent back in Ajax request made to save/update the widget instance.
+                * To prevent a "flash of replaced DOM elements and re-initialized JS
+                * components", the JS template is rendered outside of the normal form
+                * container.
+                */
+               fieldContainer = $( '<div></div>' );
+               syncContainer = widgetContainer.find( '.widget-content:first' );
+               syncContainer.before( fieldContainer );
+
+               widgetControl = new component.CustomHtmlWidgetControl({
+                       el: fieldContainer,
+                       syncContainer: syncContainer
+               });
+
+               component.widgetControls[ widgetId ] = widgetControl;
+
+               /*
+                * Render the widget once the widget parent's container finishes animating,
+                * as the widget-added event fires with a slideDown of the container.
+                * This ensures that the textarea is visible and the editor can be initialized.
+                */
+               renderWhenAnimationDone = function() {
+                       if ( ! ( wp.customize ? widgetContainer.parent().hasClass( 'expanded' ) : widgetContainer.hasClass( 'open' ) ) ) { // Core merge: The wp.customize condition can be eliminated with this change being in core: https://github.com/xwp/wordpress-develop/pull/247/commits/5322387d
+                               setTimeout( renderWhenAnimationDone, animatedCheckDelay );
+                       } else {
+                               widgetControl.initializeEditor();
+                       }
+               };
+               renderWhenAnimationDone();
+       };
+
+       /**
+        * Setup widget in accessibility mode.
+        *
+        * @returns {void}
+        */
+       component.setupAccessibleMode = function setupAccessibleMode() {
+               var widgetForm, idBase, widgetControl, fieldContainer, syncContainer;
+               widgetForm = $( '.editwidget > form' );
+               if ( 0 === widgetForm.length ) {
+                       return;
+               }
+
+               idBase = widgetForm.find( '> .widget-control-actions > .id_base' ).val();
+               if ( -1 === component.idBases.indexOf( idBase ) ) {
+                       return;
+               }
+
+               fieldContainer = $( '<div></div>' );
+               syncContainer = widgetForm.find( '> .widget-inside' );
+               syncContainer.before( fieldContainer );
+
+               widgetControl = new component.CustomHtmlWidgetControl({
+                       el: fieldContainer,
+                       syncContainer: syncContainer
+               });
+
+               widgetControl.initializeEditor();
+       };
+
+       /**
+        * Sync widget instance data sanitized from server back onto widget model.
+        *
+        * This gets called via the 'widget-updated' event when saving a widget from
+        * the widgets admin screen and also via the 'widget-synced' event when making
+        * a change to a widget in the customizer.
+        *
+        * @param {jQuery.Event} event - Event.
+        * @param {jQuery}       widgetContainer - Widget container element.
+        * @returns {void}
+        */
+       component.handleWidgetUpdated = function handleWidgetUpdated( event, widgetContainer ) {
+               var widgetForm, widgetId, widgetControl, idBase;
+               widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' );
+
+               idBase = widgetForm.find( '> .id_base' ).val();
+               if ( -1 === component.idBases.indexOf( idBase ) ) {
+                       return;
+               }
+
+               widgetId = widgetForm.find( '> .widget-id' ).val();
+               widgetControl = component.widgetControls[ widgetId ];
+               if ( ! widgetControl ) {
+                       return;
+               }
+
+               widgetControl.updateFields();
+       };
+
+       /**
+        * Initialize functionality.
+        *
+        * This function exists to prevent the JS file from having to boot itself.
+        * When WordPress enqueues this script, it should have an inline script
+        * attached which calls wp.textWidgets.init().
+        *
+        * @param {object} settings - Options for code editor, exported from PHP.
+        * @returns {void}
+        */
+       component.init = function init( settings ) {
+               var $document = $( document );
+               _.extend( component.codeEditorSettings, settings );
+
+               $document.on( 'widget-added', component.handleWidgetAdded );
+               $document.on( 'widget-synced widget-updated', component.handleWidgetUpdated );
+
+               /*
+                * Manually trigger widget-added events for media widgets on the admin
+                * screen once they are expanded. The widget-added event is not triggered
+                * for each pre-existing widget on the widgets admin screen like it is
+                * on the customizer. Likewise, the customizer only triggers widget-added
+                * when the widget is expanded to just-in-time construct the widget form
+                * when it is actually going to be displayed. So the following implements
+                * the same for the widgets admin screen, to invoke the widget-added
+                * handler when a pre-existing media widget is expanded.
+                */
+               $( function initializeExistingWidgetContainers() {
+                       var widgetContainers;
+                       if ( 'widgets' !== window.pagenow ) {
+                               return;
+                       }
+                       widgetContainers = $( '.widgets-holder-wrap:not(#available-widgets)' ).find( 'div.widget' );
+                       widgetContainers.one( 'click.toggle-widget-expanded', function toggleWidgetExpanded() {
+                               var widgetContainer = $( this );
+                               component.handleWidgetAdded( new jQuery.Event( 'widget-added' ), widgetContainer );
+                       });
+
+                       // Accessibility mode.
+                       $( window ).on( 'load', function() {
+                               component.setupAccessibleMode();
+                       });
+               });
+       };
+
+       return component;
+})( jQuery );
</ins></span></pre></div>
<a id="trunksrcwpadminplugineditorphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/plugin-editor.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/plugin-editor.php      2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/src/wp-admin/plugin-editor.php        2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -115,7 +115,40 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        // List of allowable extensions
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        $editable_extensions = array('php', 'txt', 'text', 'js', 'css', 'html', 'htm', 'xml', 'inc', 'include');
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $editable_extensions = array(
+               'bash',
+               'conf',
+               'css',
+               'diff',
+               'htm',
+               'html',
+               'http',
+               'inc',
+               'include',
+               'js',
+               'json',
+               'jsx',
+               'less',
+               'md',
+               'patch',
+               'php',
+               'php3',
+               'php4',
+               'php5',
+               'php7',
+               'phps',
+               'phtml',
+               'sass',
+               'scss',
+               'sh',
+               'sql',
+               'svg',
+               'text',
+               'txt',
+               'xml',
+               'yaml',
+               'yml',
+       );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="cx" style="display: block; padding: 0 10px">         * Filters file type extensions editable in the plugin editor.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -157,6 +190,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                '<p>' . __('<a href="https://wordpress.org/support/">Support Forums</a>') . '</p>'
</span><span class="cx" style="display: block; padding: 0 10px">        );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        $settings = wp_enqueue_code_editor( array( 'file' => $real_file ) );
+       if ( ! empty( $settings ) ) {
+               wp_enqueue_script( 'wp-theme-plugin-editor' );
+               wp_add_inline_script( 'wp-theme-plugin-editor', sprintf( 'jQuery( function() { wp.themePluginEditor.init( %s ); } )', wp_json_encode( $settings ) ) );
+       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">         require_once(ABSPATH . 'wp-admin/admin-header.php');
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        update_recently_edited(WP_PLUGIN_DIR . '/' . $file);
</span></span></pre></div>
<a id="trunksrcwpadminthemeeditorphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/theme-editor.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/theme-editor.php       2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/src/wp-admin/theme-editor.php 2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -63,7 +63,40 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> $allowed_files = $style_files = array();
</span><span class="cx" style="display: block; padding: 0 10px"> $has_templates = false;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-$default_types = array( 'php', 'css' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+$default_types = array(
+       'bash',
+       'conf',
+       'css',
+       'diff',
+       'htm',
+       'html',
+       'http',
+       'inc',
+       'include',
+       'js',
+       'json',
+       'jsx',
+       'less',
+       'md',
+       'patch',
+       'php',
+       'php3',
+       'php4',
+       'php5',
+       'php7',
+       'phps',
+       'phtml',
+       'sass',
+       'scss',
+       'sh',
+       'sql',
+       'svg',
+       'text',
+       'txt',
+       'xml',
+       'yaml',
+       'yml',
+);
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px">  * Filters the list of file types allowed for editing in the Theme editor.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -126,6 +159,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> default:
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        $settings = wp_enqueue_code_editor( compact( 'file' ) );
+       if ( ! empty( $settings ) ) {
+               wp_enqueue_script( 'wp-theme-plugin-editor' );
+               wp_add_inline_script( 'wp-theme-plugin-editor', sprintf( 'jQuery( function() { wp.themePluginEditor.init( %s ); } )', wp_json_encode( $settings ) ) );
+       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">         require_once( ABSPATH . 'wp-admin/admin-header.php' );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        update_recently_edited( $file );
</span></span></pre></div>
<a id="trunksrcwpadminusereditphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-admin/user-edit.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-admin/user-edit.php  2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/src/wp-admin/user-edit.php    2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -247,6 +247,26 @@
</span><span class="cx" style="display: block; padding: 0 10px">                <td><label for="rich_editing"><input name="rich_editing" type="checkbox" id="rich_editing" value="false" <?php if ( ! empty( $profileuser->rich_editing ) ) checked( 'false', $profileuser->rich_editing ); ?> /> <?php _e( 'Disable the visual editor when writing' ); ?></label></td>
</span><span class="cx" style="display: block; padding: 0 10px">        </tr>
</span><span class="cx" style="display: block; padding: 0 10px"> <?php endif; ?>
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+$show_syntax_highlighting_preference = (
+       // For Custom HTML widget and Additional CSS in Customizer.
+       user_can( $profileuser, 'edit_theme_options' )
+       ||
+       // Edit plugins.
+       user_can( $profileuser, 'edit_plugins' )
+       ||
+       // Edit themes.
+       user_can( $profileuser, 'edit_themes' )
+);
+?>
+<?php if ( $show_syntax_highlighting_preference ) : ?>
+       <tr class="user-syntax-highlighting-wrap">
+               <th scope="row"><?php _e( 'Syntax Highlighting' ); ?></th>
+               <td>
+                       <label for="syntax_highlighting"><input name="syntax_highlighting" type="checkbox" id="syntax_highlighting" value="false" <?php if ( ! empty( $profileuser->syntax_highlighting ) ) checked( 'false', $profileuser->syntax_highlighting ); ?> /> <?php _e( 'Disable syntax highlighting when editing code' ); ?></label>
+               </td>
+       </tr>
+<?php endif; ?>
</ins><span class="cx" style="display: block; padding: 0 10px"> <?php if ( count($_wp_admin_css_colors) > 1 && has_action('admin_color_scheme_picker') ) : ?>
</span><span class="cx" style="display: block; padding: 0 10px"> <tr class="user-admin-color-wrap">
</span><span class="cx" style="display: block; padding: 0 10px"> <th scope="row"><?php _e('Admin Color Scheme')?></th>
</span></span></pre></div>
<a id="trunksrcwpincludesauthortemplatephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/author-template.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/author-template.php 2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/src/wp-includes/author-template.php   2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -128,6 +128,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">  * - plugins_last_view
</span><span class="cx" style="display: block; padding: 0 10px">  * - plugins_per_page
</span><span class="cx" style="display: block; padding: 0 10px">  * - rich_editing
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * - syntax_highlighting
</ins><span class="cx" style="display: block; padding: 0 10px">  * - user_activation_key
</span><span class="cx" style="display: block; padding: 0 10px">  * - user_description
</span><span class="cx" style="display: block; padding: 0 10px">  * - user_email
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpcustomizemanagerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-customize-manager.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-customize-manager.php      2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/src/wp-includes/class-wp-customize-manager.php        2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -213,6 +213,21 @@
</span><span class="cx" style="display: block; padding: 0 10px">        private $_changeset_data;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Code Editor Settings for Custom CSS.
+        *
+        * This variable contains the settings returned by `wp_enqueue_code_editor()` which are then later output
+        * to the client in `WP_Customize_Manager::customize_pane_settings()`. A value of false means that the
+        * Custom CSS section or control was removed, or that the Syntax Highlighting user pref was turned off.
+        *
+        * @see wp_enqueue_code_editor()
+        * @see WP_Customize_Manager::enqueue_control_scripts()
+        * @see WP_Customize_Manager::customize_pane_settings()
+        * @since 4.9.0
+        * @var array|false
+        */
+       private $_custom_css_code_editor_settings = false;
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Constructor.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 3.4.0
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3322,6 +3337,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                foreach ( $this->controls as $control ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $control->enqueue();
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+               if ( $this->get_section( 'custom_css' ) && $this->get_control( 'custom_css' ) ) {
+                       $this->_custom_css_code_editor_settings = wp_enqueue_code_editor( array(
+                               'type' => 'text/css',
+                       ) );
+               }
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3579,6 +3600,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                'stylesheet' => $this->get_stylesheet(),
</span><span class="cx" style="display: block; padding: 0 10px">                                'active'     => $this->is_theme_active(),
</span><span class="cx" style="display: block; padding: 0 10px">                        ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                        'customCss' => array(
+                               'codeEditor' => $this->_custom_css_code_editor_settings,
+                       ),
</ins><span class="cx" style="display: block; padding: 0 10px">                         'url'      => array(
</span><span class="cx" style="display: block; padding: 0 10px">                                'preview'       => esc_url_raw( $this->get_preview_url() ),
</span><span class="cx" style="display: block; padding: 0 10px">                                'parent'        => esc_url_raw( admin_url() ),
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4177,22 +4201,53 @@
</span><span class="cx" style="display: block; padding: 0 10px">                ) );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                /* Custom CSS */
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $section_description = '<p>';
+               $section_description .= __( 'Add your own CSS code here to customize the appearance and layout of your site.', 'better-code-editing' );
+               $section_description .= sprintf(
+                       ' <a href="%1$s" class="external-link" target="_blank">%2$s<span class="screen-reader-text">%3$s</span></a>',
+                       esc_url( __( 'https://codex.wordpress.org/CSS', 'default' ) ),
+                       __( 'Learn more about CSS', 'default' ),
+                       /* translators: accessibility text */
+                       __( '(opens in a new window)', 'default' )
+               );
+               $section_description .= '</p>';
+
+               $section_description .= '<p>' . __( 'When using a keyboard to navigate:', 'better-code-editing' ) . '</p>';
+               $section_description .= '<ul>';
+               $section_description .= '<li>' . __( 'In the CSS edit field, Tab enters a tab character.', 'better-code-editing' ) . '</li>';
+               $section_description .= '<li>' . __( 'To move keyboard focus, press Esc then Tab for the next element, or Esc then Shift+Tab for the previous element.', 'better-code-editing' ) . '</li>';
+               $section_description .= '</ul>';
+
+               if ( 'false' !== wp_get_current_user()->syntax_highlighting ) {
+                       $section_description .= '<p>';
+                       $section_description .= sprintf(
+                               /* translators: placeholder is link to user profile */
+                               __( 'The edit field automatically highlights code syntax. You can disable this in your %s to work in plain text mode.', 'better-code-editing' ),
+                               sprintf(
+                                       ' <a href="%1$s" class="external-link" target="_blank">%2$s<span class="screen-reader-text">%3$s</span></a>',
+                                       esc_url( get_edit_profile_url() . '#syntax_highlighting' ),
+                                       __( 'user profile', 'better-code-editing' ),
+                                       /* translators: accessibility text */
+                                       __( '(opens in a new window)', 'default' )
+                               )
+                       );
+                       $section_description .= '</p>';
+               }
+
+               $section_description .= '<p class="section-description-buttons">';
+               $section_description .= '<button type="button" class="button-link section-description-close">' . __( 'Close', 'default' ) . '</button>';
+               $section_description .= '</p>';
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->add_section( 'custom_css', array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'title'              => __( 'Additional CSS' ),
</span><span class="cx" style="display: block; padding: 0 10px">                        'priority'           => 200,
</span><span class="cx" style="display: block; padding: 0 10px">                        'description_hidden' => true,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        'description'        => sprintf( '%s<br /><a href="%s" class="external-link" target="_blank">%s<span class="screen-reader-text">%s</span></a>',
-                               __( 'CSS allows you to customize the appearance and layout of your site with code. Separate CSS is saved for each of your themes. In the editing area the Tab key enters a tab character. To move below this area by pressing Tab, press the Esc key followed by the Tab key.' ),
-                               esc_url( __( 'https://codex.wordpress.org/CSS' ) ),
-                               __( 'Learn more about CSS' ),
-                               /* translators: accessibility text */
-                               __( '(opens in a new window)' )
-                       ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 'description'        => $section_description,
</ins><span class="cx" style="display: block; padding: 0 10px">                 ) );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $custom_css_setting = new WP_Customize_Custom_CSS_Setting( $this, sprintf( 'custom_css[%s]', get_stylesheet() ), array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'capability' => 'edit_css',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        'default' => sprintf( "/*\n%s\n*/", __( "You can add your own CSS here.\n\nClick the help icon above to learn more." ) ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 'default' => '',
</ins><span class="cx" style="display: block; padding: 0 10px">                 ) );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->add_setting( $custom_css_setting );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpuserphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-user.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-user.php   2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/src/wp-includes/class-wp-user.php     2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -32,6 +32,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">  * @property string $spam
</span><span class="cx" style="display: block; padding: 0 10px">  * @property string $deleted
</span><span class="cx" style="display: block; padding: 0 10px">  * @property string $locale
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @property string $rich_editing
+ * @property string $syntax_highlighting
</ins><span class="cx" style="display: block; padding: 0 10px">  */
</span><span class="cx" style="display: block; padding: 0 10px"> class WP_User {
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span></span></pre></div>
<a id="trunksrcwpincludescustomizeclasswpcustomizecustomcsssettingphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/customize/class-wp-customize-custom-css-setting.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/customize/class-wp-customize-custom-css-setting.php 2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/src/wp-includes/customize/class-wp-customize-custom-css-setting.php   2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -148,9 +148,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">         * Checks for imbalanced braces, brackets, and comments.
</span><span class="cx" style="display: block; padding: 0 10px">         * Notifications are rendered when the customizer state is saved.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-         * @todo There are cases where valid CSS can be incorrectly marked as invalid when strings or comments include balancing characters. To fix, CSS tokenization needs to be used.
-        *
</del><span class="cx" style="display: block; padding: 0 10px">          * @since 4.7.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @since 4.9.0 Checking for balanced characters has been moved client-side via linting in code editor.
</ins><span class="cx" style="display: block; padding: 0 10px">          *
</span><span class="cx" style="display: block; padding: 0 10px">         * @param string $css The input string.
</span><span class="cx" style="display: block; padding: 0 10px">         * @return true|WP_Error True if the input was validated, otherwise WP_Error.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -162,94 +161,6 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        $validity->add( 'illegal_markup', __( 'Markup is not allowed in CSS.' ) );
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $imbalanced = false;
-
-               // Make sure that there is a closing brace for each opening brace.
-               if ( ! $this->validate_balanced_characters( '{', '}', $css ) ) {
-                       $validity->add( 'imbalanced_curly_brackets', sprintf(
-                               /* translators: 1: {}, 2: }, 3: { */
-                               __( 'Your curly brackets %1$s are imbalanced. Make sure there is a closing %2$s for every opening %3$s.' ),
-                               '<code>{}</code>',
-                               '<code>}</code>',
-                               '<code>{</code>'
-                       ) );
-                       $imbalanced = true;
-               }
-
-               // Ensure brackets are balanced.
-               if ( ! $this->validate_balanced_characters( '[', ']', $css ) ) {
-                       $validity->add( 'imbalanced_braces', sprintf(
-                               /* translators: 1: [], 2: ], 3: [ */
-                               __( 'Your brackets %1$s are imbalanced. Make sure there is a closing %2$s for every opening %3$s.' ),
-                               '<code>[]</code>',
-                               '<code>]</code>',
-                               '<code>[</code>'
-                       ) );
-                       $imbalanced = true;
-               }
-
-               // Ensure parentheses are balanced.
-               if ( ! $this->validate_balanced_characters( '(', ')', $css ) ) {
-                       $validity->add( 'imbalanced_parentheses', sprintf(
-                               /* translators: 1: (), 2: ), 3: ( */
-                               __( 'Your parentheses %1$s are imbalanced. Make sure there is a closing %2$s for every opening %3$s.' ),
-                               '<code>()</code>',
-                               '<code>)</code>',
-                               '<code>(</code>'
-                       ) );
-                       $imbalanced = true;
-               }
-
-               // Ensure double quotes are equal.
-               if ( ! $this->validate_equal_characters( '"', $css ) ) {
-                       $validity->add( 'unequal_double_quotes', sprintf(
-                               /* translators: 1: " (double quote) */
-                               __( 'Your double quotes %1$s are uneven. Make sure there is a closing %1$s for every opening %1$s.' ),
-                               '<code>"</code>'
-                       ) );
-                       $imbalanced = true;
-               }
-
-               /*
-                * Make sure any code comments are closed properly.
-                *
-                * The first check could miss stray an unpaired comment closing figure, so if
-                * The number appears to be balanced, then check for equal numbers
-                * of opening/closing comment figures.
-                *
-                * Although it may initially appear redundant, we use the first method
-                * to give more specific feedback to the user.
-                */
-               $unclosed_comment_count = $this->validate_count_unclosed_comments( $css );
-               if ( 0 < $unclosed_comment_count ) {
-                       $validity->add( 'unclosed_comment', sprintf(
-                               /* translators: 1: number of unclosed comments, 2: *​/ */
-                               _n(
-                                       'There is %1$s unclosed code comment. Close each comment with %2$s.',
-                                       'There are %1$s unclosed code comments. Close each comment with %2$s.',
-                                       $unclosed_comment_count
-                               ),
-                               $unclosed_comment_count,
-                               '<code>*/</code>'
-                       ) );
-                       $imbalanced = true;
-               } elseif ( ! $this->validate_balanced_characters( '/*', '*/', $css ) ) {
-                       $validity->add( 'imbalanced_comments', sprintf(
-                               /* translators: 1: *​/, 2: /​* */
-                               __( 'There is an extra %1$s, indicating an end to a comment. Be sure that there is an opening %2$s for every closing %1$s.' ),
-                               '<code>*/</code>',
-                               '<code>/*</code>'
-                       ) );
-                       $imbalanced = true;
-               }
-               if ( $imbalanced && $this->is_possible_content_error( $css ) ) {
-                       $validity->add( 'possible_false_positive', sprintf(
-                               /* translators: %s: content: ""; */
-                               __( 'Imbalanced/unclosed character errors can be caused by %s declarations. You may need to remove this or add it to a custom CSS file.' ),
-                               '<code>content: "";</code>'
-                       ) );
-               }
-
</del><span class="cx" style="display: block; padding: 0 10px">                 if ( empty( $validity->errors ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                        $validity = parent::validate( $css );
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -285,109 +196,4 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                return $post_id;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
-       /**
-        * Ensure there are a balanced number of paired characters.
-        *
-        * This is used to check that the number of opening and closing
-        * characters is equal.
-        *
-        * For instance, there should be an equal number of braces ("{", "}")
-        * in the CSS.
-        *
-        * @since 4.7.0
-        *
-        * @param string $opening_char The opening character.
-        * @param string $closing_char The closing character.
-        * @param string $css The CSS input string.
-        *
-        * @return bool
-        */
-       private function validate_balanced_characters( $opening_char, $closing_char, $css ) {
-               return substr_count( $css, $opening_char ) === substr_count( $css, $closing_char );
-       }
-
-       /**
-        * Ensure there are an even number of paired characters.
-        *
-        * This is used to check that the number of a specific
-        * character is even.
-        *
-        * For instance, there should be an even number of double quotes
-        * in the CSS.
-        *
-        * @since 4.7.0
-        *
-        * @param string $char A character.
-        * @param string $css The CSS input string.
-        * @return bool Equality.
-        */
-       private function validate_equal_characters( $char, $css ) {
-               $char_count = substr_count( $css, $char );
-               return ( 0 === $char_count % 2 );
-       }
-
-       /**
-        * Count unclosed CSS Comments.
-        *
-        * Used during validation.
-        *
-        * @see self::validate()
-        *
-        * @since 4.7.0
-        *
-        * @param string $css The CSS input string.
-        * @return int Count.
-        */
-       private function validate_count_unclosed_comments( $css ) {
-               $count = 0;
-               $comments = explode( '/*', $css );
-
-               if ( ! is_array( $comments ) || ( 1 >= count( $comments ) ) ) {
-                       return $count;
-               }
-
-               unset( $comments[0] ); // The first item is before the first comment.
-               foreach ( $comments as $comment ) {
-                       if ( false === strpos( $comment, '*/' ) ) {
-                               $count++;
-                       }
-               }
-               return $count;
-       }
-
-       /**
-        * Find "content:" within a string.
-        *
-        * Imbalanced/Unclosed validation errors may be caused
-        * when a character is used in a "content:" declaration.
-        *
-        * This function is used to detect if this is a possible
-        * cause of the validation error, so that if it is,
-        * a notification may be added to the Validation Errors.
-        *
-        * Example:
-        * .element::before {
-        *   content: "(\"";
-        * }
-        * .element::after {
-        *   content: "\")";
-        * }
-        *
-        * Using ! empty() because strpos() may return non-boolean values
-        * that evaluate to false. This would be problematic when
-        * using a strict "false === strpos()" comparison.
-        *
-        * @since 4.7.0
-        *
-        * @param string $css The CSS input string.
-        * @return bool
-        */
-       private function is_possible_content_error( $css ) {
-               $found = preg_match( '/\bcontent\s*:/', $css );
-               if ( ! empty( $found ) ) {
-                       return true;
-               }
-               return false;
-       }
</del><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunksrcwpincludesgeneraltemplatephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/general-template.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/general-template.php        2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/src/wp-includes/general-template.php  2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3116,6 +3116,394 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Enqueue assets needed by the code editor for the given settings.
+ *
+ * @since 4.9.0
+ *
+ * @see wp_enqueue_editor()
+ * @see _WP_Editors::parse_settings()
+ * @param array $args {
+ *     Args.
+ *
+ *     @type string   $type     The MIME type of the file to be edited.
+ *     @type string   $file     Filename to be edited. Extension is used to sniff the type. Can be supplied as alternative to `$type` param.
+ *     @type array    $settings Settings to merge on top of defaults which derive from `$type` or `$file` args.
+ *     @type WP_Theme $theme    Theme being edited when on theme editor.
+ *     @type string   $plugin   Plugin being edited when on plugin editor.
+ * }
+ * @returns array|false Settings for the enqueued code editor, or false if the editor was not enqueued .
+ */
+function wp_enqueue_code_editor( $args ) {
+       if ( is_user_logged_in() && 'false' === wp_get_current_user()->syntax_highlighting ) {
+               return false;
+       }
+
+       $settings = array(
+               'codemirror' => array(
+                       'indentUnit' => 4,
+                       'indentWithTabs' => true,
+                       'inputStyle' => 'contenteditable',
+                       'lineNumbers' => true,
+                       'lineWrapping' => true,
+                       'styleActiveLine' => true,
+                       'continueComments' => true,
+                       'extraKeys' => array(
+                               'Ctrl-Space' => 'autocomplete',
+                               'Ctrl-/' => 'toggleComment',
+                               'Cmd-/' => 'toggleComment',
+                               'Alt-F' => 'findPersistent',
+                       ),
+                       'direction' => 'ltr', // Code is shown in LTR even in RTL languages.
+               ),
+               'csslint' => array(
+                       'errors' => true, // Parsing errors.
+                       'box-model' => true,
+                       'display-property-grouping' => true,
+                       'duplicate-properties' => true,
+                       'known-properties' => true,
+                       'outline-none' => true,
+               ),
+               'jshint' => array(
+                       // The following are copied from <https://github.com/WordPress/wordpress-develop/blob/4.8.1/.jshintrc>.
+                       'boss' => true,
+                       'curly' => true,
+                       'eqeqeq' => true,
+                       'eqnull' => true,
+                       'es3' => true,
+                       'expr' => true,
+                       'immed' => true,
+                       'noarg' => true,
+                       'nonbsp' => true,
+                       'onevar' => true,
+                       'quotmark' => 'single',
+                       'trailing' => true,
+                       'undef' => true,
+                       'unused' => true,
+
+                       'browser' => true,
+
+                       'globals' => array(
+                               '_' => false,
+                               'Backbone' => false,
+                               'jQuery' => false,
+                               'JSON' => false,
+                               'wp' => false,
+                       ),
+               ),
+               'htmlhint' => array(
+                       'tagname-lowercase' => true,
+                       'attr-lowercase' => true,
+                       'attr-value-double-quotes' => true,
+                       'doctype-first' => false,
+                       'tag-pair' => true,
+                       'spec-char-escape' => true,
+                       'id-unique' => true,
+                       'src-not-empty' => true,
+                       'attr-no-duplication' => true,
+                       'alt-require' => true,
+                       'space-tab-mixed-disabled' => 'tab',
+                       'attr-unsafe-chars' => true,
+               ),
+       );
+
+       $type = '';
+       if ( isset( $args['type'] ) ) {
+               $type = $args['type'];
+
+               // Remap MIME types to ones that CodeMirror modes will recognize.
+               if ( 'application/x-patch' === $type || 'text/x-patch' === $type ) {
+                       $type = 'text/x-diff';
+               }
+       } elseif ( isset( $args['file'] ) && false !== strpos( basename( $args['file'] ), '.' ) ) {
+               $extension = strtolower( pathinfo( $args['file'], PATHINFO_EXTENSION ) );
+               foreach ( wp_get_mime_types() as $exts => $mime ) {
+                       if ( preg_match( '!^(' . $exts . ')$!i', $extension ) ) {
+                               $type = $mime;
+                               break;
+                       }
+               }
+
+               // Supply any types that are not matched by wp_get_mime_types().
+               if ( empty( $type ) ) {
+                       switch ( $extension ) {
+                               case 'conf':
+                                       $type = 'text/nginx';
+                                       break;
+                               case 'css':
+                                       $type = 'text/css';
+                                       break;
+                               case 'diff':
+                               case 'patch':
+                                       $type = 'text/x-diff';
+                                       break;
+                               case 'html':
+                               case 'htm':
+                                       $type = 'text/html';
+                                       break;
+                               case 'http':
+                                       $type = 'message/http';
+                                       break;
+                               case 'js':
+                                       $type = 'text/javascript';
+                                       break;
+                               case 'json':
+                                       $type = 'application/json';
+                                       break;
+                               case 'jsx':
+                                       $type = 'text/jsx';
+                                       break;
+                               case 'less':
+                                       $type = 'text/x-less';
+                                       break;
+                               case 'md':
+                                       $type = 'text/x-gfm';
+                                       break;
+                               case 'php':
+                               case 'phtml':
+                               case 'php3':
+                               case 'php4':
+                               case 'php5':
+                               case 'php7':
+                               case 'phps':
+                                       $type = 'application/x-httpd-php';
+                                       break;
+                               case 'scss':
+                                       $type = 'text/x-scss';
+                                       break;
+                               case 'sass':
+                                       $type = 'text/x-sass';
+                                       break;
+                               case 'sh':
+                               case 'bash':
+                                       $type = 'text/x-sh';
+                                       break;
+                               case 'sql':
+                                       $type = 'text/x-sql';
+                                       break;
+                               case 'svg':
+                                       $type = 'application/svg+xml';
+                                       break;
+                               case 'xml':
+                                       $type = 'text/xml';
+                                       break;
+                               case 'yml':
+                               case 'yaml':
+                                       $type = 'text/x-yaml';
+                                       break;
+                               case 'txt':
+                               default:
+                                       $type = 'text/plain';
+                                       break;
+                       }
+               }
+       }
+
+       if ( 'text/css' === $type ) {
+               $settings['codemirror'] = array_merge( $settings['codemirror'], array(
+                       'mode' => 'css',
+                       'lint' => true,
+                       'autoCloseBrackets' => true,
+                       'matchBrackets' => true,
+               ) );
+       } elseif ( 'text/x-scss' === $type || 'text/x-less' === $type || 'text/x-sass' === $type ) {
+               $settings['codemirror'] = array_merge( $settings['codemirror'], array(
+                       'mode' => $type,
+                       'autoCloseBrackets' => true,
+                       'matchBrackets' => true,
+               ) );
+       } elseif ( 'text/x-diff' === $type ) {
+               $settings['codemirror'] = array_merge( $settings['codemirror'], array(
+                       'mode' => 'diff',
+               ) );
+       } elseif ( 'text/html' === $type ) {
+               $settings['codemirror'] = array_merge( $settings['codemirror'], array(
+                       'mode' => 'htmlmixed',
+                       'lint' => true,
+                       'autoCloseBrackets' => true,
+                       'autoCloseTags' => true,
+                       'matchTags' => array(
+                               'bothTags' => true,
+                       ),
+               ) );
+
+               if ( ! current_user_can( 'unfiltered_html' ) ) {
+                       $settings['htmlhint']['kses'] = wp_kses_allowed_html( 'post' );
+               }
+       } elseif ( 'text/x-gfm' === $type ) {
+               $settings['codemirror'] = array_merge( $settings['codemirror'], array(
+                       'mode' => 'gfm',
+                       'highlightFormatting' => true,
+               ) );
+       } elseif ( 'application/javascript' === $type || 'text/javascript' === $type ) {
+               $settings['codemirror'] = array_merge( $settings['codemirror'], array(
+                       'mode' => 'javascript',
+                       'lint' => true,
+                       'autoCloseBrackets' => true,
+                       'matchBrackets' => true,
+               ) );
+       } elseif ( false !== strpos( $type, 'json' ) ) {
+               $settings['codemirror'] = array_merge( $settings['codemirror'], array(
+                       'mode' => array(
+                               'name' => 'javascript',
+                       ),
+                       'lint' => true,
+                       'autoCloseBrackets' => true,
+                       'matchBrackets' => true,
+               ) );
+               if ( 'application/ld+json' === $type ) {
+                       $settings['codemirror']['mode']['jsonld'] = true;
+               } else {
+                       $settings['codemirror']['mode']['json'] = true;
+               }
+       } elseif ( false !== strpos( $type, 'jsx' ) ) {
+               $settings['codemirror'] = array_merge( $settings['codemirror'], array(
+                       'mode' => 'jsx',
+                       'autoCloseBrackets' => true,
+                       'matchBrackets' => true,
+               ) );
+       } elseif ( 'text/x-markdown' === $type ) {
+               $settings['codemirror'] = array_merge( $settings['codemirror'], array(
+                       'mode' => 'markdown',
+                       'highlightFormatting' => true,
+               ) );
+       } elseif ( 'text/nginx' === $type ) {
+               $settings['codemirror'] = array_merge( $settings['codemirror'], array(
+                       'mode' => 'nginx',
+               ) );
+       } elseif ( 'application/x-httpd-php' === $type ) {
+               $settings['codemirror'] = array_merge( $settings['codemirror'], array(
+                       'mode' => 'php',
+                       'autoCloseBrackets' => true,
+                       'autoCloseTags' => true,
+                       'matchBrackets' => true,
+                       'matchTags' => array(
+                               'bothTags' => true,
+                       ),
+               ) );
+       } elseif ( 'text/x-sql' === $type || 'text/x-mysql' === $type ) {
+               $settings['codemirror'] = array_merge( $settings['codemirror'], array(
+                       'mode' => 'sql',
+                       'autoCloseBrackets' => true,
+                       'matchBrackets' => true,
+               ) );
+       } elseif ( false !== strpos( $type, 'xml' ) ) {
+               $settings['codemirror'] = array_merge( $settings['codemirror'], array(
+                       'mode' => 'xml',
+                       'autoCloseBrackets' => true,
+                       'autoCloseTags' => true,
+                       'matchTags' => array(
+                               'bothTags' => true,
+                       ),
+               ) );
+       } elseif ( 'text/x-yaml' === $type ) {
+               $settings['codemirror'] = array_merge( $settings['codemirror'], array(
+                       'mode' => 'yaml',
+               ) );
+       } else {
+               $settings['codemirror']['mode'] = $type;
+       }
+
+       if ( ! empty( $settings['codemirror']['lint'] ) ) {
+               $settings['codemirror']['gutters'][] = 'CodeMirror-lint-markers';
+       }
+
+       // Let settings supplied via args override any defaults.
+       if ( isset( $args['settings'] ) ) {
+               foreach ( $args['settings'] as $key => $value ) {
+                       $settings[ $key ] = array_merge(
+                               $settings[ $key ],
+                               $value
+                       );
+               }
+       }
+
+       /**
+        * Filters settings that are passed into the code editor.
+        *
+        * Returning a falsey value will disable the syntax-highlighting code editor.
+        *
+        * @since 4.9.0
+        *
+        * @param array $settings The array of settings passed to the code editor. A falsey value disables the editor.
+        * @param array $args {
+        *     Args passed when calling `wp_enqueue_code_editor()`.
+        *
+        *     @type string   $type     The MIME type of the file to be edited.
+        *     @type string   $file     Filename being edited.
+        *     @type array    $settings Settings to merge on top of defaults which derive from `$type` or `$file` args.
+        *     @type WP_Theme $theme    Theme being edited when on theme editor.
+        *     @type string   $plugin   Plugin being edited when on plugin editor.
+        * }
+        */
+       $settings = apply_filters( 'wp_code_editor_settings', $settings, $args );
+
+       if ( empty( $settings ) || empty( $settings['codemirror'] ) ) {
+               return false;
+       }
+
+       wp_enqueue_script( 'code-editor' );
+       wp_enqueue_style( 'code-editor' );
+
+       wp_enqueue_script( 'codemirror' );
+       wp_enqueue_style( 'codemirror' );
+
+       if ( isset( $settings['codemirror']['mode'] ) ) {
+               $mode = $settings['codemirror']['mode'];
+               if ( is_string( $mode ) ) {
+                       $mode = array(
+                               'name' => $mode,
+                       );
+               }
+
+               if ( ! empty( $settings['codemirror']['lint'] ) ) {
+                       switch ( $mode['name'] ) {
+                               case 'css':
+                               case 'text/css':
+                               case 'text/x-scss':
+                               case 'text/x-less':
+                                       wp_enqueue_script( 'csslint' );
+                                       break;
+                               case 'htmlmixed':
+                               case 'text/html':
+                               case 'php':
+                               case 'application/x-httpd-php':
+                               case 'text/x-php':
+                                       wp_enqueue_script( 'htmlhint' );
+                                       wp_enqueue_script( 'csslint' );
+                                       wp_enqueue_script( 'jshint' );
+                                       if ( ! current_user_can( 'unfiltered_html' ) ) {
+                                               wp_enqueue_script( 'htmlhint-kses' );
+                                       }
+                                       break;
+                               case 'javascript':
+                               case 'application/ecmascript':
+                               case 'application/json':
+                               case 'application/javascript':
+                               case 'application/ld+json':
+                               case 'text/typescript':
+                               case 'application/typescript':
+                                       wp_enqueue_script( 'jshint' );
+                                       wp_enqueue_script( 'jsonlint' );
+                                       break;
+                       }
+               }
+       }
+
+       wp_add_inline_script( 'code-editor', sprintf( 'jQuery.extend( wp.codeEditor.defaultSettings, %s );', wp_json_encode( $settings ) ) );
+
+       /**
+        * Fires when scripts and styles are enqueued for the code editor.
+        *
+        * @since 4.9.0
+        *
+        * @param array $settings Settings for the enqueued code editor.
+        */
+       do_action( 'wp_enqueue_code_editor', $settings );
+
+       return $settings;
+}
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px">  * Retrieves the contents of the search WordPress query variable.
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * The search query string is passed through esc_attr() to ensure that it is safe
</span></span></pre></div>
<a id="trunksrcwpincludesjscodemirrorcodemirrormincss"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/src/wp-includes/js/codemirror/codemirror.min.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/codemirror/codemirror.min.css                            (rev 0)
+++ trunk/src/wp-includes/js/codemirror/codemirror.min.css      2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,11 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/*! This file is auto-generated from CodeMirror - github:codemirror/CodeMirror#ee20357d279bf9edfed0047d3bf2a75b5f0a040f
+
+CodeMirror, copyright (c) by Marijn Haverbeke and others
+Distributed under an MIT license: http://codemirror.net/LICENSE
+
+This is CodeMirror (http://codemirror.net), a code editor
+implemented in JavaScript on top of the browser's DOM.
+
+You can find some technical background for some of the code below
+at http://marijnhaverbeke.nl/blog/#cm-internals .
+*/.CodeMirror-Tern-tooltip,.CodeMirror-hints{-webkit-box-shadow:2px 3px 5px rgba(0,0,0,.2)}.CodeMirror{font-family:monospace;height:300px;color:#000;direction:ltr}.CodeMirror-lines{padding:4px 0}.CodeMirror pre{padding:0 4px}.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid #000;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0!important;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:b
 link 1.06s steps(1) infinite;background-color:#7e7}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-rulers{position:absolute;left:0;right:0;top:-50px;bottom:-20px;overflow:hidden}.CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-type,.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default 
 .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-invalidchar,.cm-s-default .cm-error{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0f0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#f22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:#fff}.CodeMirror-scroll{overflow:scroll!important;margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;height:100%;outline:0;position:relative}.CodeMirror-sizer{position:relative;border-right:30px solid transparent}.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-sc
 rollbar-filler,.CodeMirror-vscrollbar{position:absolute;z-index:6;display:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-30px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:0 0!important;border:none!important}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-gutter-wrapper ::selection{background-color:transparent}.CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre{-moz-border-radius:0;-webkit-border-radius:0;border-
 radius:0;border-width:0;background:0 0;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.CodeMirror-wrap pre{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;overflow:auto}.CodeMirror-rtl pre{direction:rtl}.CodeMirror-code{outline:0}.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber,.CodeMirror-scroll,.CodeMirror-sizer{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute;pointer-events:none}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:re
 lative;z-index:3}.CodeMirror-focused div.CodeMirror-cursors,div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background-color:#ffa;background-color:rgba(255,255,0,.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:''}span.CodeMirror-selectedtext{background:0 0}.CodeMirror-hints{position:absolute;z-index:10;overflow:hidden;list-style:none;margin:0;padding:2px;-moz-box-shadow:2px 3px 5px rgba(0,0,0,.2);box-shadow:2px 3px 5px rgba(0,0,0,.2);border-radius:3px;border:1px solid silver;backgr
 ound:#fff;font-size:90%;font-family:monospace;max-height:20em;overflow-y:auto}.CodeMirror-hint{margin:0;padding:0 4px;border-radius:2px;white-space:pre;color:#000;cursor:pointer}li.CodeMirror-hint-active{background:#08f;color:#fff}.CodeMirror-lint-markers{width:16px}.CodeMirror-lint-tooltip{background-color:#ffd;border:1px solid #000;border-radius:4px;color:#000;font-family:monospace;font-size:10pt;overflow:hidden;padding:2px 5px;position:fixed;white-space:pre;white-space:pre-wrap;z-index:100;max-width:600px;opacity:0;transition:opacity .4s;-moz-transition:opacity .4s;-webkit-transition:opacity .4s;-o-transition:opacity .4s;-ms-transition:opacity .4s}.CodeMirror-lint-mark-error,.CodeMirror-lint-mark-warning{background-position:left bottom;background-repeat:repeat-x}.CodeMirror-lint-mark-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdE
 NvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==)}.CodeMirror-lint-mark-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=)}.CodeMirror-lint-marker-error,.CodeMirror-lint-marker-warning{background-position:center center;background-repeat:no-repeat;cursor:pointer;display:inline-block;height:16px;width:16px;vertical-align:middle;position:relative}.CodeMirror-lint-message-error,.CodeMirror-lint-message-warning{padding-left:18px;background-position:top left;background-repeat:no-repeat}.CodeMirror-lint-marker-error,.CodeMirror-lint-message-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7
 AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=)}.CodeMirror-lint-marker-warning,.CodeMirror-lint-message-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=)}.CodeMirror-lint-marker-multiple{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC);background-repeat:no-repeat;background-position:right bottom;width:100%;height:100%}.CodeMirror-dialog{position:absolute;le
 ft:0;right:0;background:inherit;z-index:15;padding:.1em .8em;overflow:hidden;color:inherit}.CodeMirror-dialog-top{border-bottom:1px solid #eee;top:0}.CodeMirror-dialog-bottom{border-top:1px solid #eee;bottom:0}.CodeMirror-dialog input{border:none;outline:0;background:0 0;width:20em;color:inherit;font-family:monospace}.CodeMirror-dialog button{font-size:70%}.CodeMirror-fullscreen{position:fixed;top:0;left:0;right:0;bottom:0;height:auto;z-index:9}.CodeMirror-foldmarker{color:#00f;text-shadow:#b9f 1px 1px 2px,#b9f -1px -1px 2px,#b9f 1px -1px 2px,#b9f -1px 1px 2px;font-family:arial;line-height:.3;cursor:pointer}.CodeMirror-foldgutter{width:.7em}.CodeMirror-foldgutter-folded,.CodeMirror-foldgutter-open{cursor:pointer}.CodeMirror-foldgutter-open:after{content:"\25BE"}.CodeMirror-foldgutter-folded:after{content:"\25B8"}.CodeMirror-merge{position:relative;border:1px solid #ddd;white-space:pre}.CodeMirror-merge,.CodeMirror-merge .CodeMirror{height:350px}.CodeMirror-merge-
 2pane .CodeMirror-merge-pane{width:47%}.CodeMirror-merge-2pane .CodeMirror-merge-gap{width:6%}.CodeMirror-merge-3pane .CodeMirror-merge-pane{width:31%}.CodeMirror-merge-3pane .CodeMirror-merge-gap{width:3.5%}.CodeMirror-merge-pane{display:inline-block;white-space:normal;vertical-align:top}.CodeMirror-merge-pane-rightmost{position:absolute;right:0;z-index:1}.CodeMirror-merge-gap{z-index:2;display:inline-block;height:100%;-moz-box-sizing:border-box;box-sizing:border-box;overflow:hidden;border-left:1px solid #ddd;border-right:1px solid #ddd;position:relative;background:#f8f8f8}.CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt,.CodeMirror-overlayscroll .CodeMirror-gutter-filler,.CodeMirror-overlayscroll .CodeMirror-scrollbar-filler{display:none}.CodeMirror-merge-scrolllock-wrap{position:absolute;bottom:0;left:50%}.CodeMirror-merge-scrolllock{position:relative;left:-50%;cursor:pointer;color:#555;line-height:1}.CodeMirror-merge-copy,.CodeMirror-merge-copy-reverse{color:#44c;cursor:p
 ointer;position:absolute}.CodeMirror-merge-copybuttons-left,.CodeMirror-merge-copybuttons-right{position:absolute;left:0;top:0;right:0;bottom:0;line-height:1}.CodeMirror-merge-copy{z-index:3}.CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy{left:2px}.CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy{right:2px}.CodeMirror-merge-l-inserted,.CodeMirror-merge-r-inserted{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12MwuCXy3+CWyH8GBgYGJgYkAABZbAQ9ELXurwAAAABJRU5ErkJggg==);background-position:bottom left;background-repeat:repeat-x}.CodeMirror-merge-l-deleted,.CodeMirror-merge-r-deleted{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12M4Kyb2/6yY2H8GBgYGJgYkAABURgPz6Ks7wQAAAABJRU5ErkJggg==);background-position:bottom left;background-repeat:repeat-x}.CodeMirror-merge-r-chunk{background:#ffffe0}.CodeMirror-merge-r-chunk-start{border-top:1px solid #ee8}.CodeMirror-merge-r-c
 hunk-end{border-bottom:1px solid #ee8}.CodeMirror-merge-r-connect{fill:#ffffe0;stroke:#ee8;stroke-width:1px}.CodeMirror-merge-l-chunk{background:#eef}.CodeMirror-merge-l-chunk-start{border-top:1px solid #88e}.CodeMirror-merge-l-chunk-end{border-bottom:1px solid #88e}.CodeMirror-merge-l-connect{fill:#eef;stroke:#88e;stroke-width:1px}.CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk{background:#dfd}.CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start{border-top:1px solid #4e4}.CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end{border-bottom:1px solid #4e4}.CodeMirror-merge-collapsed-widget:before{content:"(...)"}.CodeMirror-merge-collapsed-widget{cursor:pointer;color:#88b;background:#eef;border:1px solid #ddf;font-size:90%;padding:0 3px;border-radius:4px}.CodeMirror-simplescroll-horizontal div,.CodeMirror-simplescroll-vertical div{position:absolute;background:#ccc;-moz-box-sizing:border-box;box-sizing:border-box;border:1px solid #bbb;border-radius:2px}.Code
 Mirror-simplescroll-horizontal,.CodeMirror-simplescroll-vertical{position:absolute;z-index:6;background:#eee}.CodeMirror-simplescroll-horizontal{bottom:0;left:0;height:8px}.CodeMirror-simplescroll-horizontal div{bottom:0;height:100%}.CodeMirror-simplescroll-vertical{right:0;top:0;width:8px}.CodeMirror-simplescroll-vertical div{right:0;width:100%}.CodeMirror-overlayscroll-horizontal div,.CodeMirror-overlayscroll-vertical div{position:absolute;background:#bcd;border-radius:3px}.CodeMirror-overlayscroll-horizontal,.CodeMirror-overlayscroll-vertical{position:absolute;z-index:6}.CodeMirror-overlayscroll-horizontal{bottom:0;left:0;height:6px}.CodeMirror-overlayscroll-horizontal div{bottom:0;height:100%}.CodeMirror-overlayscroll-vertical{right:0;top:0;width:6px}.CodeMirror-overlayscroll-vertical div{right:0;width:100%}.CodeMirror-search-match{background:gold;border-top:1px solid orange;border-bottom:1px solid orange;-moz-box-sizing:border-box;box-sizing:border-box;opacity:.5}.CodeMirror-Te
 rn-completion{padding-left:22px;position:relative;line-height:1.5}.CodeMirror-Tern-completion:before{position:absolute;left:2px;bottom:2px;border-radius:50%;font-size:12px;font-weight:700;height:15px;width:15px;line-height:16px;text-align:center;color:#fff;-moz-box-sizing:border-box;box-sizing:border-box}.CodeMirror-Tern-completion-unknown:before{content:"?";background:#4bb}.CodeMirror-Tern-completion-object:before{content:"O";background:#77c}.CodeMirror-Tern-completion-fn:before{content:"F";background:#7c7}.CodeMirror-Tern-completion-array:before{content:"A";background:#c66}.CodeMirror-Tern-completion-number:before{content:"1";background:#999}.CodeMirror-Tern-completion-string:before{content:"S";background:#999}.CodeMirror-Tern-completion-bool:before{content:"B";background:#999}.CodeMirror-Tern-completion-guess{color:#999}.CodeMirror-Tern-tooltip{border:1px solid silver;border-radius:3px;color:#444;padding:2px 5p
 x;font-size:90%;font-family:monospace;background-color:#fff;white-space:pre-wrap;max-width:40em;position:absolute;z-index:10;-moz-box-shadow:2px 3px 5px rgba(0,0,0,.2);box-shadow:2px 3px 5px rgba(0,0,0,.2);transition:opacity 1s;-moz-transition:opacity 1s;-webkit-transition:opacity 1s;-o-transition:opacity 1s;-ms-transition:opacity 1s}.CodeMirror-Tern-hint-doc{max-width:25em;margin-top:-3px}.CodeMirror-Tern-fname{color:#000}.CodeMirror-Tern-farg{color:#70a}.CodeMirror-Tern-farg-current{text-decoration:underline}.CodeMirror-Tern-type{color:#07c}.CodeMirror-Tern-fhint-guess{opacity:.7}
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjscodemirrorcodemirrorminjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/src/wp-includes/js/codemirror/codemirror.min.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/codemirror/codemirror.min.js                             (rev 0)
+++ trunk/src/wp-includes/js/codemirror/codemirror.min.js       2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,29 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/*! This file is auto-generated from CodeMirror - github:codemirror/CodeMirror#ee20357d279bf9edfed0047d3bf2a75b5f0a040f
+
+CodeMirror, copyright (c) by Marijn Haverbeke and others
+Distributed under an MIT license: http://codemirror.net/LICENSE
+
+This is CodeMirror (http://codemirror.net), a code editor
+implemented in JavaScript on top of the browser's DOM.
+
+You can find some technical background for some of the code below
+at http://marijnhaverbeke.nl/blog/#cm-internals .
+*/
+!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(a){var b=a.search(f);return b==-1?0:b}function c(a,b,c){return/\bstring\b/.test(a.getTokenTypeAt(g(b.line,0)))&&!/^[\'\"\`]/.test(c)}function d(a,b){var c=a.getMode();r
 eturn c.useInnerComments!==!1&&c.innerMode?a.getModeAt(b):c}var e={},f=/[^\s\u00a0]/,g=a.Pos;a.commands.toggleComment=function(a){a.toggleComment()},a.defineExtension("toggleComment",function(a){a||(a=e);for(var b=this,c=1/0,d=this.listSelections(),f=null,h=d.length-1;h>=0;h--){var i=d[h].from(),j=d[h].to();i.line>=c||(j.line>=c&&(j=g(c,0)),c=i.line,null==f?b.uncomment(i,j,a)?f="un":(b.lineComment(i,j,a),f="line"):"un"==f?b.uncomment(i,j,a):b.lineComment(i,j,a))}}),a.defineExtension("lineComment",function(a,h,i){i||(i=e);var j=this,k=d(j,a),l=j.getLine(a.line);if(null!=l&&!c(j,a,l)){var m=i.lineComment||k.lineComment;if(!m)return void((i.blockCommentStart||k.blockCommentStart)&&(i.fullLines=!0,j.blockComment(a,h,i)));var n=Math.min(0!=h.ch||h.line==a.line?h.line+1:h.line,j.lastLine()+1),o=null==i.padding?" ":i.padding,p=i.commentBlankLines||a.line==h.line;j.operation(function(){if(i.
 indent){for(var c=null,d=a.line;d<n;++d){var e=j.getLine(d),h=e.slice(0,b(e));(null==c||c.length>h.length)&&(c=h)}for(var d=a.line;d<n;++d){var e=j.getLine(d),k=c.length;(p||f.test(e))&&(e.slice(0,k)!=c&&(k=b(e)),j.replaceRange(c+m+o,g(d,0),g(d,k)))}}else for(var d=a.line;d<n;++d)(p||f.test(j.getLine(d)))&&j.replaceRange(m+o,g(d,0))})}}),a.defineExtension("blockComment",function(a,b,c){c||(c=e);var h=this,i=d(h,a),j=c.blockCommentStart||i.blockCommentStart,k=c.blockCommentEnd||i.blockCommentEnd;if(!j||!k)return void((c.lineComment||i.lineComment)&&0!=c.fullLines&&h.lineComment(a,b,c));if(!/\bcomment\b/.test(h.getTokenTypeAt(g(a.line,0)))){var l=Math.min(b.line,h.lastLine());l!=a.line&&0==b.ch&&f.test(h.getLine(l))&&--l;var m=null==c.padding?" ":c.padding;a.line>l||h.operation(function(){if(0!=c.fullLines){var d=f.test(h.getLine(l));h.replaceRange(m+k,g(l)),h.replaceRange(j+m,g(
 a.line,0));var e=c.blockCommentLead||i.blockCommentLead;if(null!=e)for(var n=a.line+1;n<=l;++n)(n!=l||d)&&h.replaceRange(e+m,g(n,0))}else h.replaceRange(k,b),h.replaceRange(j,a)})}}),a.defineExtension("uncomment",function(a,b,c){c||(c=e);var h,i=this,j=d(i,a),k=Math.min(0!=b.ch||b.line==a.line?b.line:b.line-1,i.lastLine()),l=Math.min(a.line,k),m=c.lineComment||j.lineComment,n=[],o=null==c.padding?" ":c.padding;a:if(m){for(var p=l;p<=k;++p){var q=i.getLine(p),r=q.indexOf(m);if(r>-1&&!/comment/.test(i.getTokenTypeAt(g(p,r+1)))&&(r=-1),r==-1&&f.test(q))break a;if(r>-1&&f.test(q.slice(0,r)))break a;n.push(q)}if(i.operation(function(){for(var a=l;a<=k;++a){var b=n[a-l],c=b.indexOf(m),d=c+m.length;c<0||(b.slice(d,d+o.length)==o&&(d+=o.length),h=!0,i.replaceRange("",g(a,c),g(a,d)))}}),h)return!0}var s=c.blockCommentStart||j.blockCommentStart,t=c.blockCommentEnd||j.blockCommentEnd;if(!s||!t)retur
 n!1;var u=c.blockCommentLead||j.blockCommentLead,v=i.getLine(l),w=v.indexOf(s);if(w==-1)return!1;var x=k==l?v:i.getLine(k),y=x.indexOf(t,k==l?w+s.length:0);y==-1&&l!=k&&(x=i.getLine(--k),y=x.indexOf(t));var z=g(l,w+1),A=g(k,y+1);if(y==-1||!/comment/.test(i.getTokenTypeAt(z))||!/comment/.test(i.getTokenTypeAt(A))||i.getRange(z,A,"\n").indexOf(t)>-1)return!1;var B=v.lastIndexOf(s,a.ch),C=B==-1?-1:v.slice(0,a.ch).indexOf(t,B+s.length);if(B!=-1&&C!=-1&&C+t.length!=a.ch)return!1;C=x.indexOf(t,b.ch);var D=x.slice(b.ch).lastIndexOf(s,C-b.ch);return B=C==-1||D==-1?-1:b.ch+D,(C==-1||B==-1||B==b.ch)&&(i.operation(function(){i.replaceRange("",g(k,y-(o&&x.slice(y-o.length,y)==o?o.length:0)),g(k,y+t.length));var a=w+s.length;if(o&&v.slice(a,a+o.length)==o&&(a+=o.length),i.replaceRange("",g(l,w),g(l,a)),u)for(var b=l+1;b<=k;++b){var c=i.getLine(b),d=c.indexOf(u);if(d!=-1&&!f.test(c.slice(0,
 d))){var e=d+u.length;o&&c.slice(e,e+o.length)==o&&(e+=o.length),i.replaceRange("",g(b,d),g(b,e))}}}),!0)})})},{"../../lib/codemirror":59}],2:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){function b(b){if(b.getOption("disableInput"))return a.Pass;for(var d,e=b.listSelections(),f=[],g=0;g<e.length;g++){var h=e[g].head;if(!/\bcomment\b/.test(b.getTokenTypeAt(h)))return a.Pass;var i=b.getModeAt(h);if(d){if(d!=i)return a.Pass}else d=i;var j=null;if(d.blockCommentStart&&d.blockCommentContinue){var k,l=b.getLine(h.line).slice(0,h.ch),m=l.indexOf(d.blockCommentEnd);if(m!=-1&&m==h.ch-d.blockCommentEnd.length);else if((k=l.indexOf(d.blockCommentStart))>-1){if(j=l.slice(0,k),/\S/.test(j)){j="";for(var 
 n=0;n<k;++n)j+=" "}}else(k=l.indexOf(d.blockCommentContinue))>-1&&!/\S/.test(l.slice(0,k))&&(j=l.slice(0,k));null!=j&&(j+=d.blockCommentContinue)}if(null==j&&d.lineComment&&c(b)){var l=b.getLine(h.line),k=l.indexOf(d.lineComment);k>-1&&(j=l.slice(0,k),/\S/.test(j)?j=null:j+=d.lineComment+l.slice(k+d.lineComment.length).match(/^\s*/)[0])}if(null==j)return a.Pass;f[g]="\n"+j}b.operation(function(){for(var a=e.length-1;a>=0;a--)b.replaceRange(f[a],e[a].from(),e[a].to(),"+insert")})}function c(a){var b=a.getOption("continueComments");return!b||"object"!=typeof b||b.continueLineComment!==!1}for(var d=["clike","css","javascript"],e=0;e<d.length;++e)a.extendMode(d[e],{blockCommentContinue:" * "});a.defineOption("continueComments",null,function(c,d,e){if(e&&e!=a.Init&&c.removeKeyMap("continueComment"),d){
 var f="Enter";"string"==typeof d?f=d:"object"==typeof d&&d.key&&(f=d.key);var g={name:"continueComment"};g[f]=b,c.addKeyMap(g)}})})},{"../../lib/codemirror":59}],3:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){function b(a,b,c){var d,e=a.getWrapperElement();return d=e.appendChild(document.createElement("div")),c?d.className="CodeMirror-dialog CodeMirror-dialog-bottom":d.className="CodeMirror-dialog CodeMirror-dialog-top","string"==typeof b?d.innerHTML=b:d.appendChild(b),d}function c(a,b){a.state.currentNotificationClose&&a.state.currentNotificationClose(),a.state.currentNotificationClose=b}a.defineExtension("openDialog",function(d,e,f){function g(
 a){if("string"==typeof a)l.value=a;else{if(j)return;j=!0,i.parentNode.removeChild(i),k.focus(),f.onClose&&f.onClose(i)}}f||(f={}),c(this,null);var h,i=b(this,d,f.bottom),j=!1,k=this,l=i.getElementsByTagName("input")[0];return l?(l.focus(),f.value&&(l.value=f.value,f.selectValueOnOpen!==!1&&l.select()),f.onInput&&a.on(l,"input",function(a){f.onInput(a,l.value,g)}),f.onKeyUp&&a.on(l,"keyup",function(a){f.onKeyUp(a,l.value,g)}),a.on(l,"keydown",function(b){f&&f.onKeyDown&&f.onKeyDown(b,l.value,g)||((27==b.keyCode||f.closeOnEnter!==!1&&13==b.keyCode)&&(l.blur(),a.e_stop(b),g()),13==b.keyCode&&e(l.value,b))}),f.closeOnBlur!==!1&&a.on(l,"blur",g)):(h=i.getElementsByTagName("button")[0])&&(a.on(h,"click",function(){g(),k.focus()}),f.closeOnBlur!==!1&&a.on(h,"blur",g),h.focus()),g}),a.defineExtension
 ("openConfirm",function(d,e,f){function g(){j||(j=!0,h.parentNode.removeChild(h),k.focus())}c(this,null);var h=b(this,d,f&&f.bottom),i=h.getElementsByTagName("button"),j=!1,k=this,l=1;i[0].focus();for(var m=0;m<i.length;++m){var n=i[m];!function(b){a.on(n,"click",function(c){a.e_preventDefault(c),g(),b&&b(k)})}(e[m]),a.on(n,"blur",function(){--l,setTimeout(function(){l<=0&&g()},200)}),a.on(n,"focus",function(){++l})}}),a.defineExtension("openNotification",function(d,e){function f(){i||(i=!0,clearTimeout(g),h.parentNode.removeChild(h))}c(this,f);var g,h=b(this,d,e&&e.bottom),i=!1,j=e&&"undefined"!=typeof e.duration?e.duration:5e3;return a.on(h,"click",function(b){a.e_preventDefault(b),f()}),j&&(g=setTimeout(f,j)),f})})},{"../../lib/codemirror":59}],4:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeo
 f b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(b,d){function e(){b.display.wrapper.offsetHeight?(c(b,d),b.display.lastWrapHeight!=b.display.wrapper.clientHeight&&b.refresh()):d.timeout=setTimeout(e,d.delay)}d.timeout=setTimeout(e,d.delay),d.hurry=function(){clearTimeout(d.timeout),d.timeout=setTimeout(e,50)},a.on(window,"mouseup",d.hurry),a.on(window,"keyup",d.hurry)}function c(b,c){clearTimeout(c.timeout),a.off(window,"mouseup",c.hurry),a.off(window,"keyup",c.hurry)}a.defineOption("autoRefresh",!1,function(a,d){a.state.autoRefresh&&(c(a,a.state.autoRefresh),a.state.autoRefresh=null),d&&0==a.display.wrapper.offsetHeight&&b(a,a.state.autoRefresh={delay:d.delay||250})})})},{"../../lib/codemirror":59}],5:[function(a,b,c){!function(d){"
 object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(a){var b=a.getWrapperElement();a.state.fullScreenRestore={scrollTop:window.pageYOffset,scrollLeft:window.pageXOffset,width:b.style.width,height:b.style.height},b.style.width="",b.style.height="auto",b.className+=" CodeMirror-fullscreen",document.documentElement.style.overflow="hidden",a.refresh()}function c(a){var b=a.getWrapperElement();b.className=b.className.replace(/\s*CodeMirror-fullscreen\b/,""),document.documentElement.style.overflow="";var c=a.state.fullScreenRestore;b.style.width=c.width,b.style.height=c.height,window.scrollTo(c.scrollLeft,c.scrollTop),a.refresh()}a.defineOption("fullScreen",!1,function(d,e,f){f==a.Init&&(f=!1),!f!=!e&&
 amp;(e?b(d):c(d))})})},{"../../lib/codemirror":59}],6:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){function b(a,b,c,d){this.cm=a,this.node=b,this.options=c,this.height=d,this.cleared=!1}function c(a){var b=a.getWrapperElement(),c=window.getComputedStyle?window.getComputedStyle(b):b.currentStyle,d=parseInt(c.height),e=a.state.panels={setHeight:b.style.height,heightLeft:d,panels:0,wrapper:document.createElement("div")};b.parentNode.insertBefore(e.wrapper,b);var f=a.hasFocus();e.wrapper.appendChild(b),f&&a.focus(),a._setSize=a.setSize,null!=d&&(a.setSize=function(b,c){if(null==c)return this._setSize(b,c);if(e.setHeight=c,"number"!=typeof c){var f=/^(\d+\.?\d*)px$/.exec(c);f?c=Number(f[1]):(e.wrapper.style.height=c,c=e.wrapper
 .offsetHeight,e.wrapper.style.height="")}a._setSize(b,e.heightLeft+=c-d),d=c})}function d(a){var b=a.state.panels;a.state.panels=null;var c=a.getWrapperElement();b.wrapper.parentNode.replaceChild(c,b.wrapper),c.style.height=b.setHeight,a.setSize=a._setSize,a.setSize()}function e(a,b){for(var c=b.nextSibling;c;c=c.nextSibling)if(c==a.getWrapperElement())return!0;return!1}a.defineExtension("addPanel",function(a,d){d=d||{},this.state.panels||c(this);var f=this.state.panels,g=f.wrapper,h=this.getWrapperElement();d.after instanceof b&&!d.after.cleared?g.insertBefore(a,d.before.node.nextSibling):d.before instanceof b&&!d.before.cleared?g.insertBefore(a,d.before.node):d.replace instanceof b&&!d.replace.cleared?(g.insertBefore(a,d.replace.node),d.replace.clear()):"bottom"==d.position?g.appendChild(a):"before-bottom"==d.position?g.insertBefore(a,h.nextSibling):"after-top"==d.position?g.insertBefore(a,h):g.insertBefore(
 a,g.firstChild);var i=d&&d.height||a.offsetHeight;return this._setSize(null,f.heightLeft-=i),f.panels++,d.stable&&e(this,a)&&this.scrollTo(null,this.getScrollInfo().top+i),new b(this,a,d,i)}),b.prototype.clear=function(){if(!this.cleared){this.cleared=!0;var a=this.cm.state.panels;this.cm._setSize(null,a.heightLeft+=this.height),this.options.stable&&e(this.cm,this.node)&&this.cm.scrollTo(null,this.cm.getScrollInfo().top-this.height),a.wrapper.removeChild(this.node),0==--a.panels&&d(this.cm)}},b.prototype.changed=function(a){var b=null==a?this.node.offsetHeight:a,c=this.cm.state.panels;this.cm._setSize(null,c.heightLeft-=b-this.height),this.height=b}})},{"../../lib/codemirror":59}],7:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirr
 or)}(function(a){function b(a){a.state.placeholder&&(a.state.placeholder.parentNode.removeChild(a.state.placeholder),a.state.placeholder=null)}function c(a){b(a);var c=a.state.placeholder=document.createElement("pre");c.style.cssText="height: 0; overflow: visible",c.className="CodeMirror-placeholder";var d=a.getOption("placeholder");"string"==typeof d&&(d=document.createTextNode(d)),c.appendChild(d),a.display.lineSpace.insertBefore(c,a.display.lineSpace.firstChild)}function d(a){f(a)&&c(a)}function e(a){var d=a.getWrapperElement(),e=f(a);d.className=d.className.replace(" CodeMirror-empty","")+(e?" CodeMirror-empty":""),e?c(a):b(a)}function f(a){return 1===a.lineCount()&&""===a.getLine(0)}a.defineOption("placeholder","",function(c,f,g){var h=g&&g!=a.Init;if(f&&!h)c.on("blur",d),c.on("change",e),c.on
 ("swapDoc",e),e(c);else if(!f&&h){c.off("blur",d),c.off("change",e),c.off("swapDoc",e),b(c);var i=c.getWrapperElement();i.className=i.className.replace(" CodeMirror-empty","")}f&&!c.hasFocus()&&d(c)})})},{"../../lib/codemirror":59}],8:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(b){b.state.rulerDiv.textContent="";var c=b.getOption("rulers"),d=b.defaultCharWidth(),e=b.charCoords(a.Pos(b.firstLine(),0),"div").left;b.state.rulerDiv.style.minHeight=b.display.scroller.offsetHeight+30+"px";for(var f=0;f<c.length;f++){var g=document.createElement("div");g.className="CodeMirror-ruler";var
  h,i=c[f];"number"==typeof i?h=i:(h=i.column,i.className&&(g.className+=" "+i.className),i.color&&(g.style.borderColor=i.color),i.lineStyle&&(g.style.borderLeftStyle=i.lineStyle),i.width&&(g.style.borderLeftWidth=i.width)),g.style.left=e+h*d+"px",b.state.rulerDiv.appendChild(g)}}a.defineOption("rulers",!1,function(a,c){a.state.rulerDiv&&(a.state.rulerDiv.parentElement.removeChild(a.state.rulerDiv),a.state.rulerDiv=null,a.off("refresh",b)),c&&c.length&&(a.state.rulerDiv=a.display.lineSpace.parentElement.insertBefore(document.createElement("div"),a.display.lineSpace),a.state.rulerDiv.className="CodeMirror-rulers",b(a),a.on("refresh",b))})})},{"../../lib/codemirror":59}],9:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&
 amp;&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){function b(a,b){return"pairs"==b&&"string"==typeof a?a:"object"==typeof a&&null!=a[b]?a[b]:n[b]}function c(a){for(var b=0;b<a.length;b++){var c=a.charAt(b),e="'"+c+"'";p[e]||(p[e]=d(c))}}function d(a){return function(b){return i(b,a)}}function e(a){var b=a.state.closeBrackets;if(!b||b.override)return b;var c=a.getModeAt(a.getCursor());return c.closeBrackets||b}function f(c){var d=e(c);if(!d||c.getOption("disableInput"))return a.Pass;for(var f=b(d,"pairs"),g=c.listSelections(),h=0;h<g.length;h++){if(!g[h].empty())return a.Pass;var i=k(c,g[h].head);if(!i||f.indexOf(i)%2!=0)return a.Pass}for(var h=g.length-1;h>=0;h--){var j=g[h].head;c.replaceRange("",o(j.line,j.ch-1),o(j.line,j.ch+1),"+delete")}}function g(c){var d=e(c),f=d&&b(d,"explode");if(!f||c.getOption(&quot
 ;disableInput"))return a.Pass;for(var g=c.listSelections(),h=0;h<g.length;h++){if(!g[h].empty())return a.Pass;var i=k(c,g[h].head);if(!i||f.indexOf(i)%2!=0)return a.Pass}c.operation(function(){c.replaceSelection("\n\n",null),c.execCommand("goCharLeft"),g=c.listSelections();for(var a=0;a<g.length;a++){var b=g[a].head.line;c.indentLine(b,null,!0),c.indentLine(b+1,null,!0)}})}function h(b){var c=a.cmpPos(b.anchor,b.head)>0;return{anchor:new o(b.anchor.line,b.anchor.ch+(c?-1:1)),head:new o(b.head.line,b.head.ch+(c?1:-1))}}function i(c,d){var f=e(c);if(!f||c.getOption("disableInput"))return a.Pass;var g=b(f,"pairs"),i=g.indexOf(d);if(i==-1)return a.Pass;for(var k,n=b(f,"triples"),p=g.charAt(i+1)==d,q=c.listSelections(),r=i%2==0,s=0;s<q.length;s++){var t,u=q[s],v=u.head,w=c.getRange(v,o(v.line,v.ch+1));if(r&&!u.empty())t="surround";else if(!p&&r||w!=d)if(p&&v.ch>1&&n.indexOf(d)&
 gt;=0&&c.getRange(o(v.line,v.ch-2),v)==d+d&&(v.ch<=2||c.getRange(o(v.line,v.ch-3),o(v.line,v.ch-2))!=d))t="addFour";else if(p){if(a.isWordChar(w)||!l(c,v,d))return a.Pass;t="both"}else{if(!r||c.getLine(v.line).length!=v.ch&&!j(w,g)&&!/\s/.test(w))return a.Pass;t="both"}else t=p&&m(c,v)?"both":n.indexOf(d)>=0&&c.getRange(v,o(v.line,v.ch+3))==d+d+d?"skipThree":"skip";if(k){if(k!=t)return a.Pass}else k=t}var x=i%2?g.charAt(i-1):d,y=i%2?d:g.charAt(i+1);c.operation(function(){if("skip"==k)c.execCommand("goCharRight");else if("skipThree"==k)for(var a=0;a<3;a++)c.execCommand("goCharRight");else if("surround"==k){for(var b=c.getSelections(),a=0;a<b.length;a++)b[a]=x+b[a]+y;c.replaceSelections(b,"around"),b=c.listSelections().slice();for(var a=0;a<b.length;a++)b[a]=h(b[a]);c.setSelections(b)}else"both"
 ==k?(c.replaceSelection(x+y,null),c.triggerElectric(x+y),c.execCommand("goCharLeft")):"addFour"==k&&(c.replaceSelection(x+x+x+x,"before"),c.execCommand("goCharRight"))})}function j(a,b){var c=b.lastIndexOf(a);return c>-1&&c%2==1}function k(a,b){var c=a.getRange(o(b.line,b.ch-1),o(b.line,b.ch+1));return 2==c.length?c:null}function l(b,c,d){var e=b.getLine(c.line),f=b.getTokenAt(c);if(/\bstring2?\b/.test(f.type)||m(b,c))return!1;var g=new a.StringStream(e.slice(0,c.ch)+d+e.slice(c.ch),4);for(g.pos=g.start=f.start;;){var h=b.getMode().token(g,f.state);if(g.pos>=c.ch+1)return/\bstring2?\b/.test(h);g.start=g.pos}}function m(a,b){var c=a.getTokenAt(o(b.line,b.ch+1));return/\bstring/.test(c.type)&&c.start==b.ch}var n={pairs:"()[]{}''\"\"",triples:"",explode:"[]{}"},o=a.Pos;a.defineOption("autoCloseBrackets",!1,function(d,e,f){f&&f!=a.Init&&(d.removeKeyMap(
 p),d.state.closeBrackets=null),e&&(c(b(e,"pairs")),d.state.closeBrackets=e,d.addKeyMap(p))});var p={Backspace:f,Enter:g};c(n.pairs+"`")})},{"../../lib/codemirror":59}],10:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror"),a("../fold/xml-fold")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../fold/xml-fold"],d):d(CodeMirror)}(function(a){function b(b){if(b.getOption("disableInput"))return a.Pass;for(var c=b.listSelections(),d=[],i=0;i<c.length;i++){if(!c[i].empty())return a.Pass;var j=c[i].head,k=b.getTokenAt(j),l=a.innerMode(b.getMode(),k.state),m=l.state;if("xml"!=l.mode.name||!m.tagName)return a.Pass;var n=b.getOption("autoCloseTags"),o="html"==l.mode.configuration,p="object"==typeof n&&n.dontCloseTags||o&&g,q="objec
 t"==typeof n&&n.indentTags||o&&h,r=m.tagName;k.end>j.ch&&(r=r.slice(0,r.length-k.end+j.ch));var s=r.toLowerCase();if(!r||"string"==k.type&&(k.end!=j.ch||!/[\"\']/.test(k.string.charAt(k.string.length-1))||1==k.string.length)||"tag"==k.type&&"closeTag"==m.type||k.string.indexOf("/")==k.string.length-1||p&&e(p,s)>-1||f(b,r,j,m,!0))return a.Pass;var t=q&&e(q,s)>-1;d[i]={indent:t,text:">"+(t?"\n\n":"")+"</"+r+">",newPos:t?a.Pos(j.line+1,0):a.Pos(j.line,j.ch+1)}}for(var i=c.length-1;i>=0;i--){var u=d[i];b.replaceRange(u.text,c[i].head,c[i].anchor,"+insert");var v=b.listSelections().slice(0);v[i]={head:u.newPos,anchor:u.newPos},b.setSelections(v),u.indent&&(b.indentLine(u.newPos.line,null,!0),b.indentLine(u.newPos.line+1,null,!0))}}function c(b,c){for(var d=b.listSelections(),e=[],g=c?"/&quot
 ;:"</",h=0;h<d.length;h++){if(!d[h].empty())return a.Pass;var i=d[h].head,j=b.getTokenAt(i),k=a.innerMode(b.getMode(),j.state),l=k.state;if(c&&("string"==j.type||"<"!=j.string.charAt(0)||j.start!=i.ch-1))return a.Pass;var m;if("xml"!=k.mode.name)if("htmlmixed"==b.getMode().name&&"javascript"==k.mode.name)m=g+"script";else{if("htmlmixed"!=b.getMode().name||"css"!=k.mode.name)return a.Pass;m=g+"style"}else{if(!l.context||!l.context.tagName||f(b,l.context.tagName,i,l))return a.Pass;m=g+l.context.tagName}">"!=b.getLine(i.line).charAt(j.end)&&(m+=">"),e[h]=m}b.replaceSelections(e),d=b.listSelections();for(var h=0;h<d.length;h++)(h==d.length-1||d[h].head.line<d[h+1].head.line)&&b.indentLine(d[h].head.line)}function d(b){return b.getOption("disableInput")?a.Pass:c(b,!0)}function e(a,b){if(a.indexOf)return a.in
 dexOf(b);for(var c=0,d=a.length;c<d;++c)if(a[c]==b)return c;return-1}function f(b,c,d,e,f){if(!a.scanForClosingTag)return!1;var g=Math.min(b.lastLine()+1,d.line+500),h=a.scanForClosingTag(b,d,null,g);if(!h||h.tag!=c)return!1;for(var i=e.context,j=f?1:0;i&&i.tagName==c;i=i.prev)++j;d=h.to;for(var k=1;k<j;k++){var l=a.scanForClosingTag(b,d,null,g);if(!l||l.tag!=c)return!1;d=l.to}return!0}a.defineOption("autoCloseTags",!1,function(c,e,f){if(f!=a.Init&&f&&c.removeKeyMap("autoCloseTags"),e){var g={name:"autoCloseTags"};("object"!=typeof e||e.whenClosing)&&(g["'/'"]=function(a){return d(a)}),("object"!=typeof e||e.whenOpening)&&(g["'>'"]=function(a){return b(a)}),c.addKeyMap(g)}});var g=["area","base","br","col","command","embed","hr","img","input","keygen","link"
 ,"meta","param","source","track","wbr"],h=["applet","blockquote","body","button","div","dl","fieldset","form","frameset","h1","h2","h3","h4","h5","h6","head","html","iframe","layer","legend","object","ol","p","select","table","ul"];a.commands.closeTag=function(a){return c(a)}})},{"../../lib/codemirror":59,"../fold/xml-fold":21}],11:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";var b=/^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*
 +-]\s|(\d+)([.)]))(\s*)/,c=/^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/,d=/[*+-]\s/;a.commands.newlineAndIndentContinueMarkdownList=function(e){if(e.getOption("disableInput"))return a.Pass;for(var f=e.listSelections(),g=[],h=0;h<f.length;h++){var i=f[h].head,j=e.getStateAfter(i.line),k=j.list!==!1,l=0!==j.quote,m=e.getLine(i.line),n=b.exec(m);if(!f[h].empty()||!k&&!l||!n)return void e.execCommand("newlineAndIndent");if(c.test(m))/>\s*$/.test(m)||e.replaceRange("",{line:i.line,ch:0},{line:i.line,ch:i.ch+1}),g[h]="\n";else{var o=n[1],p=n[5],q=d.test(n[2])||n[2].indexOf(">")>=0?n[2].replace("x"," "):parseInt(n[3],10)+1+n[4];g[h]="\n"+o+q+p}}e.replaceSelections(g)}})},{"../../lib/codemirror":59}],12:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof de
 fine&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){function b(a,b,d){var e=a.getLineHandle(b.line),f=b.ch-1,i=d&&d.afterCursor;null==i&&(i=/(^| )cm-fat-cursor($| )/.test(a.getWrapperElement().className));var j=!i&&f>=0&&h[e.text.charAt(f)]||h[e.text.charAt(++f)];if(!j)return null;var k=">"==j.charAt(1)?1:-1;if(d&&d.strict&&k>0!=(f==b.ch))return null;var l=a.getTokenTypeAt(g(b.line,f+1)),m=c(a,g(b.line,f+(k>0?1:0)),k,l||null,d);return null==m?null:{from:g(b.line,f),to:m&&m.pos,match:m&&m.ch==j.charAt(0),forward:k>0}}function c(a,b,c,d,e){for(var f=e&&e.maxScanLineLength||1e4,i=e&&e.maxScanLines||1e3,j=[],k=e&&e.bracketRegex?e.bracketRegex:/[(){}[\]]/,l=c>0?Math.min(b.line+i,a.lastLine()+1):Math.max(a.firstLine()-1,b.line-i),m=b.line;m!=l;m+=c){var n=a.getLine(m);if(n){var o=c>0?0:n.length-1,p=c>0?n.length:-1;if(!(n.len
 gth>f))for(m==b.line&&(o=b.ch-(c<0?1:0));o!=p;o+=c){var q=n.charAt(o);if(k.test(q)&&(void 0===d||a.getTokenTypeAt(g(m,o+1))==d)){var r=h[q];if(">"==r.charAt(1)==c>0)j.push(q);else{if(!j.length)return{pos:g(m,o),ch:q};j.pop()}}}}}return m-c!=(c>0?a.lastLine():a.firstLine())&&null}function d(a,c,d){for(var e=a.state.matchBrackets.maxHighlightLineLength||1e3,h=[],i=a.listSelections(),j=0;j<i.length;j++){var k=i[j].empty()&&b(a,i[j].head,d);if(k&&a.getLine(k.from.line).length<=e){var l=k.match?"CodeMirror-matchingbracket":"CodeMirror-nonmatchingbracket";h.push(a.markText(k.from,g(k.from.line,k.from.ch+1),{className:l})),k.to&&a.getLine(k.to.line).length<=e&&h.push(a.markText(k.to,g(k.to.line,k.to.ch+1),{className:l}))}}if(h.length){f&&a.state.focused&&a.focus();var m=function(){a.operation(function(){for(var a=0;a<h.length;a++)h[a].clear()})};if(!c)return m;se
 tTimeout(m,800)}}function e(a){a.operation(function(){i&&(i(),i=null),i=d(a,!1,a.state.matchBrackets)})}var f=/MSIE \d/.test(navigator.userAgent)&&(null==document.documentMode||document.documentMode<8),g=a.Pos,h={"(":")>",")":"(<","[":"]>","]":"[<","{":"}>","}":"{<"},i=null;a.defineOption("matchBrackets",!1,function(b,c,d){d&&d!=a.Init&&(b.off("cursorActivity",e),i&&(i(),i=null)),c&&(b.state.matchBrackets="object"==typeof c?c:{},b.on("cursorActivity",e))}),a.defineExtension("matchBrackets",function(){d(this,!0)}),a.defineExtension("findMatchingBracket",function(a,c,d){return(d||"boolean"==typeof c)&&(d?(d.strict=c,c=d):c=c?{strict:!0}:null),b(this,a,c)}),a.defineExtension("scanForBracket",function(a,b,d,e){retu
 rn c(this,a,b,d,e)})})},{"../../lib/codemirror":59}],13:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror"),a("../fold/xml-fold")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../fold/xml-fold"],d):d(CodeMirror)}(function(a){"use strict";function b(a){a.state.tagHit&&a.state.tagHit.clear(),a.state.tagOther&&a.state.tagOther.clear(),a.state.tagHit=a.state.tagOther=null}function c(c){c.state.failedTagMatch=!1,c.operation(function(){if(b(c),!c.somethingSelected()){var d=c.getCursor(),e=c.getViewport();e.from=Math.min(e.from,d.line),e.to=Math.max(d.line+1,e.to);var f=a.findMatchingTag(c,d,e);if(f){if(c.state.matchBothTags){var g="open"==f.at?f.open:f.close;g&&(c.state.tagHit=c.markText(g.from,g.to,{className:"CodeMirror-matchingtag"}))}var h="close"==f.at?f.ope
 n:f.close;h?c.state.tagOther=c.markText(h.from,h.to,{className:"CodeMirror-matchingtag"}):c.state.failedTagMatch=!0}}})}function d(a){a.state.failedTagMatch&&c(a)}a.defineOption("matchTags",!1,function(e,f,g){g&&g!=a.Init&&(e.off("cursorActivity",c),e.off("viewportChange",d),b(e)),f&&(e.state.matchBothTags="object"==typeof f&&f.bothTags,e.on("cursorActivity",c),e.on("viewportChange",d),c(e))}),a.commands.toMatchingTag=function(b){var c=a.findMatchingTag(b,b.getCursor());if(c){var d="close"==c.at?c.open:c.close;d&&b.extendSelection(d.to,d.from)}}})},{"../../lib/codemirror":59,"../fold/xml-fold":21}],14:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(C
 odeMirror)}(function(a){a.defineOption("showTrailingSpace",!1,function(b,c,d){d==a.Init&&(d=!1),d&&!c?b.removeOverlay("trailingspace"):!d&&c&&b.addOverlay({token:function(a){for(var b=a.string.length,c=b;c&&/\s/.test(a.string.charAt(c-1));--c);return c>a.pos?(a.pos=c,null):(a.pos=b,"trailingspace")},name:"trailingspace"})})})},{"../../lib/codemirror":59}],15:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";a.registerHelper("fold","brace",function(b,c){function d(d){for(var h=c.ch,i=0;;){var j=h<=0?-1:g.lastIndexOf(d,h-1);if(j!=-1){if(1==i&&j<c.ch)break;if(e=b.getTokenTypeAt(a.Pos(f,j+1)),!/^(comment|string)/.test(e))return j
 +1;h=j-1}else{if(1==i)break;i=1,h=g.length}}}var e,f=c.line,g=b.getLine(f),h="{",i="}",j=d("{");if(null==j&&(h="[",i="]",j=d("[")),null!=j){var k,l,m=1,n=b.lastLine();a:for(var o=f;o<=n;++o)for(var p=b.getLine(o),q=o==f?j:0;;){var r=p.indexOf(h,q),s=p.indexOf(i,q);if(r<0&&(r=p.length),s<0&&(s=p.length),q=Math.min(r,s),q==p.length)break;if(b.getTokenTypeAt(a.Pos(o,q+1))==e)if(q==r)++m;else if(!--m){k=o,l=q;break a}++q}if(null!=k&&(f!=k||l!=j))return{from:a.Pos(f,j),to:a.Pos(k,l)}}}),a.registerHelper("fold","import",function(b,c){function d(c){if(c<b.firstLine()||c>b.lastLine())return null;var d=b.getTokenAt(a.Pos(c,1));if(/\S/.test(d.string)||(d=b.getTokenAt(a.Pos(c,d.end+1))),"keyword"!=d.type||"import"!=d.string)return null;for(var e=c,f=Math.min(b.lastLine(),c+10);e<=f;++e){var g=b.getLine(e),h=g.indexOf(";");if(h!=-1)retur
 n{startCh:d.end,end:a.Pos(e,h)}}}var e,f=c.line,g=d(f);if(!g||d(f-1)||(e=d(f-2))&&e.end.line==f-1)return null;for(var h=g.end;;){var i=d(h.line+1);if(null==i)break;h=i.end}return{from:b.clipPos(a.Pos(f,g.startCh+1)),to:h}}),a.registerHelper("fold","include",function(b,c){function d(c){if(c<b.firstLine()||c>b.lastLine())return null;var d=b.getTokenAt(a.Pos(c,1));return/\S/.test(d.string)||(d=b.getTokenAt(a.Pos(c,d.end+1))),"meta"==d.type&&"#include"==d.string.slice(0,8)?d.start+8:void 0}var e=c.line,f=d(e);if(null==f||null!=d(e-1))return null;for(var g=e;;){var h=d(g+1);if(null==h)break;++g}return{from:a.Pos(e,f+1),to:b.clipPos(a.Pos(g))}})})},{"../../lib/codemirror":59}],16:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(Cod
 eMirror)}(function(a){"use strict";a.registerGlobalHelper("fold","comment",function(a){return a.blockCommentStart&&a.blockCommentEnd},function(b,c){var d=b.getModeAt(c),e=d.blockCommentStart,f=d.blockCommentEnd;if(e&&f){for(var g,h=c.line,i=b.getLine(h),j=c.ch,k=0;;){var l=j<=0?-1:i.lastIndexOf(e,j-1);if(l!=-1){if(1==k&&l<c.ch)return;if(/comment/.test(b.getTokenTypeAt(a.Pos(h,l+1)))&&(0==l||i.slice(l-f.length,l)==f||!/comment/.test(b.getTokenTypeAt(a.Pos(h,l))))){g=l+e.length;break}j=l-1}else{if(1==k)return;k=1,j=i.length}}var m,n,o=1,p=b.lastLine();a:for(var q=h;q<=p;++q)for(var r=b.getLine(q),s=q==h?g:0;;){var t=r.indexOf(e,s),u=r.indexOf(f,s);if(t<0&&(t=r.length),u<0&&(u=r.length),s=Math.min(t,u),s==r.length)break;if(s==t)++o;else if(!--o){m=q,n=s;break a}++s}if(null!=m&&(h!=m||n!=g))return{from:a.Pos(h,g),to:a.Pos(m,n)}}})})},{"../../lib/codemirror":59}],17:[function(a,
 b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(b,e,f,g){function h(a){var c=i(b,e);if(!c||c.to.line-c.from.line<j)return null;for(var d=b.findMarksAt(c.from),f=0;f<d.length;++f)if(d[f].__isFold&&"fold"!==g){if(!a)return null;c.cleared=!0,d[f].clear()}return c}if(f&&f.call){var i=f;f=null}else var i=d(b,f,"rangeFinder");"number"==typeof e&&(e=a.Pos(e,0));var j=d(b,f,"minFoldSize"),k=h(!0);if(d(b,f,"scanUp"))for(;!k&&e.line>b.firstLine();)e=a.Pos(e.line-1,0),k=h(!1);if(k&&!k.cleared&&"unfold"!==g){var l=c(b,f);a.on(l,"mousedown",function(b){m.clear(),a.e_preventDefault(b)});var m=b.markText(k.from,k.to,{replacedWith:l,clearOn
 Enter:d(b,f,"clearOnEnter"),__isFold:!0});m.on("clear",function(c,d){a.signal(b,"unfold",b,c,d)}),a.signal(b,"fold",b,k.from,k.to)}}function c(a,b){var c=d(a,b,"widget");if("string"==typeof c){var e=document.createTextNode(c);c=document.createElement("span"),c.appendChild(e),c.className="CodeMirror-foldmarker"}else c&&(c=c.cloneNode(!0));return c}function d(a,b,c){if(b&&void 0!==b[c])return b[c];var d=a.options.foldOptions;return d&&void 0!==d[c]?d[c]:e[c]}a.newFoldFunction=function(a,c){return function(d,e){b(d,e,{rangeFinder:a,
+widget:c})}},a.defineExtension("foldCode",function(a,c,d){b(this,a,c,d)}),a.defineExtension("isFolded",function(a){for(var b=this.findMarksAt(a),c=0;c<b.length;++c)if(b[c].__isFold)return!0}),a.commands.toggleFold=function(a){a.foldCode(a.getCursor())},a.commands.fold=function(a){a.foldCode(a.getCursor(),null,"fold")},a.commands.unfold=function(a){a.foldCode(a.getCursor(),null,"unfold")},a.commands.foldAll=function(b){b.operation(function(){for(var c=b.firstLine(),d=b.lastLine();c<=d;c++)b.foldCode(a.Pos(c,0),null,"fold")})},a.commands.unfoldAll=function(b){b.operation(function(){for(var c=b.firstLine(),d=b.lastLine();c<=d;c++)b.foldCode(a.Pos(c,0),null,"unfold")})},a.registerHelper("fold","combine",function(){var a=Array.prototype.slice.call(arguments,0);return function(b,c){for(var d=0;d<a.length;++d){var e=a[d](b,c);if(e)return e}}}),a.registerHelper("fold","auto",funct
 ion(a,b){for(var c=a.getHelpers(b,"fold"),d=0;d<c.length;d++){var e=c[d](a,b);if(e)return e}});var e={rangeFinder:a.fold.auto,widget:"\u2194",minFoldSize:0,scanUp:!1,clearOnEnter:!0};a.defineOption("foldOptions",null),a.defineExtension("foldOption",function(a,b){return d(this,a,b)})})},{"../../lib/codemirror":59}],18:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror"),a("./foldcode")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","./foldcode"],d):d(CodeMirror)}(function(a){"use strict";function b(a){this.options=a,this.from=this.to=0}function c(a){return a===!0&&(a={}),null==a.gutter&&(a.gutter="CodeMirror-foldgutter"),null==a.indicatorOpen&&(a.indicatorOpen="CodeMirror-foldgutter-open"),null==a.indicatorFolded&&(a.ind
 icatorFolded="CodeMirror-foldgutter-folded"),a}function d(a,b){for(var c=a.findMarks(l(b,0),l(b+1,0)),d=0;d<c.length;++d)if(c[d].__isFold&&c[d].find().from.line==b)return c[d]}function e(a){if("string"==typeof a){var b=document.createElement("div");return b.className=a+" CodeMirror-guttermarker-subtle",b}return a.cloneNode(!0)}function f(a,b,c){var f=a.state.foldGutter.options,g=b,h=a.foldOption(f,"minFoldSize"),i=a.foldOption(f,"rangeFinder");a.eachLine(b,c,function(b){var c=null;if(d(a,g))c=e(f.indicatorFolded);else{var j=l(g,0),k=i&&i(a,j);k&&k.to.line-k.from.line>=h&&(c=e(f.indicatorOpen))}a.setGutterMarker(b,f.gutter,c),++g})}function g(a){var b=a.getViewport(),c=a.state.foldGutter;c&&(a.operation(function(){f(a,b.from,b.to)}),c.from=b.from,c.to=b.to)}function h(a,b,c){var e=a.state.foldGutter;if(e){var f=e.options;if(c==f.gutter){var g=d(a,b);g?g.clear():a.foldCode(l(b,0),
 f.rangeFinder)}}}function i(a){var b=a.state.foldGutter;if(b){var c=b.options;b.from=b.to=0,clearTimeout(b.changeUpdate),b.changeUpdate=setTimeout(function(){g(a)},c.foldOnChangeTimeSpan||600)}}function j(a){var b=a.state.foldGutter;if(b){var c=b.options;clearTimeout(b.changeUpdate),b.changeUpdate=setTimeout(function(){var c=a.getViewport();b.from==b.to||c.from-b.to>20||b.from-c.to>20?g(a):a.operation(function(){c.from<b.from&&(f(a,c.from,b.from),b.from=c.from),c.to>b.to&&(f(a,b.to,c.to),b.to=c.to)})},c.updateViewportTimeSpan||400)}}function k(a,b){var c=a.state.foldGutter;if(c){var d=b.line;d>=c.from&&d<c.to&&f(a,d,d+1)}}a.defineOption("foldGutter",!1,function(d,e,f){f&&f!=a.Init&&(d.clearGutter(d.state.foldGutter.options.gutter),d.state.foldGutter=null,d.off("gutterClick",h),d.off("change",i),d.off("viewportChange",j),d.off("fold",k),d.off("unfold",k),d.off
 ("swapDoc",i)),e&&(d.state.foldGutter=new b(c(e)),g(d),d.on("gutterClick",h),d.on("change",i),d.on("viewportChange",j),d.on("fold",k),d.on("unfold",k),d.on("swapDoc",i))});var l=a.Pos})},{"../../lib/codemirror":59,"./foldcode":17}],19:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(b,c){var d=b.getLine(c),e=d.search(/\S/);return e==-1||/\bcomment\b/.test(b.getTokenTypeAt(a.Pos(c,e+1)))?-1:a.countColumn(d,null,b.getOption("tabSize"))}a.registerHelper("fold","indent",function(c,d){var e=b(c,d.line);if(!(e<0)){for(var f=null,g=d.line+1,h=c.lastLine();g<=h;++g){var i=b(c,g);if(i==-1);else{if(!(i>e))break;f=
 g}}return f?{from:a.Pos(d.line,c.getLine(d.line).length),to:a.Pos(f,c.getLine(f).length)}:void 0}})})},{"../../lib/codemirror":59}],20:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";a.registerHelper("fold","markdown",function(b,c){function d(c){var d=b.getTokenTypeAt(a.Pos(c,0));return d&&/\bheader\b/.test(d)}function e(a,b,c){var e=b&&b.match(/^#+/);return e&&d(a)?e[0].length:(e=c&&c.match(/^[=\-]+\s*$/),e&&d(a+1)?"="==c[0]?1:2:f)}var f=100,g=b.getLine(c.line),h=b.getLine(c.line+1),i=e(c.line,g,h);if(i!==f){for(var j=b.lastLine(),k=c.line,l=b.getLine(k+2);k<j&&!(e(k+1,h,l)<=i);)++k,h=l,l=b.getLine(k+2);return{from:a.Pos(c.line,g.length),to:a.Pos(k,b.getL
 ine(k).length)}}})})},{"../../lib/codemirror":59}],21:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(a,b){return a.line-b.line||a.ch-b.ch}function c(a,b,c,d){this.line=b,this.ch=c,this.cm=a,this.text=a.getLine(b),this.min=d?Math.max(d.from,a.firstLine()):a.firstLine(),this.max=d?Math.min(d.to-1,a.lastLine()):a.lastLine()}function d(a,b){var c=a.cm.getTokenTypeAt(m(a.line,b));return c&&/\btag\b/.test(c)}function e(a){if(!(a.line>=a.max))return a.ch=0,a.text=a.cm.getLine(++a.line),!0}function f(a){if(!(a.line<=a.min))return a.text=a.cm.getLine(--a.line),a.ch=a.text.length,!0}function g(a){for(;;){var b=a.text.indexOf(">",a.ch);if(b==-1){if(e(a))continue;return}{if(d(a,b+1)){var c=a.text.lastIndexOf(&qu
 ot;/",b),f=c>-1&&!/\S/.test(a.text.slice(c+1,b));return a.ch=b+1,f?"selfClose":"regular"}a.ch=b+1}}}function h(a){for(;;){var b=a.ch?a.text.lastIndexOf("<",a.ch-1):-1;if(b==-1){if(f(a))continue;return}if(d(a,b+1)){p.lastIndex=b,a.ch=b;var c=p.exec(a.text);if(c&&c.index==b)return c}else a.ch=b}}function i(a){for(;;){p.lastIndex=a.ch;var b=p.exec(a.text);if(!b){if(e(a))continue;return}{if(d(a,b.index+1))return a.ch=b.index+b[0].length,b;a.ch=b.index+1}}}function j(a){for(;;){var b=a.ch?a.text.lastIndexOf(">",a.ch-1):-1;if(b==-1){if(f(a))continue;return}{if(d(a,b+1)){var c=a.text.lastIndexOf("/",b),e=c>-1&&!/\S/.test(a.text.slice(c+1,b));return a.ch=b+1,e?"selfClose":"regular"}a.ch=b}}}function k(a,b){for(var c=[];;){var d,e=i(a),f=a.line,h=a.ch-(e?e[0].length:0);if(!e||!(d=g(a)))return;if("selfClose"!=d)if(e[1]){for(var j=c.length-1;j>=0;--j)if(c[j]==e[2]){c.leng
 th=j;break}if(j<0&&(!b||b==e[2]))return{tag:e[2],from:m(f,h),to:m(a.line,a.ch)}}else c.push(e[2])}}function l(a,b){for(var c=[];;){var d=j(a);if(!d)return;if("selfClose"!=d){var e=a.line,f=a.ch,g=h(a);if(!g)return;if(g[1])c.push(g[2]);else{for(var i=c.length-1;i>=0;--i)if(c[i]==g[2]){c.length=i;break}if(i<0&&(!b||b==g[2]))return{tag:g[2],from:m(a.line,a.ch),to:m(e,f)}}}else h(a)}}var m=a.Pos,n="A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD",o=n+"-:.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040",p=new RegExp("<(/?)(["+n+"]["+o+"]*)","g");a.registerHelper("fold","xml",function(a,b){for(var d=new c(a,b.line,0);;){var e,f=i(d);if(!f||d.line!=b.line||!(e=g(d)))return;if(!f[1]&&"selfClose"!=e){var h=m(d.line,d.ch),j=k(d,f[2]);return j&
 amp;&{from:h,to:j.from}}}}),a.findMatchingTag=function(a,d,e){var f=new c(a,d.line,d.ch,e);if(f.text.indexOf(">")!=-1||f.text.indexOf("<")!=-1){var i=g(f),j=i&&m(f.line,f.ch),n=i&&h(f);if(i&&n&&!(b(f,d)>0)){var o={from:m(f.line,f.ch),to:j,tag:n[2]};return"selfClose"==i?{open:o,close:null,at:"open"}:n[1]?{open:l(f,n[2]),close:o,at:"close"}:(f=new c(a,j.line,j.ch,e),{open:o,close:k(f,n[2]),at:"open"})}}},a.findEnclosingTag=function(a,b,d,e){for(var f=new c(a,b.line,b.ch,d);;){var g=l(f,e);if(!g)break;var h=new c(a,b.line,b.ch,d),i=k(h,g.tag);if(i)return{open:g,close:i}}},a.scanForClosingTag=function(a,b,d,e){var f=new c(a,b.line,b.ch,e?{from:0,to:e}:null);return k(f,d)}})},{"../../lib/codemirror":59}],22:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof defin
 e&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";var b=/[\w$]+/,c=500;a.registerHelper("hint","anyword",function(d,e){for(var f=e&&e.word||b,g=e&&e.range||c,h=d.getCursor(),i=d.getLine(h.line),j=h.ch,k=j;k&&f.test(i.charAt(k-1));)--k;for(var l=k!=j&&i.slice(k,j),m=e&&e.list||[],n={},o=new RegExp(f.source,"g"),p=-1;p<=1;p+=2)for(var q=h.line,r=Math.min(Math.max(q+p*g,d.firstLine()),d.lastLine())+p;q!=r;q+=p)for(var s,t=d.getLine(q);s=o.exec(t);)q==h.line&&s[0]===l||l&&0!=s[0].lastIndexOf(l,0)||Object.prototype.hasOwnProperty.call(n,s[0])||(n[s[0]]=!0,m.push(s[0]));return{list:m,from:a.Pos(h.line,k),to:a.Pos(h.line,j)}})})},{"../../lib/codemirror":59}],23:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror"),a("../../mode/css/css")
 ):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../../mode/css/css"],d):d(CodeMirror)}(function(a){"use strict";var b={link:1,visited:1,active:1,hover:1,focus:1,"first-letter":1,"first-line":1,"first-child":1,before:1,after:1,lang:1};a.registerHelper("hint","css",function(c){function d(a){for(var b in a)j&&0!=b.lastIndexOf(j,0)||l.push(b)}var e=c.getCursor(),f=c.getTokenAt(e),g=a.innerMode(c.getMode(),f.state);if("css"==g.mode.name){if("keyword"==f.type&&0=="!important".indexOf(f.string))return{list:["!important"],from:a.Pos(e.line,f.start),to:a.Pos(e.line,f.end)};var h=f.start,i=e.ch,j=f.string.slice(0,i-h);/[^\w$_-]/.test(j)&&(j="",h=i=e.ch);var k=a.resolveMode("text/css"),l=[],m=g.state.state;return"pseudo"==m||"variable-3"==f.type?d(b):"block"==m|
 |"maybeprop"==m?d(k.propertyKeywords):"prop"==m||"parens"==m||"at"==m||"params"==m?(d(k.valueKeywords),d(k.colorKeywords)):"media"!=m&&"media_parens"!=m||(d(k.mediaTypes),d(k.mediaFeatures)),l.length?{list:l,from:a.Pos(e.line,h),to:a.Pos(e.line,i)}:void 0}})})},{"../../lib/codemirror":59,"../../mode/css/css":61}],24:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror"),a("./xml-hint")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","./xml-hint"],d):d(CodeMirror)}(function(a){"use strict";function b(a){for(var b in l)l.hasOwnProperty(b)&&(a.attrs[b]=l[b])}function c(b,c){var d={schemaInfo:k};if(c)for(var e in c)d[e]=c[e];return a.hint.xml(b,d)}var d="ab aa af ak sq am ar an hy as av ae ay az bm ba eu be bn bh bi bs b
 r bg my ca ch ce ny zh cv kw co cr hr cs da dv nl dz en eo et ee fo fj fi fr ff gl ka de el gn gu ht ha he hz hi ho hu ia id ie ga ig ik io is it iu ja jv kl kn kr ks kk km ki rw ky kv kg ko ku kj la lb lg li ln lo lt lu lv gv mk mg ms ml mt mi mr mh mn na nv nb nd ne ng nn no ii nr oc oj cu om or os pa pi fa pl ps pt qu rm rn ro ru sa sc sd se sm sg sr gd sn si sk sl so st es su sw ss sv ta te tg th ti bo tk tl tn to tr ts tt tw ty ug uk ur uz ve vi vo wa cy wo fy xh yi yo za zu".split(" "),e=["_blank","_self","_top","_parent"],f=["ascii","utf-8","utf-16","latin1","latin1"],g=["get","post","put","delete"],h=["application/x-www-form-urlencoded","multipart/form-data","text/plain"],i=["all","screen","print","embossed","braille","handheld","print&quo
 t;,"projection","screen","tty","tv","speech","3d-glasses","resolution [>][<][=] [X]","device-aspect-ratio: X/Y","orientation:portrait","orientation:landscape","device-height: [X]","device-width: [X]"],j={attrs:{}},k={a:{attrs:{href:null,ping:null,type:null,media:i,target:e,hreflang:d}},abbr:j,acronym:j,address:j,applet:j,area:{attrs:{alt:null,coords:null,href:null,target:null,ping:null,media:i,hreflang:d,type:null,shape:["default","rect","circle","poly"]}},article:j,aside:j,audio:{attrs:{src:null,mediagroup:null,crossorigin:["anonymous","use-credentials"],preload:["none","metadata","auto"],autoplay:["","autoplay"],loop:["","loop"],controls:["","controls"]}},b:j,base:{attrs:{href:null,target:e}},basefont:j,bdi:j,
 bdo:j,big:j,blockquote:{attrs:{cite:null}},body:j,br:j,button:{attrs:{form:null,formaction:null,name:null,value:null,autofocus:["","autofocus"],disabled:["","autofocus"],formenctype:h,formmethod:g,formnovalidate:["","novalidate"],formtarget:e,type:["submit","reset","button"]}},canvas:{attrs:{width:null,height:null}},caption:j,center:j,cite:j,code:j,col:{attrs:{span:null}},colgroup:{attrs:{span:null}},command:{attrs:{type:["command","checkbox","radio"],label:null,icon:null,radiogroup:null,command:null,title:null,disabled:["","disabled"],checked:["","checked"]}},data:{attrs:{value:null}},datagrid:{attrs:{disabled:["","disabled"],multiple:["","multiple"]}},datalist:{attrs:{data:null}},dd:j,del:{attrs:{cite:null,datetime:null}},details:{attrs:{open:["","open"]}},dfn:j,di
 r:j,div:j,dl:j,dt:j,em:j,embed:{attrs:{src:null,type:null,width:null,height:null}},eventsource:{attrs:{src:null}},fieldset:{attrs:{disabled:["","disabled"],form:null,name:null}},figcaption:j,figure:j,font:j,footer:j,form:{attrs:{action:null,name:null,"accept-charset":f,autocomplete:["on","off"],enctype:h,method:g,novalidate:["","novalidate"],target:e}},frame:j,frameset:j,h1:j,h2:j,h3:j,h4:j,h5:j,h6:j,head:{attrs:{},children:["title","base","link","style","meta","script","noscript","command"]},header:j,hgroup:j,hr:j,html:{attrs:{manifest:null},children:["head","body"]},i:j,iframe:{attrs:{src:null,srcdoc:null,name:null,width:null,height:null,sandbox:["allow-top-navigation","allow-same-origin","allow-forms","allow-scripts"],seamless:["","seamless"]}},img:{attr
 s:{alt:null,src:null,ismap:null,usemap:null,width:null,height:null,crossorigin:["anonymous","use-credentials"]}},input:{attrs:{alt:null,dirname:null,form:null,formaction:null,height:null,list:null,max:null,maxlength:null,min:null,name:null,pattern:null,placeholder:null,size:null,src:null,step:null,value:null,width:null,accept:["audio/*","video/*","image/*"],autocomplete:["on","off"],autofocus:["","autofocus"],checked:["","checked"],disabled:["","disabled"],formenctype:h,formmethod:g,formnovalidate:["","novalidate"],formtarget:e,multiple:["","multiple"],readonly:["","readonly"],required:["","required"],type:["hidden","text","search","tel","url","email","password","datetime","date","mo
 nth","week","time","datetime-local","number","range","color","checkbox","radio","file","submit","image","reset","button"]}},ins:{attrs:{cite:null,datetime:null}},kbd:j,keygen:{attrs:{challenge:null,form:null,name:null,autofocus:["","autofocus"],disabled:["","disabled"],keytype:["RSA"]}},label:{attrs:{"for":null,form:null}},legend:j,li:{attrs:{value:null}},link:{attrs:{href:null,type:null,hreflang:d,media:i,sizes:["all","16x16","16x16 32x32","16x16 32x32 64x64"]}},map:{attrs:{name:null}},mark:j,menu:{attrs:{label:null,type:["list","context","toolbar"]}},meta:{attrs:{content:null,charset:f,name:["viewport","application-name","author","description","generator","keywords&q
 uot;],"http-equiv":["content-language","content-type","default-style","refresh"]}},meter:{attrs:{value:null,min:null,low:null,high:null,max:null,optimum:null}},nav:j,noframes:j,noscript:j,object:{attrs:{data:null,type:null,name:null,usemap:null,form:null,width:null,height:null,typemustmatch:["","typemustmatch"]}},ol:{attrs:{reversed:["","reversed"],start:null,type:["1","a","A","i","I"]}},optgroup:{attrs:{disabled:["","disabled"],label:null}},option:{attrs:{disabled:["","disabled"],label:null,selected:["","selected"],value:null}},output:{attrs:{"for":null,form:null,name:null}},p:j,param:{attrs:{name:null,value:null}},pre:j,progress:{attrs:{value:null,max:null}},q:{attrs:{cite:null}},rp:j,rt:j,ruby:j,s:j,samp:j,script:{attrs:{type:["text/javascript"],src:null,async:[&q
 uot;","async"],defer:["","defer"],charset:f}},section:j,select:{attrs:{form:null,name:null,size:null,autofocus:["","autofocus"],disabled:["","disabled"],multiple:["","multiple"]}},small:j,source:{attrs:{src:null,type:null,media:null}},span:j,strike:j,strong:j,style:{attrs:{type:["text/css"],media:i,scoped:null}},sub:j,summary:j,sup:j,table:j,tbody:j,td:{attrs:{colspan:null,rowspan:null,headers:null}},textarea:{attrs:{dirname:null,form:null,maxlength:null,name:null,placeholder:null,rows:null,cols:null,autofocus:["","autofocus"],disabled:["","disabled"],readonly:["","readonly"],required:["","required"],wrap:["soft","hard"]}},tfoot:j,th:{attrs:{colspan:null,rowspan:null,headers:null,scope:["row","col","rowgroup","colgroup"]}},thead:j,time:{attrs
 :{datetime:null}},title:j,tr:j,track:{attrs:{src:null,label:null,"default":null,kind:["subtitles","captions","descriptions","chapters","metadata"],srclang:d}},tt:j,u:j,ul:j,"var":j,video:{attrs:{src:null,poster:null,width:null,height:null,crossorigin:["anonymous","use-credentials"],preload:["auto","metadata","none"],autoplay:["","autoplay"],mediagroup:["movie"],muted:["","muted"],controls:["","controls"]}},wbr:j},l={accesskey:["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0&quot
 ;,"1","2","3","4","5","6","7","8","9"],"class":null,contenteditable:["true","false"],contextmenu:null,dir:["ltr","rtl","auto"],draggable:["true","false","auto"],dropzone:["copy","move","link","string:","file:"],hidden:["hidden"],id:null,inert:["inert"],itemid:null,itemprop:null,itemref:null,itemscope:["itemscope"],itemtype:null,lang:["en","es"],spellcheck:["true","false"],style:null,tabindex:["1","2","3","4","5","6","7","8","9"],title:null,translate:["yes","no"],onclick:null,rel:["stylesheet","alternate","author","bookmark","help",
 "license","next","nofollow","noreferrer","prefetch","prev","search","tag"]};b(j);for(var m in k)k.hasOwnProperty(m)&&k[m]!=j&&b(k[m]);a.htmlSchema=k,a.registerHelper("hint","html",c)})},{"../../lib/codemirror":59,"./xml-hint":28}],25:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){function b(a,b){for(var c=0,d=a.length;c<d;++c)b(a[c])}function c(a,b){if(!Array.prototype.indexOf){for(var c=a.length;c--;)if(a[c]===b)return!0;return!1}return a.indexOf(b)!=-1}function d(b,c,d,e){var f=b.getCursor(),g=d(b,f);if(!/\b(?:string|comment)\b/.test(g.type)){g.state=a.innerMode(b.getMode(),g.state).state,/^[\w$_]*$/.test(g.string)?g.end>f.ch&am
 p;&(g.end=f.ch,g.string=g.string.slice(0,f.ch-g.start)):g={start:f.ch,end:f.ch,string:"",state:g.state,type:"."==g.string?"property":null};for(var h=g;"property"==h.type;){if(h=d(b,j(f.line,h.start)),"."!=h.string)return;if(h=d(b,j(f.line,h.start)),!k)var k=[];k.push(h)}return{list:i(g,k,c,e),from:j(f.line,g.start),to:j(f.line,g.end)}}}function e(a,b){return d(a,n,function(a,b){return a.getTokenAt(b)},b)}function f(a,b){var c=a.getTokenAt(b);return b.ch==c.start+1&&"."==c.string.charAt(0)?(c.end=c.start,c.string=".",c.type="property"):/^\.[\w$_]*$/.test(c.string)&&(c.type="property",c.start++,c.string=c.string.replace(/\./,"")),c}function g(a,b){return d(a,o,f,b)}function h(a,b){if(Object.getOwnPropertyNames&&Object.getPrototypeOf)for(var c=a;c;c=Object.getPrototypeOf(c))Object.getOwnPropertyNames(c).forEach(b);else for(var d in a)b(d)}function i(a,d,e,f){f
 unction g(a){0!=a.lastIndexOf(n,0)||c(j,a)||j.push(a)}function i(a){"string"==typeof a?b(k,g):a instanceof Array?b(l,g):a instanceof Function&&b(m,g),h(a,g)}var j=[],n=a.string,o=f&&f.globalScope||window;if(d&&d.length){var p,q=d.pop();for(q.type&&0===q.type.indexOf("variable")?(f&&f.additionalContext&&(p=f.additionalContext[q.string]),f&&f.useGlobalScope===!1||(p=p||o[q.string])):"string"==q.type?p="":"atom"==q.type?p=1:"function"==q.type&&(null==o.jQuery||"$"!=q.string&&"jQuery"!=q.string||"function"!=typeof o.jQuery?null!=o._&&"_"==q.string&&"function"==typeof o._&&(p=o._()):p=o.jQuery());null!=p&&d.length;)p=p[d.pop().string];null!=p&&i(p)}else{for(var r=a.state.localVars;r;r=r.next)g(r.name);for(var r=a.state.globalVars;r;r=r.next)g(r.name);f&&f.useGlo
 balScope===!1||i(o),b(e,g)}return j}var j=a.Pos;a.registerHelper("hint","javascript",e),a.registerHelper("hint","coffeescript",g);var k="charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight toUpperCase toLowerCase split concat match replace search".split(" "),l="length concat join splice push pop shift unshift slice reverse sort indexOf lastIndexOf every some filter forEach map reduce reduceRight ".split(" "),m="prototype apply call bind".split(" "),n="break case catch continue debugger default delete do else false finally for function if in instanceof new null return switch throw true try typeof var void while with".split(" "),o="and break catch class continue delete do else extends false finally for if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes".split
 (" ")})},{"../../lib/codemirror":59}],26:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(a,b){this.cm=a,this.options=b,this.widget=null,this.debounce=0,this.tick=0,this.startPos=this.cm.getCursor("start"),this.startLen=this.cm.getLine(this.startPos.line).length-this.cm.getSelection().length;var c=this;a.on("cursorActivity",this.activityFunc=function(){c.cursorActivity()})}function c(b,c){var d=a.cmpPos(c.from,b.from);return d>0&&b.to.ch-b.from.ch!=c.to.ch-c.from.ch}function d(a,b,c){var d=a.options.hintOptions,e={};for(var f in p)e[f]=p[f];if(d)for(var f in d)void 0!==d[f]&&(e[f]=d[f]);if(c)for(var f in c)void 0!==c[f]&&(e[f]=c[f]);return e.hint.resolve&&(e.hint=e
 .hint.resolve(a,b)),e}function e(a){return"string"==typeof a?a:a.text}function f(a,b){function c(a,c){var e;e="string"!=typeof c?function(a){return c(a,b)}:d.hasOwnProperty(c)?d[c]:c,f[a]=e}var d={Up:function(){b.moveFocus(-1)},Down:function(){b.moveFocus(1)},PageUp:function(){b.moveFocus(-b.menuSize()+1,!0)},PageDown:function(){b.moveFocus(b.menuSize()-1,!0)},Home:function(){b.setFocus(0)},End:function(){b.setFocus(b.length-1)},Enter:b.pick,Tab:b.pick,Esc:b.close},e=a.options.customKeys,f=e?{}:d;if(e)for(var g in e)e.hasOwnProperty(g)&&c(g,e[g]);var h=a.options.extraKeys;if(h)for(var g in h)h.hasOwnProperty(g)&&c(g,h[g]);return f}function g(a,b){for(;b&&b!=a;){if("LI"===b.nodeName.toUpperCase()&&b.parentNode==a)return b;b=b.parentNode}}function h(b,c){this.completion=b,this.data=c,this.picked=!1;var d=this,h=b.cm,i=this.hints=document.createElement("ul");i.className="CodeMirror-hints",this.selectedHin
 t=c.selectedHint||0;for(var j=c.list,k=0;k<j.length;++k){var n=i.appendChild(document.createElement("li")),o=j[k],p=l+(k!=this.selectedHint?"":" "+m);null!=o.className&&(p=o.className+" "+p),n.className=p,o.render?o.render(n,c,o):n.appendChild(document.createTextNode(o.displayText||e(o))),n.hintId=k}var q=h.cursorCoords(b.options.alignWithWord?c.from:null),r=q.left,s=q.bottom,t=!0;i.style.left=r+"px",i.style.top=s+"px";var u=window.innerWidth||Math.max(document.body.offsetWidth,document.documentElement.offsetWidth),v=window.innerHeight||Math.max(document.body.offsetHeight,document.documentElement.offsetHeight);(b.options.container||document.body).appendChild(i);var w=i.getBoundingClientRect(),x=w.bottom-v,y=i.scrollHeight>i.clientHeight+1,z=h.getScrollInfo();if(x>0){var A=w.bottom-w.top,B=q.top-(q.bottom-w.top);if(B-A>0)i.style.top=(s=q.top-A)+"px",t=!1;else if(A>v){i.style.height=v-5+"
 px",i.style.top=(s=q.bottom-w.top)+"px";var C=h.getCursor();c.from.ch!=C.ch&&(q=h.cursorCoords(C),i.style.left=(r=q.left)+"px",w=i.getBoundingClientRect())}}var D=w.right-u;if(D>0&&(w.right-w.left>u&&(i.style.width=u-5+"px",D-=w.right-w.left-u),i.style.left=(r=q.left-D)+"px"),y)for(var E=i.firstChild;E;E=E.nextSibling)E.style.paddingRight=h.display.nativeBarWidth+"px";if(h.addKeyMap(this.keyMap=f(b,{moveFocus:function(a,b){d.changeActive(d.selectedHint+a,b)},setFocus:function(a){d.changeActive(a)},menuSize:function(){return d.screenAmount()},length:j.length,close:function(){b.close()},pick:function(){d.pick()},data:c})),b.options.closeOnUnfocus){var F;h.on("blur",this.onBlur=function(){F=setTimeout(function(){b.close()},100)}),h.on("focus",this.onFocus=function(){clearTimeout(F)})}return h.on("scroll",this.onScroll=function(){var a=h.getScrollInfo(),c=h.getWrapperElemen
 t().getBoundingClientRect(),d=s+z.top-a.top,e=d-(window.pageYOffset||(document.documentElement||document.body).scrollTop);return t||(e+=i.offsetHeight),e<=c.top||e>=c.bottom?b.close():(i.style.top=d+"px",void(i.style.left=r+z.left-a.left+"px"))}),a.on(i,"dblclick",function(a){var b=g(i,a.target||a.srcElement);b&&null!=b.hintId&&(d.changeActive(b.hintId),d.pick())}),a.on(i,"click",function(a){var c=g(i,a.target||a.srcElement);c&&null!=c.hintId&&(d.changeActive(c.hintId),b.options.completeOnSingleClick&&d.pick())}),a.on(i,"mousedown",function(){setTimeout(function(){h.focus()},20)}),a.signal(c,"select",j[this.selectedHint],i.childNodes[this.selectedHint]),!0}function i(a,b){if(!a.somethingSelected())return b;for(var c=[],d=0;d<b.length;d++)b[d].supportsSelection&&c.push(b[d]);return c}function j(a,b,c,d){if(a.async)a(b,d,c);else{var e=a(b,c);e&&e.then?e.then(d):
 d(e)}}function k(b,c){var d,e=b.getHelpers(c,"hint");if(e.length){var f=function(a,b,c){function d(e){return e==f.length?b(null):void j(f[e],a,c,function(a){a&&a.list.length>0?b(a):d(e+1)})}var f=i(a,e);d(0)};return f.async=!0,f.supportsSelection=!0,f}return(d=b.getHelper(b.getCursor(),"hintWords"))?function(b){return a.hint.fromList(b,{words:d})}:a.hint.anyword?function(b,c){return a.hint.anyword(b,c)}:function(){}}var l="CodeMirror-hint",m="CodeMirror-hint-active";a.showHint=function(a,b,c){if(!b)return a.showHint(c);c&&c.async&&(b.async=!0);var d={hint:b};if(c)for(var e in c)d[e]=c[e];return a.showHint(d)},a.defineExtension("showHint",function(c){c=d(this,this.getCursor("start"),c);var e=this.listSelections();if(!(e.length>1)){if(this.somethingSelected()){if(!c.hint.supportsSelection)return;for(var f=0;f<e.length;f++)if(e[f].head.line!=e[f].anchor.line)return}this.state.completionActive&a
 mp;&this.state.completionActive.close();var g=this.state.completionActive=new b(this,c);g.options.hint&&(a.signal(this,"startCompletion",this),g.update(!0))}});var n=window.requestAnimationFrame||function(a){return setTimeout(a,1e3/60)},o=window.cancelAnimationFrame||clearTimeout;b.prototype={close:function(){this.active()&&(this.cm.state.completionActive=null,this.tick=null,this.cm.off("cursorActivity",this.activityFunc),this.widget&&this.data&&a.signal(this.data,"close"),this.widget&&this.widget.close(),a.signal(this.cm,"endCompletion",this.cm))},active:function(){return this.cm.state.completionActive==this},pick:function(b,c){var d=b.list[c];d.hint?d.hint(this.cm,b,d):this.cm.replaceRange(e(d),d.from||b.from,d.to||b.to,"complete"),a.signal(b,"pick",d),this.close()},cursorActivity:function(){this.debounce&&(o(this.debounce),this.debounce=0);var a=this.cm.getCursor(),b=th
 is.cm.getLine(a.line);if(a.line!=this.startPos.line||b.length-a.ch!=this.startLen-this.startPos.ch||a.ch<this.startPos.ch||this.cm.somethingSelected()||a.ch&&this.options.closeCharacters.test(b.charAt(a.ch-1)))this.close();else{var c=this;this.debounce=n(function(){c.update()}),this.widget&&this.widget.disable()}},update:function(a){if(null!=this.tick){var b=this,c=++this.tick;j(this.options.hint,this.cm,this.options,function(d){b.tick==c&&b.finishUpdate(d,a)})}},finishUpdate:function(b,d){this.data&&a.signal(this.data,"update");var e=this.widget&&this.widget.picked||d&&this.options.completeSingle;this.widget&&this.widget.close(),b&&this.data&&c(this.data,b)||(this.data=b,b&&b.list.length&&(e&&1==b.list.length?this.pick(b,0):(this.widget=new h(this,b),a.signal(b,"shown"))))}},h.prototype={close:function(){if(this.completion.widget==this){this.completion.widget=null,
 this.hints.parentNode.removeChild(this.hints),this.completion.cm.removeKeyMap(this.keyMap);var a=this.completion.cm;this.completion.options.closeOnUnfocus&&(a.off("blur",this.onBlur),a.off("focus",this.onFocus)),a.off("scroll",this.onScroll)}},disable:function(){this.completion.cm.removeKeyMap(this.keyMap);var a=this;this.keyMap={Enter:function(){a.picked=!0}},this.completion.cm.addKeyMap(this.keyMap)},pick:function(){this.completion.pick(this.data,this.selectedHint)},changeActive:function(b,c){if(b>=this.data.list.length?b=c?this.data.list.length-1:0:b<0&&(b=c?0:this.data.list.length-1),this.selectedHint!=b){var d=this.hints.childNodes[this.selectedHint];d.className=d.className.replace(" "+m,""),d=this.hints.childNodes[this.selectedHint=b],d.className+=" "+m,d.offsetTop<this.hints.scrollTop?this.hints.scrollTop=d.offsetTop-3:d.offsetTop+d.offsetHeight>this.hints.scrollTop+this.hints.clientHeight
 &&(this.hints.scrollTop=d.offsetTop+d.offsetHeight-this.hints.clientHeight+3),a.signal(this.data,"select",this.data.list[this.selectedHint],d)}},screenAmount:function(){return Math.floor(this.hints.clientHeight/this.hints.firstChild.offsetHeight)||1}},a.registerHelper("hint","auto",{resolve:k}),a.registerHelper("hint","fromList",function(b,c){var d=b.getCursor(),e=b.getTokenAt(d),f=a.Pos(d.line,e.end);if(e.string&&/\w/.test(e.string[e.string.length-1]))var g=e.string,h=a.Pos(d.line,e.start);else var g="",h=f;for(var i=[],j=0;j<c.words.length;j++){var k=c.words[j];k.slice(0,g.length)==g&&i.push(k)}if(i.length)return{list:i,from:h,to:f}}),a.commands.autocomplete=a.showHint;var p={hint:a.hint.auto,completeSingle:!0,alignWithWord:!0,closeCharacters:/[\s()\[\]{};:>,]/,closeOnUnfocus:!0,completeOnSingleClick:!0,container:null,customKeys:null,extraKeys:null};a.defineOption("hintOptions",null
 )})},{"../../lib/codemirror":59}],27:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror"),a("../../mode/sql/sql")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../../mode/sql/sql"],d):d(CodeMirror)}(function(a){"use strict";function b(a){return"[object Array]"==Object.prototype.toString.call(a)}function c(b){var c=b.doc.modeOption;return"sql"===c&&(c="text/x-sql"),a.resolveMode(c).keywords}function d(b){var c=b.doc.modeOption;return"sql"===c&&(c="text/x-sql"),a.resolveMode(c).identifierQuote||"`"}function e(a){return"string"==typeof a?a:a.text}function f(a,c){return b(c)&&(c={columns:c}),c.text||(c.text=a),c}function g(a){var c={};if(b(a))for(var d=a.length-1;d>=0;d--){var g=a[d];c[e(g).toUpperCase()]=f(e(g),g)}else
  if(a)for(var h in a)c[h.toUpperCase()]=f(h,a[h]);return c}function h(a){return q[a.toUpperCase()]}function i(a){var b={};for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b}function j(a,b){var c=a.length,d=e(b).substr(0,c);return a.toUpperCase()===d.toUpperCase()}function k(a,c,d,e){if(b(d))for(var f=0;f<d.length;f++)j(c,d[f])&&a.push(e(d[f]));else for(var g in d)if(d.hasOwnProperty(g)){var h=d[g];h=h&&h!==!0?h.displayText?{text:h.text,displayText:h.displayText}:h.text:g,j(c,h)&&a.push(e(h))}}function l(a){"."==a.charAt(0)&&(a=a.substr(1));for(var b=a.split(t+t),c=0;c<b.length;c++)b[c]=b[c].replace(new RegExp(t,"g"),"");return b.join(t)}function m(a){for(var b=e(a).split("."),c=0;c<b.length;c++)b[c]=t+b[c].replace(new RegExp(t,"g"),t+t)+t;var d=b.join(".");return"string"==typeof a?d:(a=i(a),a.text=d,a)}function n(a,b,c,d){for(var e=!1,f=[],g=b.start,j=!0;j;)j=
 "."==b.string.charAt(0),e=e||b.string.charAt(0)==t,g=b.start,f.unshift(l(b.string)),b=d.getTokenAt(v(a.line,b.start)),"."==b.string&&(j=!0,b=d.getTokenAt(v(a.line,b.start)));var n=f.join(".");k(c,n,q,function(a){return e?m(a):a}),k(c,n,r,function(a){return e?m(a):a}),n=f.pop();var o=f.join("."),s=!1,u=o;
+if(!h(o)){var w=o;o=p(o,d),o!==w&&(s=!0)}var x=h(o);return x&&x.columns&&(x=x.columns),x&&k(c,n,x,function(a){var b=o;return 1==s&&(b=u),"string"==typeof a?a=b+"."+a:(a=i(a),a.text=b+"."+a.text),e?m(a):a}),g}function o(a,b){for(var c=a.split(/\s+/),d=0;d<c.length;d++)c[d]&&b(c[d].replace(/[,;]/g,""))}function p(a,b){for(var c=b.doc,d=c.getValue(),e=a.toUpperCase(),f="",g="",i=[],j={start:v(0,0),end:v(b.lastLine(),b.getLineHandle(b.lastLine()).length)},k=d.indexOf(u.QUERY_DIV);k!=-1;)i.push(c.posFromIndex(k)),k=d.indexOf(u.QUERY_DIV,k+1);i.unshift(v(0,0)),i.push(v(b.lastLine(),b.getLineHandle(b.lastLine()).text.length));for(var l=null,m=b.getCursor(),n=0;n<i.length;n++){if((null==l||w(m,l)>0)&&w(m,i[n])<=0){j={start:l,end:i[n]};break}l=i[n]}for(var p=c.getRange(j.start,j.end,!1),n=0;n<p.length;n++){var q=p[n];if(o(q,function(a){var b=a.toUpperCase();b===e
 &&h(f)&&(g=f),b!==u.ALIAS_KEYWORD&&(f=a)}),g)break}return g}var q,r,s,t,u={QUERY_DIV:";",ALIAS_KEYWORD:"AS"},v=a.Pos,w=a.cmpPos;a.registerHelper("hint","sql",function(a,b){q=g(b&&b.tables);var e=b&&b.defaultTable,f=b&&b.disableKeywords;r=e&&h(e),s=c(a),t=d(a),e&&!r&&(r=p(e,a)),r=r||[],r.columns&&(r=r.columns);var i,j,l,m=a.getCursor(),o=[],u=a.getTokenAt(m);return u.end>m.ch&&(u.end=m.ch,u.string=u.string.slice(0,m.ch-u.start)),u.string.match(/^[.`"\w@]\w*$/)?(l=u.string,i=u.start,j=u.end):(i=j=m.ch,l=""),"."==l.charAt(0)||l.charAt(0)==t?i=n(m,u,o,a):(k(o,l,q,function(a){return a}),k(o,l,r,function(a){return a}),f||k(o,l,s,function(a){return a.toUpperCase()})),{list:o,from:v(m.line,i),to:v(m.line,j)}})})},{"../../lib/codemirror":59,"../../mode/sql/sql":74}],28:[function(a,b,c){!function(d){"object"==
 typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(b,d){var e=d&&d.schemaInfo,f=d&&d.quoteChar||'"';if(e){var g=b.getCursor(),h=b.getTokenAt(g);h.end>g.ch&&(h.end=g.ch,h.string=h.string.slice(0,g.ch-h.start));var i=a.innerMode(b.getMode(),h.state);if("xml"==i.mode.name){var j,k,l=[],m=!1,n=/\btag\b/.test(h.type)&&!/>$/.test(h.string),o=n&&/^\w/.test(h.string);if(o){var p=b.getLine(g.line).slice(Math.max(0,h.start-2),h.start),q=/<\/$/.test(p)?"close":/<$/.test(p)?"open":null;q&&(k=h.start-("close"==q?2:1))}else n&&"<"==h.string?q="open":n&&"</"==h.string&&(q="close");if(!n&&!i.state.tagName||q){o&&(j=h.
 string),m=q;var r=i.state.context,s=r&&e[r.tagName],t=r?s&&s.children:e["!top"];if(t&&"close"!=q)for(var u=0;u<t.length;++u)j&&0!=t[u].lastIndexOf(j,0)||l.push("<"+t[u]);else if("close"!=q)for(var v in e)!e.hasOwnProperty(v)||"!top"==v||"!attrs"==v||j&&0!=v.lastIndexOf(j,0)||l.push("<"+v);r&&(!j||"close"==q&&0==r.tagName.lastIndexOf(j,0))&&l.push("</"+r.tagName+">")}else{var s=e[i.state.tagName],w=s&&s.attrs,x=e["!attrs"];if(!w&&!x)return;if(w){if(x){var y={};for(var z in x)x.hasOwnProperty(z)&&(y[z]=x[z]);for(var z in w)w.hasOwnProperty(z)&&(y[z]=w[z]);w=y}}else w=x;if("string"==h.type||"="==h.string){var A,p=b.getRange(c(g.line,Math.max(0,g.ch-60)),c(g.line,"string"==h.type?h.start:h.end)),B=p.match(/([^\s\u00a0=<>\"\']+)=$
 /);if(!B||!w.hasOwnProperty(B[1])||!(A=w[B[1]]))return;if("function"==typeof A&&(A=A.call(this,b)),"string"==h.type){j=h.string;var C=0;/['"]/.test(h.string.charAt(0))&&(f=h.string.charAt(0),j=h.string.slice(1),C++);var D=h.string.length;/['"]/.test(h.string.charAt(D-1))&&(f=h.string.charAt(D-1),j=h.string.substr(C,D-2)),m=!0}for(var u=0;u<A.length;++u)j&&0!=A[u].lastIndexOf(j,0)||l.push(f+A[u]+f)}else{"attribute"==h.type&&(j=h.string,m=!0);for(var E in w)!w.hasOwnProperty(E)||j&&0!=E.lastIndexOf(j,0)||l.push(E)}}return{list:l,from:m?c(g.line,null==k?h.start:k):g,to:m?c(g.line,h.end):g}}}}var c=a.Pos;a.registerHelper("hint","xml",b)})},{"../../lib/codemirror":59}],29:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define([
 "../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";a.registerHelper("lint","css",function(b,c){var d=[];if(!window.CSSLint)return window.console&&window.console.error("Error: window.CSSLint not defined, CodeMirror CSS linting cannot run."),d;for(var e=CSSLint.verify(b,c),f=e.messages,g=null,h=0;h<f.length;h++){g=f[h];var i=g.line-1,j=g.line-1,k=g.col-1,l=g.col;d.push({from:a.Pos(i,k),to:a.Pos(j,l),message:g.message,severity:g.type})}return d})})},{"../../lib/codemirror":59}],30:[function(a,b,c){(function(d){!function(e){"object"==typeof c&&"object"==typeof b?e(a("../../lib/codemirror"),"undefined"!=typeof window?window.HTMLHint:"undefined"!=typeof d?d.HTMLHint:null):"function"==typeof define&&define.amd?define(["../../lib/codemirror","htmlhint"],e):e(CodeMirror,window.HTMLHint)}(function(a,b){"use 
 strict";var c={"tagname-lowercase":!0,"attr-lowercase":!0,"attr-value-double-quotes":!0,"doctype-first":!1,"tag-pair":!0,"spec-char-escape":!0,"id-unique":!0,"src-not-empty":!0,"attr-no-duplication":!0};a.registerHelper("lint","html",function(d,e){var f=[];if(b&&!b.verify&&(b=b.HTMLHint),b||(b=window.HTMLHint),!b)return window.console&&window.console.error("Error: HTMLHint not found, not defined on window, or not available through define/require, CodeMirror HTML linting cannot run."),f;for(var g=b.verify(d,e&&e.rules||c),h=0;h<g.length;h++){var i=g[h],j=i.line-1,k=i.line-1,l=i.col-1,m=i.col;f.push({from:a.Pos(j,l),to:a.Pos(k,m),message:i.message,severity:i.type})}return f})})}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"
 ../../lib/codemirror":59}],31:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(a,b){if(!window.JSHINT)return window.console&&window.console.error("Error: window.JSHINT not defined, CodeMirror JavaScript linting cannot run."),[];JSHINT(a,b,b.globals);var c=JSHINT.data().errors,d=[];return c&&f(c,d),d}function c(a){return d(a,h,"warning",!0),d(a,i,"error"),e(a)?null:a}function d(a,b,c,d){var e,f,g,h,i;e=a.description;for(var j=0;j<b.length;j++)f=b[j],g="string"==typeof f?f:f[0],h="string"==typeof f?null:f[1],i=e.indexOf(g)!==-1,(d||i)&&(a.severity=c),i&&h&&(a.description=h)}function e(a){for(var b=a.description,c=0;c<g.length;c++)if(b.indexO
 f(g[c])!==-1)return!0;return!1}function f(b,d){for(var e=0;e<b.length;e++){var f=b[e];if(f){var g,h;if(g=[],f.evidence){var i=g[f.line];if(!i){var j=f.evidence;i=[],Array.prototype.forEach.call(j,function(a,b){"\t"===a&&i.push(b+1)}),g[f.line]=i}if(i.length>0){var k=f.character;i.forEach(function(a){k>a&&(k-=1)}),f.character=k}}var l=f.character-1,m=l+1;f.evidence&&(h=f.evidence.substring(l).search(/.\b/),h>-1&&(m+=h)),f.description=f.reason,f.start=f.character,f.end=m,f=c(f),f&&d.push({message:f.description,severity:f.severity,from:a.Pos(f.line-1,l),to:a.Pos(f.line-1,m)})}}}var g=["Dangerous comment"],h=[["Expected '{'","Statement body should be inside '{ }' braces."]],i=["Missing semicolon","Extra comma","Missing property name","Unmatched "," and instead saw"," is not defined","Unclosed string","Stopping, unable to c
 ontinue"];a.registerHelper("lint","javascript",b)})},{"../../lib/codemirror":59}],32:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";a.registerHelper("lint","json",function(b){var c=[];if(!window.jsonlint)return window.console&&window.console.error("Error: window.jsonlint not defined, CodeMirror JSON linting cannot run."),c;jsonlint.parseError=function(b,d){var e=d.loc;c.push({from:a.Pos(e.first_line-1,e.first_column),to:a.Pos(e.last_line-1,e.last_column),message:b})};try{jsonlint.parse(b)}catch(d){}return c})})},{"../../lib/codemirror":59}],33:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemir
 ror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(b,c){function d(b){return e.parentNode?(e.style.top=Math.max(0,b.clientY-e.offsetHeight-5)+"px",void(e.style.left=b.clientX+5+"px")):a.off(document,"mousemove",d)}var e=document.createElement("div");return e.className="CodeMirror-lint-tooltip",e.appendChild(c.cloneNode(!0)),document.body.appendChild(e),a.on(document,"mousemove",d),d(b),null!=e.style.opacity&&(e.style.opacity=1),e}function c(a){a.parentNode&&a.parentNode.removeChild(a)}function d(a){a.parentNode&&(null==a.style.opacity&&c(a),a.style.opacity=0,setTimeout(function(){c(a)},600))}function e(c,e,f){function g(){a.off(f,"mouseout",g),h&&(d(h),h=null)}var h=b(c,e),i=setInterval(function(){if(h)for(var a=f;;a=a.parentNode){if(a&&11==a.nod
 eType&&(a=a.host),a==document.body)return;if(!a){g();break}}if(!h)return clearInterval(i)},400);a.on(f,"mouseout",g)}function f(a,b,c){this.marked=[],this.options=b,this.timeout=null,this.hasGutter=c,this.onMouseOver=function(b){r(a,b)},this.waitingFor=0}function g(a,b){return b instanceof Function?{getAnnotations:b}:(b&&b!==!0||(b={}),b)}function h(a){var b=a.state.lint;b.hasGutter&&a.clearGutter(s);for(var c=0;c<b.marked.length;++c)b.marked[c].clear();b.marked.length=0}function i(b,c,d,f){var g=document.createElement("div"),h=g;return g.className="CodeMirror-lint-marker-"+c,d&&(h=g.appendChild(document.createElement("div")),h.className="CodeMirror-lint-marker-multiple"),0!=f&&a.on(h,"mouseover",function(a){e(a,b,h)}),g}function j(a,b){return"error"==a?a:b}function k(a){for(var b=[],c=0;c<a.length;++c){var d=a[c],e=d.from.line;(b[e]||(b[e]=[])).push(d)}return b}functi
 on l(a){var b=a.severity;b||(b="error");var c=document.createElement("div");return c.className="CodeMirror-lint-message-"+b,"undefined"!=typeof a.messageHTML?c.innerHTML=a.messageHTML:c.appendChild(document.createTextNode(a.message)),c}function m(b,c,d){function e(){g=-1,b.off("change",e)}var f=b.state.lint,g=++f.waitingFor;b.on("change",e),c(b.getValue(),function(c,d){b.off("change",e),f.waitingFor==g&&(d&&c instanceof a&&(c=d),o(b,c))},d,b)}function n(b){var c=b.state.lint,d=c.options,e=d.options||d,f=d.getAnnotations||b.getHelper(a.Pos(0,0),"lint");if(f)if(d.async||f.async)m(b,f,e);else{var g=f(b.getValue(),e,b);if(!g)return;g.then?g.then(function(a){o(b,a)}):o(b,g)}}function o(a,b){h(a);for(var c=a.state.lint,d=c.options,e=k(b),f=0;f<e.length;++f){var g=e[f];if(g){for(var m=null,n=c.hasGutter&&document.createDocumentFragment(),o=0;o<g.length;++o){var p=g[o],q=p.s
 everity;q||(q="error"),m=j(m,q),d.formatAnnotation&&(p=d.formatAnnotation(p)),c.hasGutter&&n.appendChild(l(p)),p.to&&c.marked.push(a.markText(p.from,p.to,{className:"CodeMirror-lint-mark-"+q,__annotation:p}))}c.hasGutter&&a.setGutterMarker(f,s,i(n,m,g.length>1,c.options.tooltips))}}d.onUpdateLinting&&d.onUpdateLinting(b,e,a)}function p(a){var b=a.state.lint;b&&(clearTimeout(b.timeout),b.timeout=setTimeout(function(){n(a)},b.options.delay||500))}function q(a,b){for(var c=b.target||b.srcElement,d=document.createDocumentFragment(),f=0;f<a.length;f++){var g=a[f];d.appendChild(l(g))}e(b,d,c)}function r(a,b){var c=b.target||b.srcElement;if(/\bCodeMirror-lint-mark-/.test(c.className)){for(var d=c.getBoundingClientRect(),e=(d.left+d.right)/2,f=(d.top+d.bottom)/2,g=a.findMarksAt(a.coordsChar({left:e,top:f},"client")),h=[],i=0;i<g.length;++i){var j=g[i].__annotation;j&&h.push(j)}h.length&&q(
 h,b)}}var s="CodeMirror-lint-markers";a.defineOption("lint",!1,function(b,c,d){if(d&&d!=a.Init&&(h(b),b.state.lint.options.lintOnChange!==!1&&b.off("change",p),a.off(b.getWrapperElement(),"mouseover",b.state.lint.onMouseOver),clearTimeout(b.state.lint.timeout),delete b.state.lint),c){for(var e=b.getOption("gutters"),i=!1,j=0;j<e.length;++j)e[j]==s&&(i=!0);var k=b.state.lint=new f(b,g(b,c),i);k.options.lintOnChange!==!1&&b.on("change",p),0!=k.options.tooltips&&"gutter"!=k.options.tooltips&&a.on(b.getWrapperElement(),"mouseover",k.onMouseOver),n(b)}}),a.defineExtension("performLint",function(){this.state.lint&&n(this)})})},{"../../lib/codemirror":59}],34:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof defi
 ne&&define.amd?define(["../../lib/codemirror","diff_match_patch"],d):d(CodeMirror)}(function(a){"use strict";function b(a,b){this.mv=a,this.type=b,this.classes="left"==b?{chunk:"CodeMirror-merge-l-chunk",start:"CodeMirror-merge-l-chunk-start",end:"CodeMirror-merge-l-chunk-end",insert:"CodeMirror-merge-l-inserted",del:"CodeMirror-merge-l-deleted",connect:"CodeMirror-merge-l-connect"}:{chunk:"CodeMirror-merge-r-chunk",start:"CodeMirror-merge-r-chunk-start",end:"CodeMirror-merge-r-chunk-end",insert:"CodeMirror-merge-r-inserted",del:"CodeMirror-merge-r-deleted",connect:"CodeMirror-merge-r-connect"}}function c(b){b.diffOutOfDate&&(b.diff=z(b.orig.getValue(),b.edit.getValue(),b.mv.options.ignoreWhitespace),b.chunks=A(b.diff),b.diffOutOfDate=!1,a.signal(b.edit,"updateDiff",b.diff))}function d(b){function d(
 a){W=!0,p=!1,"full"==a&&(b.svg&&J(b.svg),b.copyButtons&&J(b.copyButtons),j(b.edit,m.marked,b.classes),j(b.orig,o.marked,b.classes),m.from=m.to=o.from=o.to=0),c(b),b.showDifferences&&(k(b.edit,b.diff,m,DIFF_INSERT,b.classes),k(b.orig,b.diff,o,DIFF_DELETE,b.classes)),"align"==b.mv.options.connect&&s(b),n(b),null!=b.needsScrollSync&&f(b,b.needsScrollSync),W=!1}function e(a){W||(b.dealigned=!0,g(a))}function g(a){W||p||(clearTimeout(l),a===!0&&(p=!0),l=setTimeout(d,a===!0?20:250))}function h(a,c){b.diffOutOfDate||(b.diffOutOfDate=!0,m.from=m.to=o.from=o.to=0),e(c.text.length-1!=c.to.line-c.from.line)}function i(){b.diffOutOfDate=!0,b.dealigned=!0,d("full")}var l,m={from:0,to:0,marked:[]},o={from:0,to:0,marked:[]},p=!1;return b.edit.on("change",h),b.orig.on("change",h),b.edit.on("swapDoc",i),b.orig.on("swapDoc",i),"align"==b.mv.options.connect&&(
 a.on(b.edit.state.trackAlignable,"realign",e),a.on(b.orig.state.trackAlignable,"realign",e)),b.edit.on("viewportChange",function(){g(!1)}),b.orig.on("viewportChange",function(){g(!1)}),d(),d}function e(a,b){a.edit.on("scroll",function(){f(a,!0)&&n(a)}),a.orig.on("scroll",function(){f(a,!1)&&n(a),b&&f(b,!0)&&n(b)})}function f(a,b){if(a.diffOutOfDate)return a.lockScroll&&null==a.needsScrollSync&&(a.needsScrollSync=b),!1;if(a.needsScrollSync=null,!a.lockScroll)return!0;var c,d,e=+new Date;if(b?(c=a.edit,d=a.orig):(c=a.orig,d=a.edit),c.state.scrollSetBy==a&&(c.state.scrollSetAt||0)+250>e)return!1;var f=c.getScrollInfo();if("align"==a.mv.options.connect)q=f.top;else{var h,i,j=.5*f.clientHeight,k=f.top+j,l=c.lineAtHeight(k,"local"),m=D(a.chunks,l,b),n=g(c,b?m.edit:m.orig),o=g(d,b?m.orig:m.edit),p=(k-n.top)/(n.bot-n.top),q=o.top-j+p*(o.bot-o.top);if(q&g
 t;f.top&&(i=f.top/j)<1)q=q*i+f.top*(1-i);else if((h=f.height-f.clientHeight-f.top)<j){var r=d.getScrollInfo(),s=r.height-r.clientHeight-q;s>h&&(i=h/j)<1&&(q=q*i+(r.height-r.clientHeight-h)*(1-i))}}return d.scrollTo(f.left,q),d.state.scrollSetAt=e,d.state.scrollSetBy=a,!0}function g(a,b){var c=b.after;return null==c&&(c=a.lastLine()+1),{top:a.heightAtLine(b.before||0,"local"),bot:a.heightAtLine(c,"local")}}function h(a,b,c){a.lockScroll=b,b&&0!=c&&f(a,DIFF_INSERT)&&n(a),a.lockButton.innerHTML=b?"\u21db\u21da":"\u21db&nbsp;&nbsp;\u21da"}function i(a,b,c){for(var d=c.classLocation,e=0;e<d.length;e++)a.removeLineClass(b,d[e],c.chunk),a.removeLineClass(b,d[e],c.start),a.removeLineClass(b,d[e],c.end)}function j(b,c,d){for(var e=0;e<c.length;++e){var f=c[e];f instanceof a.TextMarker?f.clear():f.parent&&i(b,f,d)}c.length=0}function k(a,b,c,d,e){var f=a.getViewpor
 t();a.operation(function(){c.from==c.to||f.from-c.to>20||c.from-f.to>20?(j(a,c.marked,e),m(a,b,d,c.marked,f.from,f.to,e),c.from=f.from,c.to=f.to):(f.from<c.from&&(m(a,b,d,c.marked,f.from,c.from,e),c.from=f.from),f.to>c.to&&(m(a,b,d,c.marked,c.to,f.to,e),c.to=f.to))})}function l(a,b,c,d,e,f){for(var g=c.classLocation,h=a.getLineHandle(b),i=0;i<g.length;i++)d&&a.addLineClass(h,g[i],c.chunk),e&&a.addLineClass(h,g[i],c.start),f&&a.addLineClass(h,g[i],c.end);return h}function m(a,b,c,d,e,f,g){function h(b,c){for(var h=Math.max(e,b),i=Math.min(f,c),j=h;j<i;++j)d.push(l(a,j,g,!0,j==b,j==c-1));b==c&&h==c&&i==c&&(h?d.push(l(a,h-1,g,!1,!1,!0)):d.push(l(a,h,g,!1,!0,!1)))}for(var i=U(0,0),j=U(e,0),k=a.clipPos(U(f-1)),m=c==DIFF_DELETE?g.del:g.insert,n=0,o=!1,p=0;p<b.length;++p){var q=b[p],r=q[0],s=q[1];if(r==DIFF_EQUAL){var t=i.line+(C(b,p)?0:1);M(i,s);var u=i.line+(B(b,p)?1:0);u>t&&(o&&(h(n,t
 ),o=!1),n=u)}else if(o=!0,r==c){var v=M(i,s,!0),w=P(j,i),x=O(k,v);Q(w,x)||d.push(a.markText(w,x,{className:m})),i=v}}o&&h(n,i.line+1)}function n(a){if(a.showDifferences){if(a.svg){J(a.svg);var b=a.gap.offsetWidth;K(a.svg,"width",b,"height",a.gap.offsetHeight)}a.copyButtons&&J(a.copyButtons);for(var c=a.edit.getViewport(),d=a.orig.getViewport(),e=a.mv.wrap.getBoundingClientRect().top,f=e-a.edit.getScrollerElement().getBoundingClientRect().top+a.edit.getScrollInfo().top,g=e-a.orig.getScrollerElement().getBoundingClientRect().top+a.orig.getScrollInfo().top,h=0;h<a.chunks.length;h++){var i=a.chunks[h];i.editFrom<=c.to&&i.editTo>=c.from&&i.origFrom<=d.to&&i.origTo>=d.from&&v(a,i,g,f,b)}}}function o(a,b){for(var c=0,d=0,e=0;e<b.length;e++){var f=b[e];if(f.editTo>a&&f.editFrom<=a)return null;if(f.editFrom>a)break;c=f.editTo,d=f.origTo}return d+(a-c)}function p(a,b,c){for(var d=a.state.tra
 ckAlignable,e=a.firstLine(),f=0,g=[],h=0;;h++){for(var i=b[h],j=i?c?i.origFrom:i.editFrom:1e9;f<d.alignable.length;f+=2){var k=d.alignable[f]+1;if(!(k<=e)){if(!(k<=j))break;g.push(k)}}if(!i)break;g.push(e=c?i.origTo:i.editTo)}return g}function q(a,b,c,d){var e=0,f=0,g=0,h=0;a:for(;;e++){var i=a[e],j=b[f];if(!i&&null==j)break;for(var k=i?i[0]:1e9,l=null==j?1e9:j;g<c.length;){var m=c[g];if(m.origFrom<=l&&m.origTo>l){f++,e--;continue a}if(m.editTo>k){if(m.editFrom<=k)continue a;break}h+=m.origTo-m.origFrom-(m.editTo-m.editFrom),g++}if(k==l-h)i[d]=l,f++;else if(k<l-h)i[d]=k+h;else{var n=[l-h,null,null];n[d]=l,a.splice(e,0,n),f++}}}function r(a,b){var c=p(a.edit,a.chunks,!1),d=[];if(b)for(var e=0,f=0;e<b.chunks.length;e++){for(var g=b.chunks[e].editTo;f<c.length&&c[f]<g;)f++;f!=c.length&&c[f]==g||c.splice(f++,0,g)}for(var e=0;e<c.length;e++)d.push([c[e],null,null]);return q(d,p(a.orig,a.chunks,!0),a.chunks,1),b&&a
 mp;q(d,p(b.orig,b.chunks,!0),b.chunks,2),d}function s(a,b){if(a.dealigned||b){if(!a.orig.curOp)return a.orig.operation(function(){s(a,b)});a.dealigned=!1;var d=a.mv.left==a?a.mv.right:a.mv.left;d&&(c(d),d.dealigned=!1);for(var e=r(a,d),f=a.mv.aligners,g=0;g<f.length;g++)f[g].clear();f.length=0;var h=[a.edit,a.orig],i=[];d&&h.push(d.orig);for(var g=0;g<h.length;g++)i.push(h[g].getScrollInfo().top);for(var j=0;j<e.length;j++)t(h,e[j],f);for(var g=0;g<h.length;g++)h[g].scrollTo(null,i[g])}}function t(a,b,c){for(var d=0,e=[],f=0;f<a.length;f++)if(null!=b[f]){var g=a[f].heightAtLine(b[f],"local");e[f]=g,d=Math.max(d,g)}for(var f=0;f<a.length;f++)if(null!=b[f]){var h=d-e[f];h>1&&c.push(u(a[f],b[f],h))}}function u(a,b,c){var d=!0;b>a.lastLine()&&(b--,d=!1);var e=document.createElement("div");return e.className="CodeMirror-merge-spacer",e.style.height=c+"px",e.style.minWidth="1px",a.add
 LineWidget(b,e,{height:c,above:d,mergeSpacer:!0,handleMouseEvents:!0})}function v(a,b,c,d,e){var f="left"==a.type,g=a.orig.heightAtLine(b.origFrom,"local",!0)-c;if(a.svg){var h=g,i=a.edit.heightAtLine(b.editFrom,"local",!0)-d;if(f){var j=h;h=i,i=j}var k=a.orig.heightAtLine(b.origTo,"local",!0)-c,l=a.edit.heightAtLine(b.editTo,"local",!0)-d;if(f){var j=k;k=l,l=j}var m=" C "+e/2+" "+i+" "+e/2+" "+h+" "+(e+2)+" "+h,n=" C "+e/2+" "+k+" "+e/2+" "+l+" -1 "+l;K(a.svg.appendChild(document.createElementNS(V,"path")),"d","M -1 "+i+m+" L "+(e+2)+" "+k+n+" z","class",a.classes.connect)}if(a.copyButtons){var o=a.copyButtons.appendChild(I("div","left"==a.type?"\u21dd":"\u21dc","CodeMirror-merge-copy")),p=a.mv.options.allo
 wEditingOriginals;if(o.title=p?"Push to left":"Revert chunk",o.chunk=b,o.style.top=(b.origTo>b.origFrom?g:a.edit.heightAtLine(b.editFrom,"local")-d)+"px",p){var q=a.edit.heightAtLine(b.editFrom,"local")-d,r=a.copyButtons.appendChild(I("div","right"==a.type?"\u21dd":"\u21dc","CodeMirror-merge-copy-reverse"));r.title="Push to right",r.chunk={editFrom:b.origFrom,editTo:b.origTo,origFrom:b.editFrom,origTo:b.editTo},r.style.top=q+"px","right"==a.type?r.style.left="2px":r.style.right="2px"}}}function w(a,b,c,d){if(!a.diffOutOfDate){var e=d.origTo>c.lastLine()?U(d.origFrom-1):U(d.origFrom,0),f=U(d.origTo,0),g=d.editTo>b.lastLine()?U(d.editFrom-1):U(d.editFrom,0),h=U(d.editTo,0),i=a.mv.options.revertChunk;i?i(a.mv,c,e,f,b,g,h):b.replaceRange(c.getRange(e,f),g,h)}}function x(b){var c=b.lockButton=I("div",null,"CodeMirror
 -merge-scrolllock");c.title="Toggle locked scrolling";var d=I("div",[c],"CodeMirror-merge-scrolllock-wrap");a.on(c,"click",function(){h(b,!b.lockScroll)});var e=[d];if(b.mv.options.revertButtons!==!1&&(b.copyButtons=I("div",null,"CodeMirror-merge-copybuttons-"+b.type),a.on(b.copyButtons,"click",function(a){var c=a.target||a.srcElement;if(c.chunk)return"CodeMirror-merge-copy-reverse"==c.className?void w(b,b.orig,b.edit,c.chunk):void w(b,b.edit,b.orig,c.chunk)}),e.unshift(b.copyButtons)),"align"!=b.mv.options.connect){var f=document.createElementNS&&document.createElementNS(V,"svg");f&&!f.createSVGRect&&(f=null),b.svg=f,f&&e.push(f)}return b.gap=I("div",e,"CodeMirror-merge-gap")}function y(a){return"string"==typeof a?a:a.getValue()}function z(a,b,c){Y||(Y=new diff_match_patch);for(var d=Y.diff_main(a,b),e=0;e<
 d.length;++e){var f=d[e];(c?/[^ \t]/.test(f[1]):f[1])?e&&d[e-1][0]==f[0]&&(d.splice(e--,1),d[e][1]+=f[1]):d.splice(e--,1)}return d}function A(a){for(var b=[],c=0,d=0,e=U(0,0),f=U(0,0),g=0;g<a.length;++g){var h=a[g],i=h[0];if(i==DIFF_EQUAL){var j=!C(a,g)||e.line<c||f.line<d?1:0,k=e.line+j,l=f.line+j;M(e,h[1],null,f);var m=B(a,g)?1:0,n=e.line+m,o=f.line+m;n>k&&(g&&b.push({origFrom:d,origTo:l,editFrom:c,editTo:k}),c=n,d=o)}else M(i==DIFF_INSERT?e:f,h[1])}return(c<=e.line||d<=f.line)&&b.push({origFrom:d,origTo:f.line+1,editFrom:c,editTo:e.line+1}),b}function B(a,b){if(b==a.length-1)return!0;var c=a[b+1][1];return!(1==c.length&&b<a.length-2||10!=c.charCodeAt(0))&&(b==a.length-2||(c=a[b+2][1],(c.length>1||b==a.length-3)&&10==c.charCodeAt(0)))}function C(a,b){if(0==b)return!0;var c=a[b-1][1];return 10==c.charCodeAt(c.length-1)&&(1==b||(c=a[b-2][1],10==c.charCodeAt(c.length-1)))}function D(a,b,c)
 {for(var d,e,f,g,h=0;h<a.length;h++){var i=a[h],j=c?i.editFrom:i.origFrom,k=c?i.editTo:i.origTo;null==e&&(j>b?(e=i.editFrom,g=i.origFrom):k>b&&(e=i.editTo,g=i.origTo)),k<=b?(d=i.editTo,f=i.origTo):j<=b&&(d=i.editFrom,f=i.origFrom)}return{edit:{before:d,after:e},orig:{before:f,after:g}}}function E(b,c,d){function e(){g.clear(),b.removeLineClass(c,"wrap","CodeMirror-merge-collapsed-line")}b.addLineClass(c,"wrap","CodeMirror-merge-collapsed-line");var f=document.createElement("span");f.className="CodeMirror-merge-collapsed-widget",f.title="Identical text collapsed. Click to expand.";var g=b.markText(U(c,0),U(d-1),{inclusiveLeft:!0,inclusiveRight:!0,replacedWith:f,clearOnEnter:!0});return a.on(f,"click",e),{mark:g,clear:e}}function F(a,b){function c(){for(var a=0;a<d.length;a++)d[a].clear()}for(var d=[],e=0;e<b.length;e++){var f=b[e],g=E(f.cm,f.line,f.line+a);d.pu
 sh(g),g.mark.on("clear",c)}return d[0].mark}function G(a,b,c,d){for(var e=0;e<a.chunks.length;e++)for(var f=a.chunks[e],g=f.editFrom-b;g<f.editTo+b;g++){var h=g+c;h>=0&&h<d.length&&(d[h]=!1)}}function H(a,b){"number"!=typeof b&&(b=2);for(var c=[],d=a.editor(),e=d.firstLine(),f=e,g=d.lastLine();f<=g;f++)c.push(!0);a.left&&G(a.left,b,e,c),a.right&&G(a.right,b,e,c);for(var h=0;h<c.length;h++)if(c[h]){for(var i=h+e,j=1;h<c.length-1&&c[h+1];h++,j++);if(j>b){var k=[{line:i,cm:d}];a.left&&k.push({line:o(i,a.left.chunks),cm:a.left.orig}),a.right&&k.push({line:o(i,a.right.chunks),cm:a.right.orig});var l=F(j,k);a.options.onCollapse&&a.options.onCollapse(a,i,j,l)}}}function I(a,b,c,d){var e=document.createElement(a);if(c&&(e.className=c),d&&(e.style.cssText=d),"string"==typeof b)e.appendChild(document.createTextNode(b));else if(b)for(var f=0;f<b.lengt
 h;++f)e.appendChild(b[f]);return e}function J(a){for(var b=a.childNodes.length;b>0;--b)a.removeChild(a.firstChild)}function K(a){for(var b=1;b<arguments.length;b+=2)a.setAttribute(arguments[b],arguments[b+1])}function L(a,b){b||(b={});for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b}function M(a,b,c,d){for(var e=c?U(a.line,a.ch):a,f=0;;){var g=b.indexOf("\n",f);if(g==-1)break;++e.line,d&&++d.line,f=g+1}return e.ch=(f?0:e.ch)+(b.length-f),d&&(d.ch=(f?0:d.ch)+(b.length-f)),e}function N(a){this.cm=a,this.alignable=[],this.height=a.doc.height;var b=this;a.on("markerAdded",function(a,c){if(c.collapsed){var d=c.find(1);null!=d&&b.set(d.line,_)}}),a.on("markerCleared",function(a,c,d,e){null!=e&&c.collapsed&&b.check(e,_,b.hasMarker)}),a.on("markerChanged",this.signal.bind(this)),a.on("lineWidgetAdded",function(a,c,d){c.mergeSpacer||(c.above?b.set(d-1,$):b.set(d,Z))}),a.on("li
 neWidgetCleared",function(a,c,d){c.mergeSpacer||(c.above?b.check(d-1,$,b.hasWidgetBelow):b.check(d,Z,b.hasWidget))}),a.on("lineWidgetChanged",this.signal.bind(this)),a.on("change",function(a,c){var d=c.from.line,e=c.to.line-c.from.line,f=c.text.length-1,g=d+f;(e||f)&&b.map(d,e,f),b.check(g,_,b.hasMarker),(e||f)&&b.check(c.from.line,_,b.hasMarker)}),a.on("viewportChange",function(){b.cm.doc.height!=b.height&&b.signal()})}function O(a,b){return(a.line-b.line||a.ch-b.ch)<0?a:b}function P(a,b){return(a.line-b.line||a.ch-b.ch)>0?a:b}function Q(a,b){return a.line==b.line&&a.ch==b.ch}function R(a,b,c){for(var d=a.length-1;d>=0;d--){var e=a[d],f=(c?e.origTo:e.editTo)-1;if(f<b)return f}}function S(a,b,c){for(var d=0;d<a.length;d++){var e=a[d],f=c?e.origFrom:e.editFrom;if(f>b)return f}}function T(b,d){var e=null,f=b.state.diffViews,g=b.getCursor().line;if(f)for(var h=0;h<f.length;h++){var i=f[h],j=b==i.ori
 g;c(i);var k=d<0?R(i.chunks,g,j):S(i.chunks,g,j);null==k||null!=e&&!(d<0?k>e:k<e)||(e=k)}return null==e?a.Pass:void b.setCursor(e,0)}var U=a.Pos,V="http://www.w3.org/2000/svg";b.prototype={constructor:b,init:function(b,c,d){this.edit=this.mv.edit,(this.edit.state.diffViews||(this.edit.state.diffViews=[])).push(this),this.orig=a(b,L({value:c,readOnly:!this.mv.options.allowEditingOriginals},L(d))),"align"==this.mv.options.connect&&(this.edit.state.trackAlignable||(this.edit.state.trackAlignable=new N(this.edit)),this.orig.state.trackAlignable=new N(this.orig)),this.orig.state.diffViews=[this];var e=d.chunkClassLocation||"background";"[object Array]"!=Object.prototype.toString.call(e)&&(e=[e]),this.classes.classLocation=e,this.diff=z(y(c),y(d.value),this.mv.options.ignoreWhitespace),this.chunks=A(this.diff),this.diffOutOfDate=this.dealigned=!1,this.needsScrollSync=null,this.showDifferences=d.showDifferences!==!
 1},registerEvents:function(a){this.forceUpdate=d(this),h(this,!0,!1),e(this,a)},setShowDifferences:function(a){a=a!==!1,a!=this.showDifferences&&(this.showDifferences=a,this.forceUpdate("full"))}};var W=!1,X=a.MergeView=function(c,d){if(!(this instanceof X))return new X(c,d);this.options=d;var e=d.origLeft,f=null==d.origRight?d.orig:d.origRight,g=null!=e,h=null!=f,i=1+(g?1:0)+(h?1:0),j=[],k=this.left=null,l=this.right=null,m=this;if(g){k=this.left=new b(this,"left");var o=I("div",null,"CodeMirror-merge-pane CodeMirror-merge-left");j.push(o),j.push(x(k))}var p=I("div",null,"CodeMirror-merge-pane CodeMirror-merge-editor");if(j.push(p),h){l=this.right=new b(this,"right"),j.push(x(l));var q=I("div",null,"CodeMirror-merge-pane CodeMirror-merge-right");j.push(q)}(h?q:p).className+=" CodeMirror-merge-pane-rightmost",j.push(I("div",null,null,"height: 0; clear: both;&quo
 t;));var r=this.wrap=c.appendChild(I("div",j,"CodeMirror-merge CodeMirror-merge-"+i+"pane"));this.edit=a(p,L(d)),k&&k.init(o,e,d),l&&l.init(q,f,d),d.collapseIdentical&&this.editor().operation(function(){H(m,d.collapseIdentical)}),"align"==d.connect&&(this.aligners=[],s(this.left||this.right,!0)),k&&k.registerEvents(l),l&&l.registerEvents(k);var t=function(){k&&n(k),l&&n(l)};a.on(window,"resize",t);var u=setInterval(function(){for(var b=r.parentNode;b&&b!=document.body;b=b.parentNode);b||(clearInterval(u),a.off(window,"resize",t))},5e3)};X.prototype={constructor:X,editor:function(){return this.edit},rightOriginal:function(){return this.right&&this.right.orig},leftOriginal:function(){return this.left&&this.left.orig},setShowDifferences:function(a){this.right&&this.right.setShowDifferences(a),this.left&&this.left.setShowDiff
 erences(a)},rightChunks:function(){if(this.right)return c(this.right),this.right.chunks},leftChunks:function(){if(this.left)return c(this.left),this.left.chunks}};var Y,Z=1,$=2,_=4;N.prototype={signal:function(){a.signal(this,"realign"),this.height=this.cm.doc.height},set:function(a,b){for(var c=-1;c<this.alignable.length;c+=2){var d=this.alignable[c]-a;if(0==d){if((this.alignable[c+1]&b)==b)return;return this.alignable[c+1]|=b,void this.signal()}if(d>0)break}this.signal(),this.alignable.splice(c,0,a,b)},find:function(a){for(var b=0;b<this.alignable.length;b+=2)if(this.alignable[b]==a)return b;return-1},check:function(a,b,c){var d=this.find(a);if(d!=-1&&this.alignable[d+1]&b&&!c.call(this,a)){this.signal();var e=this.alignable[d+1]&~b;e?this.alignable[d+1]=e:this.alignable.splice(d,2)}},hasMarker:function(a){var b=this.cm.getLineHandle(a);if(b.markedSpans)for(var c=0;c<b.markedSpans.length;c++)if(b.markedSpans[c].mark.collapsed&&
 amp;null!=b.markedSpans[c].to)return!0;return!1},hasWidget:function(a){var b=this.cm.getLineHandle(a);if(b.widgets)for(var c=0;c<b.widgets.length;c++)if(!b.widgets[c].above&&!b.widgets[c].mergeSpacer)return!0;return!1},hasWidgetBelow:function(a){if(a==this.cm.lastLine())return!1;var b=this.cm.getLineHandle(a+1);if(b.widgets)for(var c=0;c<b.widgets.length;c++)if(b.widgets[c].above&&!b.widgets[c].mergeSpacer)return!0;return!1},map:function(a,b,c){for(var d=c-b,e=a+b,f=-1,g=-1,h=0;h<this.alignable.length;h+=2){var i=this.alignable[h];i==a&&this.alignable[h+1]&$&&(f=h),i==e&&this.alignable[h+1]&$&&(g=h),i<=a||(i<e?this.alignable.splice(h--,2):this.alignable[h]+=d)}if(f>-1){var j=this.alignable[f+1];j==$?this.alignable.splice(f,2):this.alignable[f+1]=j&~$}g>-1&&c&&this.set(a+c,$)}},a.commands.goNextDiff=function(a){return T(a,1)},a.commands.goPrevDiff=function(a){return T(a,-1)}})},{"../
 ../lib/codemirror":59}],35:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror"),"cjs"):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],function(a){d(a,"amd")}):d(CodeMirror,"plain")}(function(b,c){function d(a,b){var c=b;return function(){0==--c&&a()}}function e(a,c){var e=b.modes[a].dependencies;if(!e)return c();for(var f=[],g=0;g<e.length;++g)b.modes.hasOwnProperty(e[g])||f.push(e[g]);if(!f.length)return c();for(var h=d(c,f.length),g=0;g<f.length;++g)b.requireMode(f[g],h)}b.modeURL||(b.modeURL="../mode/%N/%N.js");var f={};b.requireMode=function(d,g){if("string"!=typeof d&&(d=d.name),b.modes.hasOwnProperty(d))return e(d,g);if(f.hasOwnProperty(d))return f[d].push(g);var h=b.modeURL.replace(/%N/g,d);if("plain"==c){var i=document.createElement("script");i.src=
 h;var j=document.getElementsByTagName("script")[0],k=f[d]=[g];b.on(i,"load",function(){e(d,function(){for(var a=0;a<k.length;++a)k[a]()})}),j.parentNode.insertBefore(i,j)}else"cjs"==c?(a(h),g()):"amd"==c&&requirejs([h],g)},b.autoLoadMode=function(a,c){b.modes.hasOwnProperty(c)||b.requireMode(c,function(){a.setOption("mode",a.getOption("mode"))})}})},{"../../lib/codemirror":59}],36:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";a.multiplexingMode=function(b){
+function c(a,b,c,d){if("string"==typeof b){var e=a.indexOf(b,c);return d&&e>-1?e+b.length:e}var f=b.exec(c?a.slice(c):a);return f?f.index+c+(d?f[0].length:0):-1}var d=Array.prototype.slice.call(arguments,1);return{startState:function(){return{outer:a.startState(b),innerActive:null,inner:null}},copyState:function(c){return{outer:a.copyState(b,c.outer),innerActive:c.innerActive,inner:c.innerActive&&a.copyState(c.innerActive.mode,c.inner)}},token:function(e,f){if(f.innerActive){var g=f.innerActive,h=e.string;if(!g.close&&e.sol())return f.innerActive=f.inner=null,this.token(e,f);var i=g.close?c(h,g.close,e.pos,g.parseDelimiters):-1;if(i==e.pos&&!g.parseDelimiters)return e.match(g.close),f.innerActive=f.inner=null,g.delimStyle&&g.delimStyle+" "+g.delimStyle+"-close";i>-1&&(e.string=h.slice(0,i));var j=g.mode.token(e,f.inner);return i>-1&&(e.string=h),i==e.pos&&g.parseDelimiters&&amp
 ;(f.innerActive=f.inner=null),g.innerStyle&&(j=j?j+" "+g.innerStyle:g.innerStyle),j}for(var k=1/0,h=e.string,l=0;l<d.length;++l){var m=d[l],i=c(h,m.open,e.pos);if(i==e.pos)return m.parseDelimiters||e.match(m.open),f.innerActive=m,f.inner=a.startState(m.mode,b.indent?b.indent(f.outer,""):0),m.delimStyle&&m.delimStyle+" "+m.delimStyle+"-open";i!=-1&&i<k&&(k=i)}k!=1/0&&(e.string=h.slice(0,k));var n=b.token(e,f.outer);return k!=1/0&&(e.string=h),n},indent:function(c,d){var e=c.innerActive?c.innerActive.mode:b;return e.indent?e.indent(c.innerActive?c.inner:c.outer,d):a.Pass},blankLine:function(c){var e=c.innerActive?c.innerActive.mode:b;if(e.blankLine&&e.blankLine(c.innerActive?c.inner:c.outer),c.innerActive)"\n"===c.innerActive.close&&(c.innerActive=c.inner=null);else for(var f=0;f<d.length;++f){var g=d[f];"\n"===g.open&&(c.innerActive=g,c.inner=a.
 startState(g.mode,e.indent?e.indent(c.outer,""):0))}},electricChars:b.electricChars,innerMode:function(a){return a.inner?{state:a.inner,mode:a.innerActive.mode}:{state:a.outer,mode:b}}}}})},{"../../lib/codemirror":59}],37:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";a.overlayMode=function(b,c,d){return{startState:function(){return{base:a.startState(b),overlay:a.startState(c),basePos:0,baseCur:null,overlayPos:0,overlayCur:null,streamSeen:null}},copyState:function(d){return{base:a.copyState(b,d.base),overlay:a.copyState(c,d.overlay),basePos:d.basePos,baseCur:null,overlayPos:d.overlayPos,overlayCur:null}},token:function(a,e){return(a!=e.streamSeen||Math.min(e.basePos,e.overlayPos)<a.start)&&(e.streamSeen=a,e.basePos=e
 .overlayPos=a.start),a.start==e.basePos&&(e.baseCur=b.token(a,e.base),e.basePos=a.pos),a.start==e.overlayPos&&(a.pos=a.start,e.overlayCur=c.token(a,e.overlay),e.overlayPos=a.pos),a.pos=Math.min(e.basePos,e.overlayPos),null==e.overlayCur?e.baseCur:null!=e.baseCur&&e.overlay.combineTokens||d&&null==e.overlay.combineTokens?e.baseCur+" "+e.overlayCur:e.overlayCur},indent:b.indent&&function(a,c){return b.indent(a.base,c)},electricChars:b.electricChars,innerMode:function(a){return{state:a.base,mode:b}},blankLine:function(a){var e,f;return b.blankLine&&(e=b.blankLine(a.base)),c.blankLine&&(f=c.blankLine(a.overlay)),null==f?e:d&&null!=e?e+" "+f:f}}}})},{"../../lib/codemirror":59}],38:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/co
 demirror"],d):d(CodeMirror)}(function(a){"use strict";function b(a,b){if(!a.hasOwnProperty(b))throw new Error("Undefined state "+b+" in simple mode")}function c(a,b){if(!a)return/(?:)/;var c="";return a instanceof RegExp?(a.ignoreCase&&(c="i"),a=a.source):a=String(a),new RegExp((b===!1?"":"^")+"(?:"+a+")",c)}function d(a){if(!a)return null;if(a.apply)return a;if("string"==typeof a)return a.replace(/\./g," ");for(var b=[],c=0;c<a.length;c++)b.push(a[c]&&a[c].replace(/\./g," "));return b}function e(a,e){(a.next||a.push)&&b(e,a.next||a.push),this.regex=c(a.regex),this.token=d(a.token),this.data=a}function f(a,b){return function(c,d){if(d.pending){var e=d.pending.shift();return 0==d.pending.length&&(d.pending=null),c.pos+=e.text.length,e.token}if(d.local){if(d.local.end&&c.match(d.local.end)){var f=d.local.endToken||null;
 return d.local=d.localState=null,f}var g,f=d.local.mode.token(c,d.localState);return d.local.endScan&&(g=d.local.endScan.exec(c.current()))&&(c.pos=c.start+g.index),f}for(var i=a[d.state],j=0;j<i.length;j++){var k=i[j],l=(!k.data.sol||c.sol())&&c.match(k.regex);if(l){k.data.next?d.state=k.data.next:k.data.push?((d.stack||(d.stack=[])).push(d.state),d.state=k.data.push):k.data.pop&&d.stack&&d.stack.length&&(d.state=d.stack.pop()),k.data.mode&&h(b,d,k.data.mode,k.token),k.data.indent&&d.indent.push(c.indentation()+b.indentUnit),k.data.dedent&&d.indent.pop();var m=k.token;if(m&&m.apply&&(m=m(l)),l.length>2){d.pending=[];for(var n=2;n<l.length;n++)l[n]&&d.pending.push({text:l[n],token:k.token[n-1]});return c.backUp(l[0].length-(l[1]?l[1].length:0)),m[0]}return m&&m.join?m[0]:m}}return c.next(),null}}function g(a,b){if(a===b)return!0;if(!a||"object"!=typeof a||!b||&q
 uot;object"!=typeof b)return!1;var c=0;for(var d in a)if(a.hasOwnProperty(d)){if(!b.hasOwnProperty(d)||!g(a[d],b[d]))return!1;c++}for(var d in b)b.hasOwnProperty(d)&&c--;return 0==c}function h(b,d,e,f){var h;if(e.persistent)for(var i=d.persistentStates;i&&!h;i=i.next)(e.spec?g(e.spec,i.spec):e.mode==i.mode)&&(h=i);var j=h?h.mode:e.mode||a.getMode(b,e.spec),k=h?h.state:a.startState(j);e.persistent&&!h&&(d.persistentStates={mode:j,spec:e.spec,state:k,next:d.persistentStates}),d.localState=k,d.local={mode:j,end:e.end&&c(e.end),endScan:e.end&&e.forceEnd!==!1&&c(e.end,!1),endToken:f&&f.join?f[f.length-1]:f}}function i(a,b){for(var c=0;c<b.length;c++)if(b[c]===a)return!0}function j(b,c){return function(d,e,f){if(d.local&&d.local.mode.indent)return d.local.mode.indent(d.localState,e,f);if(null==d.indent||d.local||c.dontIndentStates&&i(d.state,c.dontIndentStates)>-1)return a.Pass;var g=d.inden
 t.length-1,h=b[d.state];a:for(;;){for(var j=0;j<h.length;j++){var k=h[j];if(k.data.dedent&&k.data.dedentIfLineStart!==!1){var l=k.regex.exec(e);if(l&&l[0]){g--,(k.next||k.push)&&(h=b[k.next||k.push]),e=e.slice(l[0].length);continue a}}}break}return g<0?0:d.indent[g]}}a.defineSimpleMode=function(b,c){a.defineMode(b,function(b){return a.simpleMode(b,c)})},a.simpleMode=function(c,d){b(d,"start");var g={},h=d.meta||{},i=!1;for(var k in d)if(k!=h&&d.hasOwnProperty(k))for(var l=g[k]=[],m=d[k],n=0;n<m.length;n++){var o=m[n];l.push(new e(o,d)),(o.indent||o.dedent)&&(i=!0)}var p={startState:function(){return{state:"start",pending:null,local:null,localState:null,indent:i?[]:null}},copyState:function(b){var c={state:b.state,pending:b.pending,local:b.local,localState:null,indent:b.indent&&b.indent.slice(0)};b.localState&&(c.localState=a.copyState(b.local.mode,b.localState)),b.stack&&(c.stack=b.stack.sli
 ce(0));for(var d=b.persistentStates;d;d=d.next)c.persistentStates={mode:d.mode,spec:d.spec,state:d.state==b.localState?c.localState:a.copyState(d.mode,d.state),next:c.persistentStates};return c},token:f(g,c),innerMode:function(a){return a.local&&{mode:a.local.mode,state:a.localState}},indent:j(g,h)};if(h)for(var q in h)h.hasOwnProperty(q)&&(p[q]=h[q]);return p}})},{"../../lib/codemirror":59}],39:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror"),a("./runmode")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","./runmode"],d):d(CodeMirror)}(function(a){"use strict";function b(a,d){if(3==a.nodeType)return d.push(a.nodeValue);for(var e=a.firstChild;e;e=e.nextSibling)b(e,d),c.test(a.nodeType)&&d.push("\n")}var c=/^(p|li|div|h\\d|pre|blockquote|td)$/;a.colorize=function(c,d){c||(c=docu
 ment.body.getElementsByTagName("pre"));for(var e=0;e<c.length;++e){var f=c[e],g=f.getAttribute("data-lang")||d;if(g){var h=[];b(f,h),f.innerHTML="",a.runMode(h.join(""),g,f),f.className+=" cm-s-default"}}}})},{"../../lib/codemirror":59,"./runmode":41}],40:[function(a,b,c){window.CodeMirror={},function(){"use strict";function a(a){return a.split(/\r?\n|\r/)}function b(a){this.pos=this.start=0,this.string=a,this.lineStart=0}b.prototype={eol:function(){return this.pos>=this.string.length},sol:function(){return 0==this.pos},peek:function(){return this.string.charAt(this.pos)||null},next:function(){if(this.pos<this.string.length)return this.string.charAt(this.pos++)},eat:function(a){var b=this.string.charAt(this.pos);if("string"==typeof a)var c=b==a;else var c=b&&(a.test?a.test(b):a(b));if(c)return++this.pos,b},eatWhile:function(a){for(var b=this.pos;this.eat(a););return this.pos&gt
 ;b},eatSpace:function(){for(var a=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>a},skipToEnd:function(){this.pos=this.string.length},skipTo:function(a){var b=this.string.indexOf(a,this.pos);if(b>-1)return this.pos=b,!0},backUp:function(a){this.pos-=a},column:function(){return this.start-this.lineStart},indentation:function(){return 0},match:function(a,b,c){if("string"!=typeof a){var d=this.string.slice(this.pos).match(a);return d&&d.index>0?null:(d&&b!==!1&&(this.pos+=d[0].length),d)}var e=function(a){return c?a.toLowerCase():a},f=this.string.substr(this.pos,a.length);if(e(f)==e(a))return b!==!1&&(this.pos+=a.length),!0},current:function(){return this.string.slice(this.start,this.pos)},hideFirstChars:function(a,b){this.lineStart+=a;try{return b()}finally{this.lineStart-=a}},lookAhead:function(){return null}},CodeMirror.StringStream=b,CodeMirror.startState=function(a,b,c){return!a.startState||a.
 startState(b,c)};var c=CodeMirror.modes={},d=CodeMirror.mimeModes={};CodeMirror.defineMode=function(a,b){arguments.length>2&&(b.dependencies=Array.prototype.slice.call(arguments,2)),c[a]=b},CodeMirror.defineMIME=function(a,b){d[a]=b},CodeMirror.resolveMode=function(a){return"string"==typeof a&&d.hasOwnProperty(a)?a=d[a]:a&&"string"==typeof a.name&&d.hasOwnProperty(a.name)&&(a=d[a.name]),"string"==typeof a?{name:a}:a||{name:"null"}},CodeMirror.getMode=function(a,b){b=CodeMirror.resolveMode(b);var d=c[b.name];if(!d)throw new Error("Unknown mode: "+b);return d(a,b)},CodeMirror.registerHelper=CodeMirror.registerGlobalHelper=Math.min,CodeMirror.defineMode("null",function(){return{token:function(a){a.skipToEnd()}}}),CodeMirror.defineMIME("text/plain","null"),CodeMirror.runMode=function(b,c,d,e){var f=CodeMirror.getMode({indentUnit:2},c);if(1==d.nodeType){var g=e&&
 amp;e.tabSize||4,h=d,i=0;h.innerHTML="",d=function(a,b){if("\n"==a)return h.appendChild(document.createElement("br")),void(i=0);for(var c="",d=0;;){var e=a.indexOf("\t",d);if(e==-1){c+=a.slice(d),i+=a.length-d;break}i+=e-d,c+=a.slice(d,e);var f=g-i%g;i+=f;for(var j=0;j<f;++j)c+=" ";d=e+1}if(b){var k=h.appendChild(document.createElement("span"));k.className="cm-"+b.replace(/ +/g," cm-"),k.appendChild(document.createTextNode(c))}else h.appendChild(document.createTextNode(c))}}for(var j=a(b),k=e&&e.state||CodeMirror.startState(f),l=0,m=j.length;l<m;++l){l&&d("\n");var n=new CodeMirror.StringStream(j[l]);for(!n.string&&f.blankLine&&f.blankLine(k);!n.eol();){var o=f.token(n,k);d(n.current(),o,l,n.start,k),n.start=n.pos}}}}()},{}],41:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/code
 mirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";a.runMode=function(b,c,d,e){var f=a.getMode(a.defaults,c),g=/MSIE \d/.test(navigator.userAgent),h=g&&(null==document.documentMode||document.documentMode<9);if(d.appendChild){var i=e&&e.tabSize||a.defaults.tabSize,j=d,k=0;j.innerHTML="",d=function(a,b){if("\n"==a)return j.appendChild(document.createTextNode(h?"\r":a)),void(k=0);for(var c="",d=0;;){var e=a.indexOf("\t",d);if(e==-1){c+=a.slice(d),k+=a.length-d;break}k+=e-d,c+=a.slice(d,e);var f=i-k%i;k+=f;for(var g=0;g<f;++g)c+=" ";d=e+1}if(b){var l=j.appendChild(document.createElement("span"));l.className="cm-"+b.replace(/ +/g," cm-"),l.appendChild(document.createTextNode(c))}else j.appendChild(document.createTextNode(c))}}for(var l=a.splitLines(b),m=e&&
 e.state||a.startState(f),n=0,o=l.length;n<o;++n){n&&d("\n");var p=new a.StringStream(l[n]);for(!p.string&&f.blankLine&&f.blankLine(m);!p.eol();){var q=f.token(p,m);d(p.current(),q,n,p.start,m),p.start=p.pos}}}})},{"../../lib/codemirror":59}],42:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(a,b){function c(a){clearTimeout(d.doRedraw),d.doRedraw=setTimeout(function(){d.redraw()},a)}this.cm=a,this.options=b,this.buttonHeight=b.scrollButtonHeight||a.getOption("scrollButtonHeight"),this.annotations=[],this.doRedraw=this.doUpdate=null,this.div=a.getWrapperElement().appendChild(document.createElement("div")),this.div.style.cssText="position: absolute; right: 0; top: 0; z-
 index: 7; pointer-events: none",this.computeScale();var d=this;a.on("refresh",this.resizeHandler=function(){clearTimeout(d.doUpdate),d.doUpdate=setTimeout(function(){d.computeScale()&&c(20)},100)}),a.on("markerAdded",this.resizeHandler),a.on("markerCleared",this.resizeHandler),b.listenForChanges!==!1&&a.on("change",this.changeHandler=function(){c(250)})}a.defineExtension("annotateScrollbar",function(a){return"string"==typeof a&&(a={className:a}),new b(this,a)}),a.defineOption("scrollButtonHeight",0),b.prototype.computeScale=function(){var a=this.cm,b=(a.getWrapperElement().clientHeight-a.display.barHeight-2*this.buttonHeight)/a.getScrollerElement().scrollHeight;if(b!=this.hScale)return this.hScale=b,!0},b.prototype.update=function(a){this.annotations=a,this.redraw()},b.prototype.redraw=function(a){function b(a,b){if(i!=a.line&&(i=a.line,j=c.getLineHandle(i)),j.widgets&&
 j.widgets.length||g&&j.height>h)return c.charCoords(a,"local")[b?"top":"bottom"];var d=c.heightAtLine(j,"local");return d+(b?0:j.height)}a!==!1&&this.computeScale();var c=this.cm,d=this.hScale,e=document.createDocumentFragment(),f=this.annotations,g=c.getOption("lineWrapping"),h=g&&1.5*c.defaultTextHeight(),i=null,j=null,k=c.lastLine();if(c.display.barWidth)for(var l,m=0;m<f.length;m++){var n=f[m];if(!(n.to.line>k)){for(var o=l||b(n.from,!0)*d,p=b(n.to,!1)*d;m<f.length-1&&!(f[m+1].to.line>k)&&(l=b(f[m+1].from,!0)*d,!(l>p+.9));)n=f[++m],p=b(n.to,!1)*d;if(p!=o){var q=Math.max(p-o,3),r=e.appendChild(document.createElement("div"));r.style.cssText="position: absolute; right: 0px; width: "+Math.max(c.display.barWidth-1,2)+"px; top: "+(o+this.buttonHeight)+"px; height: "+q+"px",r.className=this.options.className,n.id&&r.setAtt
 ribute("annotation-id",n.id)}}}this.div.textContent="",this.div.appendChild(e)},b.prototype.clear=function(){this.cm.off("refresh",this.resizeHandler),this.cm.off("markerAdded",this.resizeHandler),this.cm.off("markerCleared",this.resizeHandler),this.changeHandler&&this.cm.off("change",this.changeHandler),this.div.parentNode.removeChild(this.div)}})},{"../../lib/codemirror":59}],43:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(b,d){a.changeEnd(d).line==b.lastLine()&&c(b)}function c(a){var b="";if(a.lineCount()>1){var d=a.display.scroller.clientHeight-30,e=a.getLineHandle(a.lastLine()).height;b=d-e+"px"}a.state.scrollPastEndPaddin
 g!=b&&(a.state.scrollPastEndPadding=b,a.display.lineSpace.parentNode.style.paddingBottom=b,a.off("refresh",c),a.setSize(),a.on("refresh",c))}a.defineOption("scrollPastEnd",!1,function(d,e,f){f&&f!=a.Init&&(d.off("change",b),d.off("refresh",c),d.display.lineSpace.parentNode.style.paddingBottom="",d.state.scrollPastEndPadding=null),e&&(d.on("change",b),d.on("refresh",c),c(d))})})},{"../../lib/codemirror":59}],44:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(b,c,d){function e(b){var c=a.wheelEventPixels(b)["horizontal"==f.orientation?"x":"y"],d=f.pos;f.moveTo(f.pos+c),f.pos!=d&&a.e
 _preventDefault(b)}this.orientation=c,this.scroll=d,this.screen=this.total=this.size=1,this.pos=0,this.node=document.createElement("div"),this.node.className=b+"-"+c,this.inner=this.node.appendChild(document.createElement("div"));var f=this;a.on(this.inner,"mousedown",function(b){function c(){a.off(document,"mousemove",d),a.off(document,"mouseup",c)}function d(a){return 1!=a.which?c():void f.moveTo(h+(a[e]-g)*(f.total/f.size))}if(1==b.which){a.e_preventDefault(b);var e="horizontal"==f.orientation?"pageX":"pageY",g=b[e],h=f.pos;a.on(document,"mousemove",d),a.on(document,"mouseup",c)}}),a.on(this.node,"click",function(b){a.e_preventDefault(b);var c,d=f.inner.getBoundingClientRect();c="horizontal"==f.orientation?b.clientX<d.left?-1:b.clientX>d.right?1:0:b.clientY<d.top?-1:b.clientY>d.bottom?1:0,f.moveTo(f.pos+c*f.screen)}),a.on(this.node,"mo
 usewheel",e),a.on(this.node,"DOMMouseScroll",e)}function c(a,c,d){this.addClass=a,this.horiz=new b(a,"horizontal",d),c(this.horiz.node),this.vert=new b(a,"vertical",d),c(this.vert.node),this.width=null}b.prototype.setPos=function(a,b){return a<0&&(a=0),a>this.total-this.screen&&(a=this.total-this.screen),!(!b&&a==this.pos)&&(this.pos=a,this.inner.style["horizontal"==this.orientation?"left":"top"]=a*(this.size/this.total)+"px",!0)},b.prototype.moveTo=function(a){this.setPos(a)&&this.scroll(a,this.orientation)};var d=10;b.prototype.update=function(a,b,c){var e=this.screen!=b||this.total!=a||this.size!=c;e&&(this.screen=b,this.total=a,this.size=c);var f=this.screen*(this.size/this.total);f<d&&(this.size-=d-f,f=d),this.inner.style["horizontal"==this.orientation?"width":"height"]=f+"px",this.setPos(this.pos,e)}
 ,c.prototype.update=function(a){if(null==this.width){var b=window.getComputedStyle?window.getComputedStyle(this.horiz.node):this.horiz.node.currentStyle;b&&(this.width=parseInt(b.height))}var c=this.width||0,d=a.scrollWidth>a.clientWidth+1,e=a.scrollHeight>a.clientHeight+1;return this.vert.node.style.display=e?"block":"none",this.horiz.node.style.display=d?"block":"none",e&&(this.vert.update(a.scrollHeight,a.clientHeight,a.viewHeight-(d?c:0)),this.vert.node.style.bottom=d?c+"px":"0"),d&&(this.horiz.update(a.scrollWidth,a.clientWidth,a.viewWidth-(e?c:0)-a.barLeft),this.horiz.node.style.right=e?c+"px":"0",this.horiz.node.style.left=a.barLeft+"px"),{right:e?c:0,bottom:d?c:0}},c.prototype.setScrollTop=function(a){this.vert.setPos(a)},c.prototype.setScrollLeft=function(a){this.horiz.setPos(a)},c.prototype.clear=function(){var a=this.horiz.node.parentNode;a.removeChild(t
 his.horiz.node),a.removeChild(this.vert.node)},a.scrollbarModel.simple=function(a,b){return new c("CodeMirror-simplescroll",a,b)},a.scrollbarModel.overlay=function(a,b){return new c("CodeMirror-overlayscroll",a,b)}})},{"../../lib/codemirror":59}],45:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror"),a("../dialog/dialog")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../dialog/dialog"],d):d(CodeMirror)}(function(a){"use strict";function b(a,b,c,d,e){a.openDialog?a.openDialog(b,e,{value:d,selectValueOnOpen:!0}):e(prompt(c,d))}function c(a,b){var c=Number(b);return/^[-+]/.test(b)?a.getCursor().line+c:c-1}var d='Jump to line: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror
 -search-hint">(Use line:column or scroll% syntax)</span>';a.commands.jumpToLine=function(a){var e=a.getCursor();b(a,d,"Jump to line:",e.line+1+":"+e.ch,function(b){if(b){var d;if(d=/^\s*([\+\-]?\d+)\s*\:\s*(\d+)\s*$/.exec(b))a.setCursor(c(a,d[1]),Number(d[2]));else if(d=/^\s*([\+\-]?\d+(\.\d+)?)\%\s*/.exec(b)){var f=Math.round(a.lineCount()*Number(d[1])/100);/^[-+]/.test(d[1])&&(f=e.line+f+1),a.setCursor(f-1,e.ch)}else(d=/^\s*\:?\s*([\+\-]?\d+)\s*/.exec(b))&&a.setCursor(c(a,d[1]),e.ch)}})},a.keyMap["default"]["Alt-G"]="jumpToLine"})},{"../../lib/codemirror":59,"../dialog/dialog":3}],46:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror"),a("./matchesonscrollbar")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","./matchesonscrollbar"],d
 ):d(CodeMirror)}(function(a){"use strict";function b(a){this.options={};for(var b in l)this.options[b]=(a&&a.hasOwnProperty(b)?a:l)[b];this.overlay=this.timeout=null,this.matchesonscroll=null,this.active=!1}function c(a){var b=a.state.matchHighlighter;(b.active||a.hasFocus())&&e(a,b)}function d(a){var b=a.state.matchHighlighter;b.active||(b.active=!0,e(a,b))}function e(a,b){clearTimeout(b.timeout),b.timeout=setTimeout(function(){h(a)},b.options.delay)}function f(a,b,c,d){var e=a.state.matchHighlighter;if(a.addOverlay(e.overlay=k(b,c,d)),e.options.annotateScrollbar&&a.showMatchesOnScrollbar){var f=c?new RegExp("\\b"+b+"\\b"):b;e.matchesonscroll=a.showMatchesOnScrollbar(f,!1,{className:"CodeMirror-selection-highlight-scrollbar"})}}function g(a){var b=a.state.matchHighlighter;b.overlay&&(a.removeOverlay(b.overlay),b.overlay=null,b.matchesonscroll&&(b.matchesonscroll.clear(),b.matchesonscroll=null))}function
  h(a){a.operation(function(){var b=a.state.matchHighlighter;if(g(a),!a.somethingSelected()&&b.options.showToken){for(var c=b.options.showToken===!0?/[\w$]/:b.options.showToken,d=a.getCursor(),e=a.getLine(d.line),h=d.ch,j=h;h&&c.test(e.charAt(h-1));)--h;for(;j<e.length&&c.test(e.charAt(j));)++j;return void(h<j&&f(a,e.slice(h,j),c,b.options.style))}var k=a.getCursor("from"),l=a.getCursor("to");if(k.line==l.line&&(!b.options.wordsOnly||i(a,k,l))){var m=a.getRange(k,l);b.options.trim&&(m=m.replace(/^\s+|\s+$/g,"")),m.length>=b.options.minChars&&f(a,m,!1,b.options.style)}})}function i(a,b,c){var d=a.getRange(b,c);if(null!==d.match(/^\w+$/)){if(b.ch>0){var e={line:b.line,ch:b.ch-1},f=a.getRange(e,b);if(null===f.match(/\W/))return!1}if(c.ch<a.getLine(b.line).length){var e={line:c.line,ch:c.ch+1},f=a.getRange(c,e);if(null===f.match(/\W/))return!1}return!0}return!1}function j(a,b){return!(a.s
 tart&&b.test(a.string.charAt(a.start-1))||a.pos!=a.string.length&&b.test(a.string.charAt(a.pos)))}function k(a,b,c){return{token:function(d){return!d.match(a)||b&&!j(d,b)?(d.next(),void(d.skipTo(a.charAt(0))||d.skipToEnd())):c}}}var l={style:"matchhighlight",minChars:2,delay:100,wordsOnly:!1,annotateScrollbar:!1,showToken:!1,trim:!0};a.defineOption("highlightSelectionMatches",!1,function(e,f,i){if(i&&i!=a.Init&&(g(e),clearTimeout(e.state.matchHighlighter.timeout),e.state.matchHighlighter=null,e.off("cursorActivity",c),e.off("focus",d)),f){var j=e.state.matchHighlighter=new b(f);e.hasFocus()?(j.active=!0,h(e)):e.on("focus",d),e.on("cursorActivity",c)}})})},{"../../lib/codemirror":59,"./matchesonscrollbar":47}],47:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror"),a("./searchcurs
 or"),a("../scroll/annotatescrollbar")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","./searchcursor","../scroll/annotatescrollbar"],d):d(CodeMirror)}(function(a){"use strict";function b(a,b,c,d){this.cm=a,this.options=d;var e={listenForChanges:!1};for(var f in d)e[f]=d[f];e.className||(e.className="CodeMirror-search-match"),this.annotation=a.annotateScrollbar(e),this.query=b,this.caseFold=c,this.gap={from:a.firstLine(),to:a.lastLine()+1},this.matches=[],this.update=null,this.findMatches(),this.annotation.update(this.matches);var g=this;a.on("change",this.changeHandler=function(a,b){g.onChange(b)})}function c(a,b,c){return a<=b?a:Math.max(b,a+c)}a.defineExtension("showMatchesOnScrollbar",function(a,c,d){return"string"==typeof d&&(d={className:d}),d||(d={}),new b(this,a,c,d)});var d=1e3;b.prototype.findMatches=function(){if(this.gap){for(v
 ar b=0;b<this.matches.length;b++){var c=this.matches[b];if(c.from.line>=this.gap.to)break;c.to.line>=this.gap.from&&this.matches.splice(b--,1)}for(var e=this.cm.getSearchCursor(this.query,a.Pos(this.gap.from,0),this.caseFold),f=this.options&&this.options.maxMatches||d;e.findNext();){var c={from:e.from(),to:e.to()};if(c.from.line>=this.gap.to)break;if(this.matches.splice(b++,0,c),this.matches.length>f)break}this.gap=null}},b.prototype.onChange=function(b){var d=b.from.line,e=a.changeEnd(b).line,f=e-b.to.line;if(this.gap?(this.gap.from=Math.min(c(this.gap.from,d,f),b.from.line),this.gap.to=Math.max(c(this.gap.to,d,f),b.from.line)):this.gap={from:b.from.line,to:e+1},f)for(var g=0;g<this.matches.length;g++){var h=this.matches[g],i=c(h.from.line,d,f);i!=h.from.line&&(h.from=a.Pos(i,h.from.ch));var j=c(h.to.line,d,f);j!=h.to.line&&(h.to=a.Pos(j,h.to.ch))}clearTimeout(this.update);var k=this;this.update=setTimeout(function(){k.updateAfterCh
 ange()},250)},b.prototype.updateAfterChange=function(){this.findMatches(),this.annotation.update(this.matches)},b.prototype.clear=function(){this.cm.off("change",this.changeHandler),this.annotation.clear()}})},{"../../lib/codemirror":59,"../scroll/annotatescrollbar":42,"./searchcursor":49}],48:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror"),a("./searchcursor"),a("../dialog/dialog")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","./searchcursor","../dialog/dialog"],d):d(CodeMirror)}(function(a){"use strict";function b(a,b){return"string"==typeof a?a=new RegExp(a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"),b?"gi":"g"):a.global||(a=new RegExp(a.source,a.ignoreCase?"gi":"g")),{token:functio
 n(b){a.lastIndex=b.pos;var c=a.exec(b.string);return c&&c.index==b.pos?(b.pos+=c[0].length||1,"searching"):void(c?b.pos=c.index:b.skipToEnd())}}}function c(){this.posFrom=this.posTo=this.lastQuery=this.query=null,this.overlay=null}function d(a){return a.state.search||(a.state.search=new c)}function e(a){return"string"==typeof a&&a==a.toLowerCase()}function f(a,b,c){return a.getSearchCursor(b,c,{caseFold:e(b),multiline:!0})}function g(a,b,c,d,e){a.openDialog(b,d,{value:c,selectValueOnOpen:!0,closeOnEnter:!1,onClose:function(){o(a)},onKeyDown:e})}function h(a,b,c,d,e){a.openDialog?a.openDialog(b,e,{value:d,selectValueOnOpen:!0}):e(prompt(c,d))}function i(a,b,c,d){a.openConfirm?a.openConfirm(b,d):confirm(c)&&d[0]()}function j(a){return a.replace(/\\(.)/g,function(a,b){return"n"==b?"\n":"r"==b?"\r":b})}function k(a){var b=a.match(/^\/(.*)\/([a-z]*)$/);if(b)try{a=new RegExp(b[1],b[2].indexOf("i"
 )==-1?"":"i")}catch(c){}else a=j(a);return("string"==typeof a?""==a:a.test(""))&&(a=/x^/),a}function l(a,c,d){c.queryText=d,c.query=k(d),a.removeOverlay(c.overlay,e(c.query)),c.overlay=b(c.query,e(c.query)),a.addOverlay(c.overlay),a.showMatchesOnScrollbar&&(c.annotate&&(c.annotate.clear(),c.annotate=null),c.annotate=a.showMatchesOnScrollbar(c.query,e(c.query)))}function m(b,c,e,f){var i=d(b);if(i.query)return n(b,c);var j=b.getSelection()||i.lastQuery;if(e&&b.openDialog){var k=null,m=function(c,d){a.e_stop(d),c&&(c!=i.queryText&&(l(b,i,c),i.posFrom=i.posTo=b.getCursor()),k&&(k.style.opacity=1),n(b,d.shiftKey,function(a,c){var d;c.line<3&&document.querySelector&&(d=b.display.wrapper.querySelector(".CodeMirror-dialog"))&&d.getBoundingClientRect().bottom-4>b.cursorCoords(c,"window").top&&((k=d).style.opacity=.4)}))};g(b,r,j,
 m,function(c,e){var f=a.keyName(c),g=b.getOption("extraKeys"),h=g&&g[f]||a.keyMap[b.getOption("keyMap")][f];"findNext"==h||"findPrev"==h||"findPersistentNext"==h||"findPersistentPrev"==h?(a.e_stop(c),l(b,d(b),e),b.execCommand(h)):"find"!=h&&"findPersistent"!=h||(a.e_stop(c),m(e,c))}),f&&j&&(l(b,i,j),n(b,c))}else h(b,r,"Search for:",j,function(a){a&&!i.query&&b.operation(function(){l(b,i,a),i.posFrom=i.posTo=b.getCursor(),n(b,c)})})}function n(b,c,e){b.operation(function(){var g=d(b),h=f(b,g.query,c?g.posFrom:g.posTo);(h.find(c)||(h=f(b,g.query,c?a.Pos(b.lastLine()):a.Pos(b.firstLine(),0)),h.find(c)))&&(b.setSelection(h.from(),h.to()),b.scrollIntoView({from:h.from(),to:h.to()},20),g.posFrom=h.from(),g.posTo=h.to(),e&&e(h.from(),h.to()))})}function o(a){a.operation(function(){var b=d(a);b.lastQuery=b.query,b.query&&(b.query=b
 .queryText=null,a.removeOverlay(b.overlay),b.annotate&&(b.annotate.clear(),b.annotate=null))})}function p(a,b,c){a.operation(function(){for(var d=f(a,b);d.findNext();)if("string"!=typeof b){var e=a.getRange(d.from(),d.to()).match(b);d.replace(c.replace(/\$(\d)/g,function(a,b){return e[b]}))}else d.replace(c)})}function q(a,b){if(!a.getOption("readOnly")){var c=a.getSelection()||d(a).lastQuery,e='<span class="CodeMirror-search-label">'+(b?"Replace all:":"Replace:")+"</span>";h(a,e+s,e,c,function(c){c&&(c=k(c),h(a,t,"Replace with:","",function(d){if(d=j(d),b)p(a,c,d);else{o(a);var e=f(a,c,a.getCursor("from")),g=function(){var b,j=e.from();!(b=e.findNext())&&(e=f(a,c),!(b=e.findNext())||j&&e.from().line==j.line&&e.from().ch==j.ch)||(a.setSelection(e.from(),e.to()),a.scrollIntoView({from:e.from(),to:e.to()}),i(a,u,"Replace?",[function(){
 h(b)},g,function(){p(a,c,d)}]))},h=function(a){e.replace("string"==typeof c?d:d.replace(/\$(\d)/g,function(b,c){return a[c]})),g()};g()}}))})}}var r='<span class="CodeMirror-search-label">Search:</span> <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>',s=' <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>',t='<span class="CodeMirror-search-label">With:</span> <input type="text" style="width: 10em" class="CodeMirror-search-field"/>',u='<span class="CodeMirror-search-label">Replace?</span> <butto
 n>Yes</button> <button>No</button> <button>All</button> <button>Stop</button>';a.commands.find=function(a){o(a),m(a)},a.commands.findPersistent=function(a){o(a),m(a,!1,!0)},a.commands.findPersistentNext=function(a){m(a,!1,!0,!0)},a.commands.findPersistentPrev=function(a){m(a,!0,!0,!0)},a.commands.findNext=m,a.commands.findPrev=function(a){m(a,!0)},a.commands.clearSearch=o,a.commands.replace=q,a.commands.replaceAll=function(a){q(a,!0)}})},{"../../lib/codemirror":59,"../dialog/dialog":3,"./searchcursor":49}],49:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(a){var b=a.flags;return null!=b?b:(a.ignoreCase?"i":"")+(a.global?"g":"&qu
 ot;)+(a.multiline?"m":"")}function c(a){return a.global?a:new RegExp(a.source,b(a)+"g")}function d(a){return/\\s|\\n|\n|\\W|\\D|\[\^/.test(a.source)}function e(a,b,d){b=c(b);for(var e=d.line,f=d.ch,g=a.lastLine();e<=g;e++,f=0){b.lastIndex=f;var h=a.getLine(e),i=b.exec(h);if(i)return{from:p(e,i.index),to:p(e,i.index+i[0].length),match:i}}}function f(a,b,f){if(!d(b))return e(a,b,f);b=c(b);for(var g,h=1,i=f.line,j=a.lastLine();i<=j;){for(var k=0;k<h;k++){var l=a.getLine(i++);g=null==g?l:g+"\n"+l}h*=2,b.lastIndex=f.ch;var m=b.exec(g);if(m){var n=g.slice(0,m.index).split("\n"),o=m[0].split("\n"),q=f.line+n.length-1,r=n[n.length-1].length;return{from:p(q,r),to:p(q+o.length-1,1==o.length?r+o[0].length:o[o.length-1].length),match:m}}}}function g(a,b){for(var c,d=0;;){b.lastIndex=d;var e=b.exec(a);if(!e)return c;if(c=e,d=c.index+(c[0].length||1),d==a.length)return c}}function h(a,b,d){b=c(b);for(var e=d.line,f=d.ch,h=a.firs
 tLine();e>=h;e--,f=-1){var i=a.getLine(e);f>-1&&(i=i.slice(0,f));var j=g(i,b);if(j)return{from:p(e,j.index),to:p(e,j.index+j[0].length),match:j}}}function i(a,b,d){b=c(b);for(var e,f=1,h=d.line,i=a.firstLine();h>=i;){for(var j=0;j<f;j++){var k=a.getLine(h--);e=null==e?k.slice(0,d.ch):k+"\n"+e}f*=2;var l=g(e,b);if(l){var m=e.slice(0,l.index).split("\n"),n=l[0].split("\n"),o=h+m.length,q=m[m.length-1].length;
+return{from:p(o,q),to:p(o+n.length-1,1==n.length?q+n[0].length:n[n.length-1].length),match:l}}}}function j(a,b,c,d){if(a.length==b.length)return c;for(var e=0,f=c+Math.max(0,a.length-b.length);;){if(e==f)return e;var g=e+f>>1,h=d(a.slice(0,g)).length;if(h==c)return g;h>c?f=g:e=g+1}}function k(a,b,c,d){if(!b.length)return null;var e=d?n:o,f=e(b).split(/\r|\n\r?/);a:for(var g=c.line,h=c.ch,i=a.lastLine()+1-f.length;g<=i;g++,h=0){var k=a.getLine(g).slice(h),l=e(k);if(1==f.length){var m=l.indexOf(f[0]);if(m==-1)continue a;var c=j(k,l,m,e)+h;return{from:p(g,j(k,l,m,e)+h),to:p(g,j(k,l,m+f[0].length,e)+h)}}var q=l.length-f[0].length;if(l.slice(q)==f[0]){for(var r=1;r<f.length-1;r++)if(e(a.getLine(g+r))!=f[r])continue a;var s=a.getLine(g+f.length-1),t=e(s),u=f[f.length-1];if(s.slice(0,u.length)==u)return{from:p(g,j(k,l,q,e)+h),to:p(g+f.length-1,j(s,t,u.length,e))}}}}function l(a,b,c,d){if(!b.length)return null;var e=d?n:o,f=e(b).split(/\r|\n\r?/);a:for(var g=c.line,h=c.ch,i=a
 .firstLine()-1+f.length;g>=i;g--,h=-1){var k=a.getLine(g);h>-1&&(k=k.slice(0,h));var l=e(k);if(1==f.length){var m=l.lastIndexOf(f[0]);if(m==-1)continue a;return{from:p(g,j(k,l,m,e)),to:p(g,j(k,l,m+f[0].length,e))}}var q=f[f.length-1];if(l.slice(0,q.length)==q){for(var r=1,c=g-f.length+1;r<f.length-1;r++)if(e(a.getLine(c+r))!=f[r])continue a;var s=a.getLine(g+1-f.length),t=e(s);if(t.slice(t.length-f[0].length)==f[0])return{from:p(g+1-f.length,j(s,t,s.length-f[0].length,e)),to:p(g,j(k,l,q.length,e))}}}}function m(a,b,d,g){this.atOccurrence=!1,this.doc=a,d=d?a.clipPos(d):p(0,0),this.pos={from:d,to:d};var j;"object"==typeof g?j=g.caseFold:(j=g,g=null),"string"==typeof b?(null==j&&(j=!1),this.matches=function(c,d){return(c?l:k)(a,b,d,j)}):(b=c(b),g&&g.multiline===!1?this.matches=function(c,d){return(c?h:e)(a,b,d)}:this.matches=function(c,d){return(c?i:f)(a,b,d)})}var n,o,p=a.Pos;String.prototype.normalize?(n=function(a){return a.normal
 ize("NFD").toLowerCase()},o=function(a){return a.normalize("NFD")}):(n=function(a){return a.toLowerCase()},o=function(a){return a}),m.prototype={findNext:function(){return this.find(!1)},findPrevious:function(){return this.find(!0)},find:function(b){for(var c=this.matches(b,this.doc.clipPos(b?this.pos.from:this.pos.to));c&&0==a.cmpPos(c.from,c.to);)b?c.from.ch?c.from=p(c.from.line,c.from.ch-1):c=c.from.line==this.doc.firstLine()?null:this.matches(b,this.doc.clipPos(p(c.from.line-1))):c.to.ch<this.doc.getLine(c.to.line).length?c.to=p(c.to.line,c.to.ch+1):c=c.to.line==this.doc.lastLine()?null:this.matches(b,p(c.to.line+1,0));if(c)return this.pos=c,this.atOccurrence=!0,this.pos.match||!0;var d=p(b?this.doc.firstLine():this.doc.lastLine()+1,0);return this.pos={from:d,to:d},this.atOccurrence=!1},from:function(){if(this.atOccurrence)return this.pos.from},to:function(){if(this.atOccurrence)return this.pos.to},replace:function(b,c){if(this.atOccurrence){var d=
 a.splitLines(b);this.doc.replaceRange(d,this.pos.from,this.pos.to,c),this.pos.to=p(this.pos.from.line+d.length-1,d[d.length-1].length+(1==d.length?this.pos.from.ch:0))}}},a.defineExtension("getSearchCursor",function(a,b,c){return new m(this.doc,a,b,c)}),a.defineDocExtension("getSearchCursor",function(a,b,c){return new m(this,a,b,c)}),a.defineExtension("selectMatches",function(b,c){for(var d=[],e=this.getSearchCursor(b,this.getCursor("from"),c);e.findNext()&&!(a.cmpPos(e.to(),this.getCursor("to"))>0);)d.push({anchor:e.from(),head:e.to()});d.length&&this.setSelections(d,0)})})},{"../../lib/codemirror":59}],50:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(a){fo
 r(var b=0;b<a.state.activeLines.length;b++)a.removeLineClass(a.state.activeLines[b],"wrap",f),a.removeLineClass(a.state.activeLines[b],"background",g),a.removeLineClass(a.state.activeLines[b],"gutter",h)}function c(a,b){if(a.length!=b.length)return!1;for(var c=0;c<a.length;c++)if(a[c]!=b[c])return!1;return!0}function d(a,d){for(var e=[],i=0;i<d.length;i++){var j=d[i],k=a.getOption("styleActiveLine");if("object"==typeof k&&k.nonEmpty?j.anchor.line==j.head.line:j.empty()){var l=a.getLineHandleVisualStart(j.head.line);e[e.length-1]!=l&&e.push(l)}}c(a.state.activeLines,e)||a.operation(function(){b(a);for(var c=0;c<e.length;c++)a.addLineClass(e[c],"wrap",f),a.addLineClass(e[c],"background",g),a.addLineClass(e[c],"gutter",h);a.state.activeLines=e})}function e(a,b){d(a,b.ranges)}var f="CodeMirror-activeline",g="CodeMirror-activeline-background",h="CodeMirror-
 activeline-gutter";a.defineOption("styleActiveLine",!1,function(c,f,g){var h=g!=a.Init&&g;f!=h&&(h&&(c.off("beforeSelectionChange",e),b(c),delete c.state.activeLines),f&&(c.state.activeLines=[],d(c,c.listSelections()),c.on("beforeSelectionChange",e)))})})},{"../../lib/codemirror":59}],51:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(a){a.state.markedSelection&&a.operation(function(){g(a)})}function c(a){a.state.markedSelection&&a.state.markedSelection.length&&a.operation(function(){e(a)})}function d(a,b,c,d){if(0!=j(b,c))for(var e=a.state.markedSelection,f=a.state.markedSelectionStyle,g=b.line;;){var k=g==b.line?b:i(g,0),l=g+h,m=l>=c
 .line,n=m?c:i(l,0),o=a.markText(k,n,{className:f});if(null==d?e.push(o):e.splice(d++,0,o),m)break;g=l}}function e(a){for(var b=a.state.markedSelection,c=0;c<b.length;++c)b[c].clear();b.length=0}function f(a){e(a);for(var b=a.listSelections(),c=0;c<b.length;c++)d(a,b[c].from(),b[c].to())}function g(a){if(!a.somethingSelected())return e(a);if(a.listSelections().length>1)return f(a);var b=a.getCursor("start"),c=a.getCursor("end"),g=a.state.markedSelection;if(!g.length)return d(a,b,c);var i=g[0].find(),k=g[g.length-1].find();if(!i||!k||c.line-b.line<=h||j(b,k.to)>=0||j(c,i.from)<=0)return f(a);for(;j(b,i.from)>0;)g.shift().clear(),i=g[0].find();for(j(b,i.from)<0&&(i.to.line-b.line<h?(g.shift().clear(),d(a,b,i.to,0)):d(a,b,i.from,0));j(c,k.to)<0;)g.pop().clear(),k=g[g.length-1].find();j(c,k.to)>0&&(c.line-k.from.line<h?(g.pop().clear(),d(a,k.from,c)):d(a,k.to,c))}a.defineOption("styleSelectedText",!1,functi
 on(d,g,h){var i=h&&h!=a.Init;g&&!i?(d.state.markedSelection=[],d.state.markedSelectionStyle="string"==typeof g?g:"CodeMirror-selectedtext",f(d),d.on("cursorActivity",b),d.on("change",c)):!g&&i&&(d.off("cursorActivity",b),d.off("change",c),e(d),d.state.markedSelection=d.state.markedSelectionStyle=null)});var h=8,i=a.Pos,j=a.cmpPos})},{"../../lib/codemirror":59}],52:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(a,b){var c=a.state.selectionPointer;(null==b.buttons?b.which:b.buttons)?c.mouseX=c.mouseY=null:(c.mouseX=b.clientX,c.mouseY=b.clientY),e(a)}function c(a,b){if(!a.getWrapperElement().contains(b.relatedTarget)){var c=a.state.selecti
 onPointer;c.mouseX=c.mouseY=null,e(a)}}function d(a){a.state.selectionPointer.rects=null,e(a)}function e(a){a.state.selectionPointer.willUpdate||(a.state.selectionPointer.willUpdate=!0,setTimeout(function(){f(a),a.state.selectionPointer.willUpdate=!1},50))}function f(a){var b=a.state.selectionPointer;if(b){if(null==b.rects&&null!=b.mouseX&&(b.rects=[],a.somethingSelected()))for(var c=a.display.selectionDiv.firstChild;c;c=c.nextSibling)b.rects.push(c.getBoundingClientRect());var d=!1;if(null!=b.mouseX)for(var e=0;e<b.rects.length;e++){var f=b.rects[e];f.left<=b.mouseX&&f.right>=b.mouseX&&f.top<=b.mouseY&&f.bottom>=b.mouseY&&(d=!0)}var g=d?b.value:"";a.display.lineDiv.style.cursor!=g&&(a.display.lineDiv.style.cursor=g)}}a.defineOption("selectionPointer",!1,function(e,f){var g=e.state.selectionPointer;g&&(a.off(e.getWrapperElement(),"mousemove",g.mousemove),a.off(e.getWrapperEle
 ment(),"mouseout",g.mouseout),a.off(window,"scroll",g.windowScroll),e.off("cursorActivity",d),e.off("scroll",d),e.state.selectionPointer=null,e.display.lineDiv.style.cursor=""),f&&(g=e.state.selectionPointer={value:"string"==typeof f?f:"default",mousemove:function(a){b(e,a)},mouseout:function(a){c(e,a)},windowScroll:function(){d(e)},rects:null,mouseX:null,mouseY:null,willUpdate:!1},a.on(e.getWrapperElement(),"mousemove",g.mousemove),a.on(e.getWrapperElement(),"mouseout",g.mouseout),a.on(window,"scroll",g.windowScroll),e.on("cursorActivity",d),e.on("scroll",d))})})},{"../../lib/codemirror":59}],53:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(fun
 ction(a){"use strict";function b(a,b,c){var d=a.docs[b];d?c(F(a,d)):a.options.getFile?a.options.getFile(b,c):c(null)}function c(a,b,c){for(var d in a.docs){var e=a.docs[d];if(e.doc==b)return e}if(!c)for(var f=0;;++f)if(d="[doc"+(f||"")+"]",!a.docs[d]){c=d;break}return a.addDoc(c,b)}function d(b,d){return"string"==typeof d?b.docs[d]:(d instanceof a&&(d=d.getDoc()),d instanceof a.Doc?c(b,d):void 0)}function e(a,b,d){var e=c(a,b),g=a.cachedArgHints;g&&g.doc==b&&L(g.start,d.to)>=0&&(a.cachedArgHints=null);var h=e.changed;null==h&&(e.changed=h={from:d.from.line,to:d.from.line});var i=d.from.line+(d.text.length-1);d.from.line<h.to&&(h.to=h.to-(d.to.line-i)),i>=h.to&&(h.to=i+1),h.from>d.from.line&&(h.from=d.from.line),b.lineCount()>J&&d.to-h.from>100&&setTimeout(function(){e.changed&&e.changed.to-e.changed.from>100&&f(a,e)},2
 00)}function f(a,b){a.server.request({files:[{type:"full",name:b.name,text:F(a,b)}]},function(a){a?window.console.error(a):b.changed=null})}function g(b,c,d){b.request(c,{type:"completions",types:!0,docs:!0,urls:!0},function(e,f){if(e)return D(b,c,e);var g=[],i="",j=f.start,k=f.end;'["'==c.getRange(H(j.line,j.ch-2),j)&&'"]'!=c.getRange(k,H(k.line,k.ch+2))&&(i='"]');for(var l=0;l<f.completions.length;++l){var m=f.completions[l],n=h(m.type);f.guess&&(n+=" "+I+"guess"),g.push({text:m.name+i,displayText:m.displayName||m.name,className:n,data:m})}var o={from:j,to:k,list:g},p=null;a.on(o,"close",function(){B(p)}),a.on(o,"update",function(){B(p)}),a.on(o,"select",function(a,c){B(p);var d=b.options.completionTip?b.options.completionTip(a.data):a.data.doc;d&&(p=A(c.parentNode.getBoundingClientRect().right+window.pageXOffset,c.getBoundingClientRect().top+window.pag
 eYOffset,d),p.className+=" "+I+"hint-doc")}),d(o)})}function h(a){var b;return b="?"==a?"unknown":"number"==a||"string"==a||"bool"==a?a:/^fn\(/.test(a)?"fn":/^\[/.test(a)?"array":"object",I+"completion "+I+"completion-"+b}function i(a,b,c,d,e){a.request(b,d,function(c,d){if(c)return D(a,b,c);if(a.options.typeTip)var f=a.options.typeTip(d);else{var f=w("span",null,w("strong",null,d.type||"not found"));if(d.doc&&f.appendChild(document.createTextNode(" \u2014 "+d.doc)),d.url){f.appendChild(document.createTextNode(" "));var g=f.appendChild(w("a",null,"[docs]"));g.href=d.url,g.target="_blank"}}y(b,f,a),e&&e()},c)}function j(b,c){if(E(b),!c.somethingSelected()){var d=c.getTokenAt(c.getCursor()).state,e=a.innerMode(c.getMode(),d);if("javascript"==e.mode.name){var f=e.
 state.lexical;if("call"==f.info){for(var g,h=f.pos||0,i=c.getOption("tabSize"),j=c.getCursor().line,m=Math.max(0,j-9),n=!1;j>=m;--j){for(var o=c.getLine(j),p=0,q=0;;){var r=o.indexOf("\t",q);if(r==-1)break;p+=i-(r+p)%i-1,q=r+1}if(g=f.column-p,"("==o.charAt(g)){n=!0;break}}if(n){var s=H(j,g),t=b.cachedArgHints;return t&&t.doc==c.getDoc()&&0==L(s,t.start)?k(b,c,h):void b.request(c,{type:"type",preferFunction:!0,end:s},function(a,d){!a&&d.type&&/^fn\(/.test(d.type)&&(b.cachedArgHints={start:s,type:l(d.type),name:d.exprName||d.name||"fn",guess:d.guess,doc:c.getDoc()},k(b,c,h))})}}}}}function k(a,b,c){E(a);for(var d=a.cachedArgHints,e=d.type,f=w("span",d.guess?I+"fhint-guess":null,w("span",I+"fname",d.name),"("),g=0;g<e.args.length;++g){g&&f.appendChild(document.createTextNode(", "));var h=e.args[g];f.appendChild(w(&
 quot;span",I+"farg"+(g==c?" "+I+"farg-current":""),h.name||"?")),"?"!=h.type&&(f.appendChild(document.createTextNode(":\xa0")),f.appendChild(w("span",I+"type",h.type)))}f.appendChild(document.createTextNode(e.rettype?") ->\xa0":")")),e.rettype&&f.appendChild(w("span",I+"type",e.rettype));var i=b.cursorCoords(null,"page"),j=a.activeArgHints=A(i.right+1,i.bottom,f);setTimeout(function(){j.clear=z(b,function(){a.activeArgHints==j&&E(a)})},20)}function l(a){function b(b){for(var c=0,e=d;;){var f=a.charAt(d);if(b.test(f)&&!c)return a.slice(e,d);/[{\[\(]/.test(f)?++c:/[}\]\)]/.test(f)&&--c,++d}}var c=[],d=3;if(")"!=a.charAt(d))for(;;){var e=a.slice(d).match(/^([^, \(\[\{]+): /);if(e&&(d+=e[0].length,e=e[1]),c.push({name:e,type:b(/[\),]/)}),")"==a.charAt(d))break;d+=2}var f=a.s
 lice(d).match(/^\) -> (.*)$/);return{args:c,rettype:f&&f[1]}}function m(a,b){function d(d){var e={type:"definition",variable:d||null},f=c(a,b.getDoc());a.server.request(u(a,f,e),function(c,d){if(c)return D(a,b,c);if(!d.file&&d.url)return void window.open(d.url);if(d.file){var e,g=a.docs[d.file];if(g&&(e=p(g.doc,d)))return a.jumpStack.push({file:f.name,start:b.getCursor("from"),end:b.getCursor("to")}),void o(a,f,g,e.start,e.end)}D(a,b,"Could not find a definition.")})}q(b)?d():x(b,"Jump to variable",function(a){a&&d(a)})}function n(a,b){var d=a.jumpStack.pop(),e=d&&a.docs[d.file];e&&o(a,c(a,b.getDoc()),e,d.start,d.end)}function o(a,b,c,d,e){c.doc.setSelection(d,e),b!=c&&a.options.switchToDoc&&(E(a),a.options.switchToDoc(c.name,c.doc))}function p(a,b){for(var c=b.context.slice(0,b.contextOffset).split("\n"),d=b.start.line-(c.length-1),e=H(d,(1==c.length?b.star
 t.ch:a.getLine(d).length)-c[0].length),f=a.getLine(d).slice(e.ch),g=d+1;g<a.lineCount()&&f.length<b.context.length;++g)f+="\n"+a.getLine(g);if(f.slice(0,b.context.length)==b.context)return b;for(var h,i=a.getSearchCursor(b.context,0,!1),j=1/0;i.findNext();){var k=i.from(),l=1e4*Math.abs(k.line-e.line);l||(l=Math.abs(k.ch-e.ch)),l<j&&(h=k,j=l)}if(!h)return null;if(1==c.length?h.ch+=c[0].length:h=H(h.line+(c.length-1),c[c.length-1].length),b.start.line==b.end.line)var m=H(h.line,h.ch+(b.end.ch-b.start.ch));else var m=H(h.line+(b.end.line-b.start.line),b.end.ch);return{start:h,end:m}}function q(a){var b=a.getCursor("end"),c=a.getTokenAt(b);return!(c.start<b.ch&&"comment"==c.type)&&/[\w)\]]/.test(a.getLine(b.line).slice(Math.max(b.ch-1,0),b.ch+1))}function r(a,b){var c=b.getTokenAt(b.getCursor());return/\w/.test(c.string)?void x(b,"New name for "+c.string,function(c){a.request(b,{type:"rename",
 newName:c,fullDocs:!0},function(c,d){return c?D(a,b,c):void t(a,d.changes)})}):D(a,b,"Not at a variable")}function s(a,b){var d=c(a,b.doc).name;a.request(b,{type:"refs"},function(c,e){if(c)return D(a,b,c);for(var f=[],g=0,h=b.getCursor(),i=0;i<e.refs.length;i++){var j=e.refs[i];j.file==d&&(f.push({anchor:j.start,head:j.end}),L(h,j.start)>=0&&L(h,j.end)<=0&&(g=f.length-1))}b.setSelections(f,g)})}function t(a,b){for(var c=Object.create(null),d=0;d<b.length;++d){var e=b[d];(c[e.file]||(c[e.file]=[])).push(e)}for(var f in c){var g=a.docs[f],h=c[f];if(g){h.sort(function(a,b){return L(b.start,a.start)});for(var i="*rename"+ ++K,d=0;d<h.length;++d){var e=h[d];g.doc.replaceRange(e.text,e.start,e.end,i)}}}}function u(a,b,c,d){var e=[],f=0,g=!c.fullDocs;g||delete c.fullDocs,"string"==typeof c&&(c={type:c}),c.lineCharPositions=!0,null==c.end&&(c.end=d||b.doc.getCursor("end"),b.doc.something
 Selected()&&(c.start=b.doc.getCursor("start")));var h=c.start||c.end;if(b.changed)if(b.doc.lineCount()>J&&g!==!1&&b.changed.to-b.changed.from<100&&b.changed.from<=h.line&&b.changed.to>c.end.line){e.push(v(b,h,c.end)),c.file="#0";var f=e[0].offsetLines;null!=c.start&&(c.start=H(c.start.line- -f,c.start.ch)),c.end=H(c.end.line-f,c.end.ch)}else e.push({type:"full",name:b.name,text:F(a,b)}),c.file=b.name,b.changed=null;else c.file=b.name;for(var i in a.docs){var j=a.docs[i];j.changed&&j!=b&&(e.push({type:"full",name:j.name,text:F(a,j)}),j.changed=null)}return{query:c,files:e}}function v(b,c,d){for(var e,f=b.doc,g=null,h=null,i=4,j=c.line-1,k=Math.max(0,j-50);j>=k;--j){var l=f.getLine(j),m=l.search(/\bfunction\b/);if(!(m<0)){var n=a.countColumn(l,null,i);null!=g&&g<=n||(g=n,h=j)}}null==h&&(h=k);var o=Math.min(f.lastLine(),d.line+20);if(null==g||g==a
 .countColumn(f.getLine(c.line),null,i))e=o;else for(e=d.line+1;e<o;++e){var n=a.countColumn(f.getLine(e),null,i);if(n<=g)break}var p=H(h,0);return{type:"part",name:b.name,offsetLines:p.line,text:f.getRange(p,H(e,0))}}function w(a,b){var c=document.createElement(a);b&&(c.className=b);for(var d=2;d<arguments.length;++d){var e=arguments[d];"string"==typeof e&&(e=document.createTextNode(e)),c.appendChild(e)}return c}function x(a,b,c){a.openDialog?a.openDialog(b+": <input type=text>",c):c(prompt(b,""))}function y(b,c,d){function e(){j=!0,i||f()}function f(){b.state.ternTooltip=null,h.parentNode&&C(h),k()}b.state.ternTooltip&&B(b.state.ternTooltip);var g=b.cursorCoords(),h=b.state.ternTooltip=A(g.right+1,g.bottom,c),i=!1,j=!1;a.on(h,"mousemove",function(){i=!0}),a.on(h,"mouseout",function(b){a.contains(h,b.relatedTarget||b.toElement)||(j?f():i=!1)}),setTimeout(e,d.options.hintDelay?d
 .options.hintDelay:1700);var k=z(b,f)}function z(a,b){return a.on("cursorActivity",b),a.on("blur",b),a.on("scroll",b),a.on("setDoc",b),function(){a.off("cursorActivity",b),a.off("blur",b),a.off("scroll",b),a.off("setDoc",b)}}function A(a,b,c){var d=w("div",I+"tooltip",c);return d.style.left=a+"px",d.style.top=b+"px",document.body.appendChild(d),d}function B(a){var b=a&&a.parentNode;b&&b.removeChild(a)}function C(a){a.style.opacity="0",setTimeout(function(){B(a)},1100)}function D(a,b,c){a.options.showError?a.options.showError(b,c):y(b,String(c),a)}function E(a){a.activeArgHints&&(a.activeArgHints.clear&&a.activeArgHints.clear(),B(a.activeArgHints),a.activeArgHints=null)}function F(a,b){var c=b.doc.getValue();return a.options.fileFilter&&(c=a.options.fileFilter(c,b.name,b.doc)),c}function G(a){function c(a,b){b&&a
 mp;(a.id=++e,f[e]=b),d.postMessage(a)}var d=a.worker=new Worker(a.options.workerScript);d.postMessage({type:"init",defs:a.options.defs,plugins:a.options.plugins,scripts:a.options.workerDeps});var e=0,f={};d.onmessage=function(d){var e=d.data;"getFile"==e.type?b(a,e.name,function(a,b){c({type:"getFile",err:String(a),text:b,id:e.id})}):"debug"==e.type?window.console.log(e.message):e.id&&f[e.id]&&(f[e.id](e.err,e.body),delete f[e.id])},d.onerror=function(a){for(var b in f)f[b](a);f={}},this.addFile=function(a,b){c({type:"add",name:a,text:b})},this.delFile=function(a){c({type:"del",name:a})},this.request=function(a,b){c({type:"req",body:a},b)}}a.TernServer=function(a){var c=this;this.options=a||{};var d=this.options.plugins||(this.options.plugins={});d.doc_comment||(d.doc_comment=!0),this.docs=Object.create(null),this.options.useWorker?this.server=new G(this):this.server=new tern.Server({getFile:functi
 on(a,d){return b(c,a,d)},async:!0,defs:this.options.defs||[],plugins:d}),this.trackChange=function(a,b){e(c,a,b)},this.cachedArgHints=null,this.activeArgHints=null,this.jumpStack=[],this.getHint=function(a,b){return g(c,a,b)},this.getHint.async=!0},a.TernServer.prototype={addDoc:function(b,c){var d={doc:c,name:b,changed:null};return this.server.addFile(b,F(this,d)),a.on(c,"change",this.trackChange),this.docs[b]=d},delDoc:function(b){var c=d(this,b);c&&(a.off(c.doc,"change",this.trackChange),delete this.docs[c.name],this.server.delFile(c.name))},hideDoc:function(a){E(this);var b=d(this,a);b&&b.changed&&f(this,b)},complete:function(a){a.showHint({hint:this.getHint})},showType:function(a,b,c){i(this,a,b,"type",c)},showDocs:function(a,b,c){i(this,a,b,"documentation",c)},updateArgHints:function(a){j(this,a)},jumpToDef:function(a){m(this,a)},jumpBack:function(a){n(this,a)},rename:function(a){r(this,a)},selectName:function(a){
 s(this,a)},request:function(a,b,d,e){var f=this,g=c(this,a.getDoc()),h=u(this,g,b,e),i=h.query&&this.options.queryOptions&&this.options.queryOptions[h.query.type];if(i)for(var j in i)h.query[j]=i[j];this.server.request(h,function(a,c){!a&&f.options.responseFilter&&(c=f.options.responseFilter(g,b,h,a,c)),d(a,c)})},destroy:function(){E(this),this.worker&&(this.worker.terminate(),this.worker=null)}};var H=a.Pos,I="CodeMirror-Tern-",J=250,K=0,L=a.cmpPos})},{"../../lib/codemirror":59}],54:[function(a,b,c){function d(a,b){postMessage({type:"getFile",name:a,id:++g}),h[g]=b}function e(a,b,c){c&&importScripts.apply(null,c),f=new tern.Server({getFile:d,async:!0,defs:a,plugins:b})}var f;this.onmessage=function(a){var b=a.data;switch(b.type){case"init":return e(b.defs,b.plugins,b.scripts);case"add":return f.addFile(b.name,b.text);case"del":return f.delFile(b.name);case"req":retu
 rn f.request(b.body,function(a,c){postMessage({id:b.id,body:c,err:a&&String(a)})});case"getFile":var c=h[b.id];return delete h[b.id],c(b.err,b.text);default:throw new Error("Unknown message type: "+b.type)}};var g=0,h={};this.console={log:function(a){postMessage({type:"debug",message:a})}}},{}],55:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(a,b,c){for(var d=c.paragraphStart||a.getHelper(b,"paragraphStart"),e=b.line,f=a.firstLine();e>f;--e){var g=a.getLine(e);if(d&&d.test(g))break;if(!/\S/.test(g)){++e;break}}for(var h=c.paragraphEnd||a.getHelper(b,"paragraphEnd"),i=b.line+1,j=a.lastLine();i<=j;++i){var g=a.getLine(i);if(h&&h.test(g)){++i;break}if(!/\S/.te
 st(g))break}return{from:e,to:i}}function c(a,b,c,d){for(var e=b;e<a.length&&" "==a.charAt(e);)e++;for(;e>0&&!c.test(a.slice(e-1,e+1));--e);for(var f=!0;;f=!1){var g=e;if(d)for(;" "==a.charAt(g-1);)--g;if(0!=g||!f)return{from:g,to:e};e=b}}function d(b,d,f,g){d=b.clipPos(d),f=b.clipPos(f);var h=g.column||80,i=g.wrapOn||/\s\S|-[^\.\d]/,j=g.killTrailingSpace!==!1,k=[],l="",m=d.line,n=b.getRange(d,f,!1);if(!n.length)return null;for(var o=n[0].match(/^[ \t]*/)[0],p=0;p<n.length;++p){var q=n[p],r=l.length,s=0;l&&q&&!i.test(l.charAt(l.length-1)+q.charAt(0))&&(l+=" ",s=1);var t="";if(p&&(t=q.match(/^\s*/)[0],q=q.slice(t.length)),l+=q,p){var u=l.length>h&&o==t&&c(l,h,i,j);u&&u.from==r&&u.to==r+s?(l=o+q,++m):k.push({text:[s?" ":""],from:e(m,r),to:e(m+1,t.length)})}for(;l.length>h;){var v=c(l,h,i,j);k.push({text:["",o],fro
 m:e(m,v.from),to:e(m,v.to)}),l=o+l.slice(v.to),++m}}return k.length&&b.operation(function(){for(var c=0;c<k.length;++c){var d=k[c];(d.text||a.cmpPos(d.from,d.to))&&b.replaceRange(d.text,d.from,d.to)}}),k.length?{from:k[0].from,to:a.changeEnd(k[k.length-1])}:null}var e=a.Pos;a.defineExtension("wrapParagraph",function(a,c){c=c||{},a||(a=this.getCursor());var f=b(this,a,c);return d(this,e(f.from,0),e(f.to-1),c)}),a.commands.wrapLines=function(a){a.operation(function(){for(var c=a.listSelections(),f=a.lastLine()+1,g=c.length-1;g>=0;g--){var h,i=c[g];if(i.empty()){var j=b(a,i.head,{});h={from:e(j.from,0),to:e(j.to-1)}}else h={from:i.from(),to:i.to()};h.to.line>=f||(f=h.from.line,d(a,h.from,h.to,{}))}})},a.defineExtension("wrapRange",function(a,b,c){return d(this,a,b,c||{})}),a.defineExtension("wrapParagraphsInRange",function(a,c,f){f=f||{};for(var g=this,h=[],i=a.line;i<=c.line;){var j=b(g,e(i,0),f);h.push(j),i=j.to}var k=!1;retur
 n h.length&&g.operation(function(){for(var a=h.length-1;a>=0;--a)k=k||d(g,e(h[a].from,0),e(h[a].to-1),f)}),k})})},{"../../lib/codemirror":59}],56:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../lib/codemirror")):"function"==typeof define&&define.amd?define(["../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(a,b){return a.line==b.line&&a.ch==b.ch}function c(a){I.push(a),I.length>50&&I.shift()}function d(a){return I.length?void(I[I.length-1]+=a):c(a)}function e(a){return I[I.length-(a?Math.min(a,1):1)]||""}function f(){return I.length>1&&I.pop(),e()}function g(a,e,f,g,h){null==h&&(h=a.getRange(e,f)),g&&J&&J.cm==a&&b(e,J.pos)&&a.isClean(J.gen)?d(h):c(h),a.replaceRange("",e,f,"+delete"),J=g?{cm:a,pos:e,gen:a.changeGeneration()}:null}function
  h(a,b,c){return a.findPosH(b,c,"char",!0)}function i(a,b,c){return a.findPosH(b,c,"word",!0)}function j(a,b,c){return a.findPosV(b,c,"line",a.doc.sel.goalColumn)}function k(a,b,c){return a.findPosV(b,c,"page",a.doc.sel.goalColumn)}function l(a,b,c){for(var d=b.line,e=a.getLine(d),f=/\S/.test(c<0?e.slice(0,b.ch):e.slice(b.ch)),g=a.firstLine(),h=a.lastLine();;){if(d+=c,d<g||d>h)return a.clipPos(H(d-c,c<0?0:null));e=a.getLine(d);var i=/\S/.test(e);if(i)f=!0;else if(f)return H(d,0)}}function m(a,b,c){for(var d=b.line,e=b.ch,f=a.getLine(b.line),g=!1;;){var h=f.charAt(e+(c<0?-1:0));if(h){if(g&&/[!?.]/.test(h))return H(d,e+(c>0?1:0));g||(g=/\w/.test(h)),e+=c}else{if(d==(c<0?a.firstLine():a.lastLine()))return H(d,e);if(f=a.getLine(d+c),!/\S/.test(f))return H(d,e);d+=c,e=c<0?f.length:0}}}function n(a,c,d){var e;if(a.findMatchingBracket&&(e=a.findMatchingBracket(c,{strict:!0}))&&e.match&&(e.forwar
 d?1:-1)==d)return d>0?H(e.to.line,e.to.ch+1):e.to;for(var f=!0;;f=!1){var g=a.getTokenAt(c),h=H(c.line,d<0?g.start:g.end);if(!(f&&d>0&&g.end==c.ch)&&/\w/.test(g.string))return h;var i=a.findPosH(h,d,"char");if(b(h,i))return c;c=i}}function o(a,b){var c=a.state.emacsPrefix;return c?(w(a),"-"==c?-1:Number(c)):b?null:1}function p(a){var b="string"==typeof a?function(b){b.execCommand(a)}:a;return function(a){var c=o(a);b(a);for(var d=1;d<c;++d)b(a)}}function q(a,c,d,e){var f=o(a);f<0&&(e=-e,f=-f);for(var g=0;g<f;++g){var h=d(a,c,e);if(b(h,c))break;c=h}return c}function r(a,b){var c=function(c){c.extendSelection(q(c,c.getCursor(),a,b))};return c.motion=!0,c}function s(a,b,c){for(var d,e=a.listSelections(),f=e.length;f--;)d=e[f].head,g(a,d,q(a,d,b,c),!0)}function t(a){if(a.somethingSelected()){for(var b,c=a.listSelections(),d=c.length;d--;)b=c[d],g(a,b.anchor,b.head);return!0}}function u(a,b){return a.state.em
 acsPrefix?void("-"!=b&&(a.state.emacsPrefix+=b)):(a.state.emacsPrefix=b,a.on("keyHandled",v),void a.on("inputRead",x))}function v(a,b){a.state.emacsPrefixMap||K.hasOwnProperty(b)||w(a)}function w(a){a.state.emacsPrefix=null,a.off("keyHandled",v),a.off("inputRead",x)}function x(a,b){var c=o(a);if(c>1&&"+input"==b.origin){for(var d=b.text.join("\n"),e="",f=1;f<c;++f)e+=d;a.replaceSelection(e)}}function y(a){a.state.emacsPrefixMap=!0,a.addKeyMap(M),a.on("keyHandled",z),a.on("inputRead",z)}function z(a,b){("string"!=typeof b||!/^\d$/.test(b)&&"Ctrl-U"!=b)&&(a.removeKeyMap(M),a.state.emacsPrefixMap=!1,a.off("keyHandled",z),a.off("inputRead",z))}function A(a){a.setCursor(a.getCursor()),a.setExtending(!a.getExtending()),a.on("change",function(){a.setExtending(!1)})}function B(a){a.setExtending(!1),a.setCu
 rsor(a.getCursor())}function C(a,b,c){a.openDialog?a.openDialog(b+': <input type="text" style="width: 10em"/>',c,{bottom:!0}):c(prompt(b,""))}function D(a,b){var c=a.getCursor(),d=a.findPosH(c,1,"word");a.replaceRange(b(a.getRange(c,d)),c,d),a.setCursor(d)}function E(a){for(var b=a.getCursor(),c=b.line,d=b.ch,e=[];c>=a.firstLine();){for(var f=a.getLine(c),g=null==d?f.length:d;g>0;){var d=f.charAt(--g);if(")"==d)e.push("(");else if("]"==d)e.push("[");else if("}"==d)e.push("{");else if(/[\(\{\[]/.test(d)&&(!e.length||e.pop()!=d))return a.extendSelection(H(c,g))}--c,d=null}}function F(a){a.execCommand("clearSearch"),B(a)}function G(a){M[a]=function(b){u(b,a)},L["Ctrl-"+a]=function(b){u(b,a)},K["Ctrl-"+a]=!0}var H=a.Pos,I=[],J=null,K={"Alt-G":!0,"Ctrl-X":!0,"Ctrl-Q":!0,"Ctrl-U":!0};a.emacs={kill:g,ki
 llRegion:t,repeated:p};for(var L=a.keyMap.emacs=a.normalizeKeyMap({"Ctrl-W":function(a){g(a,a.getCursor("start"),a.getCursor("end"))},"Ctrl-K":p(function(a){var b=a.getCursor(),c=a.clipPos(H(b.line)),d=a.getRange(b,c);/\S/.test(d)||(d+="\n",c=H(b.line+1,0)),g(a,b,c,!0,d)}),"Alt-W":function(a){c(a.getSelection()),B(a)},"Ctrl-Y":function(a){var b=a.getCursor();a.replaceRange(e(o(a)),b,b,"paste"),a.setSelection(b,a.getCursor())},"Alt-Y":function(a){a.replaceSelection(f(),"around","paste")},"Ctrl-Space":A,"Ctrl-Shift-2":A,"Ctrl-F":r(h,1),"Ctrl-B":r(h,-1),Right:r(h,1),Left:r(h,-1),"Ctrl-D":function(a){s(a,h,1)},Delete:function(a){t(a)||s(a,h,1)},"Ctrl-H":function(a){s(a,h,-1)},Backspace:function(a){t(a)||s(a,h,-1)},"Alt-F":r(i,1),"Alt-B":r(i,-1),"Alt-D":function(a){s(a,i,1)},"Alt-Backsp
 ace":function(a){s(a,i,-1)},"Ctrl-N":r(j,1),"Ctrl-P":r(j,-1),Down:r(j,1),Up:r(j,-1),"Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd",End:"goLineEnd",Home:"goLineStart","Alt-V":r(k,-1),"Ctrl-V":r(k,1),PageUp:r(k,-1),PageDown:r(k,1),"Ctrl-Up":r(l,-1),"Ctrl-Down":r(l,1),"Alt-A":r(m,-1),"Alt-E":r(m,1),"Alt-K":function(a){s(a,m,1)},"Ctrl-Alt-K":function(a){s(a,n,1)},"Ctrl-Alt-Backspace":function(a){s(a,n,-1)},"Ctrl-Alt-F":r(n,1),"Ctrl-Alt-B":r(n,-1),"Shift-Ctrl-Alt-2":function(a){var b=a.getCursor();a.setSelection(q(a,b,n,1),b)},"Ctrl-Alt-T":function(a){var b=n(a,a.getCursor(),-1),c=n(a,b,1),d=n(a,c,1),e=n(a,d,-1);a.replaceRange(a.getRange(e,d)+a.getRange(c,e)+a.getRange(b,c),b,d)},"Ctrl-Alt-U":p(E),"Alt-Space":function(a){for(var b=a.getCursor(),c=b.ch,d=b.ch,e
 =a.getLine(b.line);c&&/\s/.test(e.charAt(c-1));)--c;for(;d<e.length&&/\s/.test(e.charAt(d));)++d;a.replaceRange(" ",H(b.line,c),H(b.line,d))},"Ctrl-O":p(function(a){a.replaceSelection("\n","start")}),"Ctrl-T":p(function(a){a.execCommand("transposeChars")}),"Alt-C":p(function(a){D(a,function(a){var b=a.search(/\w/);return b==-1?a:a.slice(0,b)+a.charAt(b).toUpperCase()+a.slice(b+1).toLowerCase()})}),"Alt-U":p(function(a){D(a,function(a){return a.toUpperCase()})}),"Alt-L":p(function(a){D(a,function(a){return a.toLowerCase()})}),"Alt-;":"toggleComment","Ctrl-/":p("undo"),"Shift-Ctrl--":p("undo"),"Ctrl-Z":p("undo"),"Cmd-Z":p("undo"),"Shift-Alt-,":"goDocStart","Shift-Alt-.":"goDocEnd","Ctrl-S":"findPersistentNext","Ctrl
 -R":"findPersistentPrev","Ctrl-G":F,"Shift-Alt-5":"replace","Alt-/":"autocomplete",Enter:"newlineAndIndent","Ctrl-J":p(function(a){a.replaceSelection("\n","end")}),Tab:"indentAuto","Alt-G G":function(a){var b=o(a,!0);return null!=b&&b>0?a.setCursor(b-1):void C(a,"Goto line",function(b){var c;b&&!isNaN(c=Number(b))&&c==(0|c)&&c>0&&a.setCursor(c-1)})},"Ctrl-X Tab":function(a){a.indentSelection(o(a,!0)||a.getOption("indentUnit"))},"Ctrl-X Ctrl-X":function(a){a.setSelection(a.getCursor("head"),a.getCursor("anchor"))},"Ctrl-X Ctrl-S":"save","Ctrl-X Ctrl-W":"save","Ctrl-X S":"saveAll","Ctrl-X F":"open","Ctrl-X U":p("undo"),"Ctrl-X K":"close",&q
 uot;Ctrl-X Delete":function(a){g(a,a.getCursor(),m(a,a.getCursor(),1),!0)},"Ctrl-X H":"selectAll","Ctrl-Q Tab":p("insertTab"),"Ctrl-U":y}),M={"Ctrl-G":w},N=0;N<10;++N)G(String(N));G("-")})},{"../lib/codemirror":59}],57:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../lib/codemirror"),a("../addon/search/searchcursor"),a("../addon/edit/matchbrackets")):"function"==typeof define&&define.amd?define(["../lib/codemirror","../addon/search/searchcursor","../addon/edit/matchbrackets"],d):d(CodeMirror)}(function(a){"use strict";function b(b,c,d){if(d<0&&0==c.ch)return b.clipPos(o(c.line-1));var e=b.getLine(c.line);if(d>0&&c.ch>=e.length)return b.clipPos(o(c.line+1,0));for(var f,g="start",h=c.ch,i=d<0?0:e.length,j=0;h!=i;h+=d,j+
 +){var k=e.charAt(d<0?h-1:h),l="_"!=k&&a.isWordChar(k)?"w":"o";if("w"==l&&k.toUpperCase()==k&&(l="W"),"start"==g)"o"!=l&&(g="in",f=l);else if("in"==g&&f!=l){if("w"==f&&"W"==l&&d<0&&h--,"W"==f&&"w"==l&&d>0){f="w";continue}break}}return o(c.line,h)}function c(a,c){a.extendSelectionsBy(function(d){return a.display.shift||a.doc.extend||d.empty()?b(a.doc,d.head,c):c<0?d.from():d.to()})}function d(b,c){return b.isReadOnly()?a.Pass:(b.operation(function(){for(var a=b.listSelections().length,d=[],e=-1,f=0;f<a;f++){var g=b.listSelections()[f].head;if(!(g.line<=e)){var h=o(g.line+(c?0:1),0);b.replaceRange("\n",h,null,"+insertLine"),b.indentLine(h.line,null,!0),
+d.push({head:h,anchor:h}),e=g.line+1}}b.setSelections(d)}),void b.execCommand("indentAuto"))}function e(b,c){for(var d=c.ch,e=d,f=b.getLine(c.line);d&&a.isWordChar(f.charAt(d-1));)--d;for(;e<f.length&&a.isWordChar(f.charAt(e));)++e;return{from:o(c.line,d),to:o(c.line,e),word:f.slice(d,e)}}function f(a,b){for(var c=a.listSelections(),d=[],e=0;e<c.length;e++){var f=c[e],g=a.findPosV(f.anchor,b,"line"),h=a.findPosV(f.head,b,"line"),i={anchor:g,head:h};d.push(f),d.push(i)}a.setSelections(d)}function g(a,b,c){for(var d=0;d<a.length;d++)if(a[d].from()==b&&a[d].to()==c)return!0;return!1}function h(a){for(var b=a.listSelections(),c=[],d=0;d<b.length;d++){var e=b[d],f=e.head,g=a.scanForBracket(f,-1);if(!g)return!1;for(;;){var h=a.scanForBracket(f,1);if(!h)return!1;if(h.ch==u.charAt(u.indexOf(g.ch)+1)){c.push({anchor:o(g.pos.line,g.pos.ch+1),head:h.pos});break}f=o(h.pos.line,h.pos.ch+1)}}return a.setSelections(c),!0}function i(
 b,c){if(b.isReadOnly())return a.Pass;for(var d,e=b.listSelections(),f=[],g=0;g<e.length;g++){var h=e[g];if(!h.empty()){for(var i=h.from().line,j=h.to().line;g<e.length-1&&e[g+1].from().line==j;)j=e[++g].to().line;e[g].to().ch||j--,f.push(i,j)}}f.length?d=!0:f.push(b.firstLine(),b.lastLine()),b.operation(function(){for(var a=[],e=0;e<f.length;e+=2){var g=f[e],h=f[e+1],i=o(g,0),j=o(h),k=b.getRange(i,j,!1);c?k.sort():k.sort(function(a,b){var c=a.toUpperCase(),d=b.toUpperCase();return c!=d&&(a=c,b=d),a<b?-1:a==b?0:1}),b.replaceRange(k,i,j),d&&a.push({anchor:i,head:o(h+1,0)})}d&&b.setSelections(a,0)})}function j(b,c){b.operation(function(){for(var d=b.listSelections(),f=[],g=[],h=0;h<d.length;h++){var i=d[h];i.empty()?(f.push(h),g.push("")):g.push(c(b.getRange(i.from(),i.to())))}b.replaceSelections(g,"around","case");for(var j,h=f.length-1;h>=0;h--){var i=d[f[h]];if(!(j&&a.cmpPos(i.head,j)>0)){var 
 k=e(b,i.head);j=k.from,b.replaceRange(c(k.word),k.from,k.to)}}})}function k(b){var c=b.getCursor("from"),d=b.getCursor("to");if(0==a.cmpPos(c,d)){var f=e(b,c);if(!f.word)return;c=f.from,d=f.to}return{from:c,to:d,query:b.getRange(c,d),word:f}}function l(a,b){var c=k(a);if(c){var d=c.query,e=a.getSearchCursor(d,b?c.to:c.from);(b?e.findNext():e.findPrevious())?a.setSelection(e.from(),e.to()):(e=a.getSearchCursor(d,b?o(a.firstLine(),0):a.clipPos(o(a.lastLine()))),(b?e.findNext():e.findPrevious())?a.setSelection(e.from(),e.to()):c.word&&a.setSelection(c.from,c.to))}}var m=a.keyMap.sublime={fallthrough:"default"},n=a.commands,o=a.Pos,p=a.keyMap["default"]==a.keyMap.macDefault,q=p?"Cmd-":"Ctrl-",r=p?"Ctrl-":"Alt-";n[m[r+"Left"]="goSubwordLeft"]=function(a){c(a,-1)},n[m[r+"Right"]="goSubwordRight"]=function(a){c(a,1)},p&&(m["Cmd-Left"]="goLin
 eStartSmart");var s=p?"Ctrl-Alt-":"Ctrl-";n[m[s+"Up"]="scrollLineUp"]=function(a){var b=a.getScrollInfo();if(!a.somethingSelected()){var c=a.lineAtHeight(b.top+b.clientHeight,"local");a.getCursor().line>=c&&a.execCommand("goLineUp")}a.scrollTo(null,b.top-a.defaultTextHeight())},n[m[s+"Down"]="scrollLineDown"]=function(a){var b=a.getScrollInfo();if(!a.somethingSelected()){var c=a.lineAtHeight(b.top,"local")+1;a.getCursor().line<=c&&a.execCommand("goLineDown")}a.scrollTo(null,b.top+a.defaultTextHeight())},n[m["Shift-"+q+"L"]="splitSelectionByLine"]=function(a){for(var b=a.listSelections(),c=[],d=0;d<b.length;d++)for(var e=b[d].from(),f=b[d].to(),g=e.line;g<=f.line;++g)f.line>e.line&&g==f.line&&0==f.ch||c.push({anchor:g==e.line?e:o(g,0),head:g==f.line?f:o(g)});a.setSelections(c,0)},m["Shift-Tab"]=
 "indentLess",n[m.Esc="singleSelectionTop"]=function(a){var b=a.listSelections()[0];a.setSelection(b.anchor,b.head,{scroll:!1})},n[m[q+"L"]="selectLine"]=function(a){for(var b=a.listSelections(),c=[],d=0;d<b.length;d++){var e=b[d];c.push({anchor:o(e.from().line,0),head:o(e.to().line+1,0)})}a.setSelections(c)},m["Shift-Ctrl-K"]="deleteLine",n[m[q+"Enter"]="insertLineAfter"]=function(a){return d(a,!1)},n[m["Shift-"+q+"Enter"]="insertLineBefore"]=function(a){return d(a,!0)},n[m[q+"D"]="selectNextOccurrence"]=function(b){var c=b.getCursor("from"),d=b.getCursor("to"),f=b.state.sublimeFindFullWord==b.doc.sel;if(0==a.cmpPos(c,d)){var h=e(b,c);if(!h.word)return;b.setSelection(h.from,h.to),f=!0}else{var i=b.getRange(c,d),j=f?new RegExp("\\b"+i+"\\b"):i,k=b.getSearchCursor(j,d),l=k.findNext();if(l||(k=b.getSearchCursor(j,o(
 b.firstLine(),0)),l=k.findNext()),!l||g(b.listSelections(),k.from(),k.to()))return a.Pass;b.addSelection(k.from(),k.to())}f&&(b.state.sublimeFindFullWord=b.doc.sel)};var t=p?"Shift-Cmd":"Alt-Ctrl";n[m[t+"Up"]="addCursorToPrevLine"]=function(a){f(a,-1)},n[m[t+"Down"]="addCursorToNextLine"]=function(a){f(a,1)};var u="(){}[]";n[m["Shift-"+q+"Space"]="selectScope"]=function(a){h(a)||a.execCommand("selectAll")},n[m["Shift-"+q+"M"]="selectBetweenBrackets"]=function(b){if(!h(b))return a.Pass},n[m[q+"M"]="goToBracket"]=function(b){b.extendSelectionsBy(function(c){var d=b.scanForBracket(c.head,1);if(d&&0!=a.cmpPos(d.pos,c.head))return d.pos;var e=b.scanForBracket(c.head,-1);return e&&o(e.pos.line,e.pos.ch+1)||c.head})};var v=p?"Cmd-Ctrl-":"Shift-Ctrl-";n[m[v+"Up"]="swapLineUp&
 quot;]=function(b){if(b.isReadOnly())return a.Pass;for(var c=b.listSelections(),d=[],e=b.firstLine()-1,f=[],g=0;g<c.length;g++){var h=c[g],i=h.from().line-1,j=h.to().line;f.push({anchor:o(h.anchor.line-1,h.anchor.ch),head:o(h.head.line-1,h.head.ch)}),0!=h.to().ch||h.empty()||--j,i>e?d.push(i,j):d.length&&(d[d.length-1]=j),e=j}b.operation(function(){for(var a=0;a<d.length;a+=2){var c=d[a],e=d[a+1],g=b.getLine(c);b.replaceRange("",o(c,0),o(c+1,0),"+swapLine"),e>b.lastLine()?b.replaceRange("\n"+g,o(b.lastLine()),null,"+swapLine"):b.replaceRange(g+"\n",o(e,0),null,"+swapLine")}b.setSelections(f),b.scrollIntoView()})},n[m[v+"Down"]="swapLineDown"]=function(b){if(b.isReadOnly())return a.Pass;for(var c=b.listSelections(),d=[],e=b.lastLine()+1,f=c.length-1;f>=0;f--){var g=c[f],h=g.to().line+1,i=g.from().line;0!=g.to().ch||g.empty()||h--,h<e?d.push(h,i):d.length&&(d[d.length-1]=i
 ),e=i}b.operation(function(){for(var a=d.length-2;a>=0;a-=2){var c=d[a],e=d[a+1],f=b.getLine(c);c==b.lastLine()?b.replaceRange("",o(c-1),o(c),"+swapLine"):b.replaceRange("",o(c,0),o(c+1,0),"+swapLine"),b.replaceRange(f+"\n",o(e,0),null,"+swapLine")}b.scrollIntoView()})},n[m[q+"/"]="toggleCommentIndented"]=function(a){a.toggleComment({indent:!0})},n[m[q+"J"]="joinLines"]=function(a){for(var b=a.listSelections(),c=[],d=0;d<b.length;d++){for(var e=b[d],f=e.from(),g=f.line,h=e.to().line;d<b.length-1&&b[d+1].from().line==h;)h=b[++d].to().line;c.push({start:g,end:h,anchor:!e.empty()&&f})}a.operation(function(){for(var b=0,d=[],e=0;e<c.length;e++){for(var f,g=c[e],h=g.anchor&&o(g.anchor.line-b,g.anchor.ch),i=g.start;i<=g.end;i++){var j=i-b;i==g.end&&(f=o(j,a.getLine(j).length+1)),j<a.lastLine()&&(a.replaceRange(" ",o(j),o(j+
 1,/^\s*/.exec(a.getLine(j+1))[0].length)),++b)}d.push({anchor:h||f,head:f})}a.setSelections(d,0)})},n[m["Shift-"+q+"D"]="duplicateLine"]=function(a){a.operation(function(){for(var b=a.listSelections().length,c=0;c<b;c++){var d=a.listSelections()[c];d.empty()?a.replaceRange(a.getLine(d.head.line)+"\n",o(d.head.line,0)):a.replaceRange(a.getRange(d.from(),d.to()),d.from())}a.scrollIntoView()})},p||(m[q+"T"]="transposeChars"),n[m.F9="sortLines"]=function(a){i(a,!0)},n[m[q+"F9"]="sortLinesInsensitive"]=function(a){i(a,!1)},n[m.F2="nextBookmark"]=function(a){var b=a.state.sublimeBookmarks;if(b)for(;b.length;){var c=b.shift(),d=c.find();if(d)return b.push(c),a.setSelection(d.from,d.to)}},n[m["Shift-F2"]="prevBookmark"]=function(a){var b=a.state.sublimeBookmarks;if(b)for(;b.length;){b.unshift(b.pop());var c=b[b.length-1].find();if(c)return a.setSelection(c.from,c.to);b.
 pop()}},n[m[q+"F2"]="toggleBookmark"]=function(a){for(var b=a.listSelections(),c=a.state.sublimeBookmarks||(a.state.sublimeBookmarks=[]),d=0;d<b.length;d++){for(var e=b[d].from(),f=b[d].to(),g=a.findMarks(e,f),h=0;h<g.length;h++)if(g[h].sublimeBookmark){g[h].clear();for(var i=0;i<c.length;i++)c[i]==g[h]&&c.splice(i--,1);break}h==g.length&&c.push(a.markText(e,f,{sublimeBookmark:!0,clearWhenEmpty:!1}))}},n[m["Shift-"+q+"F2"]="clearBookmarks"]=function(a){var b=a.state.sublimeBookmarks;if(b)for(var c=0;c<b.length;c++)b[c].clear();b.length=0},n[m["Alt-F2"]="selectBookmarks"]=function(a){var b=a.state.sublimeBookmarks,c=[];if(b)for(var d=0;d<b.length;d++){var e=b[d].find();e?c.push({anchor:e.from,head:e.to}):b.splice(d--,0)}c.length&&a.setSelections(c,0)},m["Alt-Q"]="wrapLines";var w=q+"K ";m[w+q+"Backspace"]="delLineLeft",n[m.Back
 space="smartBackspace"]=function(b){return b.somethingSelected()?a.Pass:void b.operation(function(){for(var c=b.listSelections(),d=b.getOption("indentUnit"),e=c.length-1;e>=0;e--){var f=c[e].head,g=b.getRange({line:f.line,ch:0},f),h=a.countColumn(g,null,b.getOption("tabSize")),i=b.findPosH(f,-1,"char",!1);if(g&&!/\S/.test(g)&&h%d==0){var j=new o(f.line,a.findColumn(g,h-d,d));j.ch!=f.ch&&(i=j)}b.replaceRange("",i,f,"+delete")}})},n[m[w+q+"K"]="delLineRight"]=function(a){a.operation(function(){for(var b=a.listSelections(),c=b.length-1;c>=0;c--)a.replaceRange("",b[c].anchor,o(b[c].to().line),"+delete");a.scrollIntoView()})},n[m[w+q+"U"]="upcaseAtCursor"]=function(a){j(a,function(a){return a.toUpperCase()})},n[m[w+q+"L"]="downcaseAtCursor"]=function(a){j(a,function(a){return a.toLowerCase()})},n[m[w+q+"Space"]
 ="setSublimeMark"]=function(a){a.state.sublimeMark&&a.state.sublimeMark.clear(),a.state.sublimeMark=a.setBookmark(a.getCursor())},n[m[w+q+"A"]="selectToSublimeMark"]=function(a){var b=a.state.sublimeMark&&a.state.sublimeMark.find();b&&a.setSelection(a.getCursor(),b)},n[m[w+q+"W"]="deleteToSublimeMark"]=function(b){var c=b.state.sublimeMark&&b.state.sublimeMark.find();if(c){var d=b.getCursor(),e=c;if(a.cmpPos(d,e)>0){var f=e;e=d,d=f}b.state.sublimeKilled=b.getRange(d,e),b.replaceRange("",d,e)}},n[m[w+q+"X"]="swapWithSublimeMark"]=function(a){var b=a.state.sublimeMark&&a.state.sublimeMark.find();b&&(a.state.sublimeMark.clear(),a.state.sublimeMark=a.setBookmark(a.getCursor()),a.setCursor(b))},n[m[w+q+"Y"]="sublimeYank"]=function(a){null!=a.state.sublimeKilled&&a.replaceSelection(a.state.sublimeKilled,null,"paste")},m[w+
 q+"G"]="clearBookmarks",n[m[w+q+"C"]="showInCenter"]=function(a){var b=a.cursorCoords(null,"local");a.scrollTo(null,(b.top+b.bottom)/2-a.getScrollInfo().clientHeight/2)};var x=p?"Ctrl-Shift-":"Ctrl-Alt-";n[m[x+"Up"]="selectLinesUpward"]=function(a){a.operation(function(){for(var b=a.listSelections(),c=0;c<b.length;c++){var d=b[c];d.head.line>a.firstLine()&&a.addSelection(o(d.head.line-1,d.head.ch))}})},n[m[x+"Down"]="selectLinesDownward"]=function(a){a.operation(function(){for(var b=a.listSelections(),c=0;c<b.length;c++){var d=b[c];d.head.line<a.lastLine()&&a.addSelection(o(d.head.line+1,d.head.ch))}})},n[m[q+"F3"]="findUnder"]=function(a){l(a,!0)},n[m["Shift-"+q+"F3"]="findUnderPrevious"]=function(a){l(a,!1)},n[m["Alt-F3"]="findAllUnder"]=function(a){var b=k(a);if(b){for(var c=
 a.getSearchCursor(b.query),d=[],e=-1;c.findNext();)d.push({anchor:c.from(),head:c.to()}),c.from().line<=b.from.line&&c.from().ch<=b.from.ch&&e++;a.setSelections(d,e)}},m["Shift-"+q+"["]="fold",m["Shift-"+q+"]"]="unfold",m[w+q+"0"]=m[w+q+"J"]="unfoldAll",m[q+"I"]="findIncremental",m["Shift-"+q+"I"]="findIncrementalReverse",m[q+"H"]="replace",m.F3="findNext",m["Shift-F3"]="findPrev",a.normalizeKeyMap(m)})},{"../addon/edit/matchbrackets":12,"../addon/search/searchcursor":49,"../lib/codemirror":59}],58:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../lib/codemirror"),a("../addon/search/searchcursor"),a("../addon/dialog/dialog"),a("../addon/edit/matchbrackets.j
 s")):"function"==typeof define&&define.amd?define(["../lib/codemirror","../addon/search/searchcursor","../addon/dialog/dialog","../addon/edit/matchbrackets"],d):d(CodeMirror)}(function(a){"use strict";var b=[{keys:"<Left>",type:"keyToKey",toKeys:"h"},{keys:"<Right>",type:"keyToKey",toKeys:"l"},{keys:"<Up>",type:"keyToKey",toKeys:"k"},{keys:"<Down>",type:"keyToKey",toKeys:"j"},{keys:"<Space>",type:"keyToKey",toKeys:"l"},{keys:"<BS>",type:"keyToKey",toKeys:"h",context:"normal"},{keys:"<C-Space>",type:"keyToKey",toKeys:"W"},{keys:"<C-BS>",type:"keyToKey",toKeys:"B",context:"normal"},{keys:"<S-Space>&q
 uot;,type:"keyToKey",toKeys:"w"},{keys:"<S-BS>",type:"keyToKey",toKeys:"b",context:"normal"},{keys:"<C-n>",type:"keyToKey",toKeys:"j"},{keys:"<C-p>",type:"keyToKey",toKeys:"k"},{keys:"<C-[>",type:"keyToKey",toKeys:"<Esc>"},{keys:"<C-c>",type:"keyToKey",toKeys:"<Esc>"},{keys:"<C-[>",type:"keyToKey",toKeys:"<Esc>",context:"insert"},{keys:"<C-c>",type:"keyToKey",toKeys:"<Esc>",context:"insert"},{keys:"s",type:"keyToKey",toKeys:"cl",context:"normal"},{keys:"s",type:"keyToKey",toKeys:"c",context:"visual"},{keys:"S",type:"keyToKey",toKeys:"cc",context:"nor
 mal"},{keys:"S",type:"keyToKey",toKeys:"VdO",context:"visual"},{keys:"<Home>",type:"keyToKey",toKeys:"0"},{keys:"<End>",type:"keyToKey",toKeys:"$"},{keys:"<PageUp>",type:"keyToKey",toKeys:"<C-b>"},{keys:"<PageDown>",type:"keyToKey",toKeys:"<C-f>"},{keys:"<CR>",type:"keyToKey",toKeys:"j^",context:"normal"},{keys:"<Ins>",type:"action",action:"toggleOverwrite",context:"insert"},{keys:"H",type:"motion",motion:"moveToTopLine",motionArgs:{linewise:!0,toJumplist:!0}},{keys:"M",type:"motion",motion:"moveToMiddleLine",motionArgs:{linewise:!0,toJumplist:!0}},{keys:"L",type:"motion",motion:"moveToBottomLine",motionArg
 s:{linewise:!0,toJumplist:!0}},{keys:"h",type:"motion",motion:"moveByCharacters",motionArgs:{forward:!1}},{keys:"l",type:"motion",motion:"moveByCharacters",motionArgs:{forward:!0}},{keys:"j",type:"motion",motion:"moveByLines",motionArgs:{forward:!0,linewise:!0}},{keys:"k",type:"motion",motion:"moveByLines",motionArgs:{forward:!1,linewise:!0}},{keys:"gj",type:"motion",motion:"moveByDisplayLines",motionArgs:{forward:!0}},{keys:"gk",type:"motion",motion:"moveByDisplayLines",motionArgs:{forward:!1}},{keys:"w",type:"motion",motion:"moveByWords",motionArgs:{forward:!0,wordEnd:!1}},{keys:"W",type:"motion",motion:"moveByWords",motionArgs:{forward:!0,wordEnd:!1,bigWord:!0}},{keys:"e",type:"motion",motion:"moveByWords",motionAr
 gs:{forward:!0,wordEnd:!0,inclusive:!0}},{keys:"E",type:"motion",motion:"moveByWords",motionArgs:{forward:!0,wordEnd:!0,bigWord:!0,inclusive:!0}},{keys:"b",type:"motion",motion:"moveByWords",motionArgs:{forward:!1,wordEnd:!1}},{keys:"B",type:"motion",motion:"moveByWords",motionArgs:{forward:!1,wordEnd:!1,bigWord:!0}},{keys:"ge",type:"motion",motion:"moveByWords",motionArgs:{forward:!1,wordEnd:!0,inclusive:!0}},{keys:"gE",type:"motion",motion:"moveByWords",motionArgs:{forward:!1,wordEnd:!0,bigWord:!0,inclusive:!0}},{keys:"{",type:"motion",motion:"moveByParagraph",motionArgs:{forward:!1,toJumplist:!0}},{keys:"}",type:"motion",motion:"moveByParagraph",motionArgs:{forward:!0,toJumplist:!0}},{keys:"<C-f>",type:"motion",motion:"moveByPage",motionA
 rgs:{forward:!0}},{keys:"<C-b>",type:"motion",motion:"moveByPage",motionArgs:{forward:!1}},{keys:"<C-d>",type:"motion",motion:"moveByScroll",motionArgs:{forward:!0,explicitRepeat:!0}},{keys:"<C-u>",type:"motion",motion:"moveByScroll",motionArgs:{forward:!1,explicitRepeat:!0}},{keys:"gg",type:"motion",motion:"moveToLineOrEdgeOfDocument",motionArgs:{forward:!1,explicitRepeat:!0,linewise:!0,toJumplist:!0}},{keys:"G",type:"motion",motion:"moveToLineOrEdgeOfDocument",motionArgs:{forward:!0,explicitRepeat:!0,linewise:!0,toJumplist:!0}},{keys:"0",type:"motion",motion:"moveToStartOfLine"},{keys:"^",type:"motion",motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:"+",type:"motion",motion:"moveByLines",motionArgs:{forward:!0,toFirstChar:!0}
 },{keys:"-",type:"motion",motion:"moveByLines",motionArgs:{forward:!1,toFirstChar:!0}},{keys:"_",type:"motion",motion:"moveByLines",motionArgs:{forward:!0,toFirstChar:!0,repeatOffset:-1}},{keys:"$",type:"motion",motion:"moveToEol",motionArgs:{inclusive:!0}},{keys:"%",type:"motion",motion:"moveToMatchedSymbol",motionArgs:{inclusive:!0,toJumplist:!0}},{keys:"f<character>",type:"motion",motion:"moveToCharacter",motionArgs:{forward:!0,inclusive:!0}},{keys:"F<character>",type:"motion",motion:"moveToCharacter",motionArgs:{forward:!1}},{keys:"t<character>",type:"motion",motion:"moveTillCharacter",motionArgs:{forward:!0,inclusive:!0}},{keys:"T<character>",type:"motion",motion:"moveTillCharacter",motionArgs:{forward:!1}},{keys:&quot
 ;;",type:"motion",motion:"repeatLastCharacterSearch",motionArgs:{forward:!0}},{keys:",",type:"motion",motion:"repeatLastCharacterSearch",motionArgs:{forward:!1}},{keys:"'<character>",type:"motion",motion:"goToMark",motionArgs:{toJumplist:!0,linewise:!0}},{keys:"`<character>",type:"motion",motion:"goToMark",motionArgs:{toJumplist:!0}},{keys:"]`",type:"motion",motion:"jumpToMark",motionArgs:{forward:!0}},{keys:"[`",type:"motion",motion:"jumpToMark",motionArgs:{forward:!1}},{keys:"]'",type:"motion",motion:"jumpToMark",motionArgs:{forward:!0,linewise:!0}},{keys:"['",type:"motion",motion:"jumpToMark",motionArgs:{forward:!1,linewise:!0}},{keys:"]p",type:"action",action:"paste",isEdit:!0,actionArgs:{after:!0,isEdit:!0
 ,matchIndent:!0}},{keys:"[p",type:"action",action:"paste",isEdit:!0,actionArgs:{after:!1,isEdit:!0,matchIndent:!0}},{keys:"]<character>",type:"motion",motion:"moveToSymbol",motionArgs:{forward:!0,toJumplist:!0}},{keys:"[<character>",type:"motion",motion:"moveToSymbol",motionArgs:{forward:!1,toJumplist:!0}},{keys:"|",type:"motion",motion:"moveToColumn"},{keys:"o",type:"motion",motion:"moveToOtherHighlightedEnd",context:"visual"},{keys:"O",type:"motion",motion:"moveToOtherHighlightedEnd",motionArgs:{sameLine:!0},context:"visual"},{keys:"d",type:"operator",operator:"delete"},{keys:"y",type:"operator",operator:"yank"},{keys:"c",type:"operator",operator:"change"},{keys:">",type:
 "operator",operator:"indent",operatorArgs:{indentRight:!0}},{keys:"<",type:"operator",operator:"indent",operatorArgs:{indentRight:!1}},{keys:"g~",type:"operator",operator:"changeCase"},{keys:"gu",type:"operator",operator:"changeCase",operatorArgs:{toLower:!0},isEdit:!0},{keys:"gU",type:"operator",operator:"changeCase",operatorArgs:{toLower:!1},isEdit:!0},{keys:"n",type:"motion",motion:"findNext",motionArgs:{forward:!0,toJumplist:!0}},{keys:"N",type:"motion",motion:"findNext",motionArgs:{forward:!1,toJumplist:!0}},{keys:"x",type:"operatorMotion",operator:"delete",motion:"moveByCharacters",motionArgs:{forward:!0},operatorMotionArgs:{visualLine:!1}},{keys:"X",type:"operatorMotion",operator:"delete",motion:"moveBy
 Characters",motionArgs:{forward:!1},operatorMotionArgs:{visualLine:!0}},{keys:"D",type:"operatorMotion",operator:"delete",motion:"moveToEol",motionArgs:{inclusive:!0},context:"normal"},{keys:"D",type:"operator",operator:"delete",operatorArgs:{linewise:!0},context:"visual"},{keys:"Y",type:"operatorMotion",operator:"yank",motion:"expandToLine",motionArgs:{linewise:!0},context:"normal"},{keys:"Y",type:"operator",operator:"yank",operatorArgs:{linewise:!0},context:"visual"},{keys:"C",type:"operatorMotion",operator:"change",motion:"moveToEol",motionArgs:{inclusive:!0},context:"normal"},{keys:"C",type:"operator",operator:"change",operatorArgs:{linewise:!0},context:"visual"},{keys:"~",type:"operatorMotion&
 quot;,operator:"changeCase",motion:"moveByCharacters",motionArgs:{forward:!0},operatorArgs:{shouldMoveCursor:!0},context:"normal"},{keys:"~",type:"operator",operator:"changeCase",context:"visual"},{keys:"<C-w>",type:"operatorMotion",operator:"delete",motion:"moveByWords",motionArgs:{forward:!1,wordEnd:!1},context:"insert"},{keys:"<C-i>",type:"action",action:"jumpListWalk",actionArgs:{forward:!0}},{keys:"<C-o>",type:"action",action:"jumpListWalk",actionArgs:{forward:!1}},{keys:"<C-e>",type:"action",action:"scroll",actionArgs:{forward:!0,linewise:!0}},{keys:"<C-y>",type:"action",action:"scroll",actionArgs:{forward:!1,linewise:!0}},{keys:"a",type:"action",action:"enterInsertMode",isEdit:!0,a
 ctionArgs:{insertAt:"charAfter"},context:"normal"},{keys:"A",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{insertAt:"eol"},context:"normal"},{keys:"A",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{insertAt:"endOfSelectedArea"},context:"visual"},{keys:"i",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{insertAt:"inplace"},context:"normal"},{keys:"I",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{insertAt:"firstNonBlank"},context:"normal"},{keys:"I",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{insertAt:"startOfSelectedArea"},context:"visual"},{keys:"o",type:"action",action:"newLineAndEnterInsertMode",isEdit:!0,interlac
 eInsertRepeat:!0,actionArgs:{after:!0},context:"normal"},{keys:"O",type:"action",action:"newLineAndEnterInsertMode",isEdit:!0,interlaceInsertRepeat:!0,actionArgs:{after:!1},context:"normal"},{keys:"v",type:"action",action:"toggleVisualMode"},{keys:"V",type:"action",action:"toggleVisualMode",actionArgs:{linewise:!0}},{keys:"<C-v>",type:"action",action:"toggleVisualMode",actionArgs:{blockwise:!0}},{keys:"<C-q>",type:"action",action:"toggleVisualMode",actionArgs:{blockwise:!0}},{keys:"gv",type:"action",action:"reselectLastSelection"},{keys:"J",type:"action",action:"joinLines",isEdit:!0},{keys:"p",type:"action",action:"paste",isEdit:!0,actionArgs:{after:!0,isEdit:!0}},{keys:"P",type:"action",action:&
 quot;paste",isEdit:!0,actionArgs:{after:!1,isEdit:!0}},{keys:"r<character>",type:"action",action:"replace",isEdit:!0},{keys:"@<character>",type:"action",action:"replayMacro"},{keys:"q<character>",type:"action",action:"enterMacroRecordMode"},{keys:"R",type:"action",action:"enterInsertMode",isEdit:!0,actionArgs:{replace:!0}},{keys:"u",type:"action",action:"undo",context:"normal"},{keys:"u",type:"operator",operator:"changeCase",operatorArgs:{toLower:!0},context:"visual",isEdit:!0},{keys:"U",type:"operator",operator:"changeCase",operatorArgs:{toLower:!1},context:"visual",isEdit:!0},{keys:"<C-r>",type:"action",action:"redo"},{keys:"m<character>",type:"action",action:&q
 uot;setMark"},{keys:'"<character>',type:"action",action:"setRegister"},{keys:"zz",type:"action",action:"scrollToCursor",actionArgs:{position:"center"}},{keys:"z.",type:"action",action:"scrollToCursor",actionArgs:{position:"center"},motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:"zt",type:"action",action:"scrollToCursor",actionArgs:{position:"top"}},{keys:"z<CR>",type:"action",action:"scrollToCursor",actionArgs:{position:"top"},motion:"moveToFirstNonWhiteSpaceCharacter"},{keys:"z-",type:"action",action:"scrollToCursor",actionArgs:{position:"bottom"}},{keys:"zb",type:"action",action:"scrollToCursor",actionArgs:{position:"bottom"},motion:"moveToFirstNonWhiteSpaceCharacter"},{k
 eys:".",type:"action",action:"repeatLastEdit"},{keys:"<C-a>",type:"action",action:"incrementNumberToken",isEdit:!0,actionArgs:{increase:!0,backtrack:!1}},{keys:"<C-x>",type:"action",action:"incrementNumberToken",isEdit:!0,actionArgs:{increase:!1,backtrack:!1}},{keys:"<C-t>",type:"action",action:"indent",actionArgs:{indentRight:!0},context:"insert"},{keys:"<C-d>",type:"action",action:"indent",actionArgs:{indentRight:!1},context:"insert"},{keys:"a<character>",type:"motion",motion:"textObjectManipulation"},{keys:"i<character>",type:"motion",motion:"textObjectManipulation",motionArgs:{textObjectInner:!0}},{keys:"/",type:"search",searchArgs:{forward:!0,querySrc:"prompt",toJumplist:!0}},{keys:&quot
 ;?",type:"search",searchArgs:{forward:!1,querySrc:"prompt",toJumplist:!0}},{keys:"*",type:"search",searchArgs:{forward:!0,querySrc:"wordUnderCursor",wholeWordOnly:!0,toJumplist:!0}},{keys:"#",type:"search",searchArgs:{forward:!1,querySrc:"wordUnderCursor",wholeWordOnly:!0,toJumplist:!0}},{keys:"g*",type:"search",searchArgs:{forward:!0,querySrc:"wordUnderCursor",toJumplist:!0}},{keys:"g#",type:"search",searchArgs:{forward:!1,querySrc:"wordUnderCursor",toJumplist:!0}},{keys:":",type:"ex"}],c=[{name:"colorscheme",shortName:"colo"},{name:"map"},{name:"imap",shortName:"im"},{name:"nmap",shortName:"nm"},{name:"vmap",shortName:"vm"},{name:"unmap"},{name:"write",shortName:"w"},{name:"undo",shortName:&
 quot;u"},{name:"redo",shortName:"red"},{name:"set",shortName:"se"},{name:"set",shortName:"se"},{name:"setlocal",shortName:"setl"},{name:"setglobal",shortName:"setg"},{name:"sort",shortName:"sor"},{name:"substitute",shortName:"s",possiblyAsync:!0},{name:"nohlsearch",shortName:"noh"},{name:"yank",shortName:"y"},{name:"delmarks",shortName:"delm"},{name:"registers",shortName:"reg",excludeFromCommandHistory:!0},{name:"global",shortName:"g"}],d=a.Pos,e=function(){function e(b){b.setOption("disableInput",!0),b.setOption("showCursorWhenSelecting",!1),a.signal(b,"vim-mode-change",{mode:"normal"}),b.on("cursorActivity",bb),x(b),a.on(b.getInputField(),"paste",k(b))}function f(b){b.setOption(&qu
 ot;disableInput",!1),b.off("cursorActivity",bb),a.off(b.getInputField(),"paste",k(b)),b.state.vim=null}function g(b,c){this==a.keyMap.vim&&a.rmClass(b.getWrapperElement(),"cm-fat-cursor"),c&&c.attach==h||f(b)}function h(b,c){this==a.keyMap.vim&&a.addClass(b.getWrapperElement(),"cm-fat-cursor"),c&&c.attach==h||e(b)}function i(b,c){if(c){if(this[b])return this[b];var d=j(b);if(!d)return!1;var e=a.Vim.findKey(c,d);return"function"==typeof e&&a.signal(c,"vim-keypress",d),e}}function j(a){if("'"==a.charAt(0))return a.charAt(1);var b=a.split(/-(?!$)/),c=b[b.length-1];if(1==b.length&&1==b[0].length)return!1;if(2==b.length&&"Shift"==b[0]&&1==c.length)return!1;for(var d=!1,e=0;e<b.length;e++){var f=b[e];f in ib?b[e]=ib[f]:d=!0,f in jb&&(b[e]=jb[f])}return!!d&&(q(c)&&(b[b.length-1]=c.toLowerCase()),"<"+b.jo
 in("-")+">")}function k(a){var b=a.state.vim;return b.onPasteFn||(b.onPasteFn=function(){b.insertMode||(a.setCursor(L(a.getCursor(),0,1)),Bb.enterInsertMode(a,{},b))}),b.onPasteFn}function l(a,b){for(var c=[],d=a;d<a+b;d++)c.push(String.fromCharCode(d));return c}function m(a,b){return b>=a.firstLine()&&b<=a.lastLine()}function n(a){return/^[a-z]$/.test(a)}function o(a){return"()[]{}".indexOf(a)!=-1}function p(a){return kb.test(a)}function q(a){return/^[A-Z]$/.test(a)}function r(a){return/^\s*$/.test(a)}function s(a,b){for(var c=0;c<b.length;c++)if(b[c]==a)return!0;return!1}function t(a,b,c,d,e){if(void 0===b&&!e)throw Error("defaultValue is required unless callback is provided");if(c||(c="string"),sb[a]={type:c,defaultValue:b,callback:e},d)for(var f=0;f<d.length;f++)sb[d[f]]=sb[a];b&&u(a,b)}function u(a,b,c,d){var e=sb[a];d=d||{};var f=d.scope;if(!e)return new Error("Unknown option: &quo
 t;+a);if("boolean"==e.type){if(b&&b!==!0)return new Error("Invalid argument: "+a+"="+b);b!==!1&&(b=!0)}e.callback?("local"!==f&&e.callback(b,void 0),"global"!==f&&c&&e.callback(b,c)):("local"!==f&&(e.value="boolean"==e.type?!!b:b),"global"!==f&&c&&(c.state.vim.options[a]={value:b}))}function v(a,b,c){var d=sb[a];c=c||{};var e=c.scope;if(!d)return new Error("Unknown option: "+a);{if(!d.callback){var f="global"!==e&&b&&b.state.vim.options[a];return(f||"local"!==e&&d||{}).value}var f=b&&d.callback(void 0,b);if("global"!==e&&void 0!==f)return f;if("local"!==e)return d.callback()}}function w(){this.latestRegister=void 0,this.isPlaying=!1,this.isRecording=!1,this.replaySearchQueries=[],this.onRecordingDone=void 0,this.lastInsertModeChanges=ub()}function x(a){
 return a.state.vim||(a.state.vim={inputState:new z,lastEditInputState:void 0,lastEditActionCommand:void 0,lastHPos:-1,lastHSPos:-1,lastMotion:null,marks:{},fakeCursor:null,insertMode:!1,insertModeRepeat:void 0,visualMode:!1,visualLine:!1,visualBlock:!1,lastSelection:null,lastPastedText:null,sel:{},options:{}}),a.state.vim}function y(){vb={searchQuery:null,searchIsReversed:!1,lastSubstituteReplacePart:void 0,jumpList:tb(),macroModeState:new w,lastCharacterSearch:{increment:0,forward:!0,selectedCharacter:""},registerController:new D({}),searchHistoryController:new E,exCommandHistoryController:new E};for(var a in sb){var b=sb[a];b.value=b.defaultValue}}function z(){this.prefixRepeat=[],this.motionRepeat=[],this.operator=null,this.operatorArgs=null,this.motion=null,this.motionArgs=null,this.keyBuffer=[],this.registerName=null}function A(b,c){b.state.vim.inputState=new z,a.signal(b,"vim-command-done",c)}function B(a,b,c){this.clear(),this.keyBuffer=[a||""],t
 his.insertModeChanges=[],this.searchQueries=[],this.linewise=!!b,this.blockwise=!!c}function C(a,b){var c=vb.registerController.registers;if(!a||1!=a.length)throw Error("Register name must be 1 character");if(c[a])throw Error("Register already defined "+a);c[a]=b,rb.push(a)}function D(a){this.registers=a,this.unnamedRegister=a['"']=new B,a["."]=new B,a[":"]=new B,a["/"]=new B}function E(){this.historyBuffer=[],this.iterator=0,this.initialPrefix=null}function F(a,b){zb[a]=b}function G(a,b){for(var c=[],d=0;d<b;d++)c.push(a);return c}function H(a,b){Ab[a]=b}function I(a,b){Bb[a]=b}function J(a,b,c){var e=Math.min(Math.max(a.firstLine(),b.line),a.lastLine()),f=X(a,e)-1;f=c?f+1:f;var g=Math.min(Math.max(0,b.ch),f);return d(e,g)}function K(a){var b={};for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b}function L(a,b,c){return"object"==typeof b&&(c=b.ch,b=b.line),d(a.line+b,a.ch+c)}function M(a,b){re
 turn{line:b.line-a.line,ch:b.line-a.line}}function N(a,b,c,d){for(var e,f=[],g=[],h=0;h<b.length;h++){var i=b[h];"insert"==c&&"insert"!=i.context||i.context&&i.context!=c||d.operator&&"action"==i.type||!(e=O(a,i.keys))||("partial"==e&&f.push(i),"full"==e&&g.push(i))}return{partial:f.length&&f,full:g.length&&g}}function O(a,b){if("<character>"==b.slice(-11)){var c=b.length-11,d=a.slice(0,c),e=b.slice(0,c);return d==e&&a.length>c?"full":0==e.indexOf(d)&&"partial"}return a==b?"full":0==b.indexOf(a)&&"partial"}function P(a){var b=/^.*(<[^>]+>)$/.exec(a),c=b?b[1]:a.slice(-1);if(c.length>1)switch(c){case"<CR>":c="\n";break;case"<Space>":c=" ";break;default:c=""}return c}function Q(a,b,c){return function(){for(var d=0;d<c;d++
 )b(a)}}function R(a){return d(a.line,a.ch)}function S(a,b){return a.ch==b.ch&&a.line==b.line}function T(a,b){return a.line<b.line||a.line==b.line&&a.ch<b.ch}function U(a,b){return arguments.length>2&&(b=U.apply(void 0,Array.prototype.slice.call(arguments,1))),T(a,b)?a:b}function V(a,b){return arguments.length>2&&(b=V.apply(void 0,Array.prototype.slice.call(arguments,1))),T(a,b)?b:a}function W(a,b,c){var d=T(a,b),e=T(b,c);return d&&e}function X(a,b){return a.getLine(b).length}function Y(a){return a.trim?a.trim():a.replace(/^\s+|\s+$/g,"")}function Z(a){return a.replace(/([.?*+$\[\]\/\\(){}|\-])/g,"\\$1")}function $(a,b,c){var e=X(a,b),f=new Array(c-e+1).join(" ");a.setCursor(d(b,e)),a.replaceRange(f,a.getCursor())}function _(a,b){var c=[],e=a.listSelections(),f=R(a.clipPos(b)),g=!S(b,f),h=a.getCursor("head"),i=ba(e,h),j=S(e[i].head,e[i].anchor),k=e.length-1,l=k-i>i?k:0,m=e[l].anchor,n=Math.
 min(m.line,f.line),o=Math.max(m.line,f.line),p=m.ch,q=f.ch,r=e[l].head.ch-p,s=q-p;r>0&&s<=0?(p++,g||q--):r<0&&s>=0?(p--,j||q++):r<0&&s==-1&&(p--,q++);for(var t=n;t<=o;t++){var u={anchor:new d(t,p),head:new d(t,q)};c.push(u)}return a.setSelections(c),b.ch=q,m.ch=p,m}function aa(a,b,c){for(var d=[],e=0;e<c;e++){var f=L(b,e,0);d.push({anchor:f,head:f})}a.setSelections(d,0)}function ba(a,b,c){for(var d=0;d<a.length;d++){var e="head"!=c&&S(a[d].anchor,b),f="anchor"!=c&&S(a[d].head,b);if(e||f)return d}return-1}function ca(a,b){var c=b.lastSelection,e=function(){var b=a.listSelections(),c=b[0],d=b[b.length-1],e=T(c.anchor,c.head)?c.anchor:c.head,f=T(d.anchor,d.head)?d.head:d.anchor;return[e,f]},f=function(){var b=a.getCursor(),e=a.getCursor(),f=c.visualBlock;if(f){var g=f.width,h=f.height;e=d(b.line+h,b.ch+g);for(var i=[],j=b.line;j<e.line;j++){var k=d(j,b.ch),l=d(j,e.ch),m={anchor:k,head:l};i.pu
 sh(m)}a.setSelections(i)}else{var n=c.anchorMark.find(),o=c.headMark.find(),p=o.line-n.line,q=o.ch-n.ch;e={line:e.line+p,ch:p?e.ch:q+e.ch},c.visualLine&&(b=d(b.line,0),e=d(e.line,X(a,e.line))),a.setSelection(b,e)}return[b,e]};return b.visualMode?e():f()}function da(a,b){var c=b.sel.anchor,d=b.sel.head;b.lastPastedText&&(d=a.posFromIndex(a.indexFromPos(c)+b.lastPastedText.length),b.lastPastedText=null),b.lastSelection={anchorMark:a.setBookmark(c),
+headMark:a.setBookmark(d),anchor:R(c),head:R(d),visualMode:b.visualMode,visualLine:b.visualLine,visualBlock:b.visualBlock}}function ea(a,b,c){var e,f=a.state.vim.sel,g=f.head,h=f.anchor;return T(c,b)&&(e=c,c=b,b=e),T(g,h)?(g=U(b,g),h=V(h,c)):(h=U(b,h),g=V(g,c),g=L(g,0,-1),g.ch==-1&&g.line!=a.firstLine()&&(g=d(g.line-1,X(a,g.line-1)))),[h,g]}function fa(a,b,c){var d=a.state.vim;b=b||d.sel;var c=c||d.visualLine?"line":d.visualBlock?"block":"char",e=ga(a,b,c);a.setSelections(e.ranges,e.primary),cb(a)}function ga(a,b,c,e){var f=R(b.head),g=R(b.anchor);if("char"==c){var h=e||T(b.head,b.anchor)?0:1,i=T(b.head,b.anchor)?1:0;return f=L(b.head,0,h),g=L(b.anchor,0,i),{ranges:[{anchor:g,head:f}],primary:0}}if("line"==c){if(T(b.head,b.anchor))f.ch=0,g.ch=X(a,g.line);else{g.ch=0;var j=a.lastLine();f.line>j&&(f.line=j),f.ch=X(a,f.line)}return{ranges:[{anchor:g,head:f}],primary:0}}if("block"==c){for(var 
 k=Math.min(g.line,f.line),l=Math.min(g.ch,f.ch),m=Math.max(g.line,f.line),n=Math.max(g.ch,f.ch)+1,o=m-k+1,p=f.line==k?0:o-1,q=[],r=0;r<o;r++)q.push({anchor:d(k+r,l),head:d(k+r,n)});return{ranges:q,primary:p}}}function ha(a){var b=a.getCursor("head");return 1==a.getSelection().length&&(b=U(b,a.getCursor("anchor"))),b}function ia(b,c){var d=b.state.vim;c!==!1&&b.setCursor(J(b,d.sel.head)),da(b,d),d.visualMode=!1,d.visualLine=!1,d.visualBlock=!1,a.signal(b,"vim-mode-change",{mode:"normal"}),d.fakeCursor&&d.fakeCursor.clear()}function ja(a,b,c){var d=a.getRange(b,c);if(/\n\s*$/.test(d)){var e=d.split("\n");e.pop();for(var f,f=e.pop();e.length>0&&f&&r(f);f=e.pop())c.line--,c.ch=0;f?(c.line--,c.ch=X(a,c.line)):c.ch=0}}function ka(a,b,c){b.ch=0,c.ch=0,c.line++}function la(a){if(!a)return 0;var b=a.search(/\S/);return b==-1?a.length:b}function ma(a,b,c,e,f){for(var g=ha(a),h=a.getLine(g.line),i=g
 .ch,j=f?lb[0]:mb[0];!j(h.charAt(i));)if(i++,i>=h.length)return null;e?j=mb[0]:(j=lb[0],j(h.charAt(i))||(j=lb[1]));for(var k=i,l=i;j(h.charAt(k))&&k<h.length;)k++;for(;j(h.charAt(l))&&l>=0;)l--;if(l++,b){for(var m=k;/\s/.test(h.charAt(k))&&k<h.length;)k++;if(m==k){for(var n=l;/\s/.test(h.charAt(l-1))&&l>0;)l--;l||(l=n)}}return{start:d(g.line,l),end:d(g.line,k)}}function na(a,b,c){S(b,c)||vb.jumpList.add(a,b,c)}function oa(a,b){vb.lastCharacterSearch.increment=a,vb.lastCharacterSearch.forward=b.forward,vb.lastCharacterSearch.selectedCharacter=b.selectedCharacter}function pa(a,b,c,e){var f=R(a.getCursor()),g=c?1:-1,h=c?a.lineCount():-1,i=f.ch,j=f.line,k=a.getLine(j),l={lineText:k,nextCh:k.charAt(i),lastCh:null,index:i,symb:e,reverseSymb:(c?{")":"(","}":"{"}:{"(":")","{":"}"})[e],forward:c,depth:0,curMoveThrough:!1},m=Cb[e];if(!m)return f;var n=Db[m].init,o=Db[m
 ].isComplete;for(n&&n(l);j!==h&&b;){if(l.index+=g,l.nextCh=l.lineText.charAt(l.index),!l.nextCh){if(j+=g,l.lineText=a.getLine(j)||"",g>0)l.index=0;else{var p=l.lineText.length;l.index=p>0?p-1:0}l.nextCh=l.lineText.charAt(l.index)}o(l)&&(f.line=j,f.ch=l.index,b--)}return l.nextCh||l.curMoveThrough?d(j,l.index):f}function qa(a,b,c,d,e){var f=b.line,g=b.ch,h=a.getLine(f),i=c?1:-1,j=d?mb:lb;if(e&&""==h){if(f+=i,h=a.getLine(f),!m(a,f))return null;g=c?0:h.length}for(;;){if(e&&""==h)return{from:0,to:0,line:f};for(var k=i>0?h.length:-1,l=k,n=k;g!=k;){for(var o=!1,p=0;p<j.length&&!o;++p)if(j[p](h.charAt(g))){for(l=g;g!=k&&j[p](h.charAt(g));)g+=i;if(n=g,o=l!=n,l==b.ch&&f==b.line&&n==l+i)continue;return{from:Math.min(l,n+1),to:Math.max(l,n),line:f}}o||(g+=i)}if(f+=i,!m(a,f))return null;h=a.getLine(f),g=i>0?0:h.length}}function ra(a,b,c,e,f,g){var h=R(b),i=[];(e&&!f||!e&a
 mp;&f)&&c++;for(var j=!(e&&f),k=0;k<c;k++){var l=qa(a,b,e,g,j);if(!l){var m=X(a,a.lastLine());i.push(e?{line:a.lastLine(),from:m,to:m}:{line:0,from:0,to:0});break}i.push(l),b=d(l.line,e?l.to-1:l.from)}var n=i.length!=c,o=i[0],p=i.pop();return e&&!f?(n||o.from==h.ch&&o.line==h.line||(p=i.pop()),d(p.line,p.from)):e&&f?d(p.line,p.to-1):!e&&f?(n||o.to==h.ch&&o.line==h.line||(p=i.pop()),d(p.line,p.to)):d(p.line,p.from)}function sa(a,b,c,e){for(var f,g=a.getCursor(),h=g.ch,i=0;i<b;i++){var j=a.getLine(g.line);if(f=va(h,j,e,c,!0),f==-1)return null;h=f}return d(a.getCursor().line,f)}function ta(a,b){var c=a.getCursor().line;return J(a,d(c,b-1))}function ua(a,b,c,d){s(c,qb)&&(b.marks[c]&&b.marks[c].clear(),b.marks[c]=a.setBookmark(d))}function va(a,b,c,d,e){var f;return d?(f=b.indexOf(c,a+1),f==-1||e||(f-=1)):(f=b.lastIndexOf(c,a-1),f==-1||e||(f+=1)),f}function wa(a,b,c,e,f){function g(b){return!a.getLine(b)}fu
 nction h(a,b,c){return c?g(a)!=g(a+b):!g(a)&&g(a+b)}var i,j,k=b.line,l=a.firstLine(),m=a.lastLine(),n=k;if(e){for(;l<=n&&n<=m&&c>0;)h(n,e)&&c--,n+=e;return new d(n,0)}var o=a.state.vim;if(o.visualLine&&h(k,1,!0)){var p=o.sel.anchor;h(p.line,-1,!0)&&(f&&p.line==k||(k+=1))}var q=g(k);for(n=k;n<=m&&c;n++)h(n,1,!0)&&(f&&g(n)==q||c--);for(j=new d(n,0),n>m&&!q?q=!0:f=!1,n=k;n>l&&(f&&g(n)!=q&&n!=k||!h(n,-1,!0));n--);return i=new d(n,0),{start:i,end:j}}function xa(a,b,c,e){var f,g,h=b,i={"(":/[()]/,")":/[()]/,"[":/[[\]]/,"]":/[[\]]/,"{":/[{}]/,"}":/[{}]/}[c],j={"(":"(",")":"(","[":"[","]":"[","{":"{","}":"{"}[c],k=a.getLine(h.line).charAt(h.ch),l=k===j?1:0;if(f=a.scanForBracket(d(h.line
 ,h.ch+l),-1,null,{bracketRegex:i}),g=a.scanForBracket(d(h.line,h.ch+l),1,null,{bracketRegex:i}),!f||!g)return{start:h,end:h};if(f=f.pos,g=g.pos,f.line==g.line&&f.ch>g.ch||f.line>g.line){var m=f;f=g,g=m}return e?g.ch+=1:f.ch+=1,{start:f,end:g}}function ya(a,b,c,e){var f,g,h,i,j=R(b),k=a.getLine(j.line),l=k.split(""),m=l.indexOf(c);if(j.ch<m?j.ch=m:m<j.ch&&l[j.ch]==c&&(g=j.ch,--j.ch),l[j.ch]!=c||g)for(h=j.ch;h>-1&&!f;h--)l[h]==c&&(f=h+1);else f=j.ch+1;if(f&&!g)for(h=f,i=l.length;h<i&&!g;h++)l[h]==c&&(g=h);return f&&g?(e&&(--f,++g),{start:d(j.line,f),end:d(j.line,g)}):{start:j,end:j}}function za(){}function Aa(a){var b=a.state.vim;return b.searchState_||(b.searchState_=new za)}function Ba(a,b,c,d,e){a.openDialog?a.openDialog(b,d,{bottom:!0,value:e.value,onKeyDown:e.onKeyDown,onKeyUp:e.onKeyUp,selectValueOnOpen:!1}):d(prompt(c,""))}function Ca(a){var b=Da(a)||[];if(!b.le
 ngth)return[];var c=[];if(0===b[0]){for(var d=0;d<b.length;d++)"number"==typeof b[d]&&c.push(a.substring(b[d]+1,b[d+1]));return c}}function Da(a){for(var b=!1,c=[],d=0;d<a.length;d++){var e=a.charAt(d);b||"/"!=e||c.push(d),b=!b&&"\\"==e}return c}function Ea(a){for(var b="|(){",c="}",d=!1,e=[],f=-1;f<a.length;f++){var g=a.charAt(f)||"",h=a.charAt(f+1)||"",i=h&&b.indexOf(h)!=-1;d?("\\"===g&&i||e.push(g),d=!1):"\\"===g?(d=!0,h&&c.indexOf(h)!=-1&&(i=!0),i&&"\\"!==h||e.push(g)):(e.push(g),i&&"\\"!==h&&e.push("\\"))}return e.join("")}function Fa(a){for(var b=!1,c=[],d=-1;d<a.length;d++){var e=a.charAt(d)||"",f=a.charAt(d+1)||"";Eb[e+f]?(c.push(Eb[e+f]),d++):b?(c.push(e),b=!1):"\\"===e?(b=!0,p(f)||"$"===f?c.push("$"):"/"
 !==f&&"\\"!==f&&c.push("\\")):("$"===e&&c.push("$"),c.push(e),"/"===f&&c.push("\\"))}return c.join("")}function Ga(b){for(var c=new a.StringStream(b),d=[];!c.eol();){for(;c.peek()&&"\\"!=c.peek();)d.push(c.next());var e=!1;for(var f in Fb)if(c.match(f,!0)){e=!0,d.push(Fb[f]);break}e||d.push(c.next())}return d.join("")}function Ha(a,b,c){var d=vb.registerController.getRegister("/");if(d.setText(a),a instanceof RegExp)return a;var e,f,g=Da(a);if(g.length){e=a.substring(0,g[0]);var h=a.substring(g[0]);f=h.indexOf("i")!=-1}else e=a;if(!e)return null;v("pcre")||(e=Ea(e)),c&&(b=/^[^A-Z]*$/.test(e));var i=new RegExp(e,b||f?"i":void 0);return i}function Ia(a,b){a.openNotification?a.openNotification('<span style="color: red">'+b+"</span>",{bottom:!0,duration:5e3}):alert(b)}function Ja(
 a,b){var c='<span style="font-family: monospace; white-space: pre">'+(a||"")+'<input type="text"></span>';return b&&(c+=' <span style="color: #888">'+b+"</span>"),c}function Ka(a,b){var c=(b.prefix||"")+" "+(b.desc||""),d=Ja(b.prefix,b.desc);Ba(a,d,c,b.onClose,b)}function La(a,b){if(a instanceof RegExp&&b instanceof RegExp){for(var c=["global","multiline","ignoreCase","source"],d=0;d<c.length;d++){var e=c[d];if(a[e]!==b[e])return!1}return!0}return!1}function Ma(a,b,c,d){if(b){var e=Aa(a),f=Ha(b,!!c,!!d);if(f)return Oa(a,f),La(f,e.getQuery())?f:(e.setQuery(f),f)}}function Na(a){if("^"==a.source.charAt(0))var b=!0;return{token:function(c){if(b&&!c.sol())return void c.skipToEnd();var d=c.match(a,!1);if(d)return 0==d[0].length?(c.next(),"searching"):c.sol()||(c.backUp(1),a.exec(c.next()+d[0]))
 ?(c.match(a),"searching"):(c.next(),null);for(;!c.eol()&&(c.next(),!c.match(a,!1)););},query:a}}function Oa(a,b){var c=Aa(a),d=c.getOverlay();d&&b==d.query||(d&&a.removeOverlay(d),d=Na(b),a.addOverlay(d),a.showMatchesOnScrollbar&&(c.getScrollbarAnnotate()&&c.getScrollbarAnnotate().clear(),c.setScrollbarAnnotate(a.showMatchesOnScrollbar(b))),c.setOverlay(d))}function Pa(a,b,c,e){return void 0===e&&(e=1),a.operation(function(){for(var f=a.getCursor(),g=a.getSearchCursor(c,f),h=0;h<e;h++){var i=g.find(b);if(0==h&&i&&S(g.from(),f)&&(i=g.find(b)),!i&&(g=a.getSearchCursor(c,b?d(a.lastLine()):d(a.firstLine(),0)),!g.find(b)))return}return g.from()})}function Qa(a){var b=Aa(a);a.removeOverlay(Aa(a).getOverlay()),b.setOverlay(null),b.getScrollbarAnnotate()&&(b.getScrollbarAnnotate().clear(),b.setScrollbarAnnotate(null))}function Ra(a,b,c){return"number"!=typeof a&&(a=a.line),
 b instanceof Array?s(a,b):c?a>=b&&a<=c:a==b}function Sa(a){var b=a.getScrollInfo(),c=6,d=10,e=a.coordsChar({left:0,top:c+b.top},"local"),f=b.clientHeight-d+b.top,g=a.coordsChar({left:0,top:f},"local");return{top:e.line,bottom:g.line}}function Ta(a,b,c){if("'"==c){var d=a.doc.history.done,e=d[d.length-2];return e&&e.ranges&&e.ranges[0].head}var f=b.marks[c];return f&&f.find()}function Ua(b,c,d,e,f,g,h,i,j){function k(){b.operation(function(){for(;!p;)l(),m();n()})}function l(){var a=b.getRange(g.from(),g.to()),c=a.replace(h,i);g.replace(c)}function m(){for(;g.findNext()&&Ra(g.from(),e,f);)if(d||!q||g.from().line!=q.line)return b.scrollIntoView(g.from(),30),b.setSelection(g.from(),g.to()),q=g.from(),void(p=!1);p=!0}function n(a){if(a&&a(),b.focus(),q){b.setCursor(q);var c=b.state.vim;c.exMode=!1,c.lastHPos=c.lastHSPos=q.ch}j&&j()}function o(c,d,e){a.e_stop(c);var f=a.keyName(c);switch(f){case&q
 uot;Y":l(),m();break;case"N":m();break;case"A":var g=j;j=void 0,b.operation(k),j=g;break;case"L":l();case"Q":case"Esc":case"Ctrl-C":case"Ctrl-[":n(e)}return p&&n(e),!0}b.state.vim.exMode=!0;var p=!1,q=g.from();return m(),p?void Ia(b,"No matches for "+h.source):c?void Ka(b,{prefix:"replace with <strong>"+i+"</strong> (y/n/a/q/l)",onKeyDown:o}):(k(),void(j&&j()))}function Va(b){var c=b.state.vim,d=vb.macroModeState,e=vb.registerController.getRegister("."),f=d.isPlaying,g=d.lastInsertModeChanges,h=[];if(!f){for(var i=g.inVisualBlock?c.lastSelection.visualBlock.height:1,j=g.changes,h=[],k=0;k<j.length;)h.push(j[k]),j[k]instanceof eb?k++:k+=i;g.changes=h,b.off("change",ab),a.off(b.getInputField(),"keydown",fb)}!f&&c.insertModeRepeat>1&&(gb(b,c,c.insertModeRepeat-1,!0),c.lastEditInputState.repeatOverride=c.
 insertModeRepeat),delete c.insertModeRepeat,c.insertMode=!1,b.setCursor(b.getCursor().line,b.getCursor().ch-1),b.setOption("keyMap","vim"),b.setOption("disableInput",!0),b.toggleOverwrite(!1),e.setText(g.changes.join("")),a.signal(b,"vim-mode-change",{mode:"normal"}),d.isRecording&&$a(d)}function Wa(a){b.unshift(a)}function Xa(a,b,c,d,e){var f={keys:a,type:b};f[b]=c,f[b+"Args"]=d;for(var g in e)f[g]=e[g];Wa(f)}function Ya(b,c,d,e){var f=vb.registerController.getRegister(e);if(":"==e)return f.keyBuffer[0]&&Jb.processCommand(b,f.keyBuffer[0]),void(d.isPlaying=!1);var g=f.keyBuffer,h=0;d.isPlaying=!0,d.replaySearchQueries=f.searchQueries.slice(0);for(var i=0;i<g.length;i++)for(var j,k,l=g[i];l;)if(j=/<\w+-.+?>|<\w+>|./.exec(l),k=j[0],l=l.substring(j.index+k.length),a.Vim.handleKey(b,k,"macro"),c.insertMode){var m=f.insertModeChanges[h++].changes;vb.macroModeState.las
 tInsertModeChanges.changes=m,hb(b,m,1),Va(b)}d.isPlaying=!1}function Za(a,b){if(!a.isPlaying){var c=a.latestRegister,d=vb.registerController.getRegister(c);d&&d.pushText(b)}}function $a(a){if(!a.isPlaying){var b=a.latestRegister,c=vb.registerController.getRegister(b);c&&c.pushInsertModeChanges&&c.pushInsertModeChanges(a.lastInsertModeChanges)}}function _a(a,b){if(!a.isPlaying){var c=a.latestRegister,d=vb.registerController.getRegister(c);d&&d.pushSearchQuery&&d.pushSearchQuery(b)}}function ab(a,b){var c=vb.macroModeState,d=c.lastInsertModeChanges;if(!c.isPlaying)for(;b;){if(d.expectCursorActivityForChange=!0,"+input"==b.origin||"paste"==b.origin||void 0===b.origin){var e=b.text.join("\n");d.maybeReset&&(d.changes=[],d.maybeReset=!1),a.state.overwrite&&!/\n/.test(e)?d.changes.push([e]):d.changes.push(e)}b=b.next}}function bb(a){var b=a.state.vim;if(b.insertMode){var c=vb.macroModeState;if(c.isPlayin
 g)return;var d=c.lastInsertModeChanges;d.expectCursorActivityForChange?d.expectCursorActivityForChange=!1:d.maybeReset=!0}else a.curOp.isVimOp||db(a,b);b.visualMode&&cb(a)}function cb(a){var b=a.state.vim,c=J(a,R(b.sel.head)),d=L(c,0,1);b.fakeCursor&&b.fakeCursor.clear(),b.fakeCursor=a.markText(c,d,{className:"cm-animate-fat-cursor"})}function db(b,c){var d=b.getCursor("anchor"),e=b.getCursor("head");if(c.visualMode&&!b.somethingSelected()?ia(b,!1):c.visualMode||c.insertMode||!b.somethingSelected()||(c.visualMode=!0,c.visualLine=!1,a.signal(b,"vim-mode-change",{mode:"visual"})),c.visualMode){var f=T(e,d)?0:-1,g=T(e,d)?-1:0;e=L(e,0,f),d=L(d,0,g),c.sel={anchor:d,head:e},ua(b,c,"<",U(e,d)),ua(b,c,">",V(e,d))}else c.insertMode||(c.lastHPos=b.getCursor().ch)}function eb(a){this.keyName=a}function fb(b){function c(){return e.maybeReset&&(e.changes=[],e.maybeReset=!1),e.changes.push(
 new eb(f)),!0}var d=vb.macroModeState,e=d.lastInsertModeChanges,f=a.keyName(b);f&&(f.indexOf("Delete")==-1&&f.indexOf("Backspace")==-1||a.lookupKey(f,"vim-insert",c))}function gb(a,b,c,d){function e(){h?yb.processAction(a,b,b.lastEditActionCommand):yb.evalInput(a,b)}function f(c){if(g.lastInsertModeChanges.changes.length>0){c=b.lastEditActionCommand?c:1;var d=g.lastInsertModeChanges;hb(a,d.changes,c)}}var g=vb.macroModeState;g.isPlaying=!0;var h=!!b.lastEditActionCommand,i=b.inputState;if(b.inputState=b.lastEditInputState,h&&b.lastEditActionCommand.interlaceInsertRepeat)for(var j=0;j<c;j++)e(),f(1);else d||e(),f(c);b.inputState=i,b.insertMode&&!d&&Va(a),g.isPlaying=!1}function hb(b,c,d){function e(c){return"string"==typeof c?a.commands[c](b):c(b),!0}var f=b.getCursor("head"),g=vb.macroModeState.lastInsertModeChanges.inVisualBlock;if(g){var h=b.state.vim,i=h.lastSelection,j=M(i.anchor,i.he
 ad);aa(b,f,j.line+1),d=b.listSelections().length,b.setCursor(f)}for(var k=0;k<d;k++){g&&b.setCursor(L(f,k,0));for(var l=0;l<c.length;l++){var m=c[l];if(m instanceof eb)a.lookupKey(m.keyName,"vim-insert",e);else if("string"==typeof m){var n=b.getCursor();b.replaceRange(m,n,n)}else{var o=b.getCursor(),p=L(o,0,m[0].length);b.replaceRange(m[0],o,p)}}}g&&b.setCursor(L(f,0,1))}a.defineOption("vimMode",!1,function(b,c,d){c&&"vim"!=b.getOption("keyMap")?b.setOption("keyMap","vim"):!c&&d!=a.Init&&/^vim/.test(b.getOption("keyMap"))&&b.setOption("keyMap","default")});var ib={Shift:"S",Ctrl:"C",Alt:"A",Cmd:"D",Mod:"A"},jb={Enter:"CR",Backspace:"BS",Delete:"Del",Insert:"Ins"},kb=/[\d]/,lb=[a.isWordChar,function(b){return b&&!a.isWordChar(b)&&am
 p;!/\s/.test(b)}],mb=[function(a){return/\S/.test(a)}],nb=l(65,26),ob=l(97,26),pb=l(48,10),qb=[].concat(nb,ob,pb,["<",">"]),rb=[].concat(nb,ob,pb,["-",'"',".",":","/"]),sb={};t("filetype",void 0,"string",["ft"],function(a,b){if(void 0!==b){if(void 0===a){var c=b.getOption("mode");return"null"==c?"":c}var c=""==a?"null":a;b.setOption("mode",c)}});var tb=function(){function a(a,b,h){function i(b){var e=++d%c,f=g[e];f&&f.clear(),g[e]=a.setBookmark(b)}var j=d%c,k=g[j];if(k){var l=k.find();l&&!S(l,b)&&i(b)}else i(b);i(h),e=d,f=d-c+1,f<0&&(f=0)}function b(a,b){d+=b,d>e?d=e:d<f&&(d=f);var h=g[(c+d)%c];if(h&&!h.find()){var i,j=b>0?1:-1,k=a.getCursor();do if(d+=j,h=g[(c+d)%c],h&&(i=h.find())&&!S(k,i))break;while(d<e&&d>f)}return h}var c=100,d=-1
 ,e=0,f=0,g=new Array(c);return{cachedCursor:void 0,add:a,move:b}},ub=function(a){return a?{changes:a.changes,expectCursorActivityForChange:a.expectCursorActivityForChange}:{changes:[],expectCursorActivityForChange:!1}};w.prototype={exitMacroRecordMode:function(){var a=vb.macroModeState;a.onRecordingDone&&a.onRecordingDone(),a.onRecordingDone=void 0,a.isRecording=!1},enterMacroRecordMode:function(a,b){var c=vb.registerController.getRegister(b);c&&(c.clear(),this.latestRegister=b,a.openDialog&&(this.onRecordingDone=a.openDialog("(recording)["+b+"]",null,{bottom:!0})),this.isRecording=!0)}};var vb,wb,xb={buildKeyMap:function(){},getRegisterController:function(){return vb.registerController},resetVimGlobalState_:y,getVimGlobalState_:function(){return vb},maybeInitVimState_:x,suppressErrorLogging:!1,InsertModeKey:eb,map:function(a,b,c){Jb.map(a,b,c)},unmap:function(a,b){Jb.unmap(a,b)},setOption:u,getOption:v,defineOption:t,defineEx:function(a,b
 ,c){if(b){if(0!==a.indexOf(b))throw new Error('(Vim.defineEx) "'+b+'" is not a prefix of "'+a+'", command not registered')}else b=a;Ib[a]=c,Jb.commandMap_[b]={name:a,shortName:b,type:"api"}},handleKey:function(a,b,c){var d=this.findKey(a,b,c);if("function"==typeof d)return d()},findKey:function(c,d,e){function f(){var a=vb.macroModeState;if(a.isRecording){if("q"==d)return a.exitMacroRecordMode(),A(c),!0;"mapping"!=e&&Za(a,d)}}function g(){if("<Esc>"==d)return A(c),l.visualMode?ia(c):l.insertMode&&Va(c),!0}function h(b){for(var e;b;)e=/<\w+-.+?>|<\w+>|./.exec(b),d=e[0],b=b.substring(e.index+d.length),a.Vim.handleKey(c,d,"mapping")}function i(){if(g())return!0;for(var a=l.inputState.keyBuffer=l.inputState.keyBuffer+d,e=1==d.length,f=yb.matchCommand(a,b,l.inputState,"insert");a.length>1&&"full"!=f.type;){var a=l.inputState.keyBuffer=a.slice(1)
 ,h=yb.matchCommand(a,b,l.inputState,"insert");"none"!=h.type&&(f=h)}if("none"==f.type)return A(c),!1;if("partial"==f.type)return wb&&window.clearTimeout(wb),wb=window.setTimeout(function(){l.insertMode&&l.inputState.keyBuffer&&A(c)},v("insertModeEscKeysTimeout")),!e;if(wb&&window.clearTimeout(wb),e){for(var i=c.listSelections(),j=0;j<i.length;j++){var k=i[j].head;c.replaceRange("",L(k,0,-(a.length-1)),k,"+input")}vb.macroModeState.lastInsertModeChanges.changes.pop()}return A(c),f.command}function j(){if(f()||g())return!0;var a=l.inputState.keyBuffer=l.inputState.keyBuffer+d;if(/^[1-9]\d*$/.test(a))return!0;var e=/^(\d*)(.*)$/.exec(a);if(!e)return A(c),!1;var h=l.visualMode?"visual":"normal",i=yb.matchCommand(e[2]||e[1],b,l.inputState,h);if("none"==i.type)return A(c),!1;if("partial"==i.type)return!0;l.inputState.keyBuffer="&quot
 ;;var e=/^(\d*)(.*)$/.exec(a);return e[1]&&"0"!=e[1]&&l.inputState.pushRepeatDigit(e[1]),i.command}var k,l=x(c);return k=l.insertMode?i():j(),k===!1?void 0:k===!0?function(){return!0}:function(){return c.operation(function(){c.curOp.isVimOp=!0;try{"keyToKey"==k.type?h(k.toKeys):yb.processCommand(c,l,k)}catch(b){throw c.state.vim=void 0,x(c),a.Vim.suppressErrorLogging||console.log(b),b}return!0})}},handleEx:function(a,b){Jb.processCommand(a,b)},defineMotion:F,defineAction:I,defineOperator:H,mapCommand:Xa,_mapCommand:Wa,defineRegister:C,exitVisualMode:ia,exitInsertMode:Va};z.prototype.pushRepeatDigit=function(a){this.operator?this.motionRepeat=this.motionRepeat.concat(a):this.prefixRepeat=this.prefixRepeat.concat(a)},z.prototype.getRepeat=function(){var a=0;return(this.prefixRepeat.length>0||this.motionRepeat.length>0)&&(a=1,this.prefixRepeat.length>0&&(a*=parseInt(this.prefixRepeat.join(""),10)),this.motionRepeat.
 length>0&&(a*=parseInt(this.motionRepeat.join(""),10))),a},B.prototype={setText:function(a,b,c){this.keyBuffer=[a||""],this.linewise=!!b,this.blockwise=!!c},pushText:function(a,b){b&&(this.linewise||this.keyBuffer.push("\n"),this.linewise=!0),this.keyBuffer.push(a)},pushInsertModeChanges:function(a){this.insertModeChanges.push(ub(a))},pushSearchQuery:function(a){this.searchQueries.push(a)},clear:function(){this.keyBuffer=[],this.insertModeChanges=[],this.searchQueries=[],this.linewise=!1},toString:function(){return this.keyBuffer.join("")}},D.prototype={pushText:function(a,b,c,d,e){d&&"\n"!==c.charAt(c.length-1)&&(c+="\n");var f=this.isValidRegister(a)?this.getRegister(a):null;if(!f){switch(b){case"yank":this.registers[0]=new B(c,d,e);break;case"delete":case"change":c.indexOf("\n")==-1?this.registers["-"]=new B(c,d):(this.shiftNumericRegist
 ers_(),this.registers[1]=new B(c,d))}return void this.unnamedRegister.setText(c,d,e)}var g=q(a);g?f.pushText(c,d):f.setText(c,d,e),this.unnamedRegister.setText(f.toString(),d)},getRegister:function(a){return this.isValidRegister(a)?(a=a.toLowerCase(),this.registers[a]||(this.registers[a]=new B),this.registers[a]):this.unnamedRegister},isValidRegister:function(a){return a&&s(a,rb)},shiftNumericRegisters_:function(){for(var a=9;a>=2;a--)this.registers[a]=this.getRegister(""+(a-1))}},E.prototype={nextMatch:function(a,b){var c=this.historyBuffer,d=b?-1:1;null===this.initialPrefix&&(this.initialPrefix=a);for(var e=this.iterator+d;b?e>=0:e<c.length;e+=d)for(var f=c[e],g=0;g<=f.length;g++)if(this.initialPrefix==f.substring(0,g))return this.iterator=e,f;return e>=c.length?(this.iterator=c.length,this.initialPrefix):e<0?a:void 0},pushInput:function(a){var b=this.historyBuffer.indexOf(a);b>-1&&this.historyBuffer.splice(b,1),a.length&&
 amp;this.historyBuffer.push(a)},reset:function(){this.initialPrefix=null,this.iterator=this.historyBuffer.length}};var yb={matchCommand:function(a,b,c,d){var e=N(a,b,d,c);if(!e.full&&!e.partial)return{type:"none"};if(!e.full&&e.partial)return{type:"partial"};for(var f,g=0;g<e.full.length;g++){var h=e.full[g];f||(f=h)}if("<character>"==f.keys.slice(-11)){var i=P(a);if(!i)return{type:"none"};c.selectedCharacter=i}return{type:"full",command:f}},processCommand:function(a,b,c){switch(b.inputState.repeatOverride=c.repeatOverride,c.type){case"motion":this.processMotion(a,b,c);break;case"operator":this.processOperator(a,b,c);break;case"operatorMotion":this.processOperatorMotion(a,b,c);break;case"action":this.processAction(a,b,c);break;case"search":this.processSearch(a,b,c);break;case"ex":case"keyToEx":this.processEx(a,b,c)}},processMotion:function(
 a,b,c){b.inputState.motion=c.motion,b.inputState.motionArgs=K(c.motionArgs),this.evalInput(a,b)},processOperator:function(a,b,c){var d=b.inputState;if(d.operator){if(d.operator==c.operator)return d.motion="expandToLine",d.motionArgs={linewise:!0},void this.evalInput(a,b);A(a)}d.operator=c.operator,d.operatorArgs=K(c.operatorArgs),b.visualMode&&this.evalInput(a,b)},processOperatorMotion:function(a,b,c){var d=b.visualMode,e=K(c.operatorMotionArgs);e&&d&&e.visualLine&&(b.visualLine=!0),this.processOperator(a,b,c),d||this.processMotion(a,b,c)},processAction:function(a,b,c){var d=b.inputState,e=d.getRepeat(),f=!!e,g=K(c.actionArgs)||{};d.selectedCharacter&&(g.selectedCharacter=d.selectedCharacter),c.operator&&this.processOperator(a,b,c),c.motion&&this.processMotion(a,b,c),(c.motion||c.operator)&&this.evalInput(a,b),g.repeat=e||1,g.repeatIsExplicit=f,g.registerName=d.registerName,A(a),b.lastMotion=null,c.isEdit&
 &this.recordLastEdit(b,d,c),Bb[c.action](a,g,b)},processSearch:function(b,c,d){function e(a,e,f){vb.searchHistoryController.pushInput(a),vb.searchHistoryController.reset();try{Ma(b,a,e,f)}catch(g){return Ia(b,"Invalid regex: "+a),void A(b)}yb.processMotion(b,c,{type:"motion",motion:"findNext",motionArgs:{forward:!0,toJumplist:d.searchArgs.toJumplist}})}function f(a){b.scrollTo(m.left,m.top),e(a,!0,!0);var c=vb.macroModeState;c.isRecording&&_a(c,a)}function g(c,d,e){var f,g,h=a.keyName(c);"Up"==h||"Down"==h?(f="Up"==h,g=c.target?c.target.selectionEnd:0,d=vb.searchHistoryController.nextMatch(d,f)||"",e(d),g&&c.target&&(c.target.selectionEnd=c.target.selectionStart=Math.min(g,c.target.value.length))):"Left"!=h&&"Right"!=h&&"Ctrl"!=h&&"Alt"!=h&&"Shift"!=h&&vb.searchHistoryController.reset();var j;try{j
 =Ma(b,d,!0,!0)}catch(c){}j?b.scrollIntoView(Pa(b,!i,j),30):(Qa(b),b.scrollTo(m.left,m.top))}function h(c,d,e){var f=a.keyName(c);"Esc"==f||"Ctrl-C"==f||"Ctrl-["==f||"Backspace"==f&&""==d?(vb.searchHistoryController.pushInput(d),vb.searchHistoryController.reset(),Ma(b,l),Qa(b),b.scrollTo(m.left,m.top),a.e_stop(c),A(b),e(),b.focus()):"Up"==f||"Down"==f?a.e_stop(c):"Ctrl-U"==f&&(a.e_stop(c),e(""))}if(b.getSearchCursor){var i=d.searchArgs.forward,j=d.searchArgs.wholeWordOnly;Aa(b).setReversed(!i);var k=i?"/":"?",l=Aa(b).getQuery(),m=b.getScrollInfo();switch(d.searchArgs.querySrc){case"prompt":var n=vb.macroModeState;if(n.isPlaying){var o=n.replaySearchQueries.shift();e(o,!0,!1)}else Ka(b,{onClose:f,prefix:k,desc:Gb,onKeyUp:g,onKeyDown:h});break;case"wordUnderCursor":var p=ma(b,!1,!0,!1,!0),q=!0;if(p||(p=ma(b,!1,!0,!1,!1),q=!1),!p)return;var o=
 b.getLine(p.start.line).substring(p.start.ch,p.end.ch);o=q&&j?"\\b"+o+"\\b":Z(o),vb.jumpList.cachedCursor=b.getCursor(),b.setCursor(p.start),e(o,!0,!1)}}},processEx:function(b,c,d){function e(a){vb.exCommandHistoryController.pushInput(a),vb.exCommandHistoryController.reset(),Jb.processCommand(b,a)}function f(c,d,e){var f,g,h=a.keyName(c);("Esc"==h||"Ctrl-C"==h||"Ctrl-["==h||"Backspace"==h&&""==d)&&(vb.exCommandHistoryController.pushInput(d),vb.exCommandHistoryController.reset(),a.e_stop(c),A(b),e(),b.focus()),"Up"==h||"Down"==h?(a.e_stop(c),f="Up"==h,g=c.target?c.target.selectionEnd:0,d=vb.exCommandHistoryController.nextMatch(d,f)||"",e(d),g&&c.target&&(c.target.selectionEnd=c.target.selectionStart=Math.min(g,c.target.value.length))):"Ctrl-U"==h?(a.e_stop(c),e("")):"Left"!=h&&"Right"!=h&a
 mp;&"Ctrl"!=h&&"Alt"!=h&&"Shift"!=h&&vb.exCommandHistoryController.reset()}"keyToEx"==d.type?Jb.processCommand(b,d.exArgs.input):c.visualMode?Ka(b,{onClose:e,prefix:":",value:"'<,'>",onKeyDown:f}):Ka(b,{onClose:e,prefix:":",onKeyDown:f})},evalInput:function(a,b){var c,e,f,g=b.inputState,h=g.motion,i=g.motionArgs||{},j=g.operator,k=g.operatorArgs||{},l=g.registerName,m=b.sel,n=R(b.visualMode?J(a,m.head):a.getCursor("head")),o=R(b.visualMode?J(a,m.anchor):a.getCursor("anchor")),p=R(n),q=R(o);if(j&&this.recordLastEdit(b,g),f=void 0!==g.repeatOverride?g.repeatOverride:g.getRepeat(),f>0&&i.explicitRepeat?i.repeatIsExplicit=!0:(i.noRepeat||!i.explicitRepeat&&0===f)&&(f=1,i.repeatIsExplicit=!1),g.selectedCharacter&&(i.selectedCharacter=k.selectedCharacter=g.selectedCharacter),i.repeat=f,A(a),h){var r=zb[h](a,n,i,b);if(b.lastM
 otion=zb[h],!r)return;if(i.toJumplist){var s=vb.jumpList,t=s.cachedCursor;t?(na(a,t,r),delete s.cachedCursor):na(a,n,r)}r instanceof Array?(e=r[0],c=r[1]):c=r,c||(c=R(n)),b.visualMode?(b.visualBlock&&c.ch===1/0||(c=J(a,c,b.visualBlock)),e&&(e=J(a,e,!0)),e=e||q,m.anchor=e,m.head=c,fa(a),ua(a,b,"<",T(e,c)?e:c),ua(a,b,">",T(e,c)?c:e)):j||(c=J(a,c),a.setCursor(c.line,c.ch))}if(j){if(k.lastSel){e=q;var u=k.lastSel,v=Math.abs(u.head.line-u.anchor.line),w=Math.abs(u.head.ch-u.anchor.ch);c=u.visualLine?d(q.line+v,q.ch):u.visualBlock?d(q.line+v,q.ch+w):u.head.line==u.anchor.line?d(q.line,q.ch+w):d(q.line+v,q.ch),b.visualMode=!0,b.visualLine=u.visualLine,b.visualBlock=u.visualBlock,m=b.sel={anchor:e,head:c},fa(a)}else b.visualMode&&(k.lastSel={anchor:R(m.anchor),head:R(m.head),visualBlock:b.visualBlock,visualLine:b.visualLine});var x,y,z,B,C;if(b.visualMode){if(x=U(m.head,m.anchor),y=V(m.head,m.anchor),z=b.visualLine||k.linewise,B=b.visualBloc
 k?"block":z?"line":"char",C=ga(a,{anchor:x,head:y},B),z){var D=C.ranges;if("block"==B)for(var E=0;E<D.length;E++)D[E].head.ch=X(a,D[E].head.line);else"line"==B&&(D[0].head=d(D[0].head.line+1,0))}}else{if(x=R(e||q),y=R(c||p),T(y,x)){var F=x;x=y,y=F}z=i.linewise||k.linewise,z?ka(a,x,y):i.forward&&ja(a,x,y),B="char";var G=!i.inclusive||z;C=ga(a,{anchor:x,head:y},B,G)}a.setSelections(C.ranges,C.primary),b.lastMotion=null,k.repeat=f,k.registerName=l,k.linewise=z;var H=Ab[j](a,k,C.ranges,q,c);b.visualMode&&ia(a,null!=H),H&&a.setCursor(H)}},recordLastEdit:function(a,b,c){var d=vb.macroModeState;d.isPlaying||(a.lastEditInputState=b,a.lastEditActionCommand=c,d.lastInsertModeChanges.changes=[],d.lastInsertModeChanges.expectCursorActivityForChange=!1)}},zb={moveToTopLine:function(a,b,c){var e=Sa(a).top+c.repeat-1;return d(e,la(a.getLine(e)))},moveToMiddleLine:function(a){var b=Sa(a),c=Math.floor(.5*(
 b.top+b.bottom));return d(c,la(a.getLine(c)))},moveToBottomLine:function(a,b,c){var e=Sa(a).bottom-c.repeat+1;return d(e,la(a.getLine(e)))},expandToLine:function(a,b,c){var e=b;return d(e.line+c.repeat-1,1/0)},findNext:function(a,b,c){var d=Aa(a),e=d.getQuery();if(e){var f=!c.forward;return f=d.isReversed()?!f:f,Oa(a,e),Pa(a,f,e,c.repeat)}},goToMark:function(a,b,c,d){var e=Ta(a,d,c.selectedCharacter);return e?c.linewise?{line:e.line,ch:la(a.getLine(e.line))}:e:null},moveToOtherHighlightedEnd:function(a,b,c,e){if(e.visualBlock&&c.sameLine){var f=e.sel;return[J(a,d(f.anchor.line,f.head.ch)),J(a,d(f.head.line,f.anchor.ch))]}return[e.sel.head,e.sel.anchor]},jumpToMark:function(a,b,c,e){for(var f=b,g=0;g<c.repeat;g++){var h=f;for(var i in e.marks)if(n(i)){var j=e.marks[i].find(),k=c.forward?T(j,h):T(h,j);if(!(k||c.linewise&&j.line==h.line)){var l=S(h,f),m=c.forward?W(h,j,f):W(f,j,h);(l||m)&&(f=j)}}}return c.linewise&&(f=d(f.line,la(a.getLine(f.line)))),
 f},moveByCharacters:function(a,b,c){var e=b,f=c.repeat,g=c.forward?e.ch+f:e.ch-f;return d(e.line,g)},moveByLines:function(a,b,c,e){var f=b,g=f.ch;switch(e.lastMotion){case this.moveByLines:case this.moveByDisplayLines:case this.moveByScroll:case this.moveToColumn:case this.moveToEol:g=e.lastHPos;break;default:e.lastHPos=g}var h=c.repeat+(c.repeatOffset||0),i=c.forward?f.line+h:f.line-h,j=a.firstLine(),k=a.lastLine();return i<j&&f.line==j?this.moveToStartOfLine(a,b,c,e):i>k&&f.line==k?this.moveToEol(a,b,c,e):(c.toFirstChar&&(g=la(a.getLine(i)),e.lastHPos=g),e.lastHSPos=a.charCoords(d(i,g),"div").left,d(i,g))},moveByDisplayLines:function(a,b,c,e){var f=b;switch(e.lastMotion){case this.moveByDisplayLines:case this.moveByScroll:case this.moveByLines:case this.moveToColumn:case this.moveToEol:break;default:e.lastHSPos=a.charCoords(f,"div").left}var g=c.repeat,h=a.findPosV(f,c.forward?g:-g,"line",e.lastHSPos);if(h.hitSide)if(c.fo
 rward)var i=a.charCoords(h,"div"),j={top:i.top+8,left:e.lastHSPos},h=a.coordsChar(j,"div");else{var k=a.charCoords(d(a.firstLine(),0),"div");k.left=e.lastHSPos,h=a.coordsChar(k,"div")}return e.lastHPos=h.ch,h},moveByPage:function(a,b,c){var d=b,e=c.repeat;return a.findPosV(d,c.forward?e:-e,"page")},moveByParagraph:function(a,b,c){var d=c.forward?1:-1;return wa(a,b,c.repeat,d)},moveByScroll:function(a,b,c,d){var e=a.getScrollInfo(),f=null,g=c.repeat;g||(g=e.clientHeight/(2*a.defaultTextHeight()));var h=a.charCoords(b,"local");c.repeat=g;var f=zb.moveByDisplayLines(a,b,c,d);if(!f)return null;var i=a.charCoords(f,"local");return a.scrollTo(null,e.top+i.top-h.top),f},moveByWords:function(a,b,c){return ra(a,b,c.repeat,!!c.forward,!!c.wordEnd,!!c.bigWord)},moveTillCharacter:function(a,b,c){var d=c.repeat,e=sa(a,d,c.forward,c.selectedCharacter),f=c.forward?-1:1;return oa(f,c),e?(e.ch+=f,e):null},moveToCharacter:function(
 a,b,c){var d=c.repeat;return oa(0,c),sa(a,d,c.forward,c.selectedCharacter)||b},moveToSymbol:function(a,b,c){var d=c.repeat;return pa(a,d,c.forward,c.selectedCharacter)||b},moveToColumn:function(a,b,c,d){var e=c.repeat;return d.lastHPos=e-1,d.lastHSPos=a.charCoords(b,"div").left,ta(a,e)},moveToEol:function(a,b,c,e){var f=b;e.lastHPos=1/0;var g=d(f.line+c.repeat-1,1/0),h=a.clipPos(g);return h.ch--,e.lastHSPos=a.charCoords(h,"div").left,g},moveToFirstNonWhiteSpaceCharacter:function(a,b){var c=b;return d(c.line,la(a.getLine(c.line)))},moveToMatchedSymbol:function(a,b){for(var c,e=b,f=e.line,g=e.ch,h=a.getLine(f);g<h.length;g++)if(c=h.charAt(g),c&&o(c)){var i=a.getTokenTypeAt(d(f,g+1));if("string"!==i&&"comment"!==i)break}if(g<h.length){var j=a.findMatchingBracket(d(f,g));return j.to}return e},moveToStartOfLine:function(a,b){return d(b.line,0)},moveToLineOrEdgeOfDocument:function(a,b,c){var e=c.forward?a.lastLine():a.firstLine
 ();
+return c.repeatIsExplicit&&(e=c.repeat-a.getOption("firstLineNumber")),d(e,la(a.getLine(e)))},textObjectManipulation:function(a,b,c,d){var e={"(":")",")":"(","{":"}","}":"{","[":"]","]":"["},f={"'":!0,'"':!0},g=c.selectedCharacter;"b"==g?g="(":"B"==g&&(g="{");var h,i=!c.textObjectInner;if(e[g])h=xa(a,b,g,i);else if(f[g])h=ya(a,b,g,i);else if("W"===g)h=ma(a,i,!0,!0);else if("w"===g)h=ma(a,i,!0,!1);else{if("p"!==g)return null;if(h=wa(a,b,c.repeat,0,i),c.linewise=!0,d.visualMode)d.visualLine||(d.visualLine=!0);else{var j=d.inputState.operatorArgs;j&&(j.linewise=!0),h.end.line--}}return a.state.vim.visualMode?ea(a,h.start,h.end):[h.start,h.end]},repeatLastCharacterSearch:function(a,b,c){var d=vb.lastCharacterSearch,e=c.repeat,f=c.forward===d.forward,g=
 (d.increment?1:0)*(f?-1:1);a.moveH(-g,"char"),c.inclusive=!!f;var h=sa(a,e,f,d.selectedCharacter);return h?(h.ch+=g,h):(a.moveH(g,"char"),b)}},Ab={change:function(b,c,e){var f,g,h=b.state.vim;if(vb.macroModeState.lastInsertModeChanges.inVisualBlock=h.visualBlock,h.visualMode){g=b.getSelection();var i=G("",e.length);b.replaceSelections(i),f=U(e[0].head,e[0].anchor)}else{var j=e[0].anchor,k=e[0].head;g=b.getRange(j,k);var l=h.lastEditInputState||{};if("moveByWords"==l.motion&&!r(g)){var m=/\s+$/.exec(g);m&&l.motionArgs&&l.motionArgs.forward&&(k=L(k,0,-m[0].length),g=g.slice(0,-m[0].length))}var n=new d(j.line-1,Number.MAX_VALUE),o=b.firstLine()==b.lastLine();k.line>b.lastLine()&&c.linewise&&!o?b.replaceRange("",n,k):b.replaceRange("",j,k),c.linewise&&(o||(b.setCursor(n),a.commands.newlineAndIndent(b)),j.ch=Number.MAX_VALUE),f=j}vb.registerController.pushText(c.registe
 rName,"change",g,c.linewise,e.length>1),Bb.enterInsertMode(b,{head:f},b.state.vim)},"delete":function(a,b,c){var e,f,g=a.state.vim;if(g.visualBlock){f=a.getSelection();var h=G("",c.length);a.replaceSelections(h),e=c[0].anchor}else{var i=c[0].anchor,j=c[0].head;b.linewise&&j.line!=a.firstLine()&&i.line==a.lastLine()&&i.line==j.line-1&&(i.line==a.firstLine()?i.ch=0:i=d(i.line-1,X(a,i.line-1))),f=a.getRange(i,j),a.replaceRange("",i,j),e=i,b.linewise&&(e=zb.moveToFirstNonWhiteSpaceCharacter(a,i))}return vb.registerController.pushText(b.registerName,"delete",f,b.linewise,g.visualBlock),J(a,e)},indent:function(a,b,c){var d=a.state.vim,e=c[0].anchor.line,f=d.visualBlock?c[c.length-1].anchor.line:c[0].head.line,g=d.visualMode?b.repeat:1;b.linewise&&f--;for(var h=e;h<=f;h++)for(var i=0;i<g;i++)a.indentLine(h,b.indentRight);return zb.moveToFirstNonWhiteSpaceCharacter(a,c[0].anchor)},chan
 geCase:function(a,b,c,d,e){for(var f=a.getSelections(),g=[],h=b.toLower,i=0;i<f.length;i++){var j=f[i],k="";if(h===!0)k=j.toLowerCase();else if(h===!1)k=j.toUpperCase();else for(var l=0;l<j.length;l++){var m=j.charAt(l);k+=q(m)?m.toLowerCase():m.toUpperCase()}g.push(k)}return a.replaceSelections(g),b.shouldMoveCursor?e:!a.state.vim.visualMode&&b.linewise&&c[0].anchor.line+1==c[0].head.line?zb.moveToFirstNonWhiteSpaceCharacter(a,d):b.linewise?d:U(c[0].anchor,c[0].head)},yank:function(a,b,c,d){var e=a.state.vim,f=a.getSelection(),g=e.visualMode?U(e.sel.anchor,e.sel.head,c[0].head,c[0].anchor):d;return vb.registerController.pushText(b.registerName,"yank",f,b.linewise,e.visualBlock),g}},Bb={jumpListWalk:function(a,b,c){if(!c.visualMode){var d=b.repeat,e=b.forward,f=vb.jumpList,g=f.move(a,e?d:-d),h=g?g.find():void 0;h=h?h:a.getCursor(),a.setCursor(h)}},scroll:function(a,b,c){if(!c.visualMode){var d=b.repeat||1,e=a.defaultTextHeight(),f=a.getScrol
 lInfo().top,g=e*d,h=b.forward?f+g:f-g,i=R(a.getCursor()),j=a.charCoords(i,"local");if(b.forward)h>j.top?(i.line+=(h-j.top)/e,i.line=Math.ceil(i.line),a.setCursor(i),j=a.charCoords(i,"local"),a.scrollTo(null,j.top)):a.scrollTo(null,h);else{var k=h+a.getScrollInfo().clientHeight;k<j.bottom?(i.line-=(j.bottom-k)/e,i.line=Math.floor(i.line),a.setCursor(i),j=a.charCoords(i,"local"),a.scrollTo(null,j.bottom-a.getScrollInfo().clientHeight)):a.scrollTo(null,h)}}},scrollToCursor:function(a,b){var c=a.getCursor().line,e=a.charCoords(d(c,0),"local"),f=a.getScrollInfo().clientHeight,g=e.top,h=e.bottom-g;switch(b.position){case"center":g=g-f/2+h;break;case"bottom":g=g-f+h}a.scrollTo(null,g)},replayMacro:function(a,b,c){var d=b.selectedCharacter,e=b.repeat,f=vb.macroModeState;for("@"==d&&(d=f.latestRegister);e--;)Ya(a,c,f,d)},enterMacroRecordMode:function(a,b){var c=vb.macroModeState,d=b.selectedCharacter;vb.regis
 terController.isValidRegister(d)&&c.enterMacroRecordMode(a,d)},toggleOverwrite:function(b){b.state.overwrite?(b.toggleOverwrite(!1),b.setOption("keyMap","vim-insert"),a.signal(b,"vim-mode-change",{mode:"insert"})):(b.toggleOverwrite(!0),b.setOption("keyMap","vim-replace"),a.signal(b,"vim-mode-change",{mode:"replace"}))},enterInsertMode:function(b,c,e){if(!b.getOption("readOnly")){e.insertMode=!0,e.insertModeRepeat=c&&c.repeat||1;var f=c?c.insertAt:null,g=e.sel,h=c.head||b.getCursor("head"),i=b.listSelections().length;if("eol"==f)h=d(h.line,X(b,h.line));else if("charAfter"==f)h=L(h,0,1);else if("firstNonBlank"==f)h=zb.moveToFirstNonWhiteSpaceCharacter(b,h);else if("startOfSelectedArea"==f)e.visualBlock?(h=d(Math.min(g.head.line,g.anchor.line),Math.min(g.head.ch,g.anchor.ch)),i=Math.abs(g.head.line-g.anchor.line)+1):h=g.head.line&l
 t;g.anchor.line?g.head:d(g.anchor.line,0);else if("endOfSelectedArea"==f)e.visualBlock?(h=d(Math.min(g.head.line,g.anchor.line),Math.max(g.head.ch+1,g.anchor.ch)),i=Math.abs(g.head.line-g.anchor.line)+1):h=g.head.line>=g.anchor.line?L(g.head,0,1):d(g.anchor.line,0);else if("inplace"==f&&e.visualMode)return;b.setOption("disableInput",!1),c&&c.replace?(b.toggleOverwrite(!0),b.setOption("keyMap","vim-replace"),a.signal(b,"vim-mode-change",{mode:"replace"})):(b.toggleOverwrite(!1),b.setOption("keyMap","vim-insert"),a.signal(b,"vim-mode-change",{mode:"insert"})),vb.macroModeState.isPlaying||(b.on("change",ab),a.on(b.getInputField(),"keydown",fb)),e.visualMode&&ia(b),aa(b,h,i)}},toggleVisualMode:function(b,c,e){var f,g=c.repeat,h=b.getCursor();e.visualMode?e.visualLine^c.linewise||e.visualBlock^c.blockwise?(e.visualLine=!!c.linewise,e
 .visualBlock=!!c.blockwise,a.signal(b,"vim-mode-change",{mode:"visual",subMode:e.visualLine?"linewise":e.visualBlock?"blockwise":""}),fa(b)):ia(b):(e.visualMode=!0,e.visualLine=!!c.linewise,e.visualBlock=!!c.blockwise,f=J(b,d(h.line,h.ch+g-1),!0),e.sel={anchor:h,head:f},a.signal(b,"vim-mode-change",{mode:"visual",subMode:e.visualLine?"linewise":e.visualBlock?"blockwise":""}),fa(b),ua(b,e,"<",U(h,f)),ua(b,e,">",V(h,f)))},reselectLastSelection:function(b,c,d){var e=d.lastSelection;if(d.visualMode&&da(b,d),e){var f=e.anchorMark.find(),g=e.headMark.find();if(!f||!g)return;d.sel={anchor:f,head:g},d.visualMode=!0,d.visualLine=e.visualLine,d.visualBlock=e.visualBlock,fa(b),ua(b,d,"<",U(f,g)),ua(b,d,">",V(f,g)),a.signal(b,"vim-mode-change",{mode:"visual",subMode:d.visualLine?"linewise":d.visualBlock?&quo
 t;blockwise":""})}},joinLines:function(a,b,c){var e,f;if(c.visualMode){if(e=a.getCursor("anchor"),f=a.getCursor("head"),T(f,e)){var g=f;f=e,e=g}f.ch=X(a,f.line)-1}else{var h=Math.max(b.repeat,2);e=a.getCursor(),f=J(a,d(e.line+h-1,1/0))}for(var i=0,j=e.line;j<f.line;j++){i=X(a,e.line);var g=d(e.line+1,X(a,e.line+1)),k=a.getRange(e,g);k=k.replace(/\n\s*/g," "),a.replaceRange(k,e,g)}var l=d(e.line,i);c.visualMode&&ia(a,!1),a.setCursor(l)},newLineAndEnterInsertMode:function(b,c,e){e.insertMode=!0;var f=R(b.getCursor());if(f.line!==b.firstLine()||c.after){f.line=c.after?f.line:f.line-1,f.ch=X(b,f.line),b.setCursor(f);var g=a.commands.newlineAndIndentContinueComment||a.commands.newlineAndIndent;g(b)}else b.replaceRange("\n",d(b.firstLine(),0)),b.setCursor(b.firstLine(),0);this.enterInsertMode(b,{repeat:c.repeat},e)},paste:function(a,b,c){var e=R(a.getCursor()),f=vb.registerController.getRegister(b.registerName),g=f.toString
 ();if(g){if(b.matchIndent){var h=a.getOption("tabSize"),i=function(a){var b=a.split("\t").length-1,c=a.split(" ").length-1;return b*h+1*c},j=a.getLine(a.getCursor().line),k=i(j.match(/^\s*/)[0]),l=g.replace(/\n$/,""),m=g!==l,n=i(g.match(/^\s*/)[0]),g=l.replace(/^\s*/gm,function(b){var c=k+(i(b)-n);if(c<0)return"";if(a.getOption("indentWithTabs")){var d=Math.floor(c/h);return Array(d+1).join("\t")}return Array(c+1).join(" ")});g+=m?"\n":""}if(b.repeat>1)var g=Array(b.repeat+1).join(g);var o=f.linewise,p=f.blockwise;if(o)c.visualMode?g=c.visualLine?g.slice(0,-1):"\n"+g.slice(0,g.length-1)+"\n":b.after?(g="\n"+g.slice(0,g.length-1),e.ch=X(a,e.line)):e.ch=0;else{if(p){g=g.split("\n");for(var q=0;q<g.length;q++)g[q]=""==g[q]?" ":g[q]}e.ch+=b.after?1:0}var r,s;if(c.visualMode){c.lastPastedText=g;var t,u=ca(a,c),v=u[0],w=u[
 1],x=a.getSelection(),y=a.listSelections(),z=new Array(y.length).join("1").split("1");c.lastSelection&&(t=c.lastSelection.headMark.find()),vb.registerController.unnamedRegister.setText(x),p?(a.replaceSelections(z),w=d(v.line+g.length-1,v.ch),a.setCursor(v),_(a,w),a.replaceSelections(g),r=v):c.visualBlock?(a.replaceSelections(z),a.setCursor(v),a.replaceRange(g,v,v),r=v):(a.replaceRange(g,v,w),r=a.posFromIndex(a.indexFromPos(v)+g.length-1)),t&&(c.lastSelection.headMark=a.setBookmark(t)),o&&(r.ch=0)}else if(p){a.setCursor(e);for(var q=0;q<g.length;q++){var A=e.line+q;A>a.lastLine()&&a.replaceRange("\n",d(A,0));var B=X(a,A);B<e.ch&&$(a,A,e.ch)}a.setCursor(e),_(a,d(e.line+g.length-1,e.ch)),a.replaceSelections(g),r=e}else a.replaceRange(g,e),o&&b.after?r=d(e.line+1,la(a.getLine(e.line+1))):o&&!b.after?r=d(e.line,la(a.getLine(e.line))):!o&&b.after?(s=a.indexFromPos(e),r=a.posFromIndex(s+g
 .length-1)):(s=a.indexFromPos(e),r=a.posFromIndex(s+g.length));c.visualMode&&ia(a,!1),a.setCursor(r)}},undo:function(b,c){b.operation(function(){Q(b,a.commands.undo,c.repeat)(),b.setCursor(b.getCursor("anchor"))})},redo:function(b,c){Q(b,a.commands.redo,c.repeat)()},setRegister:function(a,b,c){c.inputState.registerName=b.selectedCharacter},setMark:function(a,b,c){var d=b.selectedCharacter;ua(a,c,d,a.getCursor())},replace:function(b,c,e){var f,g,h=c.selectedCharacter,i=b.getCursor(),j=b.listSelections();if(e.visualMode)i=b.getCursor("start"),g=b.getCursor("end");else{var k=b.getLine(i.line);f=i.ch+c.repeat,f>k.length&&(f=k.length),g=d(i.line,f)}if("\n"==h)e.visualMode||b.replaceRange("",i,g),(a.commands.newlineAndIndentContinueComment||a.commands.newlineAndIndent)(b);else{var l=b.getRange(i,g);if(l=l.replace(/[^\n]/g,h),e.visualBlock){var m=new Array(b.getOption("tabSize")+1).join(" ");l=b.getSel
 ection(),l=l.replace(/\t/g,m).replace(/[^\n]/g,h).split("\n"),b.replaceSelections(l)}else b.replaceRange(l,i,g);e.visualMode?(i=T(j[0].anchor,j[0].head)?j[0].anchor:j[0].head,b.setCursor(i),ia(b,!1)):b.setCursor(L(g,0,-1))}},incrementNumberToken:function(a,b){for(var c,e,f,g,h,i=a.getCursor(),j=a.getLine(i.line),k=/-?\d+/g;null!==(c=k.exec(j))&&(h=c[0],e=c.index,f=e+h.length,!(i.ch<f)););if((b.backtrack||!(f<=i.ch))&&h){var l=b.increase?1:-1,m=parseInt(h)+l*b.repeat,n=d(i.line,e),o=d(i.line,f);g=m.toString(),a.replaceRange(g,n,o),a.setCursor(d(i.line,e+g.length-1))}},repeatLastEdit:function(a,b,c){var d=c.lastEditInputState;if(d){var e=b.repeat;e&&b.repeatIsExplicit?c.lastEditInputState.repeatOverride=e:e=c.lastEditInputState.repeatOverride||e,gb(a,c,e,!1)}},indent:function(a,b){a.indentLine(a.getCursor().line,b.indentRight)},exitInsertMode:Va},Cb={"(":"bracket",")":"bracket","{":"bracket&
 quot;,"}":"bracket","[":"section","]":"section","*":"comment","/":"comment",m:"method",M:"method","#":"preprocess"},Db={bracket:{isComplete:function(a){if(a.nextCh===a.symb){if(a.depth++,a.depth>=1)return!0}else a.nextCh===a.reverseSymb&&a.depth--;return!1}},section:{init:function(a){a.curMoveThrough=!0,a.symb=(a.forward?"]":"[")===a.symb?"{":"}"},isComplete:function(a){return 0===a.index&&a.nextCh===a.symb}},comment:{isComplete:function(a){var b="*"===a.lastCh&&"/"===a.nextCh;return a.lastCh=a.nextCh,b}},method:{init:function(a){a.symb="m"===a.symb?"{":"}",a.reverseSymb="{"===a.symb?"}":"{"},isComplete:function(a){return a.nextCh===a.symb}},preprocess:{init:function(a){a.index=0},isComplete:function(
 a){if("#"===a.nextCh){var b=a.lineText.match(/#(\w+)/)[1];if("endif"===b){if(a.forward&&0===a.depth)return!0;a.depth++}else if("if"===b){if(!a.forward&&0===a.depth)return!0;a.depth--}if("else"===b&&0===a.depth)return!0}return!1}}};t("pcre",!0,"boolean"),za.prototype={getQuery:function(){return vb.query},setQuery:function(a){vb.query=a},getOverlay:function(){return this.searchOverlay},setOverlay:function(a){this.searchOverlay=a},isReversed:function(){return vb.isReversed},setReversed:function(a){vb.isReversed=a},getScrollbarAnnotate:function(){return this.annotate},setScrollbarAnnotate:function(a){this.annotate=a}};var Eb={"\\n":"\n","\\r":"\r","\\t":"\t"},Fb={"\\/":"/","\\\\":"\\","\\n":"\n","\\r":"\r","\\t":"\t"},Gb="(Javascript regexp)&
 quot;,Hb=function(){this.buildCommandMap_()};Hb.prototype={processCommand:function(a,b,c){var d=this;a.operation(function(){a.curOp.isVimOp=!0,d._processCommand(a,b,c)})},_processCommand:function(b,c,d){var e=b.state.vim,f=vb.registerController.getRegister(":"),g=f.toString();e.visualMode&&ia(b);var h=new a.StringStream(c);f.setText(c);var i=d||{};i.input=c;try{this.parseInput_(b,h,i)}catch(j){throw Ia(b,j),j}var k,l;if(i.commandName){if(k=this.matchCommand_(i.commandName)){if(l=k.name,k.excludeFromCommandHistory&&f.setText(g),this.parseCommandArgs_(h,i,k),"exToKey"==k.type){for(var m=0;m<k.toKeys.length;m++)a.Vim.handleKey(b,k.toKeys[m],"mapping");return}if("exToEx"==k.type)return void this.processCommand(b,k.toInput)}}else void 0!==i.line&&(l="move");if(!l)return void Ia(b,'Not an editor command ":'+c+'"');try{Ib[l](b,i),k&&k.possiblyAsync||!i.callback||i.callback()}catch(j){throw Ia(b,j
 ),j}},parseInput_:function(a,b,c){b.eatWhile(":"),b.eat("%")?(c.line=a.firstLine(),c.lineEnd=a.lastLine()):(c.line=this.parseLineSpec_(a,b),void 0!==c.line&&b.eat(",")&&(c.lineEnd=this.parseLineSpec_(a,b)));var d=b.match(/^(\w+)/);return d?c.commandName=d[1]:c.commandName=b.match(/.*/)[0],c},parseLineSpec_:function(a,b){var c=b.match(/^(\d+)/);if(c)return parseInt(c[1],10)-1;switch(b.next()){case".":return this.parseLineSpecOffset_(b,a.getCursor().line);case"$":return this.parseLineSpecOffset_(b,a.lastLine());case"'":var d=b.next(),e=Ta(a,a.state.vim,d);if(!e)throw new Error("Mark not set");return this.parseLineSpecOffset_(b,e.line);case"-":case"+":return b.backUp(1),this.parseLineSpecOffset_(b,a.getCursor().line);default:return void b.backUp(1)}},parseLineSpecOffset_:function(a,b){var c=a.match(/^([+-])?(\d+)/);if(c){var d=parseInt(c[2],10);"-"==c[1]?b-=d:b+=d}return 
 b},parseCommandArgs_:function(a,b,c){if(!a.eol()){b.argString=a.match(/.*/)[0];var d=c.argDelimiter||/\s+/,e=Y(b.argString).split(d);e.length&&e[0]&&(b.args=e)}},matchCommand_:function(a){for(var b=a.length;b>0;b--){var c=a.substring(0,b);if(this.commandMap_[c]){var d=this.commandMap_[c];if(0===d.name.indexOf(a))return d}}return null},buildCommandMap_:function(){this.commandMap_={};for(var a=0;a<c.length;a++){var b=c[a],d=b.shortName||b.name;this.commandMap_[d]=b}},map:function(a,c,d){if(":"!=a&&":"==a.charAt(0)){if(d)throw Error("Mode not supported for ex mappings");var e=a.substring(1);":"!=c&&":"==c.charAt(0)?this.commandMap_[e]={name:e,type:"exToEx",toInput:c.substring(1),user:!0}:this.commandMap_[e]={name:e,type:"exToKey",toKeys:c,user:!0}}else if(":"!=c&&":"==c.charAt(0)){var f={keys:a,type:"keyToEx",exArgs:{input:c.substring(1)}};d&
 amp;&(f.context=d),b.unshift(f)}else{var f={keys:a,type:"keyToKey",toKeys:c};d&&(f.context=d),b.unshift(f)}},unmap:function(a,c){if(":"!=a&&":"==a.charAt(0)){if(c)throw Error("Mode not supported for ex mappings");var d=a.substring(1);if(this.commandMap_[d]&&this.commandMap_[d].user)return void delete this.commandMap_[d]}else for(var e=a,f=0;f<b.length;f++)if(e==b[f].keys&&b[f].context===c)return void b.splice(f,1);throw Error("No such mapping.")}};var Ib={colorscheme:function(a,b){return!b.args||b.args.length<1?void Ia(a,a.getOption("theme")):void a.setOption("theme",b.args[0])},map:function(a,b,c){var d=b.args;return!d||d.length<2?void(a&&Ia(a,"Invalid mapping: "+b.input)):void Jb.map(d[0],d[1],c)},imap:function(a,b){this.map(a,b,"insert")},nmap:function(a,b){this.map(a,b,"normal")},vmap:function(a,b){this.map(a,b,"visual&quot
 ;)},unmap:function(a,b,c){var d=b.args;return!d||d.length<1?void(a&&Ia(a,"No such mapping: "+b.input)):void Jb.unmap(d[0],c)},move:function(a,b){yb.processCommand(a,a.state.vim,{type:"motion",motion:"moveToLineOrEdgeOfDocument",motionArgs:{forward:!1,explicitRepeat:!0,linewise:!0},repeatOverride:b.line+1})},set:function(a,b){var c=b.args,d=b.setCfg||{};if(!c||c.length<1)return void(a&&Ia(a,"Invalid mapping: "+b.input));var e=c[0].split("="),f=e[0],g=e[1],h=!1;if("?"==f.charAt(f.length-1)){if(g)throw Error("Trailing characters: "+b.argString);f=f.substring(0,f.length-1),h=!0}void 0===g&&"no"==f.substring(0,2)&&(f=f.substring(2),g=!1);var i=sb[f]&&"boolean"==sb[f].type;if(i&&void 0==g&&(g=!0),!i&&void 0===g||h){var j=v(f,a,d);j instanceof Error?Ia(a,j.message):j===!0||j===!1?Ia(a," "+(j?"":"no")+f)
 :Ia(a,"  "+f+"="+j)}else{var k=u(f,g,a,d);k instanceof Error&&Ia(a,k.message)}},setlocal:function(a,b){b.setCfg={scope:"local"},this.set(a,b)},setglobal:function(a,b){b.setCfg={scope:"global"},this.set(a,b)},registers:function(a,b){var c=b.args,d=vb.registerController.registers,e="----------Registers----------<br><br>";if(c){var f;c=c.join("");for(var g=0;g<c.length;g++)if(f=c.charAt(g),vb.registerController.isValidRegister(f)){var h=d[f]||new B;e+='"'+f+"    "+h.toString()+"<br>"}}else for(var f in d){var i=d[f].toString();i.length&&(e+='"'+f+"    "+i+"<br>")}Ia(a,e)},sort:function(b,c){function e(){if(c.argString){var b=new a.StringStream(c.argString);if(b.eat("!")&&(h=!0),b.eol())return;if(!b.eatSpace())return"Invalid arguments";var d=b.match(/([dinuox]+)?\s*(\/.+\/)?\s*/);if(!d&&!b.eol())retur
 n"Invalid arguments";if(d[1]){i=d[1].indexOf("i")!=-1,j=d[1].indexOf("u")!=-1;var e=d[1].indexOf("d")!=-1||d[1].indexOf("n")!=-1&&1,f=d[1].indexOf("x")!=-1&&1,g=d[1].indexOf("o")!=-1&&1;if(e+f+g>1)return"Invalid arguments";k=e&&"decimal"||f&&"hex"||g&&"octal"}d[2]&&(l=new RegExp(d[2].substr(1,d[2].length-2),i?"i":""))}}function f(a,b){if(h){var c;c=a,a=b,b=c}i&&(a=a.toLowerCase(),b=b.toLowerCase());var d=k&&s.exec(a),e=k&&s.exec(b);return d?(d=parseInt((d[1]+d[2]).toLowerCase(),t),e=parseInt((e[1]+e[2]).toLowerCase(),t),d-e):a<b?-1:1}function g(a,b){if(h){var c;c=a,a=b,b=c}return i&&(a[0]=a[0].toLowerCase(),b[0]=b[0].toLowerCase()),a[0]<b[0]?-1:1}var h,i,j,k,l,m=e();if(m)return void Ia(b,m+": "+c.argString);var n=c.line||b.firstLine(),o=c.lineEnd||c.
 line||b.lastLine();if(n!=o){var p=d(n,0),q=d(o,X(b,o)),r=b.getRange(p,q).split("\n"),s=l?l:"decimal"==k?/(-?)([\d]+)/:"hex"==k?/(-?)(?:0x)?([0-9a-f]+)/i:"octal"==k?/([0-7]+)/:null,t="decimal"==k?10:"hex"==k?16:"octal"==k?8:null,u=[],v=[];if(k||l)for(var w=0;w<r.length;w++){var x=l?r[w].match(l):null;x&&""!=x[0]?u.push(x):!l&&s.exec(r[w])?u.push(r[w]):v.push(r[w])}else v=r;if(u.sort(l?g:f),l)for(var w=0;w<u.length;w++)u[w]=u[w].input;else k||v.sort(f);if(r=h?u.concat(v):v.concat(u),j){var y,z=r;r=[];for(var w=0;w<z.length;w++)z[w]!=y&&r.push(z[w]),y=z[w]}b.replaceRange(r.join("\n"),p,q)}},global:function(a,b){var c=b.argString;if(!c)return void Ia(a,"Regular Expression missing from global");var d,e=void 0!==b.line?b.line:a.firstLine(),f=b.lineEnd||b.line||a.lastLine(),g=Ca(c),h=c;if(g.length&&(h=g[0],d=g.slice(1,g.length).join("/")),h)
 try{Ma(a,h,!0,!0)}catch(i){return void Ia(a,"Invalid regex: "+h)}for(var j=Aa(a).getQuery(),k=[],l="",m=e;m<=f;m++){var n=j.test(a.getLine(m));n&&(k.push(m+1),l+=a.getLine(m)+"<br>")}if(!d)return void Ia(a,l);var o=0,p=function(){if(o<k.length){var b=k[o]+d;Jb.processCommand(a,b,{callback:p})}o++};p()},substitute:function(a,b){if(!a.getSearchCursor)throw new Error("Search feature not available. Requires searchcursor.js or any other getSearchCursor implementation.");var c,e,f,g,h=b.argString,i=h?Ca(h):[],j="",k=!1,l=!1;if(i.length)c=i[0],j=i[1],c&&"$"===c[c.length-1]&&(c=c.slice(0,c.length-1)+"\\n",j=j?j+"\n":"\n"),void 0!==j&&(j=v("pcre")?Ga(j):Fa(j),vb.lastSubstituteReplacePart=j),e=i[2]?i[2].split(" "):[];else if(h&&h.length)return void Ia(a,"Substitutions should be of the form :s/pattern/replace/");if(e&&am
 p;(f=e[0],g=parseInt(e[1]),f&&(f.indexOf("c")!=-1&&(k=!0,f.replace("c","")),f.indexOf("g")!=-1&&(l=!0,f.replace("g","")),c=c+"/"+f)),c)try{Ma(a,c,!0,!0)}catch(m){return void Ia(a,"Invalid regex: "+c)}if(j=j||vb.lastSubstituteReplacePart,void 0===j)return void Ia(a,"No previous substitute regular expression");var n=Aa(a),o=n.getQuery(),p=void 0!==b.line?b.line:a.getCursor().line,q=b.lineEnd||p;p==a.firstLine()&&q==a.lastLine()&&(q=1/0),g&&(p=q,q=p+g-1);var r=J(a,d(p,0)),s=a.getSearchCursor(o,r);Ua(a,k,l,p,q,s,o,j,b.callback)},redo:a.commands.redo,undo:a.commands.undo,write:function(b){a.commands.save?a.commands.save(b):b.save&&b.save()},nohlsearch:function(a){Qa(a)},yank:function(a){var b=R(a.getCursor()),c=b.line,d=a.getLine(c);vb.registerController.pushText("0","yank",d,!0,!0)},delmarks:function(b,c){if(!c.argString||!
 Y(c.argString))return void Ia(b,"Argument required");for(var d=b.state.vim,e=new a.StringStream(Y(c.argString));!e.eol();){e.eatSpace();var f=e.pos;if(!e.match(/[a-zA-Z]/,!1))return void Ia(b,"Invalid argument: "+c.argString.substring(f));var g=e.next();if(e.match("-",!0)){if(!e.match(/[a-zA-Z]/,!1))return void Ia(b,"Invalid argument: "+c.argString.substring(f));var h=g,i=e.next();if(!(n(h)&&n(i)||q(h)&&q(i)))return void Ia(b,"Invalid argument: "+h+"-");var j=h.charCodeAt(0),k=i.charCodeAt(0);if(j>=k)return void Ia(b,"Invalid argument: "+c.argString.substring(f));for(var l=0;l<=k-j;l++){var m=String.fromCharCode(j+l);delete d.marks[m]}}else delete d.marks[g]}}},Jb=new Hb;return a.keyMap.vim={attach:h,detach:g,call:i},t("insertModeEscKeysTimeout",200,"number"),a.keyMap["vim-insert"]={fallthrough:["default"],attach:h,detach:g,call:i},a.keyMap["vim-re
 place"]={Backspace:"goCharLeft",fallthrough:["vim-insert"],attach:h,detach:g,call:i},y(),xb};a.Vim=e()})},{"../addon/dialog/dialog":3,"../addon/edit/matchbrackets.js":12,"../addon/search/searchcursor":49,"../lib/codemirror":59}],59:[function(a,b,c){!function(a,d){"object"==typeof c&&"undefined"!=typeof b?b.exports=d():"function"==typeof define&&define.amd?define(d):a.CodeMirror=d()}(this,function(){"use strict";function a(a){return new RegExp("(^|\\s)"+a+"(?:$|\\s)\\s*")}function b(a){for(var b=a.childNodes.length;b>0;--b)a.removeChild(a.firstChild);return a}function c(a,c){return b(a).appendChild(c)}function d(a,b,c,d){var e=document.createElement(a);if(c&&(e.className=c),d&&(e.style.cssText=d),"string"==typeof b)e.appendChild(document.createTextNode(b));else if(b)for(var f=0;f<b.length;++f)e.appendChild(b[f]);r
 eturn e}function e(a,b,c,e){var f=d(a,b,c,e);return f.setAttribute("role","presentation"),f}function f(a,b){if(3==b.nodeType&&(b=b.parentNode),a.contains)return a.contains(b);do if(11==b.nodeType&&(b=b.host),b==a)return!0;while(b=b.parentNode)}function g(){var a;try{a=document.activeElement}catch(b){a=document.body||null}for(;a&&a.shadowRoot&&a.shadowRoot.activeElement;)a=a.shadowRoot.activeElement;return a}function h(b,c){var d=b.className;a(c).test(d)||(b.className+=(d?" ":"")+c)}function i(b,c){for(var d=b.split(" "),e=0;e<d.length;e++)d[e]&&!a(d[e]).test(c)&&(c+=" "+d[e]);return c}function j(a){var b=Array.prototype.slice.call(arguments,1);return function(){return a.apply(null,b)}}function k(a,b,c){b||(b={});for(var d in a)!a.hasOwnProperty(d)||c===!1&&b.hasOwnProperty(d)||(b[d]=a[d]);return b}function l(a,b,c,d,e){null==b&&(b=a.search(/[^\s\u00a0]/),b==
 -1&&(b=a.length));for(var f=d||0,g=e||0;;){var h=a.indexOf("\t",f);if(h<0||h>=b)return g+(b-f);g+=h-f,g+=c-g%c,f=h+1}}function m(a,b){for(var c=0;c<a.length;++c)if(a[c]==b)return c;return-1}function n(a,b,c){for(var d=0,e=0;;){var f=a.indexOf("\t",d);f==-1&&(f=a.length);var g=f-d;if(f==a.length||e+g>=b)return d+Math.min(g,b-e);if(e+=f-d,e+=c-e%c,d=f+1,e>=b)return d}}function o(a){for(;Qg.length<=a;)Qg.push(p(Qg)+" ");return Qg[a]}function p(a){return a[a.length-1]}function q(a,b){for(var c=[],d=0;d<a.length;d++)c[d]=b(a[d],d);return c}function r(a,b,c){for(var d=0,e=c(b);d<a.length&&c(a[d])<=e;)d++;a.splice(d,0,b)}function s(){}function t(a,b){var c;return Object.create?c=Object.create(a):(s.prototype=a,c=new s),b&&k(b,c),c}function u(a){return/\w/.test(a)||a>"\x80"&&(a.toUpperCase()!=a.toLowerCase()||Rg.test(a))}function v(a,b){return b?!!(b.source.indexOf("\\w")&
 gt;-1&&u(a))||b.test(a):u(a)}function w(a){for(var b in a)if(a.hasOwnProperty(b)&&a[b])return!1;return!0}function x(a){return a.charCodeAt(0)>=768&&Sg.test(a)}function y(a,b,c){for(;(c<0?b>0:b<a.length)&&x(a.charAt(b));)b+=c;return b}function z(a,b,c){for(;;){if(Math.abs(b-c)<=1)return a(b)?b:c;var d=Math.floor((b+c)/2);a(d)?c=d:b=d}}function A(a,b,c){var f=this;this.input=c,f.scrollbarFiller=d("div",null,"CodeMirror-scrollbar-filler"),f.scrollbarFiller.setAttribute("cm-not-content","true"),f.gutterFiller=d("div",null,"CodeMirror-gutter-filler"),f.gutterFiller.setAttribute("cm-not-content","true"),f.lineDiv=e("div",null,"CodeMirror-code"),f.selectionDiv=d("div",null,null,"position: relative; z-index: 1"),f.cursorDiv=d("div",null,"CodeMirror-cursors"),f.measure=d("div",null,"CodeMirror
 -measure"),f.lineMeasure=d("div",null,"CodeMirror-measure"),f.lineSpace=e("div",[f.measure,f.lineMeasure,f.selectionDiv,f.cursorDiv,f.lineDiv],null,"position: relative; outline: none");var g=e("div",[f.lineSpace],"CodeMirror-lines");f.mover=d("div",[g],null,"position: relative"),f.sizer=d("div",[f.mover],"CodeMirror-sizer"),f.sizerWidth=null,f.heightForcer=d("div",null,null,"position: absolute; height: "+Lg+"px; width: 1px;"),f.gutters=d("div",null,"CodeMirror-gutters"),f.lineGutter=null,f.scroller=d("div",[f.sizer,f.heightForcer,f.gutters],"CodeMirror-scroll"),f.scroller.setAttribute("tabIndex","-1"),f.wrapper=d("div",[f.scrollbarFiller,f.gutterFiller,f.scroller],"CodeMirror"),ng&&og<8&&(f.gutters.style.zIndex=-1,f.scroller.style.paddingRight=0),pg||jg
 &&yg||(f.scroller.draggable=!0),a&&(a.appendChild?a.appendChild(f.wrapper):a(f.wrapper)),f.viewFrom=f.viewTo=b.first,f.reportedViewFrom=f.reportedViewTo=b.first,f.view=[],f.renderedView=null,f.externalMeasured=null,f.viewOffset=0,f.lastWrapHeight=f.lastWrapWidth=0,f.updateLineNumbers=null,f.nativeBarWidth=f.barHeight=f.barWidth=0,f.scrollbarsClipped=!1,f.lineNumWidth=f.lineNumInnerWidth=f.lineNumChars=null,f.alignWidgets=!1,f.cachedCharWidth=f.cachedTextHeight=f.cachedPaddingH=null,f.maxLine=null,f.maxLineLength=0,f.maxLineChanged=!1,f.wheelDX=f.wheelDY=f.wheelStartX=f.wheelStartY=null,f.shift=!1,f.selForContextMenu=null,f.activeTouch=null,c.init(f)}function B(a,b){if(b-=a.first,b<0||b>=a.size)throw new Error("There is no line "+(b+a.first)+" in the document.");for(var c=a;!c.lines;)for(var d=0;;++d){var e=c.children[d],f=e.chunkSize();if(b<f){c=e;break}b-=f}return c.lines[b]}function C(a,b,c){var d=[],e=b.line;return a.iter(b.line,c.line
 +1,function(a){var f=a.text;e==c.line&&(f=f.slice(0,c.ch)),e==b.line&&(f=f.slice(b.ch)),d.push(f),++e}),d}function D(a,b,c){var d=[];return a.iter(b,c,function(a){d.push(a.text)}),d}function E(a,b){var c=b-a.height;if(c)for(var d=a;d;d=d.parent)d.height+=c}function F(a){if(null==a.parent)return null;for(var b=a.parent,c=m(b.lines,a),d=b.parent;d;b=d,d=d.parent)for(var e=0;d.children[e]!=b;++e)c+=d.children[e].chunkSize();return c+b.first}function G(a,b){var c=a.first;a:do{for(var d=0;d<a.children.length;++d){var e=a.children[d],f=e.height;if(b<f){a=e;continue a}b-=f,c+=e.chunkSize()}return c}while(!a.lines);for(var g=0;g<a.lines.length;++g){var h=a.lines[g],i=h.height;if(b<i)break;b-=i}return c+g}function H(a,b){return b>=a.first&&b<a.first+a.size}function I(a,b){return String(a.lineNumberFormatter(b+a.firstLineNumber))}function J(a,b,c){return void 0===c&&(c=null),this instanceof J?(this.line=a,this.ch=b,void(this.sticky=c)):new J(a
 ,b,c)}function K(a,b){return a.line-b.line||a.ch-b.ch}function L(a,b){return a.sticky==b.sticky&&0==K(a,b)}function M(a){return J(a.line,a.ch)}function N(a,b){return K(a,b)<0?b:a}function O(a,b){return K(a,b)<0?a:b}function P(a,b){return Math.max(a.first,Math.min(b,a.first+a.size-1))}function Q(a,b){if(b.line<a.first)return J(a.first,0);var c=a.first+a.size-1;return b.line>c?J(c,B(a,c).text.length):R(b,B(a,b.line).text.length)}function R(a,b){var c=a.ch;return null==c||c>b?J(a.line,b):c<0?J(a.line,0):a}function S(a,b){for(var c=[],d=0;d<b.length;d++)c[d]=Q(a,b[d]);return c}function T(){Tg=!0}function U(){Ug=!0}function V(a,b,c){this.marker=a,this.from=b,this.to=c}function W(a,b){if(a)for(var c=0;c<a.length;++c){var d=a[c];if(d.marker==b)return d}}function X(a,b){for(var c,d=0;d<a.length;++d)a[d]!=b&&(c||(c=[])).push(a[d]);return c}function Y(a,b){a.markedSpans=a.markedSpans?a.markedSpans.concat([b]):[b],b.marker.attachLine(a)}function Z(a,b
 ,c){var d;if(a)for(var e=0;e<a.length;++e){var f=a[e],g=f.marker,h=null==f.from||(g.inclusiveLeft?f.from<=b:f.from<b);if(h||f.from==b&&"bookmark"==g.type&&(!c||!f.marker.insertLeft)){var i=null==f.to||(g.inclusiveRight?f.to>=b:f.to>b);(d||(d=[])).push(new V(g,f.from,i?null:f.to))}}return d}function $(a,b,c){var d;if(a)for(var e=0;e<a.length;++e){var f=a[e],g=f.marker,h=null==f.to||(g.inclusiveRight?f.to>=b:f.to>b);if(h||f.from==b&&"bookmark"==g.type&&(!c||f.marker.insertLeft)){var i=null==f.from||(g.inclusiveLeft?f.from<=b:f.from<b);(d||(d=[])).push(new V(g,i?null:f.from-b,null==f.to?null:f.to-b))}}return d}function _(a,b){if(b.full)return null;var c=H(a,b.from.line)&&B(a,b.from.line).markedSpans,d=H(a,b.to.line)&&B(a,b.to.line).markedSpans;if(!c&&!d)return null;var e=b.from.ch,f=b.to.ch,g=0==K(b.from,b.to),h=Z(c,e,g),i=$(d,f,g),j=1==b.text.length,k=p(b.text).length+(j?e:0);if(h
 )for(var l=0;l<h.length;++l){var m=h[l];if(null==m.to){var n=W(i,m.marker);n?j&&(m.to=null==n.to?null:n.to+k):m.to=e}}if(i)for(var o=0;o<i.length;++o){var q=i[o];if(null!=q.to&&(q.to+=k),null==q.from){var r=W(h,q.marker);r||(q.from=k,j&&(h||(h=[])).push(q))}else q.from+=k,j&&(h||(h=[])).push(q)}h&&(h=aa(h)),i&&i!=h&&(i=aa(i));var s=[h];if(!j){var t,u=b.text.length-2;if(u>0&&h)for(var v=0;v<h.length;++v)null==h[v].to&&(t||(t=[])).push(new V(h[v].marker,null,null));for(var w=0;w<u;++w)s.push(t);s.push(i)}return s}function aa(a){for(var b=0;b<a.length;++b){var c=a[b];null!=c.from&&c.from==c.to&&c.marker.clearWhenEmpty!==!1&&a.splice(b--,1)}return a.length?a:null}function ba(a,b,c){var d=null;if(a.iter(b.line,c.line+1,function(a){if(a.markedSpans)for(var b=0;b<a.markedSpans.length;++b){var c=a.markedSpans[b].marker;!c.readOnly||d&&m(d,c)!=-1||(d||(d=[])).push(c)}}
 ),!d)return null;for(var e=[{from:b,to:c}],f=0;f<d.length;++f)for(var g=d[f],h=g.find(0),i=0;i<e.length;++i){var j=e[i];if(!(K(j.to,h.from)<0||K(j.from,h.to)>0)){var k=[i,1],l=K(j.from,h.from),n=K(j.to,h.to);(l<0||!g.inclusiveLeft&&!l)&&k.push({from:j.from,to:h.from}),(n>0||!g.inclusiveRight&&!n)&&k.push({from:h.to,to:j.to}),e.splice.apply(e,k),i+=k.length-3}}return e}function ca(a){var b=a.markedSpans;if(b){for(var c=0;c<b.length;++c)b[c].marker.detachLine(a);a.markedSpans=null}}function da(a,b){if(b){for(var c=0;c<b.length;++c)b[c].marker.attachLine(a);a.markedSpans=b}}function ea(a){return a.inclusiveLeft?-1:0}function fa(a){return a.inclusiveRight?1:0}function ga(a,b){var c=a.lines.length-b.lines.length;if(0!=c)return c;var d=a.find(),e=b.find(),f=K(d.from,e.from)||ea(a)-ea(b);if(f)return-f;var g=K(d.to,e.to)||fa(a)-fa(b);return g?g:b.id-a.id}function ha(a,b){var c,d=Ug&&a.markedSpans;if(d)for(var e=void 0,f=0;f<
 d.length;++f)e=d[f],e.marker.collapsed&&null==(b?e.from:e.to)&&(!c||ga(c,e.marker)<0)&&(c=e.marker);return c}function ia(a){return ha(a,!0)}function ja(a){return ha(a,!1)}function ka(a,b,c,d,e){var f=B(a,b),g=Ug&&f.markedSpans;if(g)for(var h=0;h<g.length;++h){var i=g[h];if(i.marker.collapsed){var j=i.marker.find(0),k=K(j.from,c)||ea(i.marker)-ea(e),l=K(j.to,d)||fa(i.marker)-fa(e);
+if(!(k>=0&&l<=0||k<=0&&l>=0)&&(k<=0&&(i.marker.inclusiveRight&&e.inclusiveLeft?K(j.to,c)>=0:K(j.to,c)>0)||k>=0&&(i.marker.inclusiveRight&&e.inclusiveLeft?K(j.from,d)<=0:K(j.from,d)<0)))return!0}}}function la(a){for(var b;b=ia(a);)a=b.find(-1,!0).line;return a}function ma(a){for(var b;b=ja(a);)a=b.find(1,!0).line;return a}function na(a){for(var b,c;b=ja(a);)a=b.find(1,!0).line,(c||(c=[])).push(a);return c}function oa(a,b){var c=B(a,b),d=la(c);return c==d?b:F(d)}function pa(a,b){if(b>a.lastLine())return b;var c,d=B(a,b);if(!qa(a,d))return b;for(;c=ja(d);)d=c.find(1,!0).line;return F(d)+1}function qa(a,b){var c=Ug&&b.markedSpans;if(c)for(var d=void 0,e=0;e<c.length;++e)if(d=c[e],d.marker.collapsed){if(null==d.from)return!0;if(!d.marker.widgetNode&&0==d.from&&d.marker.inclusiveLeft&&ra(a,b,d))return!0}}function ra(a,b,c){if(null==c.to){var d=c.marker.find(1,!0);ret
 urn ra(a,d.line,W(d.line.markedSpans,c.marker))}if(c.marker.inclusiveRight&&c.to==b.text.length)return!0;for(var e=void 0,f=0;f<b.markedSpans.length;++f)if(e=b.markedSpans[f],e.marker.collapsed&&!e.marker.widgetNode&&e.from==c.to&&(null==e.to||e.to!=c.from)&&(e.marker.inclusiveLeft||c.marker.inclusiveRight)&&ra(a,b,e))return!0}function sa(a){a=la(a);for(var b=0,c=a.parent,d=0;d<c.lines.length;++d){var e=c.lines[d];if(e==a)break;b+=e.height}for(var f=c.parent;f;c=f,f=c.parent)for(var g=0;g<f.children.length;++g){var h=f.children[g];if(h==c)break;b+=h.height}return b}function ta(a){if(0==a.height)return 0;for(var b,c=a.text.length,d=a;b=ia(d);){var e=b.find(0,!0);d=e.from.line,c+=e.from.ch-e.to.ch}for(d=a;b=ja(d);){var f=b.find(0,!0);c-=d.text.length-f.from.ch,d=f.to.line,c+=d.text.length-f.to.ch}return c}function ua(a){var b=a.display,c=a.doc;b.maxLine=B(c,c.first),b.maxLineLength=ta(b.maxLine),b.maxLineChanged=!0,c.iter(functi
 on(a){var c=ta(a);c>b.maxLineLength&&(b.maxLineLength=c,b.maxLine=a)})}function va(a,b,c,d){if(!a)return d(b,c,"ltr");for(var e=!1,f=0;f<a.length;++f){var g=a[f];(g.from<c&&g.to>b||b==c&&g.to==b)&&(d(Math.max(g.from,b),Math.min(g.to,c),1==g.level?"rtl":"ltr"),e=!0)}e||d(b,c,"ltr")}function wa(a,b,c){var d;Vg=null;for(var e=0;e<a.length;++e){var f=a[e];if(f.from<b&&f.to>b)return e;f.to==b&&(f.from!=f.to&&"before"==c?d=e:Vg=e),f.from==b&&(f.from!=f.to&&"before"!=c?d=e:Vg=e)}return null!=d?d:Vg}function xa(a,b){var c=a.order;return null==c&&(c=a.order=Wg(a.text,b)),c}function ya(a,b,c){var d=y(a.text,b+c,c);return d<0||d>a.text.length?null:d}function za(a,b,c){var d=ya(a,b.ch,c);return null==d?null:new J(b.line,d,c<0?"after":"before")}function Aa(a,b,c,d,e){if(a){var f=xa(c,b.doc.direction);if(f){va
 r g,h=e<0?p(f):f[0],i=e<0==(1==h.level),j=i?"after":"before";if(h.level>0){var k=Zb(b,c);g=e<0?c.text.length-1:0;var l=$b(b,k,g).top;g=z(function(a){return $b(b,k,a).top==l},e<0==(1==h.level)?h.from:h.to-1,g),"before"==j&&(g=ya(c,g,1))}else g=e<0?h.to:h.from;return new J(d,g,j)}}return new J(d,e<0?c.text.length:0,e<0?"before":"after")}function Ba(a,b,c,d){var e=xa(b,a.doc.direction);if(!e)return za(b,c,d);c.ch>=b.text.length?(c.ch=b.text.length,c.sticky="before"):c.ch<=0&&(c.ch=0,c.sticky="after");var f=wa(e,c.ch,c.sticky),g=e[f];if("ltr"==a.doc.direction&&g.level%2==0&&(d>0?g.to>c.ch:g.from<c.ch))return za(b,c,d);var h,i=function(a,c){return ya(b,a instanceof J?a.ch:a,c)},j=function(c){return a.options.lineWrapping?(h=h||Zb(a,b),qc(a,b,h,c)):{begin:0,end:b.text.length}},k=j("before"==c.sticky?i(c,-1):c.ch);if("rtl&quot
 ;==a.doc.direction||1==g.level){var l=1==g.level==d<0,m=i(c,l?1:-1);if(null!=m&&(l?m<=g.to&&m<=k.end:m>=g.from&&m>=k.begin)){var n=l?"before":"after";return new J(c.line,m,n)}}var o=function(a,b,d){for(var f=function(a,b){return b?new J(c.line,i(a,1),"before"):new J(c.line,a,"after")};a>=0&&a<e.length;a+=b){var g=e[a],h=b>0==(1!=g.level),j=h?d.begin:i(d.end,-1);if(g.from<=j&&j<g.to)return f(j,h);if(j=h?g.from:i(g.to,-1),d.begin<=j&&j<d.end)return f(j,h)}},p=o(f+d,d,k);if(p)return p;var q=d>0?k.end:i(k.begin,-1);return null==q||d>0&&q==b.text.length||!(p=o(d>0?0:e.length-1,d,j(q)))?null:p}function Ca(a,b){return a._handlers&&a._handlers[b]||Xg}function Da(a,b,c){if(a.removeEventListener)a.removeEventListener(b,c,!1);else if(a.detachEvent)a.detachEvent("on"+b,c);else{var d=a._handlers,e=d&&d[b];if(e){var f=m(e,c);f>-1
 &&(d[b]=e.slice(0,f).concat(e.slice(f+1)))}}}function Ea(a,b){var c=Ca(a,b);if(c.length)for(var d=Array.prototype.slice.call(arguments,2),e=0;e<c.length;++e)c[e].apply(null,d)}function Fa(a,b,c){return"string"==typeof b&&(b={type:b,preventDefault:function(){this.defaultPrevented=!0}}),Ea(a,c||b.type,a,b),La(b)||b.codemirrorIgnore}function Ga(a){var b=a._handlers&&a._handlers.cursorActivity;if(b)for(var c=a.curOp.cursorActivityHandlers||(a.curOp.cursorActivityHandlers=[]),d=0;d<b.length;++d)m(c,b[d])==-1&&c.push(b[d])}function Ha(a,b){return Ca(a,b).length>0}function Ia(a){a.prototype.on=function(a,b){Yg(this,a,b)},a.prototype.off=function(a,b){Da(this,a,b)}}function Ja(a){a.preventDefault?a.preventDefault():a.returnValue=!1}function Ka(a){a.stopPropagation?a.stopPropagation():a.cancelBubble=!0}function La(a){return null!=a.defaultPrevented?a.defaultPrevented:0==a.returnValue}function Ma(a){Ja(a),Ka(a)}function Na(a){return a.target|
 |a.srcElement}function Oa(a){var b=a.which;return null==b&&(1&a.button?b=1:2&a.button?b=3:4&a.button&&(b=2)),zg&&a.ctrlKey&&1==b&&(b=3),b}function Pa(a){if(null==Jg){var b=d("span","\u200b");c(a,d("span",[b,document.createTextNode("x")])),0!=a.firstChild.offsetHeight&&(Jg=b.offsetWidth<=1&&b.offsetHeight>2&&!(ng&&og<8))}var e=Jg?d("span","\u200b"):d("span","\xa0",null,"display: inline-block; width: 1px; margin-right: -1px");return e.setAttribute("cm-text",""),e}function Qa(a){if(null!=Kg)return Kg;var d=c(a,document.createTextNode("A\u062eA")),e=Dg(d,0,1).getBoundingClientRect(),f=Dg(d,1,2).getBoundingClientRect();return b(a),!(!e||e.left==e.right)&&(Kg=f.right-e.right<3)}function Ra(a){if(null!=bh)return bh;var b=c(a,d("span","x")),e=b.getBou
 ndingClientRect(),f=Dg(b,0,1).getBoundingClientRect();return bh=Math.abs(e.left-f.left)>1}function Sa(a,b){arguments.length>2&&(b.dependencies=Array.prototype.slice.call(arguments,2)),ch[a]=b}function Ta(a,b){dh[a]=b}function Ua(a){if("string"==typeof a&&dh.hasOwnProperty(a))a=dh[a];else if(a&&"string"==typeof a.name&&dh.hasOwnProperty(a.name)){var b=dh[a.name];"string"==typeof b&&(b={name:b}),a=t(b,a),a.name=b.name}else{if("string"==typeof a&&/^[\w\-]+\/[\w\-]+\+xml$/.test(a))return Ua("application/xml");if("string"==typeof a&&/^[\w\-]+\/[\w\-]+\+json$/.test(a))return Ua("application/json")}return"string"==typeof a?{name:a}:a||{name:"null"}}function Va(a,b){b=Ua(b);var c=ch[b.name];if(!c)return Va(a,"text/plain");var d=c(a,b);if(eh.hasOwnProperty(b.name)){var e=eh[b.name];for(var f in e)e.hasOwnProperty(f)&&(d.hasO
 wnProperty(f)&&(d["_"+f]=d[f]),d[f]=e[f])}if(d.name=b.name,b.helperType&&(d.helperType=b.helperType),b.modeProps)for(var g in b.modeProps)d[g]=b.modeProps[g];return d}function Wa(a,b){var c=eh.hasOwnProperty(a)?eh[a]:eh[a]={};k(b,c)}function Xa(a,b){if(b===!0)return b;if(a.copyState)return a.copyState(b);var c={};for(var d in b){var e=b[d];e instanceof Array&&(e=e.concat([])),c[d]=e}return c}function Ya(a,b){for(var c;a.innerMode&&(c=a.innerMode(b),c&&c.mode!=a);)b=c.state,a=c.mode;return c||{mode:a,state:b}}function Za(a,b,c){return!a.startState||a.startState(b,c)}function $a(a,b,c,d){var e=[a.state.modeGen],f={};gb(a,b.text,a.doc.mode,c,function(a,b){return e.push(a,b)},f,d);for(var g=c.state,h=function(d){var g=a.state.overlays[d],h=1,i=0;c.state=!0,gb(a,b.text,g.mode,c,function(a,b){for(var c=h;i<a;){var d=e[h];d>a&&e.splice(h,1,a,e[h+1],d),h+=2,i=Math.min(a,d)}if(b)if(g.opaque)e.splice(c,h-c,a,"overlay "+
 b),h=c+2;else for(;c<h;c+=2){var f=e[c+1];e[c+1]=(f?f+" ":"")+"overlay "+b}},f)},i=0;i<a.state.overlays.length;++i)h(i);return c.state=g,{styles:e,classes:f.bgClass||f.textClass?f:null}}function _a(a,b,c){if(!b.styles||b.styles[0]!=a.state.modeGen){var d=ab(a,F(b)),e=b.text.length>a.options.maxHighlightLength&&Xa(a.doc.mode,d.state),f=$a(a,b,d);e&&(d.state=e),b.stateAfter=d.save(!e),b.styles=f.styles,f.classes?b.styleClasses=f.classes:b.styleClasses&&(b.styleClasses=null),c===a.doc.highlightFrontier&&(a.doc.modeFrontier=Math.max(a.doc.modeFrontier,++a.doc.highlightFrontier))}return b.styles}function ab(a,b,c){var d=a.doc,e=a.display;if(!d.mode.startState)return new hh(d,!0,b);var f=hb(a,b,c),g=f>d.first&&B(d,f-1).stateAfter,h=g?hh.fromSaved(d,g,f):new hh(d,Za(d.mode),f);return d.iter(f,b,function(c){bb(a,c.text,h);var d=h.line;c.stateAfter=d==b-1||d%5==0||d>=e.viewFrom&&d<e.viewTo?h.save(
 ):null,h.nextLine()}),c&&(d.modeFrontier=h.line),h}function bb(a,b,c,d){var e=a.doc.mode,f=new fh(b,a.options.tabSize,c);for(f.start=f.pos=d||0,""==b&&cb(e,c.state);!f.eol();)db(e,f,c.state),f.start=f.pos}function cb(a,b){if(a.blankLine)return a.blankLine(b);if(a.innerMode){var c=Ya(a,b);return c.mode.blankLine?c.mode.blankLine(c.state):void 0}}function db(a,b,c,d){for(var e=0;e<10;e++){d&&(d[0]=Ya(a,c).mode);var f=a.token(b,c);if(b.pos>b.start)return f}throw new Error("Mode "+a.name+" failed to advance stream.")}function eb(a,b,c,d){var e,f=a.doc,g=f.mode;b=Q(f,b);var h,i=B(f,b.line),j=ab(a,b.line,c),k=new fh(i.text,a.options.tabSize,j);for(d&&(h=[]);(d||k.pos<b.ch)&&!k.eol();)k.start=k.pos,e=db(g,k,j.state),d&&h.push(new ih(k,e,Xa(f.mode,j.state)));return d?h:new ih(k,e,j.state)}function fb(a,b){if(a)for(;;){var c=a.match(/(?:^|\s+)line-(background-)?(\S+)/);if(!c)break;a=a.slice(0,c.index)+a.sl
 ice(c.index+c[0].length);var d=c[1]?"bgClass":"textClass";null==b[d]?b[d]=c[2]:new RegExp("(?:^|s)"+c[2]+"(?:$|s)").test(b[d])||(b[d]+=" "+c[2])}return a}function gb(a,b,c,d,e,f,g){var h=c.flattenSpans;null==h&&(h=a.options.flattenSpans);var i,j=0,k=null,l=new fh(b,a.options.tabSize,d),m=a.options.addModeClass&&[null];for(""==b&&fb(cb(c,d.state),f);!l.eol();){if(l.pos>a.options.maxHighlightLength?(h=!1,g&&bb(a,b,d,l.pos),l.pos=b.length,i=null):i=fb(db(c,l,d.state,m),f),m){var n=m[0].name;n&&(i="m-"+(i?n+" "+i:n))}if(!h||k!=i){for(;j<l.start;)j=Math.min(l.start,j+5e3),e(j,k);k=i}l.start=l.pos}for(;j<l.pos;){var o=Math.min(l.pos,j+5e3);e(o,k),j=o}}function hb(a,b,c){for(var d,e,f=a.doc,g=c?-1:b-(a.doc.mode.innerMode?1e3:100),h=b;h>g;--h){if(h<=f.first)return f.first;var i=B(f,h-1),j=i.stateAfter;if(j&&(!c||h+(j instanceof gh?j.lookAhead:0)<=
 f.modeFrontier))return h;var k=l(i.text,null,a.options.tabSize);(null==e||d>k)&&(e=h-1,d=k)}return e}function ib(a,b){if(a.modeFrontier=Math.min(a.modeFrontier,b),!(a.highlightFrontier<b-10)){for(var c=a.first,d=b-1;d>c;d--){var e=B(a,d).stateAfter;if(e&&(!(e instanceof gh)||d+e.lookAhead<b)){c=d+1;break}}a.highlightFrontier=Math.min(a.highlightFrontier,c)}}function jb(a,b,c,d){a.text=b,a.stateAfter&&(a.stateAfter=null),a.styles&&(a.styles=null),null!=a.order&&(a.order=null),ca(a),da(a,c);var e=d?d(a):1;e!=a.height&&E(a,e)}function kb(a){a.parent=null,ca(a)}function lb(a,b){if(!a||/^\s*$/.test(a))return null;var c=b.addModeClass?mh:lh;return c[a]||(c[a]=a.replace(/\S+/g,"cm-$&"))}function mb(a,b){var c=e("span",null,null,pg?"padding-right: .1px":null),d={pre:e("pre",[c],"CodeMirror-line"),content:c,col:0,pos:0,cm:a,trailingSpace:!1,splitSpaces:(ng||pg)&&a.getOpti
 on("lineWrapping")};b.measure={};for(var f=0;f<=(b.rest?b.rest.length:0);f++){var g=f?b.rest[f-1]:b.line,h=void 0;d.pos=0,d.addToken=ob,Qa(a.display.measure)&&(h=xa(g,a.doc.direction))&&(d.addToken=qb(d.addToken,h)),d.map=[];var j=b!=a.display.externalMeasured&&F(g);sb(g,d,_a(a,g,j)),g.styleClasses&&(g.styleClasses.bgClass&&(d.bgClass=i(g.styleClasses.bgClass,d.bgClass||"")),g.styleClasses.textClass&&(d.textClass=i(g.styleClasses.textClass,d.textClass||""))),0==d.map.length&&d.map.push(0,0,d.content.appendChild(Pa(a.display.measure))),0==f?(b.measure.map=d.map,b.measure.cache={}):((b.measure.maps||(b.measure.maps=[])).push(d.map),(b.measure.caches||(b.measure.caches=[])).push({}))}if(pg){var k=d.content.lastChild;(/\bcm-tab\b/.test(k.className)||k.querySelector&&k.querySelector(".cm-tab"))&&(d.content.className="cm-tab-wrap-hack")}return Ea(a,"renderLine&
 quot;,a,b.line,d.pre),d.pre.className&&(d.textClass=i(d.pre.className,d.textClass||"")),d}function nb(a){var b=d("span","\u2022","cm-invalidchar");return b.title="\\u"+a.charCodeAt(0).toString(16),b.setAttribute("aria-label",b.title),b}function ob(a,b,c,e,f,g,h){if(b){var i,j=a.splitSpaces?pb(b,a.trailingSpace):b,k=a.cm.state.specialChars,l=!1;if(k.test(b)){i=document.createDocumentFragment();for(var m=0;;){k.lastIndex=m;var n=k.exec(b),p=n?n.index-m:b.length-m;if(p){var q=document.createTextNode(j.slice(m,m+p));ng&&og<9?i.appendChild(d("span",[q])):i.appendChild(q),a.map.push(a.pos,a.pos+p,q),a.col+=p,a.pos+=p}if(!n)break;m+=p+1;var r=void 0;if("\t"==n[0]){var s=a.cm.options.tabSize,t=s-a.col%s;r=i.appendChild(d("span",o(t),"cm-tab")),r.setAttribute("role","presentation"),r.setAttribute("cm-text","\t"),a.col+=t}else"\r&q
 uot;==n[0]||"\n"==n[0]?(r=i.appendChild(d("span","\r"==n[0]?"\u240d":"\u2424","cm-invalidchar")),r.setAttribute("cm-text",n[0]),a.col+=1):(r=a.cm.options.specialCharPlaceholder(n[0]),r.setAttribute("cm-text",n[0]),ng&&og<9?i.appendChild(d("span",[r])):i.appendChild(r),a.col+=1);a.map.push(a.pos,a.pos+1,r),a.pos++}}else a.col+=b.length,i=document.createTextNode(j),a.map.push(a.pos,a.pos+b.length,i),ng&&og<9&&(l=!0),a.pos+=b.length;if(a.trailingSpace=32==j.charCodeAt(b.length-1),c||e||f||l||h){var u=c||"";e&&(u+=e),f&&(u+=f);var v=d("span",[i],u,h);return g&&(v.title=g),a.content.appendChild(v)}a.content.appendChild(i)}}function pb(a,b){if(a.length>1&&!/  /.test(a))return a;for(var c=b,d="",e=0;e<a.length;e++){var f=a.charAt(e);" "!=f||!c||e!=a.length-1&&32!=a.charCodeAt(e+1)||(f=&q
 uot;\xa0"),d+=f,c=" "==f}return d}function qb(a,b){return function(c,d,e,f,g,h,i){e=e?e+" cm-force-border":"cm-force-border";for(var j=c.pos,k=j+d.length;;){for(var l=void 0,m=0;m<b.length&&(l=b[m],!(l.to>j&&l.from<=j));m++);if(l.to>=k)return a(c,d,e,f,g,h,i);a(c,d.slice(0,l.to-j),e,f,null,h,i),f=null,d=d.slice(l.to-j),j=l.to}}}function rb(a,b,c,d){var e=!d&&c.widgetNode;e&&a.map.push(a.pos,a.pos+b,e),!d&&a.cm.display.input.needsContentAttribute&&(e||(e=a.content.appendChild(document.createElement("span"))),e.setAttribute("cm-marker",c.id)),e&&(a.cm.display.input.setUneditable(e),a.content.appendChild(e)),a.pos+=b,a.trailingSpace=!1}function sb(a,b,c){var d=a.markedSpans,e=a.text,f=0;if(d)for(var g,h,i,j,k,l,m,n=e.length,o=0,p=1,q="",r=0;;){if(r==o){i=j=k=l=h="",m=null,r=1/0;for(var s=[],t=void 0,u=0;u<d.length;++u){var v=d[u],w=v.marker;&
 quot;bookmark"==w.type&&v.from==o&&w.widgetNode?s.push(w):v.from<=o&&(null==v.to||v.to>o||w.collapsed&&v.to==o&&v.from==o)?(null!=v.to&&v.to!=o&&r>v.to&&(r=v.to,j=""),w.className&&(i+=" "+w.className),w.css&&(h=(h?h+";":"")+w.css),w.startStyle&&v.from==o&&(k+=" "+w.startStyle),w.endStyle&&v.to==r&&(t||(t=[])).push(w.endStyle,v.to),w.title&&!l&&(l=w.title),w.collapsed&&(!m||ga(m.marker,w)<0)&&(m=v)):v.from>o&&r>v.from&&(r=v.from)}if(t)for(var x=0;x<t.length;x+=2)t[x+1]==r&&(j+=" "+t[x]);if(!m||m.from==o)for(var y=0;y<s.length;++y)rb(b,0,s[y]);if(m&&(m.from||0)==o){if(rb(b,(null==m.to?n+1:m.to)-o,m.marker,null==m.from),null==m.to)return;m.to==o&&(m=!1)}}if(o>=n)break;for(var z=Math.min(n,r);;){if(q){var A=o+q.leng
 th;if(!m){var B=A>z?q.slice(0,z-o):q;b.addToken(b,B,g?g+i:i,k,o+B.length==r?j:"",l,h)}if(A>=z){q=q.slice(z-o),o=z;break}o=A,k=""}q=e.slice(f,f=c[p++]),g=lb(c[p++],b.cm.options)}}else for(var C=1;C<c.length;C+=2)b.addToken(b,e.slice(f,f=c[C]),lb(c[C+1],b.cm.options))}function tb(a,b,c){this.line=b,this.rest=na(b),this.size=this.rest?F(p(this.rest))-c+1:1,this.node=this.text=null,this.hidden=qa(a,b)}function ub(a,b,c){for(var d,e=[],f=b;f<c;f=d){var g=new tb(a.doc,B(a.doc,f),f);d=f+g.size,e.push(g)}return e}function vb(a){nh?nh.ops.push(a):a.ownsGroup=nh={ops:[a],delayedCallbacks:[]}}function wb(a){var b=a.delayedCallbacks,c=0;do{for(;c<b.length;c++)b[c].call(null);for(var d=0;d<a.ops.length;d++){var e=a.ops[d];if(e.cursorActivityHandlers)for(;e.cursorActivityCalled<e.cursorActivityHandlers.length;)e.cursorActivityHandlers[e.cursorActivityCalled++].call(null,e.cm)}}while(c<b.length)}function xb(a,b){var c=a.ownsGroup;if(c)try{wb(c)}finally{n
 h=null,b(c)}}function yb(a,b){var c=Ca(a,b);if(c.length){var d,e=Array.prototype.slice.call(arguments,2);nh?d=nh.delayedCallbacks:oh?d=oh:(d=oh=[],setTimeout(zb,0));for(var f=function(a){d.push(function(){return c[a].apply(null,e)})},g=0;g<c.length;++g)f(g)}}function zb(){var a=oh;oh=null;for(var b=0;b<a.length;++b)a[b]()}function Ab(a,b,c,d){for(var e=0;e<b.changes.length;e++){var f=b.changes[e];"text"==f?Eb(a,b):"gutter"==f?Gb(a,b,c,d):"class"==f?Fb(a,b):"widget"==f&&Hb(a,b,d)}b.changes=null}function Bb(a){return a.node==a.text&&(a.node=d("div",null,null,"position: relative"),a.text.parentNode&&a.text.parentNode.replaceChild(a.node,a.text),a.node.appendChild(a.text),ng&&og<8&&(a.node.style.zIndex=2)),a.node}function Cb(a,b){var c=b.bgClass?b.bgClass+" "+(b.line.bgClass||""):b.line.bgClass;if(c&&(c+=" CodeMirror-linebackground"),b.bac
 kground)c?b.background.className=c:(b.background.parentNode.removeChild(b.background),b.background=null);else if(c){var e=Bb(b);b.background=e.insertBefore(d("div",null,c),e.firstChild),a.display.input.setUneditable(b.background)}}function Db(a,b){var c=a.display.externalMeasured;return c&&c.line==b.line?(a.display.externalMeasured=null,b.measure=c.measure,c.built):mb(a,b)}function Eb(a,b){var c=b.text.className,d=Db(a,b);b.text==b.node&&(b.node=d.pre),b.text.parentNode.replaceChild(d.pre,b.text),b.text=d.pre,d.bgClass!=b.bgClass||d.textClass!=b.textClass?(b.bgClass=d.bgClass,b.textClass=d.textClass,Fb(a,b)):c&&(b.text.className=c)}function Fb(a,b){Cb(a,b),b.line.wrapClass?Bb(b).className=b.line.wrapClass:b.node!=b.text&&(b.node.className="");var c=b.textClass?b.textClass+" "+(b.line.textClass||""):b.line.textClass;b.text.className=c||""}function Gb(a,b,c,e){if(b.gutter&&(b.node.removeChild(b.g
 utter),b.gutter=null),b.gutterBackground&&(b.node.removeChild(b.gutterBackground),b.gutterBackground=null),b.line.gutterClass){var f=Bb(b);b.gutterBackground=d("div",null,"CodeMirror-gutter-background "+b.line.gutterClass,"left: "+(a.options.fixedGutter?e.fixedPos:-e.gutterTotalWidth)+"px; width: "+e.gutterTotalWidth+"px"),a.display.input.setUneditable(b.gutterBackground),f.insertBefore(b.gutterBackground,b.text)}var g=b.line.gutterMarkers;if(a.options.lineNumbers||g){var h=Bb(b),i=b.gutter=d("div",null,"CodeMirror-gutter-wrapper","left: "+(a.options.fixedGutter?e.fixedPos:-e.gutterTotalWidth)+"px");if(a.display.input.setUneditable(i),h.insertBefore(i,b.text),b.line.gutterClass&&(i.className+=" "+b.line.gutterClass),!a.options.lineNumbers||g&&g["CodeMirror-linenumbers"]||(b.lineNumber=i.appendChild(d("div",I(a.options,c),"CodeMirror-lin
 enumber CodeMirror-gutter-elt","left: "+e.gutterLeft["CodeMirror-linenumbers"]+"px; width: "+a.display.lineNumInnerWidth+"px"))),g)for(var j=0;j<a.options.gutters.length;++j){var k=a.options.gutters[j],l=g.hasOwnProperty(k)&&g[k];l&&i.appendChild(d("div",[l],"CodeMirror-gutter-elt","left: "+e.gutterLeft[k]+"px; width: "+e.gutterWidth[k]+"px"))}}}function Hb(a,b,c){b.alignable&&(b.alignable=null);for(var d=b.node.firstChild,e=void 0;d;d=e)e=d.nextSibling,"CodeMirror-linewidget"==d.className&&b.node.removeChild(d);Jb(a,b,c)}function Ib(a,b,c,d){var e=Db(a,b);return b.text=b.node=e.pre,e.bgClass&&(b.bgClass=e.bgClass),e.textClass&&(b.textClass=e.textClass),Fb(a,b),Gb(a,b,c,d),Jb(a,b,d),b.node}function Jb(a,b,c){if(Kb(a,b.line,b,c,!0),b.rest)for(var d=0;d<b.rest.length;d++)Kb(a,b.rest[d],b,c,!1)}function Kb(a,b,c,e,f){if(b.widgets
 )for(var g=Bb(c),h=0,i=b.widgets;h<i.length;++h){var j=i[h],k=d("div",[j.node],"CodeMirror-linewidget");j.handleMouseEvents||k.setAttribute("cm-ignore-events","true"),Lb(j,k,c,e),a.display.input.setUneditable(k),f&&j.above?g.insertBefore(k,c.gutter||c.text):g.appendChild(k),yb(j,"redraw")}}function Lb(a,b,c,d){if(a.noHScroll){(c.alignable||(c.alignable=[])).push(b);var e=d.wrapperWidth;b.style.left=d.fixedPos+"px",a.coverGutter||(e-=d.gutterTotalWidth,b.style.paddingLeft=d.gutterTotalWidth+"px"),b.style.width=e+"px"}a.coverGutter&&(b.style.zIndex=5,b.style.position="relative",a.noHScroll||(b.style.marginLeft=-d.gutterTotalWidth+"px"))}function Mb(a){if(null!=a.height)return a.height;var b=a.doc.cm;if(!b)return 0;if(!f(document.body,a.node)){var e="position: relative;";a.coverGutter&&(e+="margin-left: -"+b.display.gutters.offsetWidth+&quot
 ;px;"),a.noHScroll&&(e+="width: "+b.display.wrapper.clientWidth+"px;"),c(b.display.measure,d("div",[a.node],null,e))}return a.height=a.node.parentNode.offsetHeight}function Nb(a,b){for(var c=Na(b);c!=a.wrapper;c=c.parentNode)if(!c||1==c.nodeType&&"true"==c.getAttribute("cm-ignore-events")||c.parentNode==a.sizer&&c!=a.mover)return!0}function Ob(a){return a.lineSpace.offsetTop}function Pb(a){return a.mover.offsetHeight-a.lineSpace.offsetHeight}function Qb(a){if(a.cachedPaddingH)return a.cachedPaddingH;var b=c(a.measure,d("pre","x")),e=window.getComputedStyle?window.getComputedStyle(b):b.currentStyle,f={left:parseInt(e.paddingLeft),right:parseInt(e.paddingRight)};return isNaN(f.left)||isNaN(f.right)||(a.cachedPaddingH=f),f}function Rb(a){return Lg-a.display.nativeBarWidth}function Sb(a){return a.display.scroller.clientWidth-Rb(a)-a.display.barWidth}function Tb(a){return a.display.scroller
 .clientHeight-Rb(a)-a.display.barHeight}function Ub(a,b,c){var d=a.options.lineWrapping,e=d&&Sb(a);if(!b.measure.heights||d&&b.measure.width!=e){var f=b.measure.heights=[];if(d){b.measure.width=e;for(var g=b.text.firstChild.getClientRects(),h=0;h<g.length-1;h++){var i=g[h],j=g[h+1];Math.abs(i.bottom-j.bottom)>2&&f.push((i.bottom+j.top)/2-c.top)}}f.push(c.bottom-c.top)}}function Vb(a,b,c){if(a.line==b)return{map:a.measure.map,cache:a.measure.cache};for(var d=0;d<a.rest.length;d++)if(a.rest[d]==b)return{map:a.measure.maps[d],cache:a.measure.caches[d]};for(var e=0;e<a.rest.length;e++)if(F(a.rest[e])>c)return{map:a.measure.maps[e],cache:a.measure.caches[e],before:!0}}function Wb(a,b){b=la(b);var d=F(b),e=a.display.externalMeasured=new tb(a.doc,b,d);e.lineN=d;var f=e.built=mb(a,e);return e.text=f.pre,c(a.display.lineMeasure,f.pre),e}function Xb(a,b,c,d){return $b(a,Zb(a,b),c,d)}function Yb(a,b){if(b>=a.display.viewFrom&&b<a.display.vie
 wTo)return a.display.view[zc(a,b)];var c=a.display.externalMeasured;return c&&b>=c.lineN&&b<c.lineN+c.size?c:void 0}function Zb(a,b){var c=F(b),d=Yb(a,c);d&&!d.text?d=null:d&&d.changes&&(Ab(a,d,c,uc(a)),a.curOp.forceUpdate=!0),d||(d=Wb(a,b));var e=Vb(d,b,c);return{line:b,view:d,rect:null,map:e.map,cache:e.cache,before:e.before,hasHeights:!1}}function $b(a,b,c,d,e){b.before&&(c=-1);var f,g=c+(d||"");return b.cache.hasOwnProperty(g)?f=b.cache[g]:(b.rect||(b.rect=b.view.text.getBoundingClientRect()),b.hasHeights||(Ub(a,b.view,b.rect),b.hasHeights=!0),f=bc(a,b,c,d),f.bogus||(b.cache[g]=f)),{left:f.left,right:f.right,top:e?f.rtop:f.top,bottom:e?f.rbottom:f.bottom}}function _b(a,b,c){for(var d,e,f,g,h,i,j=0;j<a.length;j+=3)if(h=a[j],i=a[j+1],b<h?(e=0,f=1,g="left"):b<i?(e=b-h,f=e+1):(j==a.length-3||b==i&&a[j+3]>b)&&(f=i-h,e=f-1,b>=i&&(g="right")),null!=e){if(d=a[j+2],h
 ==i&&c==(d.insertLeft?"left":"right")&&(g=c),"left"==c&&0==e)for(;j&&a[j-2]==a[j-3]&&a[j-1].insertLeft;)d=a[(j-=3)+2],g="left";if("right"==c&&e==i-h)for(;j<a.length-3&&a[j+3]==a[j+4]&&!a[j+5].insertLeft;)d=a[(j+=3)+2],g="right";break}return{node:d,start:e,end:f,collapse:g,coverStart:h,coverEnd:i}}function ac(a,b){var c=ph;if("left"==b)for(var d=0;d<a.length&&(c=a[d]).left==c.right;d++);else for(var e=a.length-1;e>=0&&(c=a[e]).left==c.right;e--);return c}function bc(a,b,c,d){var e,f=_b(b.map,c,d),g=f.node,h=f.start,i=f.end,j=f.collapse;if(3==g.nodeType){for(var k=0;k<4;k++){for(;h&&x(b.line.text.charAt(f.coverStart+h));)--h;for(;f.coverStart+i<f.coverEnd&&x(b.line.text.charAt(f.coverStart+i));)++i;if(e=ng&&og<9&&0==h&&i==f.coverEnd-f.coverStart?g.parentNode.getBoundingClientRect(
 ):ac(Dg(g,h,i).getClientRects(),d),e.left||e.right||0==h)break;i=h,h-=1,j="right"}ng&&og<11&&(e=cc(a.display.measure,e))}else{h>0&&(j=d="right");var l;e=a.options.lineWrapping&&(l=g.getClientRects()).length>1?l["right"==d?l.length-1:0]:g.getBoundingClientRect()}if(ng&&og<9&&!h&&(!e||!e.left&&!e.right)){var m=g.parentNode.getClientRects()[0];e=m?{left:m.left,right:m.left+tc(a.display),top:m.top,bottom:m.bottom}:ph}for(var n=e.top-b.rect.top,o=e.bottom-b.rect.top,p=(n+o)/2,q=b.view.measure.heights,r=0;r<q.length-1&&!(p<q[r]);r++);var s=r?q[r-1]:0,t=q[r],u={left:("right"==j?e.right:e.left)-b.rect.left,right:("left"==j?e.left:e.right)-b.rect.left,top:s,bottom:t};return e.left||e.right||(u.bogus=!0),a.options.singleCursorHeightPerLine||(u.rtop=n,u.rbottom=o),u}function cc(a,b){if(!window.screen||null==screen.logicalXDPI||screen.logicalXDPI==screen.de
 viceXDPI||!Ra(a))return b;var c=screen.logicalXDPI/screen.deviceXDPI,d=screen.logicalYDPI/screen.deviceYDPI;return{left:b.left*c,right:b.right*c,top:b.top*d,bottom:b.bottom*d}}function dc(a){if(a.measure&&(a.measure.cache={},a.measure.heights=null,a.rest))for(var b=0;b<a.rest.length;b++)a.measure.caches[b]={}}function ec(a){a.display.externalMeasure=null,b(a.display.lineMeasure);for(var c=0;c<a.display.view.length;c++)dc(a.display.view[c])}function fc(a){ec(a),a.display.cachedCharWidth=a.display.cachedTextHeight=a.display.cachedPaddingH=null,a.options.lineWrapping||(a.display.maxLineChanged=!0),a.display.lineNumChars=null}function gc(){return rg&&xg?-(document.body.getBoundingClientRect().left-parseInt(getComputedStyle(document.body).marginLeft)):window.pageXOffset||(document.documentElement||document.body).scrollLeft}function hc(){return rg&&xg?-(document.body.getBoundingClientRect().top-parseInt(getComputedStyle(document.body).marginTop)):window.pageY
 Offset||(document.documentElement||document.body).scrollTop}function ic(a,b,c,d,e){if(!e&&b.widgets)for(var f=0;f<b.widgets.length;++f)if(b.widgets[f].above){var g=Mb(b.widgets[f]);c.top+=g,c.bottom+=g}if("line"==d)return c;d||(d="local");var h=sa(b);if("local"==d?h+=Ob(a.display):h-=a.display.viewOffset,"page"==d||"window"==d){var i=a.display.lineSpace.getBoundingClientRect();h+=i.top+("window"==d?0:hc());var j=i.left+("window"==d?0:gc());c.left+=j,c.right+=j}return c.top+=h,c.bottom+=h,c}function jc(a,b,c){if("div"==c)return b;var d=b.left,e=b.top;if("page"==c)d-=gc(),e-=hc();else if("local"==c||!c){var f=a.display.sizer.getBoundingClientRect();d+=f.left,e+=f.top}var g=a.display.lineSpace.getBoundingClientRect();return{left:d-g.left,top:e-g.top}}function kc(a,b,c,d,e){return d||(d=B(a.doc,b.line)),ic(a,d,Xb(a,d,b.ch,e),c)}function lc(a,b,c,d,e,f){function g(b,g){var h=$b(
 a,e,b,g?"right":"left",f);return g?h.left=h.right:h.right=h.left,ic(a,d,h,c)}function h(a,b,c){var d=i[b],e=d.level%2!=0;return g(c?a-1:a,e!=c)}d=d||B(a.doc,b.line),e||(e=Zb(a,d));var i=xa(d,a.doc.direction),j=b.ch,k=b.sticky;if(j>=d.text.length?(j=d.text.length,k="before"):j<=0&&(j=0,k="after"),!i)return g("before"==k?j-1:j,"before"==k);var l=wa(i,j,k),m=Vg,n=h(j,l,"before"==k);return null!=m&&(n.other=h(j,m,"before"!=k)),n}function mc(a,b){var c=0;b=Q(a.doc,b),a.options.lineWrapping||(c=tc(a.display)*b.ch);var d=B(a.doc,b.line),e=sa(d)+Ob(a.display);return{left:c,right:c,top:e,bottom:e+d.height}}function nc(a,b,c,d,e){var f=J(a,b,c);return f.xRel=e,d&&(f.outside=!0),f}function oc(a,b,c){var d=a.doc;if(c+=a.display.viewOffset,c<0)return nc(d.first,0,null,!0,-1);var e=G(d,c),f=d.first+d.size-1;if(e>f)return nc(d.first+d.size-1,B(d,f).text.length,null,!0,1);b<0&&
 amp;(b=0);for(var g=B(d,e);;){var h=rc(a,g,e,b,c),i=ja(g),j=i&&i.find(0,!0);if(!i||!(h.ch>j.from.ch||h.ch==j.from.ch&&h.xRel>0))return h;e=F(g=j.to.line)}}function pc(a,b,c,d){var e=function(d){return ic(a,b,$b(a,c,d),"line")},f=b.text.length,g=z(function(a){return e(a-1).bottom<=d},f,0);return f=z(function(a){return e(a).top>d},g,f),{begin:g,end:f}}function qc(a,b,c,d){var e=ic(a,b,$b(a,c,d),"line").top;return pc(a,b,c,e)}function rc(a,b,c,d,e){e-=sa(b);var f,g=0,h=b.text.length,i=Zb(a,b),j=xa(b,a.doc.direction);if(j){if(a.options.lineWrapping){var k;k=pc(a,b,i,e),g=k.begin,h=k.end}f=new J(c,Math.floor(g+(h-g)/2));var l,m,n=lc(a,f,"line",b,i).left,o=n<d?1:-1,p=n-d,q=Math.ceil((h-g)/4);a:do{l=p,m=f;for(var r=0;r<q;++r){var s=f;if(f=Ba(a,b,f,o),null==f||f.ch<g||h<=("before"==f.sticky?f.ch-1:f.ch)){f=s;break a}}if(p=lc(a,f,"line",b,i).left-d,q>1){var t=Math.abs(p-l)/q;q=Math.min(q,Math.ceil(Ma
 th.abs(p)/t)),o=p<0?1:-1}}while(0!=p&&(q>1||o<0!=p<0&&Math.abs(p)<=Math.abs(l)));if(Math.abs(p)>Math.abs(l)){if(p<0==l<0)throw new Error("Broke out of infinite loop in coordsCharInner");f=m}}else{var u=z(function(c){var f=ic(a,b,$b(a,i,c),"line");return f.top>e?(h=Math.min(c,h),!0):!(f.bottom<=e)&&(f.left>d||!(f.right<d)&&d-f.left<f.right-d)},g,h);u=y(b.text,u,1),f=new J(c,u,u==h?"before":"after")}var v=lc(a,f,"line",b,i);return(e<v.top||v.bottom<e)&&(f.outside=!0),f.xRel=d<v.left?-1:d>v.right?1:0,f}function sc(a){if(null!=a.cachedTextHeight)return a.cachedTextHeight;if(null==kh){kh=d("pre");for(var e=0;e<49;++e)kh.appendChild(document.createTextNode("x")),kh.appendChild(d("br"));kh.appendChild(document.createTextNode("x"))}c(a.measure,kh);var f=kh.offsetHeight/50;return f>3&&(a.cachedTextHe
 ight=f),b(a.measure),f||1}function tc(a){if(null!=a.cachedCharWidth)return a.cachedCharWidth;var b=d("span","xxxxxxxxxx"),e=d("pre",[b]);c(a.measure,e);var f=b.getBoundingClientRect(),g=(f.right-f.left)/10;return g>2&&(a.cachedCharWidth=g),g||10}function uc(a){for(var b=a.display,c={},d={},e=b.gutters.clientLeft,f=b.gutters.firstChild,g=0;f;f=f.nextSibling,++g)c[a.options.gutters[g]]=f.offsetLeft+f.clientLeft+e,d[a.options.gutters[g]]=f.clientWidth;return{fixedPos:vc(b),gutterTotalWidth:b.gutters.offsetWidth,gutterLeft:c,gutterWidth:d,wrapperWidth:b.wrapper.clientWidth}}function vc(a){return a.scroller.getBoundingClientRect().left-a.sizer.getBoundingClientRect().left}function wc(a){var b=sc(a.display),c=a.options.lineWrapping,d=c&&Math.max(5,a.display.scroller.clientWidth/tc(a.display)-3);return function(e){if(qa(a.doc,e))return 0;var f=0;if(e.widgets)for(var g=0;g<e.widgets.length;g++)e.widgets[g].height&&(f+=e.widgets[g].
 height);return c?f+(Math.ceil(e.text.length/d)||1)*b:f+b}}function xc(a){var b=a.doc,c=wc(a);b.iter(function(a){var b=c(a);b!=a.height&&E(a,b)})}function yc(a,b,c,d){var e=a.display;if(!c&&"true"==Na(b).getAttribute("cm-not-content"))return null;var f,g,h=e.lineSpace.getBoundingClientRect();try{f=b.clientX-h.left,g=b.clientY-h.top}catch(b){return null}var i,j=oc(a,f,g);if(d&&1==j.xRel&&(i=B(a.doc,j.line).text).length==j.ch){var k=l(i,i.length,a.options.tabSize)-i.length;j=J(j.line,Math.max(0,Math.round((f-Qb(a.display).left)/tc(a.display))-k))}return j}function zc(a,b){if(b>=a.display.viewTo)return null;if(b-=a.display.viewFrom,b<0)return null;for(var c=a.display.view,d=0;d<c.length;d++)if(b-=c[d].size,b<0)return d}function Ac(a){a.display.input.showSelection(a.display.input.prepareSelection())}function Bc(a,b){for(var c=a.doc,d={},e=d.cursors=document.createDocumentFragment(),f=d.selection=document.createDocumentFragme
 nt(),g=0;g<c.sel.ranges.length;g++)if(b!==!1||g!=c.sel.primIndex){var h=c.sel.ranges[g];if(!(h.from().line>=a.display.viewTo||h.to().line<a.display.viewFrom)){var i=h.empty();(i||a.options.showCursorWhenSelecting)&&Cc(a,h.head,e),i||Ec(a,h,f)}}return d}function Cc(a,b,c){var e=lc(a,b,"div",null,null,!a.options.singleCursorHeightPerLine),f=c.appendChild(d("div","\xa0","CodeMirror-cursor"));if(f.style.left=e.left+"px",f.style.top=e.top+"px",f.style.height=Math.max(0,e.bottom-e.top)*a.options.cursorHeight+"px",e.other){var g=c.appendChild(d("div","\xa0","CodeMirror-cursor CodeMirror-secondarycursor"));g.style.display="",g.style.left=e.other.left+"px",g.style.top=e.other.top+"px",g.style.height=.85*(e.other.bottom-e.other.top)+"px"}}function Dc(a,b){return a.top-b.top||a.left-b.left}function Ec(a,b,c){
+function e(a,b,c,e){b<0&&(b=0),b=Math.round(b),e=Math.round(e),i.appendChild(d("div",null,"CodeMirror-selected","position: absolute; left: "+a+"px;\n                             top: "+b+"px; width: "+(null==c?l-a:c)+"px;\n                             height: "+(e-b)+"px"))}function f(b,c,d){function f(c,d){return kc(a,J(b,c),"div",j,d)}var g,i,j=B(h,b),m=j.text.length;return va(xa(j,h.direction),c||0,null==d?m:d,function(a,b,h){var j,n;if("ltr"==h){j=f(a,"left"),n=f(b-1,"right");var o=null==c&&0==a?k:j.left,p=null==d&&b==m?l:n.right;n.top-j.top<=3?e(o,n.top,p-o,n.bottom):(e(o,j.top,null,j.bottom),j.bottom<n.top&&e(k,j.bottom,null,n.top),e(k,n.top,n.right,n.bottom))}else{j=f(a,"right"),n=f(b-1,"left");var q=null==c&&0==a?l:j.right,r=null==d&&b==m?k:n.left;n.top-j.top<=3?e(r,n.top,q-r,n.bottom):(e
 (k,j.top,q-k,j.bottom),j.bottom<n.top&&e(k,j.bottom,null,n.top),e(r,n.top,null,n.bottom))}(!g||Dc(j,g)<0)&&(g=j),Dc(n,g)<0&&(g=n),(!i||Dc(j,i)<0)&&(i=j),Dc(n,i)<0&&(i=n)}),{start:g,end:i}}var g=a.display,h=a.doc,i=document.createDocumentFragment(),j=Qb(a.display),k=j.left,l=Math.max(g.sizerWidth,Sb(a)-g.sizer.offsetLeft)-j.right,m=b.from(),n=b.to();if(m.line==n.line)f(m.line,m.ch,n.ch);else{var o=B(h,m.line),p=B(h,n.line),q=la(o)==la(p),r=f(m.line,m.ch,q?o.text.length+1:null).end,s=f(n.line,q?0:null,n.ch).start;q&&(r.top<s.top-2?(e(r.right,r.top,null,r.bottom),e(k,s.top,s.left,s.bottom)):e(r.right,r.top,s.left-r.right,r.bottom)),r.bottom<s.top&&e(k,r.bottom,null,s.top)}c.appendChild(i)}function Fc(a){if(a.state.focused){var b=a.display;clearInterval(b.blinker);var c=!0;b.cursorDiv.style.visibility="",a.options.cursorBlinkRate>0?b.blinker=setInterval(function(){return b.cursorDiv.style.visibilit
 y=(c=!c)?"":"hidden"},a.options.cursorBlinkRate):a.options.cursorBlinkRate<0&&(b.cursorDiv.style.visibility="hidden")}}function Gc(a){a.state.focused||(a.display.input.focus(),Ic(a))}function Hc(a){a.state.delayingBlurEvent=!0,setTimeout(function(){a.state.delayingBlurEvent&&(a.state.delayingBlurEvent=!1,Jc(a))},100)}function Ic(a,b){a.state.delayingBlurEvent&&(a.state.delayingBlurEvent=!1),"nocursor"!=a.options.readOnly&&(a.state.focused||(Ea(a,"focus",a,b),a.state.focused=!0,h(a.display.wrapper,"CodeMirror-focused"),a.curOp||a.display.selForContextMenu==a.doc.sel||(a.display.input.reset(),pg&&setTimeout(function(){return a.display.input.reset(!0)},20)),a.display.input.receivedFocus()),Fc(a))}function Jc(a,b){a.state.delayingBlurEvent||(a.state.focused&&(Ea(a,"blur",a,b),a.state.focused=!1,Gg(a.display.wrapper,"CodeMirror-focused")),clearInterval(a.disp
 lay.blinker),setTimeout(function(){a.state.focused||(a.display.shift=!1)},150))}function Kc(a){for(var b=a.display,c=b.lineDiv.offsetTop,d=0;d<b.view.length;d++){var e=b.view[d],f=void 0;if(!e.hidden){if(ng&&og<8){var g=e.node.offsetTop+e.node.offsetHeight;f=g-c,c=g}else{var h=e.node.getBoundingClientRect();f=h.bottom-h.top}var i=e.line.height-f;if(f<2&&(f=sc(b)),(i>.005||i<-.005)&&(E(e.line,f),Lc(e.line),e.rest))for(var j=0;j<e.rest.length;j++)Lc(e.rest[j])}}}function Lc(a){if(a.widgets)for(var b=0;b<a.widgets.length;++b)a.widgets[b].height=a.widgets[b].node.parentNode.offsetHeight}function Mc(a,b,c){var d=c&&null!=c.top?Math.max(0,c.top):a.scroller.scrollTop;d=Math.floor(d-Ob(a));var e=c&&null!=c.bottom?c.bottom:d+a.wrapper.clientHeight,f=G(b,d),g=G(b,e);if(c&&c.ensure){var h=c.ensure.from.line,i=c.ensure.to.line;h<f?(f=h,g=G(b,sa(B(b,h))+a.wrapper.clientHeight)):Math.min(i,b.lastLine())>=g&&(f=G(b,
 sa(B(b,i))-a.wrapper.clientHeight),g=i)}return{from:f,to:Math.max(g,f+1)}}function Nc(a){var b=a.display,c=b.view;if(b.alignWidgets||b.gutters.firstChild&&a.options.fixedGutter){for(var d=vc(b)-b.scroller.scrollLeft+a.doc.scrollLeft,e=b.gutters.offsetWidth,f=d+"px",g=0;g<c.length;g++)if(!c[g].hidden){a.options.fixedGutter&&(c[g].gutter&&(c[g].gutter.style.left=f),c[g].gutterBackground&&(c[g].gutterBackground.style.left=f));var h=c[g].alignable;if(h)for(var i=0;i<h.length;i++)h[i].style.left=f}a.options.fixedGutter&&(b.gutters.style.left=d+e+"px")}}function Oc(a){if(!a.options.lineNumbers)return!1;var b=a.doc,c=I(a.options,b.first+b.size-1),e=a.display;if(c.length!=e.lineNumChars){var f=e.measure.appendChild(d("div",[d("div",c)],"CodeMirror-linenumber CodeMirror-gutter-elt")),g=f.firstChild.offsetWidth,h=f.offsetWidth-g;return e.lineGutter.style.width="",e.lineNumInnerWidth=Math.
 max(g,e.lineGutter.offsetWidth-h)+1,e.lineNumWidth=e.lineNumInnerWidth+h,e.lineNumChars=e.lineNumInnerWidth?c.length:-1,e.lineGutter.style.width=e.lineNumWidth+"px",Fd(a),!0}return!1}function Pc(a,b){if(!Fa(a,"scrollCursorIntoView")){var c=a.display,e=c.sizer.getBoundingClientRect(),f=null;if(b.top+e.top<0?f=!0:b.bottom+e.top>(window.innerHeight||document.documentElement.clientHeight)&&(f=!1),null!=f&&!vg){var g=d("div","\u200b",null,"position: absolute;\n                         top: "+(b.top-c.viewOffset-Ob(a.display))+"px;\n                         height: "+(b.bottom-b.top+Rb(a)+c.barHeight)+"px;\n                         left: "+b.left+"px; width: "+Math.max(2,b.right-b.left)+"px;");a.display.lineSpace.appendChild(g),g.scrollIntoView(f),a.display.lineSpace.removeChild(g)}}}function Qc(a,b,c,d){null==d&&(d=0);var e;a.options.lineWrapping||b!=c||(b=b.ch?J(b.line
 ,"before"==b.sticky?b.ch-1:b.ch,"after"):b,c="before"==b.sticky?J(b.line,b.ch+1,"before"):b);for(var f=0;f<5;f++){var g=!1,h=lc(a,b),i=c&&c!=b?lc(a,c):h;e={left:Math.min(h.left,i.left),top:Math.min(h.top,i.top)-d,right:Math.max(h.left,i.left),bottom:Math.max(h.bottom,i.bottom)+d};var j=Sc(a,e),k=a.doc.scrollTop,l=a.doc.scrollLeft;if(null!=j.scrollTop&&(Zc(a,j.scrollTop),Math.abs(a.doc.scrollTop-k)>1&&(g=!0)),null!=j.scrollLeft&&(_c(a,j.scrollLeft),Math.abs(a.doc.scrollLeft-l)>1&&(g=!0)),!g)break}return e}function Rc(a,b){var c=Sc(a,b);null!=c.scrollTop&&Zc(a,c.scrollTop),null!=c.scrollLeft&&_c(a,c.scrollLeft)}function Sc(a,b){var c=a.display,d=sc(a.display);b.top<0&&(b.top=0);var e=a.curOp&&null!=a.curOp.scrollTop?a.curOp.scrollTop:c.scroller.scrollTop,f=Tb(a),g={};b.bottom-b.top>f&&(b.bottom=b.top+f);var h=a.doc.height+Pb(c),i=b.top<d,j=b.bottom&
 gt;h-d;if(b.top<e)g.scrollTop=i?0:b.top;else if(b.bottom>e+f){var k=Math.min(b.top,(j?h:b.bottom)-f);k!=e&&(g.scrollTop=k)}var l=a.curOp&&null!=a.curOp.scrollLeft?a.curOp.scrollLeft:c.scroller.scrollLeft,m=Sb(a)-(a.options.fixedGutter?c.gutters.offsetWidth:0),n=b.right-b.left>m;return n&&(b.right=b.left+m),b.left<10?g.scrollLeft=0:b.left<l?g.scrollLeft=Math.max(0,b.left-(n?0:10)):b.right>m+l-3&&(g.scrollLeft=b.right+(n?0:10)-m),g}function Tc(a,b){null!=b&&(Xc(a),a.curOp.scrollTop=(null==a.curOp.scrollTop?a.doc.scrollTop:a.curOp.scrollTop)+b)}function Uc(a){Xc(a);var b=a.getCursor();a.curOp.scrollToPos={from:b,to:b,margin:a.options.cursorScrollMargin}}function Vc(a,b,c){null==b&&null==c||Xc(a),null!=b&&(a.curOp.scrollLeft=b),null!=c&&(a.curOp.scrollTop=c)}function Wc(a,b){Xc(a),a.curOp.scrollToPos=b}function Xc(a){var b=a.curOp.scrollToPos;if(b){a.curOp.scrollToPos=null;var c=mc(a,b.from),d=mc(a,b.to);Y
 c(a,c,d,b.margin)}}function Yc(a,b,c,d){var e=Sc(a,{left:Math.min(b.left,c.left),top:Math.min(b.top,c.top)-d,right:Math.max(b.right,c.right),bottom:Math.max(b.bottom,c.bottom)+d});Vc(a,e.scrollLeft,e.scrollTop)}function Zc(a,b){Math.abs(a.doc.scrollTop-b)<2||(jg||Dd(a,{top:b}),$c(a,b,!0),jg&&Dd(a),wd(a,100))}function $c(a,b,c){b=Math.min(a.display.scroller.scrollHeight-a.display.scroller.clientHeight,b),(a.display.scroller.scrollTop!=b||c)&&(a.doc.scrollTop=b,a.display.scrollbars.setScrollTop(b),a.display.scroller.scrollTop!=b&&(a.display.scroller.scrollTop=b))}function _c(a,b,c,d){b=Math.min(b,a.display.scroller.scrollWidth-a.display.scroller.clientWidth),(c?b==a.doc.scrollLeft:Math.abs(a.doc.scrollLeft-b)<2)&&!d||(a.doc.scrollLeft=b,Nc(a),a.display.scroller.scrollLeft!=b&&(a.display.scroller.scrollLeft=b),a.display.scrollbars.setScrollLeft(b))}function ad(a){var b=a.display,c=b.gutters.offsetWidth,d=Math.round(a.doc.height+Pb(a.display
 ));return{clientHeight:b.scroller.clientHeight,viewHeight:b.wrapper.clientHeight,scrollWidth:b.scroller.scrollWidth,clientWidth:b.scroller.clientWidth,viewWidth:b.wrapper.clientWidth,barLeft:a.options.fixedGutter?c:0,docHeight:d,scrollHeight:d+Rb(a)+b.barHeight,nativeBarWidth:b.nativeBarWidth,gutterWidth:c}}function bd(a,b){b||(b=ad(a));var c=a.display.barWidth,d=a.display.barHeight;cd(a,b);for(var e=0;e<4&&c!=a.display.barWidth||d!=a.display.barHeight;e++)c!=a.display.barWidth&&a.options.lineWrapping&&Kc(a),cd(a,ad(a)),c=a.display.barWidth,d=a.display.barHeight}function cd(a,b){var c=a.display,d=c.scrollbars.update(b);c.sizer.style.paddingRight=(c.barWidth=d.right)+"px",c.sizer.style.paddingBottom=(c.barHeight=d.bottom)+"px",c.heightForcer.style.borderBottom=d.bottom+"px solid transparent",d.right&&d.bottom?(c.scrollbarFiller.style.display="block",c.scrollbarFiller.style.height=d.bottom+"px",c.scro
 llbarFiller.style.width=d.right+"px"):c.scrollbarFiller.style.display="",d.bottom&&a.options.coverGutterNextToScrollbar&&a.options.fixedGutter?(c.gutterFiller.style.display="block",c.gutterFiller.style.height=d.bottom+"px",c.gutterFiller.style.width=b.gutterWidth+"px"):c.gutterFiller.style.display=""}function dd(a){a.display.scrollbars&&(a.display.scrollbars.clear(),a.display.scrollbars.addClass&&Gg(a.display.wrapper,a.display.scrollbars.addClass)),a.display.scrollbars=new sh[a.options.scrollbarStyle](function(b){a.display.wrapper.insertBefore(b,a.display.scrollbarFiller),Yg(b,"mousedown",function(){a.state.focused&&setTimeout(function(){return a.display.input.focus()},0)}),b.setAttribute("cm-not-content","true")},function(b,c){"horizontal"==c?_c(a,b):Zc(a,b)},a),a.display.scrollbars.addClass&&h(a.display.wrapper,a.display.scrollbars.add
 Class)}function ed(a){a.curOp={cm:a,viewChanged:!1,startHeight:a.doc.height,forceUpdate:!1,updateInput:null,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++th},vb(a.curOp)}function fd(a){var b=a.curOp;xb(b,function(a){for(var b=0;b<a.ops.length;b++)a.ops[b].cm.curOp=null;gd(a)})}function gd(a){for(var b=a.ops,c=0;c<b.length;c++)hd(b[c]);for(var d=0;d<b.length;d++)id(b[d]);for(var e=0;e<b.length;e++)jd(b[e]);for(var f=0;f<b.length;f++)kd(b[f]);for(var g=0;g<b.length;g++)ld(b[g])}function hd(a){var b=a.cm,c=b.display;yd(b),a.updateMaxLine&&ua(b),a.mustUpdate=a.viewChanged||a.forceUpdate||null!=a.scrollTop||a.scrollToPos&&(a.scrollToPos.from.line<c.viewFrom||a.scrollToPos.to.line>=c.viewTo)||c.maxLineChanged&&b.options.lineWrapping,a.update=a.mustUpdate&&new uh(b,a.mustUpdate&&{top:a.scrollTop,ens
 ure:a.scrollToPos},a.forceUpdate)}function id(a){a.updatedDisplay=a.mustUpdate&&Bd(a.cm,a.update)}function jd(a){var b=a.cm,c=b.display;a.updatedDisplay&&Kc(b),a.barMeasure=ad(b),c.maxLineChanged&&!b.options.lineWrapping&&(a.adjustWidthTo=Xb(b,c.maxLine,c.maxLine.text.length).left+3,b.display.sizerWidth=a.adjustWidthTo,a.barMeasure.scrollWidth=Math.max(c.scroller.clientWidth,c.sizer.offsetLeft+a.adjustWidthTo+Rb(b)+b.display.barWidth),a.maxScrollLeft=Math.max(0,c.sizer.offsetLeft+a.adjustWidthTo-Sb(b))),(a.updatedDisplay||a.selectionChanged)&&(a.preparedSelection=c.input.prepareSelection(a.focus))}function kd(a){var b=a.cm;null!=a.adjustWidthTo&&(b.display.sizer.style.minWidth=a.adjustWidthTo+"px",a.maxScrollLeft<b.doc.scrollLeft&&_c(b,Math.min(b.display.scroller.scrollLeft,a.maxScrollLeft),!0),b.display.maxLineChanged=!1);var c=a.focus&&a.focus==g()&&(!document.hasFocus||document.hasFocus());a.prep
 aredSelection&&b.display.input.showSelection(a.preparedSelection,c),(a.updatedDisplay||a.startHeight!=b.doc.height)&&bd(b,a.barMeasure),a.updatedDisplay&&Gd(b,a.barMeasure),a.selectionChanged&&Fc(b),b.state.focused&&a.updateInput&&b.display.input.reset(a.typing),c&&Gc(a.cm)}function ld(a){var b=a.cm,c=b.display,d=b.doc;if(a.updatedDisplay&&Cd(b,a.update),null==c.wheelStartX||null==a.scrollTop&&null==a.scrollLeft&&!a.scrollToPos||(c.wheelStartX=c.wheelStartY=null),null!=a.scrollTop&&$c(b,a.scrollTop,a.forceScroll),null!=a.scrollLeft&&_c(b,a.scrollLeft,!0,!0),a.scrollToPos){var e=Qc(b,Q(d,a.scrollToPos.from),Q(d,a.scrollToPos.to),a.scrollToPos.margin);Pc(b,e)}var f=a.maybeHiddenMarkers,g=a.maybeUnhiddenMarkers;if(f)for(var h=0;h<f.length;++h)f[h].lines.length||Ea(f[h],"hide");if(g)for(var i=0;i<g.length;++i)g[i].lines.length&&Ea(g[i],"unhide");c.wrapper.off
 setHeight&&(d.scrollTop=b.display.scroller.scrollTop),a.changeObjs&&Ea(b,"changes",b,a.changeObjs),a.update&&a.update.finish()}function md(a,b){if(a.curOp)return b();ed(a);try{return b()}finally{fd(a)}}function nd(a,b){return function(){if(a.curOp)return b.apply(a,arguments);ed(a);try{return b.apply(a,arguments)}finally{fd(a)}}}function od(a){return function(){if(this.curOp)return a.apply(this,arguments);ed(this);try{return a.apply(this,arguments)}finally{fd(this)}}}function pd(a){return function(){var b=this.cm;if(!b||b.curOp)return a.apply(this,arguments);ed(b);try{return a.apply(this,arguments)}finally{fd(b)}}}function qd(a,b,c,d){null==b&&(b=a.doc.first),null==c&&(c=a.doc.first+a.doc.size),d||(d=0);var e=a.display;if(d&&c<e.viewTo&&(null==e.updateLineNumbers||e.updateLineNumbers>b)&&(e.updateLineNumbers=b),a.curOp.viewChanged=!0,b>=e.viewTo)Ug&&oa(a.doc,b)<e.viewTo&&sd(a);else i
 f(c<=e.viewFrom)Ug&&pa(a.doc,c+d)>e.viewFrom?sd(a):(e.viewFrom+=d,e.viewTo+=d);else if(b<=e.viewFrom&&c>=e.viewTo)sd(a);else if(b<=e.viewFrom){var f=td(a,c,c+d,1);f?(e.view=e.view.slice(f.index),e.viewFrom=f.lineN,e.viewTo+=d):sd(a)}else if(c>=e.viewTo){var g=td(a,b,b,-1);g?(e.view=e.view.slice(0,g.index),e.viewTo=g.lineN):sd(a)}else{var h=td(a,b,b,-1),i=td(a,c,c+d,1);h&&i?(e.view=e.view.slice(0,h.index).concat(ub(a,h.lineN,i.lineN)).concat(e.view.slice(i.index)),e.viewTo+=d):sd(a)}var j=e.externalMeasured;j&&(c<j.lineN?j.lineN+=d:b<j.lineN+j.size&&(e.externalMeasured=null))}function rd(a,b,c){a.curOp.viewChanged=!0;var d=a.display,e=a.display.externalMeasured;if(e&&b>=e.lineN&&b<e.lineN+e.size&&(d.externalMeasured=null),!(b<d.viewFrom||b>=d.viewTo)){var f=d.view[zc(a,b)];if(null!=f.node){var g=f.changes||(f.changes=[]);m(g,c)==-1&&g.push(c)}}}function sd(a){a.display.viewFrom
 =a.display.viewTo=a.doc.first,a.display.view=[],a.display.viewOffset=0}function td(a,b,c,d){var e,f=zc(a,b),g=a.display.view;if(!Ug||c==a.doc.first+a.doc.size)return{index:f,lineN:c};for(var h=a.display.viewFrom,i=0;i<f;i++)h+=g[i].size;if(h!=b){if(d>0){if(f==g.length-1)return null;e=h+g[f].size-b,f++}else e=h-b;b+=e,c+=e}for(;oa(a.doc,c)!=c;){if(f==(d<0?0:g.length-1))return null;c+=d*g[f-(d<0?1:0)].size,f+=d}return{index:f,lineN:c}}function ud(a,b,c){var d=a.display,e=d.view;0==e.length||b>=d.viewTo||c<=d.viewFrom?(d.view=ub(a,b,c),d.viewFrom=b):(d.viewFrom>b?d.view=ub(a,b,d.viewFrom).concat(d.view):d.viewFrom<b&&(d.view=d.view.slice(zc(a,b))),d.viewFrom=b,d.viewTo<c?d.view=d.view.concat(ub(a,d.viewTo,c)):d.viewTo>c&&(d.view=d.view.slice(0,zc(a,c)))),d.viewTo=c}function vd(a){for(var b=a.display.view,c=0,d=0;d<b.length;d++){var e=b[d];e.hidden||e.node&&!e.changes||++c}return c}function wd(a,b){a.doc.highlightFrontier<a.dis
 play.viewTo&&a.state.highlight.set(b,j(xd,a))}function xd(a){var b=a.doc;if(!(b.highlightFrontier>=a.display.viewTo)){var c=+new Date+a.options.workTime,d=ab(a,b.highlightFrontier),e=[];b.iter(d.line,Math.min(b.first+b.size,a.display.viewTo+500),function(f){if(d.line>=a.display.viewFrom){var g=f.styles,h=f.text.length>a.options.maxHighlightLength?Xa(b.mode,d.state):null,i=$a(a,f,d,!0);h&&(d.state=h),f.styles=i.styles;var j=f.styleClasses,k=i.classes;k?f.styleClasses=k:j&&(f.styleClasses=null);for(var l=!g||g.length!=f.styles.length||j!=k&&(!j||!k||j.bgClass!=k.bgClass||j.textClass!=k.textClass),m=0;!l&&m<g.length;++m)l=g[m]!=f.styles[m];l&&e.push(d.line),f.stateAfter=d.save(),d.nextLine()}else f.text.length<=a.options.maxHighlightLength&&bb(a,f.text,d),f.stateAfter=d.line%5==0?d.save():null,d.nextLine();if(+new Date>c)return wd(a,a.options.workDelay),!0}),b.highlightFrontier=d.line,b.modeFrontier=Math.max(b.mo
 deFrontier,d.line),e.length&&md(a,function(){for(var b=0;b<e.length;b++)rd(a,e[b],"text")})}}function yd(a){var b=a.display;!b.scrollbarsClipped&&b.scroller.offsetWidth&&(b.nativeBarWidth=b.scroller.offsetWidth-b.scroller.clientWidth,b.heightForcer.style.height=Rb(a)+"px",b.sizer.style.marginBottom=-b.nativeBarWidth+"px",b.sizer.style.borderRightWidth=Rb(a)+"px",b.scrollbarsClipped=!0)}function zd(a){if(a.hasFocus())return null;var b=g();if(!b||!f(a.display.lineDiv,b))return null;var c={activeElt:b};if(window.getSelection){var d=window.getSelection();d.anchorNode&&d.extend&&f(a.display.lineDiv,d.anchorNode)&&(c.anchorNode=d.anchorNode,c.anchorOffset=d.anchorOffset,c.focusNode=d.focusNode,c.focusOffset=d.focusOffset)}return c}function Ad(a){if(a&&a.activeElt&&a.activeElt!=g()&&(a.activeElt.focus(),a.anchorNode&&f(document.body,a.anchorNode)&&f(document.bo
 dy,a.focusNode))){var b=window.getSelection(),c=document.createRange();c.setEnd(a.anchorNode,a.anchorOffset),c.collapse(!1),b.removeAllRanges(),b.addRange(c),b.extend(a.focusNode,a.focusOffset)}}function Bd(a,c){var d=a.display,e=a.doc;if(c.editorIsHidden)return sd(a),!1;if(!c.force&&c.visible.from>=d.viewFrom&&c.visible.to<=d.viewTo&&(null==d.updateLineNumbers||d.updateLineNumbers>=d.viewTo)&&d.renderedView==d.view&&0==vd(a))return!1;Oc(a)&&(sd(a),c.dims=uc(a));var f=e.first+e.size,g=Math.max(c.visible.from-a.options.viewportMargin,e.first),h=Math.min(f,c.visible.to+a.options.viewportMargin);d.viewFrom<g&&g-d.viewFrom<20&&(g=Math.max(e.first,d.viewFrom)),d.viewTo>h&&d.viewTo-h<20&&(h=Math.min(f,d.viewTo)),Ug&&(g=oa(a.doc,g),h=pa(a.doc,h));var i=g!=d.viewFrom||h!=d.viewTo||d.lastWrapHeight!=c.wrapperHeight||d.lastWrapWidth!=c.wrapperWidth;ud(a,g,h),d.viewOffset=sa(B(a.doc,d.v
 iewFrom)),a.display.mover.style.top=d.viewOffset+"px";var j=vd(a);if(!i&&0==j&&!c.force&&d.renderedView==d.view&&(null==d.updateLineNumbers||d.updateLineNumbers>=d.viewTo))return!1;var k=zd(a);return j>4&&(d.lineDiv.style.display="none"),Ed(a,d.updateLineNumbers,c.dims),j>4&&(d.lineDiv.style.display=""),d.renderedView=d.view,Ad(k),b(d.cursorDiv),b(d.selectionDiv),d.gutters.style.height=d.sizer.style.minHeight=0,i&&(d.lastWrapHeight=c.wrapperHeight,d.lastWrapWidth=c.wrapperWidth,wd(a,400)),d.updateLineNumbers=null,!0}function Cd(a,b){for(var c=b.viewport,d=!0;(d&&a.options.lineWrapping&&b.oldDisplayWidth!=Sb(a)||(c&&null!=c.top&&(c={top:Math.min(a.doc.height+Pb(a.display)-Tb(a),c.top)}),b.visible=Mc(a.display,a.doc,c),!(b.visible.from>=a.display.viewFrom&&b.visible.to<=a.display.viewTo)))&&Bd(a,b);d=!1){Kc(a);var e=ad(a);Ac(a),bd(a,e),Gd
 (a,e),b.force=!1}b.signal(a,"update",a),a.display.viewFrom==a.display.reportedViewFrom&&a.display.viewTo==a.display.reportedViewTo||(b.signal(a,"viewportChange",a,a.display.viewFrom,a.display.viewTo),a.display.reportedViewFrom=a.display.viewFrom,a.display.reportedViewTo=a.display.viewTo)}function Dd(a,b){var c=new uh(a,b);if(Bd(a,c)){Kc(a),Cd(a,c);var d=ad(a);Ac(a),bd(a,d),Gd(a,d),c.finish()}}function Ed(a,c,d){function e(b){var c=b.nextSibling;return pg&&zg&&a.display.currentWheelTarget==b?b.style.display="none":b.parentNode.removeChild(b),c}for(var f=a.display,g=a.options.lineNumbers,h=f.lineDiv,i=h.firstChild,j=f.view,k=f.viewFrom,l=0;l<j.length;l++){var n=j[l];if(n.hidden);else if(n.node&&n.node.parentNode==h){for(;i!=n.node;)i=e(i);var o=g&&null!=c&&c<=k&&n.lineNumber;n.changes&&(m(n.changes,"gutter")>-1&&(o=!1),Ab(a,n,k,d)),o&&(b(n.lineNumber),n.line
 Number.appendChild(document.createTextNode(I(a.options,k)))),i=n.node.nextSibling}else{var p=Ib(a,n,k,d);h.insertBefore(p,i)}k+=n.size}for(;i;)i=e(i)}function Fd(a){var b=a.display.gutters.offsetWidth;a.display.sizer.style.marginLeft=b+"px"}function Gd(a,b){a.display.sizer.style.minHeight=b.docHeight+"px",a.display.heightForcer.style.top=b.docHeight+"px",a.display.gutters.style.height=b.docHeight+a.display.barHeight+Rb(a)+"px"}function Hd(a){var c=a.display.gutters,e=a.options.gutters;b(c);for(var f=0;f<e.length;++f){var g=e[f],h=c.appendChild(d("div",null,"CodeMirror-gutter "+g));"CodeMirror-linenumbers"==g&&(a.display.lineGutter=h,h.style.width=(a.display.lineNumWidth||1)+"px")}c.style.display=f?"":"none",Fd(a)}function Id(a){var b=m(a.gutters,"CodeMirror-linenumbers");b==-1&&a.lineNumbers?a.gutters=a.gutters.concat(["CodeMirror-linenumbers"]):
 b>-1&&!a.lineNumbers&&(a.gutters=a.gutters.slice(0),a.gutters.splice(b,1))}function Jd(a){var b=a.wheelDeltaX,c=a.wheelDeltaY;return null==b&&a.detail&&a.axis==a.HORIZONTAL_AXIS&&(b=a.detail),null==c&&a.detail&&a.axis==a.VERTICAL_AXIS?c=a.detail:null==c&&(c=a.wheelDelta),{x:b,y:c}}function Kd(a){var b=Jd(a);return b.x*=wh,b.y*=wh,b}function Ld(a,b){var c=Jd(b),d=c.x,e=c.y,f=a.display,g=f.scroller,h=g.scrollWidth>g.clientWidth,i=g.scrollHeight>g.clientHeight;if(d&&h||e&&i){if(e&&zg&&pg)a:for(var j=b.target,k=f.view;j!=g;j=j.parentNode)for(var l=0;l<k.length;l++)if(k[l].node==j){a.display.currentWheelTarget=j;break a}if(d&&!jg&&!sg&&null!=wh)return e&&i&&Zc(a,Math.max(0,g.scrollTop+e*wh)),_c(a,Math.max(0,g.scrollLeft+d*wh)),(!e||e&&i)&&Ja(b),void(f.wheelStartX=null);if(e&&null!=wh){var m=e*wh,n=a.doc.scrollTop,o=n+f
 .wrapper.clientHeight;m<0?n=Math.max(0,n+m-50):o=Math.min(a.doc.height,o+m+50),Dd(a,{top:n,bottom:o})}vh<20&&(null==f.wheelStartX?(f.wheelStartX=g.scrollLeft,f.wheelStartY=g.scrollTop,f.wheelDX=d,f.wheelDY=e,setTimeout(function(){if(null!=f.wheelStartX){var a=g.scrollLeft-f.wheelStartX,b=g.scrollTop-f.wheelStartY,c=b&&f.wheelDY&&b/f.wheelDY||a&&f.wheelDX&&a/f.wheelDX;f.wheelStartX=f.wheelStartY=null,c&&(wh=(wh*vh+c)/(vh+1),++vh)}},200)):(f.wheelDX+=d,f.wheelDY+=e))}}function Md(a,b){var c=a[b];a.sort(function(a,b){return K(a.from(),b.from())}),b=m(a,c);for(var d=1;d<a.length;d++){var e=a[d],f=a[d-1];if(K(f.to(),e.from())>=0){var g=O(f.from(),e.from()),h=N(f.to(),e.to()),i=f.empty()?e.from()==e.head:f.from()==f.head;d<=b&&--b,a.splice(--d,2,new yh(i?h:g,i?g:h))}}return new xh(a,b)}function Nd(a,b){return new xh([new yh(a,b||a)],0)}function Od(a){return a.text?J(a.from.line+a.text.length-1,p(a.text).length+(1==a.te
 xt.length?a.from.ch:0)):a.to}function Pd(a,b){if(K(a,b.from)<0)return a;if(K(a,b.to)<=0)return Od(b);var c=a.line+b.text.length-(b.to.line-b.from.line)-1,d=a.ch;return a.line==b.to.line&&(d+=Od(b).ch-b.to.ch),J(c,d)}function Qd(a,b){for(var c=[],d=0;d<a.sel.ranges.length;d++){var e=a.sel.ranges[d];c.push(new yh(Pd(e.anchor,b),Pd(e.head,b)))}return Md(c,a.sel.primIndex)}function Rd(a,b,c){return a.line==b.line?J(c.line,a.ch-b.ch+c.ch):J(c.line+(a.line-b.line),a.ch)}function Sd(a,b,c){for(var d=[],e=J(a.first,0),f=e,g=0;g<b.length;g++){var h=b[g],i=Rd(h.from,e,f),j=Rd(Od(h),e,f);if(e=h.to,f=j,"around"==c){var k=a.sel.ranges[g],l=K(k.head,k.anchor)<0;d[g]=new yh(l?j:i,l?i:j)}else d[g]=new yh(i,i)}return new xh(d,a.sel.primIndex)}function Td(a){a.doc.mode=Va(a.options,a.doc.modeOption),Ud(a)}function Ud(a){a.doc.iter(function(a){a.stateAfter&&(a.stateAfter=null),a.styles&&(a.styles=null)}),a.doc.modeFrontier=a.doc.highlightFrontier=a.doc.
 first,wd(a,100),a.state.modeGen++,a.curOp&&qd(a)}function Vd(a,b){return 0==b.from.ch&&0==b.to.ch&&""==p(b.text)&&(!a.cm||a.cm.options.wholeLineUpdateBefore)}function Wd(a,b,c,d){function e(a){return c?c[a]:null}function f(a,c,e){jb(a,c,e,d),yb(a,"change",a,b)}function g(a,b){for(var c=[],f=a;f<b;++f)c.push(new jh(j[f],e(f),d));return c}var h=b.from,i=b.to,j=b.text,k=B(a,h.line),l=B(a,i.line),m=p(j),n=e(j.length-1),o=i.line-h.line;if(b.full)a.insert(0,g(0,j.length)),a.remove(j.length,a.size-j.length);else if(Vd(a,b)){var q=g(0,j.length-1);f(l,l.text,n),o&&a.remove(h.line,o),q.length&&a.insert(h.line,q)}else if(k==l)if(1==j.length)f(k,k.text.slice(0,h.ch)+m+k.text.slice(i.ch),n);else{var r=g(1,j.length-1);r.push(new jh(m+k.text.slice(i.ch),n,d)),f(k,k.text.slice(0,h.ch)+j[0],e(0)),a.insert(h.line+1,r)}else if(1==j.length)f(k,k.text.slice(0,h.ch)+j[0]+l.text.slice(i.ch),e(0)),a.remove(h.line+1,o);else{f(k,k.text.sl
 ice(0,h.ch)+j[0],e(0)),f(l,m+l.text.slice(i.ch),n);var s=g(1,j.length-1);o>1&&a.remove(h.line+1,o-1),a.insert(h.line+1,s)}yb(a,"change",a,b)}function Xd(a,b,c){function d(a,e,f){if(a.linked)for(var g=0;g<a.linked.length;++g){var h=a.linked[g];if(h.doc!=e){var i=f&&h.sharedHist;c&&!i||(b(h.doc,i),d(h.doc,a,i))}}}d(a,null,!0)}function Yd(a,b){if(b.cm)throw new Error("This document is already in use.");a.doc=b,b.cm=a,xc(a),Td(a),Zd(a),a.options.lineWrapping||ua(a),a.options.mode=b.modeOption,qd(a)}function Zd(a){("rtl"==a.doc.direction?h:Gg)(a.display.lineDiv,"CodeMirror-rtl")}function $d(a){md(a,function(){Zd(a),qd(a)})}function _d(a){this.done=[],this.undone=[],this.undoDepth=1/0,this.lastModTime=this.lastSelTime=0,this.lastOp=this.lastSelOp=null,this.lastOrigin=this.lastSelOrigin=null,this.generation=this.maxGeneration=a||1}function ae(a,b){var c={from:M(b.from),to:Od(b),text:C(a,b.from,b.to)};return he(a,c,b.from
 .line,b.to.line+1),Xd(a,function(a){return he(a,c,b.from.line,b.to.line+1)},!0),c}function be(a){for(;a.length;){var b=p(a);if(!b.ranges)break;a.pop()}}function ce(a,b){return b?(be(a.done),p(a.done)):a.done.length&&!p(a.done).ranges?p(a.done):a.done.length>1&&!a.done[a.done.length-2].ranges?(a.done.pop(),p(a.done)):void 0}function de(a,b,c,d){var e=a.history;e.undone.length=0;var f,g,h=+new Date;if((e.lastOp==d||e.lastOrigin==b.origin&&b.origin&&("+"==b.origin.charAt(0)&&a.cm&&e.lastModTime>h-a.cm.options.historyEventDelay||"*"==b.origin.charAt(0)))&&(f=ce(e,e.lastOp==d)))g=p(f.changes),0==K(b.from,b.to)&&0==K(b.from,g.to)?g.to=Od(b):f.changes.push(ae(a,b));else{var i=p(e.done);for(i&&i.ranges||ge(a.sel,e.done),f={changes:[ae(a,b)],generation:e.generation},e.done.push(f);e.done.length>e.undoDepth;)e.done.shift(),e.done[0].ranges||e.done.shift()}e.done.push(c),e.generation=++e.maxGen
 eration,e.lastModTime=e.lastSelTime=h,e.lastOp=e.lastSelOp=d,e.lastOrigin=e.lastSelOrigin=b.origin,g||Ea(a,"historyAdded")}function ee(a,b,c,d){var e=b.charAt(0);return"*"==e||"+"==e&&c.ranges.length==d.ranges.length&&c.somethingSelected()==d.somethingSelected()&&new Date-a.history.lastSelTime<=(a.cm?a.cm.options.historyEventDelay:500)}function fe(a,b,c,d){var e=a.history,f=d&&d.origin;c==e.lastSelOp||f&&e.lastSelOrigin==f&&(e.lastModTime==e.lastSelTime&&e.lastOrigin==f||ee(a,f,p(e.done),b))?e.done[e.done.length-1]=b:ge(b,e.done),e.lastSelTime=+new Date,e.lastSelOrigin=f,e.lastSelOp=c,d&&d.clearRedo!==!1&&be(e.undone)}function ge(a,b){var c=p(b);c&&c.ranges&&c.equals(a)||b.push(a)}function he(a,b,c,d){var e=b["spans_"+a.id],f=0;a.iter(Math.max(a.first,c),Math.min(a.first+a.size,d),function(c){c.markedSpans&&((e||(e=b["spans_"+a.id]={}))
 [f]=c.markedSpans),++f})}function ie(a){if(!a)return null;for(var b,c=0;c<a.length;++c)a[c].marker.explicitlyCleared?b||(b=a.slice(0,c)):b&&b.push(a[c]);return b?b.length?b:null:a}function je(a,b){var c=b["spans_"+a.id];if(!c)return null;for(var d=[],e=0;e<b.text.length;++e)d.push(ie(c[e]));return d}function ke(a,b){var c=je(a,b),d=_(a,b);if(!c)return d;if(!d)return c;for(var e=0;e<c.length;++e){var f=c[e],g=d[e];if(f&&g)a:for(var h=0;h<g.length;++h){for(var i=g[h],j=0;j<f.length;++j)if(f[j].marker==i.marker)continue a;f.push(i)}else g&&(c[e]=g)}return c}function le(a,b,c){for(var d=[],e=0;e<a.length;++e){var f=a[e];if(f.ranges)d.push(c?xh.prototype.deepCopy.call(f):f);else{var g=f.changes,h=[];d.push({changes:h});for(var i=0;i<g.length;++i){var j=g[i],k=void 0;if(h.push({from:j.from,to:j.to,text:j.text}),b)for(var l in j)(k=l.match(/^spans_(\d+)$/))&&m(b,Number(k[1]))>-1&&(p(h)[l]=j[l],delete j[l])}}}return d
 }function me(a,b,c,d){if(d){var e=a.anchor;if(c){var f=K(b,e)<0;f!=K(c,e)<0?(e=b,b=c):f!=K(b,c)<0&&(b=c)}return new yh(e,b)}return new yh(c||b,b)}function ne(a,b,c,d,e){null==e&&(e=a.cm&&(a.cm.display.shift||a.extend)),te(a,new xh([me(a.sel.primary(),b,c,e)],0),d)}function oe(a,b,c){for(var d=[],e=a.cm&&(a.cm.display.shift||a.extend),f=0;f<a.sel.ranges.length;f++)d[f]=me(a.sel.ranges[f],b[f],null,e);var g=Md(d,a.sel.primIndex);te(a,g,c)}function pe(a,b,c,d){var e=a.sel.ranges.slice(0);e[b]=c,te(a,Md(e,a.sel.primIndex),d)}function qe(a,b,c,d){te(a,Nd(b,c),d)}function re(a,b,c){var d={ranges:b.ranges,update:function(b){var c=this;this.ranges=[];for(var d=0;d<b.length;d++)c.ranges[d]=new yh(Q(a,b[d].anchor),Q(a,b[d].head))},origin:c&&c.origin};return Ea(a,"beforeSelectionChange",a,d),a.cm&&Ea(a.cm,"beforeSelectionChange",a.cm,d),d.ranges!=b.ranges?Md(d.ranges,d.ranges.length-1):b}function se(a,b,c){var d
 =a.history.done,e=p(d);e&&e.ranges?(d[d.length-1]=b,ue(a,b,c)):te(a,b,c)}function te(a,b,c){ue(a,b,c),fe(a,a.sel,a.cm?a.cm.curOp.id:NaN,c)}function ue(a,b,c){(Ha(a,"beforeSelectionChange")||a.cm&&Ha(a.cm,"beforeSelectionChange"))&&(b=re(a,b,c));var d=c&&c.bias||(K(b.primary().head,a.sel.primary().head)<0?-1:1);ve(a,xe(a,b,d,!0)),c&&c.scroll===!1||!a.cm||Uc(a.cm)}function ve(a,b){b.equals(a.sel)||(a.sel=b,a.cm&&(a.cm.curOp.updateInput=a.cm.curOp.selectionChanged=!0,Ga(a.cm)),yb(a,"cursorActivity",a))}function we(a){ve(a,xe(a,a.sel,null,!1))}function xe(a,b,c,d){for(var e,f=0;f<b.ranges.length;f++){var g=b.ranges[f],h=b.ranges.length==a.sel.ranges.length&&a.sel.ranges[f],i=ze(a,g.anchor,h&&h.anchor,c,d),j=ze(a,g.head,h&&h.head,c,d);(e||i!=g.anchor||j!=g.head)&&(e||(e=b.ranges.slice(0,f)),e[f]=new yh(i,j))}return e?Md(e,b.primIndex):b}function ye(a,b,c,d,e){var f=B(a,b.li
 ne);if(f.markedSpans)for(var g=0;g<f.markedSpans.length;++g){var h=f.markedSpans[g],i=h.marker;if((null==h.from||(i.inclusiveLeft?h.from<=b.ch:h.from<b.ch))&&(null==h.to||(i.inclusiveRight?h.to>=b.ch:h.to>b.ch))){if(e&&(Ea(i,"beforeCursorEnter"),i.explicitlyCleared)){if(f.markedSpans){--g;continue}break}if(!i.atomic)continue;if(c){var j=i.find(d<0?1:-1),k=void 0;if((d<0?i.inclusiveRight:i.inclusiveLeft)&&(j=Ae(a,j,-d,j&&j.line==b.line?f:null)),j&&j.line==b.line&&(k=K(j,c))&&(d<0?k<0:k>0))return ye(a,j,b,d,e)}var l=i.find(d<0?-1:1);return(d<0?i.inclusiveLeft:i.inclusiveRight)&&(l=Ae(a,l,d,l.line==b.line?f:null)),l?ye(a,l,b,d,e):null}}return b}function ze(a,b,c,d,e){var f=d||1,g=ye(a,b,c,f,e)||!e&&ye(a,b,c,f,!0)||ye(a,b,c,-f,e)||!e&&ye(a,b,c,-f,!0);return g?g:(a.cantEdit=!0,J(a.first,0))}function Ae(a,b,c,d){return c<0&&0==b.ch?b.line>a.first?Q(a,
 J(b.line-1)):null:c>0&&b.ch==(d||B(a,b.line)).text.length?b.line<a.first+a.size-1?J(b.line+1,0):null:new J(b.line,b.ch+c)}function Be(a){a.setSelection(J(a.firstLine(),0),J(a.lastLine()),Ng)}function Ce(a,b,c){var d={canceled:!1,from:b.from,to:b.to,text:b.text,origin:b.origin,cancel:function(){return d.canceled=!0}};return c&&(d.update=function(b,c,e,f){b&&(d.from=Q(a,b)),c&&(d.to=Q(a,c)),e&&(d.text=e),void 0!==f&&(d.origin=f)}),Ea(a,"beforeChange",a,d),a.cm&&Ea(a.cm,"beforeChange",a.cm,d),d.canceled?null:{from:d.from,to:d.to,text:d.text,origin:d.origin}}function De(a,b,c){if(a.cm){if(!a.cm.curOp)return nd(a.cm,De)(a,b,c);if(a.cm.state.suppressEdits)return}if(!(Ha(a,"beforeChange")||a.cm&&Ha(a.cm,"beforeChange"))||(b=Ce(a,b,!0))){var d=Tg&&!c&&ba(a,b.from,b.to);if(d)for(var e=d.length-1;e>=0;--e)Ee(a,{from:d[e].from,to:d[e].to,text:e?[""]:b.text,
 origin:b.origin});else Ee(a,b)}}function Ee(a,b){if(1!=b.text.length||""!=b.text[0]||0!=K(b.from,b.to)){var c=Qd(a,b);de(a,b,c,a.cm?a.cm.curOp.id:NaN),He(a,b,c,_(a,b));var d=[];Xd(a,function(a,c){c||m(d,a.history)!=-1||(Me(a.history,b),d.push(a.history)),He(a,b,null,_(a,b))})}}function Fe(a,b,c){if(!a.cm||!a.cm.state.suppressEdits||c){for(var d,e=a.history,f=a.sel,g="undo"==b?e.done:e.undone,h="undo"==b?e.undone:e.done,i=0;i<g.length&&(d=g[i],c?!d.ranges||d.equals(a.sel):d.ranges);i++);if(i!=g.length){for(e.lastOrigin=e.lastSelOrigin=null;d=g.pop(),d.ranges;){if(ge(d,h),c&&!d.equals(a.sel))return void te(a,d,{clearRedo:!1});f=d}var j=[];ge(f,h),h.push({changes:j,generation:e.generation}),e.generation=d.generation||++e.maxGeneration;for(var k=Ha(a,"beforeChange")||a.cm&&Ha(a.cm,"beforeChange"),l=function(c){var e=d.changes[c];if(e.origin=b,
+k&&!Ce(a,e,!1))return g.length=0,{};j.push(ae(a,e));var f=c?Qd(a,e):p(g);He(a,e,f,ke(a,e)),!c&&a.cm&&a.cm.scrollIntoView({from:e.from,to:Od(e)});var h=[];Xd(a,function(a,b){b||m(h,a.history)!=-1||(Me(a.history,e),h.push(a.history)),He(a,e,null,ke(a,e))})},n=d.changes.length-1;n>=0;--n){var o=l(n);if(o)return o.v}}}}function Ge(a,b){if(0!=b&&(a.first+=b,a.sel=new xh(q(a.sel.ranges,function(a){return new yh(J(a.anchor.line+b,a.anchor.ch),J(a.head.line+b,a.head.ch))}),a.sel.primIndex),a.cm)){qd(a.cm,a.first,a.first-b,b);for(var c=a.cm.display,d=c.viewFrom;d<c.viewTo;d++)rd(a.cm,d,"gutter")}}function He(a,b,c,d){if(a.cm&&!a.cm.curOp)return nd(a.cm,He)(a,b,c,d);if(b.to.line<a.first)return void Ge(a,b.text.length-1-(b.to.line-b.from.line));if(!(b.from.line>a.lastLine())){if(b.from.line<a.first){var e=b.text.length-1-(a.first-b.from.line);Ge(a,e),b={from:J(a.first,0),to:J(b.to.line+e,b.to.ch),text:[p(b.text)],origin:b.origin}
 }var f=a.lastLine();b.to.line>f&&(b={from:b.from,to:J(f,B(a,f).text.length),text:[b.text[0]],origin:b.origin}),b.removed=C(a,b.from,b.to),c||(c=Qd(a,b)),a.cm?Ie(a.cm,b,d):Wd(a,b,d),ue(a,c,Ng)}}function Ie(a,b,c){var d=a.doc,e=a.display,f=b.from,g=b.to,h=!1,i=f.line;a.options.lineWrapping||(i=F(la(B(d,f.line))),d.iter(i,g.line+1,function(a){if(a==e.maxLine)return h=!0,!0})),d.sel.contains(b.from,b.to)>-1&&Ga(a),Wd(d,b,c,wc(a)),a.options.lineWrapping||(d.iter(i,f.line+b.text.length,function(a){var b=ta(a);b>e.maxLineLength&&(e.maxLine=a,e.maxLineLength=b,e.maxLineChanged=!0,h=!1)}),h&&(a.curOp.updateMaxLine=!0)),ib(d,f.line),wd(a,400);var j=b.text.length-(g.line-f.line)-1;b.full?qd(a):f.line!=g.line||1!=b.text.length||Vd(a.doc,b)?qd(a,f.line,g.line+1,j):rd(a,f.line,"text");var k=Ha(a,"changes"),l=Ha(a,"change");if(l||k){var m={from:f,to:g,text:b.text,removed:b.removed,origin:b.origin};l&&yb(a,"change&q
 uot;,a,m),k&&(a.curOp.changeObjs||(a.curOp.changeObjs=[])).push(m)}a.display.selForContextMenu=null}function Je(a,b,c,d,e){if(d||(d=c),K(d,c)<0){var f=d;d=c,c=f}"string"==typeof b&&(b=a.splitLines(b)),De(a,{from:c,to:d,text:b,origin:e})}function Ke(a,b,c,d){c<a.line?a.line+=d:b<a.line&&(a.line=b,a.ch=0)}function Le(a,b,c,d){for(var e=0;e<a.length;++e){var f=a[e],g=!0;if(f.ranges){f.copied||(f=a[e]=f.deepCopy(),f.copied=!0);for(var h=0;h<f.ranges.length;h++)Ke(f.ranges[h].anchor,b,c,d),Ke(f.ranges[h].head,b,c,d)}else{for(var i=0;i<f.changes.length;++i){var j=f.changes[i];if(c<j.from.line)j.from=J(j.from.line+d,j.from.ch),j.to=J(j.to.line+d,j.to.ch);else if(b<=j.to.line){g=!1;break}}g||(a.splice(0,e+1),e=0)}}}function Me(a,b){var c=b.from.line,d=b.to.line,e=b.text.length-(d-c)-1;Le(a.done,c,d,e),Le(a.undone,c,d,e)}function Ne(a,b,c,d){var e=b,f=b;return"number"==typeof b?f=B(a,P(a,b)):e=F(b),null==e?null:(d(f,e)&&
 amp;a.cm&&rd(a.cm,e,c),f)}function Oe(a){var b=this;this.lines=a,this.parent=null;for(var c=0,d=0;d<a.length;++d)a[d].parent=b,c+=a[d].height;this.height=c}function Pe(a){var b=this;this.children=a;for(var c=0,d=0,e=0;e<a.length;++e){var f=a[e];c+=f.chunkSize(),d+=f.height,f.parent=b}this.size=c,this.height=d,this.parent=null}function Qe(a,b,c){sa(b)<(a.curOp&&a.curOp.scrollTop||a.doc.scrollTop)&&Tc(a,c)}function Re(a,b,c,d){var e=new zh(a,c,d),f=a.cm;return f&&e.noHScroll&&(f.display.alignWidgets=!0),Ne(a,b,"widget",function(b){var c=b.widgets||(b.widgets=[]);if(null==e.insertAt?c.push(e):c.splice(Math.min(c.length-1,Math.max(0,e.insertAt)),0,e),e.line=b,f&&!qa(a,b)){var d=sa(b)<a.scrollTop;E(b,b.height+Mb(e)),d&&Tc(f,e.height),f.curOp.forceUpdate=!0}return!0}),yb(f,"lineWidgetAdded",f,e,"number"==typeof b?b:F(b)),e}function Se(a,b,c,d,f){if(d&&d.shared)return Te(a,b,c,d,f);if(
 a.cm&&!a.cm.curOp)return nd(a.cm,Se)(a,b,c,d,f);var g=new Bh(a,f),h=K(b,c);if(d&&k(d,g,!1),h>0||0==h&&g.clearWhenEmpty!==!1)return g;if(g.replacedWith&&(g.collapsed=!0,g.widgetNode=e("span",[g.replacedWith],"CodeMirror-widget"),d.handleMouseEvents||g.widgetNode.setAttribute("cm-ignore-events","true"),d.insertLeft&&(g.widgetNode.insertLeft=!0)),g.collapsed){if(ka(a,b.line,b,c,g)||b.line!=c.line&&ka(a,c.line,b,c,g))throw new Error("Inserting collapsed marker partially overlapping an existing one");U()}g.addToHistory&&de(a,{from:b,to:c,origin:"markText"},a.sel,NaN);var i,j=b.line,l=a.cm;if(a.iter(j,c.line+1,function(a){l&&g.collapsed&&!l.options.lineWrapping&&la(a)==l.display.maxLine&&(i=!0),g.collapsed&&j!=b.line&&E(a,0),Y(a,new V(g,j==b.line?b.ch:null,j==c.line?c.ch:null)),++j}),g.collapsed&&a.iter(b.line,c.line
 +1,function(b){qa(a,b)&&E(b,0)}),g.clearOnEnter&&Yg(g,"beforeCursorEnter",function(){return g.clear()}),g.readOnly&&(T(),(a.history.done.length||a.history.undone.length)&&a.clearHistory()),g.collapsed&&(g.id=++Ah,g.atomic=!0),l){if(i&&(l.curOp.updateMaxLine=!0),g.collapsed)qd(l,b.line,c.line+1);else if(g.className||g.title||g.startStyle||g.endStyle||g.css)for(var m=b.line;m<=c.line;m++)rd(l,m,"text");g.atomic&&we(l.doc),yb(l,"markerAdded",l,g)}return g}function Te(a,b,c,d,e){d=k(d),d.shared=!1;var f=[Se(a,b,c,d,e)],g=f[0],h=d.widgetNode;return Xd(a,function(a){h&&(d.widgetNode=h.cloneNode(!0)),f.push(Se(a,Q(a,b),Q(a,c),d,e));for(var i=0;i<a.linked.length;++i)if(a.linked[i].isParent)return;g=p(f)}),new Ch(f,g)}function Ue(a){return a.findMarks(J(a.first,0),a.clipPos(J(a.lastLine())),function(a){return a.parent})}function Ve(a,b){for(var c=0;c<b.length;c++){var d=b[c],e=d.find(),f=a.
 clipPos(e.from),g=a.clipPos(e.to);if(K(f,g)){var h=Se(a,f,g,d.primary,d.primary.type);d.markers.push(h),h.parent=d}}}function We(a){for(var b=function(b){var c=a[b],d=[c.primary.doc];Xd(c.primary.doc,function(a){return d.push(a)});for(var e=0;e<c.markers.length;e++){var f=c.markers[e];m(d,f.doc)==-1&&(f.parent=null,c.markers.splice(e--,1))}},c=0;c<a.length;c++)b(c)}function Xe(a){var b=this;if($e(b),!Fa(b,a)&&!Nb(b.display,a)){Ja(a),ng&&(Fh=+new Date);var c=yc(b,a,!0),d=a.dataTransfer.files;if(c&&!b.isReadOnly())if(d&&d.length&&window.FileReader&&window.File)for(var e=d.length,f=Array(e),g=0,h=function(a,d){if(!b.options.allowDropFileTypes||m(b.options.allowDropFileTypes,a.type)!=-1){var h=new FileReader;h.onload=nd(b,function(){var a=h.result;if(/[\x00-\x08\x0e-\x1f]{2}/.test(a)&&(a=""),f[d]=a,++g==e){c=Q(b.doc,c);var i={from:c,to:c,text:b.doc.splitLines(f.join(b.doc.lineSeparator())),origin:"paste
 "};De(b.doc,i),se(b.doc,Nd(c,Od(i)))}}),h.readAsText(a)}},i=0;i<e;++i)h(d[i],i);else{if(b.state.draggingText&&b.doc.sel.contains(c)>-1)return b.state.draggingText(a),void setTimeout(function(){return b.display.input.focus()},20);try{var j=a.dataTransfer.getData("Text");if(j){var k;if(b.state.draggingText&&!b.state.draggingText.copy&&(k=b.listSelections()),ue(b.doc,Nd(c,c)),k)for(var l=0;l<k.length;++l)Je(b.doc,"",k[l].anchor,k[l].head,"drag");b.replaceSelection(j,"around","paste"),b.display.input.focus()}}catch(a){}}}}function Ye(a,b){if(ng&&(!a.state.draggingText||+new Date-Fh<100))return void Ma(b);if(!Fa(a,b)&&!Nb(a.display,b)&&(b.dataTransfer.setData("Text",a.getSelection()),b.dataTransfer.effectAllowed="copyMove",b.dataTransfer.setDragImage&&!tg)){var c=d("img",null,null,"position: fixed; left: 0; top: 0;");c.src=&quo
 t;data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",sg&&(c.width=c.height=1,a.display.wrapper.appendChild(c),c._top=c.offsetTop),b.dataTransfer.setDragImage(c,0,0),sg&&c.parentNode.removeChild(c)}}function Ze(a,b){var e=yc(a,b);if(e){var f=document.createDocumentFragment();Cc(a,e,f),a.display.dragCursor||(a.display.dragCursor=d("div",null,"CodeMirror-cursors CodeMirror-dragcursors"),a.display.lineSpace.insertBefore(a.display.dragCursor,a.display.cursorDiv)),c(a.display.dragCursor,f)}}function $e(a){a.display.dragCursor&&(a.display.lineSpace.removeChild(a.display.dragCursor),a.display.dragCursor=null)}function _e(a){if(document.getElementsByClassName)for(var b=document.getElementsByClassName("CodeMirror"),c=0;c<b.length;c++){var d=b[c].CodeMirror;d&&a(d)}}function af(){Gh||(bf(),Gh=!0)}function bf(){var a;Yg(window,"resize",function(){null==a&&(a=setTimeout(function(){a=n
 ull,_e(cf)},100))}),Yg(window,"blur",function(){return _e(Jc)})}function cf(a){var b=a.display;b.lastWrapHeight==b.wrapper.clientHeight&&b.lastWrapWidth==b.wrapper.clientWidth||(b.cachedCharWidth=b.cachedTextHeight=b.cachedPaddingH=null,b.scrollbarsClipped=!1,a.setSize())}function df(a){var b=a.split(/-(?!$)/);a=b[b.length-1];for(var c,d,e,f,g=0;g<b.length-1;g++){var h=b[g];if(/^(cmd|meta|m)$/i.test(h))f=!0;else if(/^a(lt)?$/i.test(h))c=!0;else if(/^(c|ctrl|control)$/i.test(h))d=!0;else{if(!/^s(hift)?$/i.test(h))throw new Error("Unrecognized modifier name: "+h);e=!0}}return c&&(a="Alt-"+a),d&&(a="Ctrl-"+a),f&&(a="Cmd-"+a),e&&(a="Shift-"+a),a}function ef(a){var b={};for(var c in a)if(a.hasOwnProperty(c)){var d=a[c];if(/^(name|fallthrough|(de|at)tach)$/.test(c))continue;if("..."==d){delete a[c];continue}for(var e=q(c.split(" "),df),f=0;f<e.length;f++){var g=voi
 d 0,h=void 0;f==e.length-1?(h=e.join(" "),g=d):(h=e.slice(0,f+1).join(" "),g="...");var i=b[h];if(i){if(i!=g)throw new Error("Inconsistent bindings for "+h)}else b[h]=g}delete a[c]}for(var j in b)a[j]=b[j];return a}function ff(a,b,c,d){b=kf(b);var e=b.call?b.call(a,d):b[a];if(e===!1)return"nothing";if("..."===e)return"multi";if(null!=e&&c(e))return"handled";if(b.fallthrough){if("[object Array]"!=Object.prototype.toString.call(b.fallthrough))return ff(a,b.fallthrough,c,d);for(var f=0;f<b.fallthrough.length;f++){var g=ff(a,b.fallthrough[f],c,d);if(g)return g}}}function gf(a){var b="string"==typeof a?a:Hh[a.keyCode];return"Ctrl"==b||"Alt"==b||"Shift"==b||"Mod"==b}function hf(a,b,c){var d=a;return b.altKey&&"Alt"!=d&&(a="Alt-"+a),(Eg?b.metaKey:b.ctrlKey)&&"Ctrl"!=d&&(a="Ct
 rl-"+a),(Eg?b.ctrlKey:b.metaKey)&&"Cmd"!=d&&(a="Cmd-"+a),!c&&b.shiftKey&&"Shift"!=d&&(a="Shift-"+a),a}function jf(a,b){if(sg&&34==a.keyCode&&a["char"])return!1;var c=Hh[a.keyCode];return null!=c&&!a.altGraphKey&&hf(c,a,b)}function kf(a){return"string"==typeof a?Lh[a]:a}function lf(a,b){for(var c=a.doc.sel.ranges,d=[],e=0;e<c.length;e++){for(var f=b(c[e]);d.length&&K(f.from,p(d).to)<=0;){var g=d.pop();if(K(g.from,f.from)<0){f.from=g.from;break}}d.push(f)}md(a,function(){for(var b=d.length-1;b>=0;b--)Je(a.doc,"",d[b].from,d[b].to,"+delete");Uc(a)})}function mf(a,b){var c=B(a.doc,b),d=la(c);return d!=c&&(b=F(d)),Aa(!0,a,d,b,1)}function nf(a,b){var c=B(a.doc,b),d=ma(c);return d!=c&&(b=F(d)),Aa(!0,a,c,b,-1)}function of(a,b){var c=mf(a,b.line),d=B(a.doc,c.line),e=xa(d,a.doc.direction);if(!e||0==e[0]
 .level){var f=Math.max(0,d.text.search(/\S/)),g=b.line==c.line&&b.ch<=f&&b.ch;return J(c.line,g?0:f,c.sticky)}return c}function pf(a,b,c){if("string"==typeof b&&(b=Mh[b],!b))return!1;a.display.input.ensurePolled();var d=a.display.shift,e=!1;try{a.isReadOnly()&&(a.state.suppressEdits=!0),c&&(a.display.shift=!1),e=b(a)!=Mg}finally{a.display.shift=d,a.state.suppressEdits=!1}return e}function qf(a,b,c){for(var d=0;d<a.state.keyMaps.length;d++){var e=ff(b,a.state.keyMaps[d],c,a);if(e)return e}return a.options.extraKeys&&ff(b,a.options.extraKeys,c,a)||ff(b,a.options.keyMap,c,a)}function rf(a,b,c,d){var e=a.state.keySeq;if(e){if(gf(b))return"handled";Nh.set(50,function(){a.state.keySeq==e&&(a.state.keySeq=null,a.display.input.reset())}),b=e+" "+b}var f=qf(a,b,d);return"multi"==f&&(a.state.keySeq=b),"handled"==f&&yb(a,"keyHandled",a,b,c),"handled&quo
 t;!=f&&"multi"!=f||(Ja(c),Fc(a)),e&&!f&&/\'$/.test(b)?(Ja(c),!0):!!f}function sf(a,b){var c=jf(b,!0);return!!c&&(b.shiftKey&&!a.state.keySeq?rf(a,"Shift-"+c,b,function(b){return pf(a,b,!0)})||rf(a,c,b,function(b){if("string"==typeof b?/^go[A-Z]/.test(b):b.motion)return pf(a,b)}):rf(a,c,b,function(b){return pf(a,b)}))}function tf(a,b,c){return rf(a,"'"+c+"'",b,function(b){return pf(a,b,!0)})}function uf(a){var b=this;if(b.curOp.focus=g(),!Fa(b,a)){ng&&og<11&&27==a.keyCode&&(a.returnValue=!1);var c=a.keyCode;b.display.shift=16==c||a.shiftKey;var d=sf(b,a);sg&&(Oh=d?c:null,!d&&88==c&&!ah&&(zg?a.metaKey:a.ctrlKey)&&b.replaceSelection("",null,"cut")),18!=c||/\bCodeMirror-crosshair\b/.test(b.display.lineDiv.className)||vf(b)}}function vf(a){function b(a){18!=a.keyCode&&a.altKey||(Gg(c,"CodeMirror-cross
 hair"),Da(document,"keyup",b),Da(document,"mouseover",b))}var c=a.display.lineDiv;h(c,"CodeMirror-crosshair"),Yg(document,"keyup",b),Yg(document,"mouseover",b)}function wf(a){16==a.keyCode&&(this.doc.sel.shift=!1),Fa(this,a)}function xf(a){var b=this;if(!(Nb(b.display,a)||Fa(b,a)||a.ctrlKey&&!a.altKey||zg&&a.metaKey)){var c=a.keyCode,d=a.charCode;if(sg&&c==Oh)return Oh=null,void Ja(a);if(!sg||a.which&&!(a.which<10)||!sf(b,a)){var e=String.fromCharCode(null==d?c:d);"\b"!=e&&(tf(b,a,e)||b.display.input.onKeyPress(a))}}}function yf(a,b){var c=+new Date;return Sh&&Sh.compare(c,a,b)?(Rh=Sh=null,"triple"):Rh&&Rh.compare(c,a,b)?(Sh=new Qh(c,a,b),Rh=null,"double"):(Rh=new Qh(c,a,b),Sh=null,"single")}function zf(a){var b=this,c=b.display;if(!(Fa(b,a)||c.activeTouch&&c.input.supportsTouch())){if(c.input.ensurePolled(),c.shift
 =a.shiftKey,Nb(c,a))return void(pg||(c.scroller.draggable=!1,setTimeout(function(){return c.scroller.draggable=!0},100)));if(!Hf(b,a)){var d=yc(b,a),e=Oa(a),f=d?yf(d,e):"single";window.focus(),1==e&&b.state.selectingText&&b.state.selectingText(a),d&&Af(b,e,d,f,a)||(1==e?d?Cf(b,d,f,a):Na(a)==c.scroller&&Ja(a):2==e?(d&&ne(b.doc,d),setTimeout(function(){return c.input.focus()},20)):3==e&&(Fg?If(b,a):Hc(b)))}}}function Af(a,b,c,d,e){var f="Click";return"double"==d?f="Double"+f:"triple"==d&&(f="Triple"+f),f=(1==b?"Left":2==b?"Middle":"Right")+f,rf(a,hf(f,e),e,function(b){if("string"==typeof b&&(b=Mh[b]),!b)return!1;var d=!1;try{a.isReadOnly()&&(a.state.suppressEdits=!0),d=b(a,c)!=Mg}finally{a.state.suppressEdits=!1}return d})}function Bf(a,b,c){var d=a.getOption("configureMouse"),e=d?d(a,b,c):{};if(null==e.un
 it){var f=Ag?c.shiftKey&&c.metaKey:c.altKey;e.unit=f?"rectangle":"single"==b?"char":"double"==b?"word":"line"}return(null==e.extend||a.doc.extend)&&(e.extend=a.doc.extend||c.shiftKey),null==e.addNew&&(e.addNew=zg?c.metaKey:c.ctrlKey),null==e.moveOnDrag&&(e.moveOnDrag=!(zg?c.altKey:c.ctrlKey)),e}function Cf(a,b,c,d){ng?setTimeout(j(Gc,a),0):a.curOp.focus=g();var e,f=Bf(a,c,d),h=a.doc.sel;a.options.dragDrop&&Zg&&!a.isReadOnly()&&"single"==c&&(e=h.contains(b))>-1&&(K((e=h.ranges[e]).from(),b)<0||b.xRel>0)&&(K(e.to(),b)>0||b.xRel<0)?Df(a,d,b,f):Ff(a,d,b,f)}function Df(a,b,c,d){var e=a.display,f=!1,g=nd(a,function(b){pg&&(e.scroller.draggable=!1),a.state.draggingText=!1,Da(document,"mouseup",g),Da(document,"mousemove",h),Da(e.scroller,"dragstart",i),Da(e.scroller,"drop",g),f||(J
 a(b),d.addNew||ne(a.doc,c,null,null,d.extend),pg||ng&&9==og?setTimeout(function(){document.body.focus(),e.input.focus()},20):e.input.focus())}),h=function(a){f=f||Math.abs(b.clientX-a.clientX)+Math.abs(b.clientY-a.clientY)>=10},i=function(){return f=!0};pg&&(e.scroller.draggable=!0),a.state.draggingText=g,g.copy=!d.moveOnDrag,e.scroller.dragDrop&&e.scroller.dragDrop(),Yg(document,"mouseup",g),Yg(document,"mousemove",h),Yg(e.scroller,"dragstart",i),Yg(e.scroller,"drop",g),Hc(a),setTimeout(function(){return e.input.focus()},20)}function Ef(a,b,c){if("char"==c)return new yh(b,b);if("word"==c)return a.findWordAt(b);if("line"==c)return new yh(J(b.line,0),Q(a.doc,J(b.line+1,0)));var d=c(a,b);return new yh(d.from,d.to)}function Ff(a,b,c,d){function e(b){if(0!=K(r,b))if(r=b,"rectangle"==d.unit){for(var e=[],f=a.options.tabSize,g=l(B(j,c.line).text,c.ch,f),h=l(B(j,b.line).text,b.ch,f),i
 =Math.min(g,h),p=Math.max(g,h),q=Math.min(c.line,b.line),s=Math.min(a.lastLine(),Math.max(c.line,b.line));q<=s;q++){var t=B(j,q).text,u=n(t,i,f);i==p?e.push(new yh(J(q,u),J(q,u))):t.length>u&&e.push(new yh(J(q,u),J(q,n(t,p,f))))}e.length||e.push(new yh(c,c)),te(j,Md(o.ranges.slice(0,m).concat(e),m),{origin:"*mouse",scroll:!1}),a.scrollIntoView(b)}else{var v,w=k,x=Ef(a,b,d.unit),y=w.anchor;K(x.anchor,y)>0?(v=x.head,y=O(w.from(),x.anchor)):(v=x.anchor,y=N(w.to(),x.head));var z=o.ranges.slice(0);z[m]=new yh(Q(j,y),v),te(j,Md(z,m),Og)}}function f(b){var c=++t,h=yc(a,b,!0,"rectangle"==d.unit);if(h)if(0!=K(h,r)){a.curOp.focus=g(),e(h);var k=Mc(i,j);(h.line>=k.to||h.line<k.from)&&setTimeout(nd(a,function(){t==c&&f(b)}),150)}else{var l=b.clientY<s.top?-20:b.clientY>s.bottom?20:0;l&&setTimeout(nd(a,function(){t==c&&(i.scroller.scrollTop+=l,f(b))}),50)}}function h(b){a.state.selectingText=!1,t=1/0,Ja(b),i.input.f
 ocus(),Da(document,"mousemove",u),Da(document,"mouseup",v),j.history.lastSelOrigin=null}var i=a.display,j=a.doc;Ja(b);var k,m,o=j.sel,p=o.ranges;if(d.addNew&&!d.extend?(m=j.sel.contains(c),k=m>-1?p[m]:new yh(c,c)):(k=j.sel.primary(),m=j.sel.primIndex),"rectangle"==d.unit)d.addNew||(k=new yh(c,c)),c=yc(a,b,!0,!0),m=-1;else{var q=Ef(a,c,d.unit);k=d.extend?me(k,q.anchor,q.head,d.extend):q}d.addNew?m==-1?(m=p.length,te(j,Md(p.concat([k]),m),{scroll:!1,origin:"*mouse"})):p.length>1&&p[m].empty()&&"char"==d.unit&&!d.extend?(te(j,Md(p.slice(0,m).concat(p.slice(m+1)),0),{scroll:!1,origin:"*mouse"}),o=j.sel):pe(j,m,k,Og):(m=0,te(j,new xh([k],0),Og),o=j.sel);var r=c,s=i.wrapper.getBoundingClientRect(),t=0,u=nd(a,function(a){Oa(a)?f(a):h(a)}),v=nd(a,h);a.state.selectingText=v,Yg(document,"mousemove",u),Yg(document,"mouseup",v)}function Gf(a,b,c,d){var e,f;try{e=b.clientX,f=b.cl
 ientY}catch(b){return!1}if(e>=Math.floor(a.display.gutters.getBoundingClientRect().right))return!1;d&&Ja(b);var g=a.display,h=g.lineDiv.getBoundingClientRect();if(f>h.bottom||!Ha(a,c))return La(b);f-=h.top-g.viewOffset;for(var i=0;i<a.options.gutters.length;++i){var j=g.gutters.childNodes[i];if(j&&j.getBoundingClientRect().right>=e){var k=G(a.doc,f),l=a.options.gutters[i];return Ea(a,c,a,k,l,b),La(b)}}}function Hf(a,b){return Gf(a,b,"gutterClick",!0)}function If(a,b){Nb(a.display,b)||Jf(a,b)||Fa(a,b,"contextmenu")||a.display.input.onContextMenu(b)}function Jf(a,b){return!!Ha(a,"gutterContextMenu")&&Gf(a,b,"gutterContextMenu",!1)}function Kf(a){a.display.wrapper.className=a.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+a.options.theme.replace(/(^|\s)\s*/g," cm-s-"),fc(a)}function Lf(a){function b(b,d,e,f){a.defaults[b]=d,e&&(c[b]=f?function(a,b,c){c!=Th&&e(a,b,c)}:e)
 }var c=a.optionHandlers;a.defineOption=b,a.Init=Th,b("value","",function(a,b){return a.setValue(b)},!0),b("mode",null,function(a,b){a.doc.modeOption=b,Td(a)},!0),b("indentUnit",2,Td,!0),b("indentWithTabs",!1),b("smartIndent",!0),b("tabSize",4,function(a){Ud(a),fc(a),qd(a)},!0),b("lineSeparator",null,function(a,b){if(a.doc.lineSep=b,b){var c=[],d=a.doc.first;a.doc.iter(function(a){for(var e=0;;){var f=a.text.indexOf(b,e);if(f==-1)break;e=f+b.length,c.push(J(d,f))}d++});for(var e=c.length-1;e>=0;e--)Je(a.doc,b,c[e],J(c[e].line,c[e].ch+b.length))}}),b("specialChars",/[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff]/g,function(a,b,c){a.state.specialChars=new RegExp(b.source+(b.test("\t")?"":"|\t"),"g"),c!=Th&&a.refresh()}),b("specialCharPlaceholder",nb,function(a){return a.refresh()},!0),b("electricChars",
 !0),b("inputStyle",yg?"contenteditable":"textarea",function(){throw new Error("inputStyle can not (yet) be changed in a running editor")},!0),b("spellcheck",!1,function(a,b){return a.getInputField().spellcheck=b},!0),b("rtlMoveVisually",!Bg),b("wholeLineUpdateBefore",!0),b("theme","default",function(a){Kf(a),Mf(a)},!0),b("keyMap","default",function(a,b,c){var d=kf(b),e=c!=Th&&kf(c);e&&e.detach&&e.detach(a,d),d.attach&&d.attach(a,e||null)}),b("extraKeys",null),b("configureMouse",null),b("lineWrapping",!1,Of,!0),b("gutters",[],function(a){Id(a.options),Mf(a)},!0),b("fixedGutter",!0,function(a,b){a.display.gutters.style.left=b?vc(a.display)+"px":"0",a.refresh()},!0),b("coverGutterNextToScrollbar",!1,function(a){return bd(a)},!0),b("scrollbarStyle","nati
 ve",function(a){dd(a),bd(a),a.display.scrollbars.setScrollTop(a.doc.scrollTop),a.display.scrollbars.setScrollLeft(a.doc.scrollLeft)},!0),b("lineNumbers",!1,function(a){Id(a.options),Mf(a)},!0),b("firstLineNumber",1,Mf,!0),b("lineNumberFormatter",function(a){return a},Mf,!0),b("showCursorWhenSelecting",!1,Ac,!0),b("resetSelectionOnContextMenu",!0),b("lineWiseCopyCut",!0),b("pasteLinesPerSelection",!0),b("readOnly",!1,function(a,b){"nocursor"==b&&(Jc(a),a.display.input.blur()),a.display.input.readOnlyChanged(b)}),b("disableInput",!1,function(a,b){b||a.display.input.reset()},!0),b("dragDrop",!0,Nf),b("allowDropFileTypes",null),b("cursorBlinkRate",530),b("cursorScrollMargin",0),b("cursorHeight",1,Ac,!0),b("singleCursorHeightPerLine",!0,Ac,!0),b("workTime",100),b("workDelay",100),b("flattenSpa
 ns",!0,Ud,!0),b("addModeClass",!1,Ud,!0),b("pollInterval",100),b("undoDepth",200,function(a,b){return a.doc.history.undoDepth=b}),b("historyEventDelay",1250),b("viewportMargin",10,function(a){return a.refresh()},!0),b("maxHighlightLength",1e4,Ud,!0),b("moveInputWithCursor",!0,function(a,b){b||a.display.input.resetPosition()}),b("tabindex",null,function(a,b){return a.display.input.getField().tabIndex=b||""}),b("autofocus",null),b("direction","ltr",function(a,b){return a.doc.setDirection(b)},!0)}function Mf(a){Hd(a),qd(a),Nc(a)}function Nf(a,b,c){var d=c&&c!=Th;if(!b!=!d){var e=a.display.dragFunctions,f=b?Yg:Da;f(a.display.scroller,"dragstart",e.start),f(a.display.scroller,"dragenter",e.enter),f(a.display.scroller,"dragover",e.over),f(a.display.scroller,"dragleave",e.leave),f(a.display.scroller,"drop",e.d
 rop)}}function Of(a){a.options.lineWrapping?(h(a.display.wrapper,"CodeMirror-wrap"),a.display.sizer.style.minWidth="",a.display.sizerWidth=null):(Gg(a.display.wrapper,"CodeMirror-wrap"),ua(a)),xc(a),qd(a),fc(a),setTimeout(function(){return bd(a)},100)}function Pf(a,b){var c=this;if(!(this instanceof Pf))return new Pf(a,b);this.options=b=b?k(b):{},k(Uh,b,!1),Id(b);var d=b.value;"string"==typeof d&&(d=new Eh(d,b.mode,null,b.lineSeparator,b.direction)),this.doc=d;var e=new Pf.inputStyles[b.inputStyle](this),f=this.display=new A(a,d,e);f.wrapper.CodeMirror=this,Hd(this),Kf(this),b.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),dd(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:!1,cutIncoming:!1,selectingText:!1,draggingText:!1,highlight:new Ig,keySeq:null,specialChars:null},b.autofocus&&!yg&&f.input.focus(),n
 g&&og<11&&setTimeout(function(){return c.display.input.reset(!0)},20),Qf(this),af(),ed(this),this.curOp.forceUpdate=!0,Yd(this,d),b.autofocus&&!yg||this.hasFocus()?setTimeout(j(Ic,this),20):Jc(this);for(var g in Vh)Vh.hasOwnProperty(g)&&Vh[g](c,b[g],Th);Oc(this),b.finishInit&&b.finishInit(this);for(var h=0;h<Wh.length;++h)Wh[h](c);fd(this),pg&&b.lineWrapping&&"optimizelegibility"==getComputedStyle(f.lineDiv).textRendering&&(f.lineDiv.style.textRendering="auto")}function Qf(a){function b(){e.activeTouch&&(f=setTimeout(function(){return e.activeTouch=null},1e3),g=e.activeTouch,g.end=+new Date)}function c(a){if(1!=a.touches.length)return!1;var b=a.touches[0];return b.radiusX<=1&&b.radiusY<=1}function d(a,b){if(null==b.left)return!0;var c=b.left-a.left,d=b.top-a.top;return c*c+d*d>400}var e=a.display;Yg(e.scroller,"mousedown",nd(a,zf)),ng&&og<11?Yg(e.sc
 roller,"dblclick",nd(a,function(b){if(!Fa(a,b)){var c=yc(a,b);if(c&&!Hf(a,b)&&!Nb(a.display,b)){Ja(b);var d=a.findWordAt(c);ne(a.doc,d.anchor,d.head)}}})):Yg(e.scroller,"dblclick",function(b){return Fa(a,b)||Ja(b)}),Fg||Yg(e.scroller,"contextmenu",function(b){return If(a,b)});var f,g={end:0};Yg(e.scroller,"touchstart",function(b){if(!Fa(a,b)&&!c(b)){e.input.ensurePolled(),clearTimeout(f);var d=+new Date;e.activeTouch={start:d,moved:!1,prev:d-g.end<=300?g:null},1==b.touches.length&&(e.activeTouch.left=b.touches[0].pageX,e.activeTouch.top=b.touches[0].pageY)}}),Yg(e.scroller,"touchmove",function(){e.activeTouch&&(e.activeTouch.moved=!0)}),Yg(e.scroller,"touchend",function(c){var f=e.activeTouch;if(f&&!Nb(e,c)&&null!=f.left&&!f.moved&&new Date-f.start<300){var g,h=a.coordsChar(e.activeTouch,"page");g=!f.prev||d(f,f.prev)?new yh(h,h):!f.prev
 .prev||d(f,f.prev.prev)?a.findWordAt(h):new yh(J(h.line,0),Q(a.doc,J(h.line+1,0))),a.setSelection(g.anchor,g.head),a.focus(),Ja(c)}b()}),Yg(e.scroller,"touchcancel",b),Yg(e.scroller,"scroll",function(){e.scroller.clientHeight&&(Zc(a,e.scroller.scrollTop),_c(a,e.scroller.scrollLeft,!0),Ea(a,"scroll",a))}),Yg(e.scroller,"mousewheel",function(b){return Ld(a,b)}),Yg(e.scroller,"DOMMouseScroll",function(b){return Ld(a,b)}),Yg(e.wrapper,"scroll",function(){return e.wrapper.scrollTop=e.wrapper.scrollLeft=0}),e.dragFunctions={enter:function(b){Fa(a,b)||Ma(b)},over:function(b){Fa(a,b)||(Ze(a,b),Ma(b))},start:function(b){return Ye(a,b)},drop:nd(a,Xe),leave:function(b){Fa(a,b)||$e(a)}};var h=e.input.getField();Yg(h,"keyup",function(b){return wf.call(a,b)}),Yg(h,"keydown",nd(a,uf)),Yg(h,"keypress",nd(a,xf)),Yg(h,"focus",function(b){return Ic(a,b)}),Yg(h,"blur",function(b){return
  Jc(a,b)})}function Rf(a,b,c,d){var e,f=a.doc;null==c&&(c="add"),"smart"==c&&(f.mode.indent?e=ab(a,b).state:c="prev");var g=a.options.tabSize,h=B(f,b),i=l(h.text,null,g);h.stateAfter&&(h.stateAfter=null);var j,k=h.text.match(/^\s*/)[0];if(d||/\S/.test(h.text)){if("smart"==c&&(j=f.mode.indent(e,h.text.slice(k.length),h.text),j==Mg||j>150)){if(!d)return;c="prev"}}else j=0,c="not";"prev"==c?j=b>f.first?l(B(f,b-1).text,null,g):0:"add"==c?j=i+a.options.indentUnit:"subtract"==c?j=i-a.options.indentUnit:"number"==typeof c&&(j=i+c),j=Math.max(0,j);var m="",n=0;if(a.options.indentWithTabs)for(var p=Math.floor(j/g);p;--p)n+=g,m+="\t";if(n<j&&(m+=o(j-n)),m!=k)return Je(f,m,J(b,0),J(b,k.length),"+input"),h.stateAfter=null,!0;for(var q=0;q<f.sel.ranges.length;q++){var r=f.sel.ranges[q];if(r.head.line==b&&
 amp;r.head.ch<k.length){var s=J(b,k.length);pe(f,q,new yh(s,s));break}}}function Sf(a){Xh=a}function Tf(a,b,c,d,e){var f=a.doc;a.display.shift=!1,d||(d=f.sel);var g=a.state.pasteIncoming||"paste"==e,h=$g(b),i=null;if(g&&d.ranges.length>1)if(Xh&&Xh.text.join("\n")==b){if(d.ranges.length%Xh.text.length==0){i=[];for(var j=0;j<Xh.text.length;j++)i.push(f.splitLines(Xh.text[j]))}}else h.length==d.ranges.length&&a.options.pasteLinesPerSelection&&(i=q(h,function(a){return[a]}));for(var k,l=d.ranges.length-1;l>=0;l--){var m=d.ranges[l],n=m.from(),o=m.to();m.empty()&&(c&&c>0?n=J(n.line,n.ch-c):a.state.overwrite&&!g?o=J(o.line,Math.min(B(f,o.line).text.length,o.ch+p(h).length)):Xh&&Xh.lineWise&&Xh.text.join("\n")==b&&(n=o=J(n.line,0))),k=a.curOp.updateInput;var r={from:n,to:o,text:i?i[l%i.length]:h,origin:e||(g?"paste":a.state.cutIncoming?"cut":&quot
 ;+input")};De(a.doc,r),yb(a,"inputRead",a,r)}b&&!g&&Vf(a,b),Uc(a),a.curOp.updateInput=k,a.curOp.typing=!0,a.state.pasteIncoming=a.state.cutIncoming=!1}function Uf(a,b){var c=a.clipboardData&&a.clipboardData.getData("Text");if(c)return a.preventDefault(),b.isReadOnly()||b.options.disableInput||md(b,function(){return Tf(b,c,0,null,"paste")}),!0}function Vf(a,b){if(a.options.electricChars&&a.options.smartIndent)for(var c=a.doc.sel,d=c.ranges.length-1;d>=0;d--){var e=c.ranges[d];if(!(e.head.ch>100||d&&c.ranges[d-1].head.line==e.head.line)){var f=a.getModeAt(e.head),g=!1;if(f.electricChars){for(var h=0;h<f.electricChars.length;h++)if(b.indexOf(f.electricChars.charAt(h))>-1){g=Rf(a,e.head.line,"smart");break}}else f.electricInput&&f.electricInput.test(B(a.doc,e.head.line).text.slice(0,e.head.ch))&&(g=Rf(a,e.head.line,"smart"));g&&yb(a,"electricInput"
 ,a,e.head.line)}}}function Wf(a){for(var b=[],c=[],d=0;d<a.doc.sel.ranges.length;d++){var e=a.doc.sel.ranges[d].head.line,f={anchor:J(e,0),head:J(e+1,0)};c.push(f),b.push(a.getRange(f.anchor,f.head))}return{text:b,ranges:c}}function Xf(a,b){a.setAttribute("autocorrect","off"),a.setAttribute("autocapitalize","off"),a.setAttribute("spellcheck",!!b)}function Yf(){var a=d("textarea",null,null,"position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none"),b=d("div",[a],null,"overflow: hidden; position: relative; width: 3px; height: 0px;");return pg?a.style.width="1000px":a.setAttribute("wrap","off"),wg&&(a.style.border="1px solid black"),Xf(a),b}function Zf(a,b,c,d,e){function f(){var d=b.line+c;return!(d<a.first||d>=a.first+a.size)&&(b=new J(d,b.ch,b.sticky),j=B(a,d))}function g(d){var g;if(g=e?Ba(a.cm,j,b,c):
 za(j,b,c),null==g){if(d||!f())return!1;b=Aa(e,a.cm,j,b.line,c)}else b=g;return!0}var h=b,i=c,j=B(a,b.line);if("char"==d)g();else if("column"==d)g(!0);else if("word"==d||"group"==d)for(var k=null,l="group"==d,m=a.cm&&a.cm.getHelper(b,"wordChars"),n=!0;!(c<0)||g(!n);n=!1){var o=j.text.charAt(b.ch)||"\n",p=v(o,m)?"w":l&&"\n"==o?"n":!l||/\s/.test(o)?null:"p";if(!l||n||p||(p="s"),k&&k!=p){c<0&&(c=1,g(),b.sticky="after");break}if(p&&(k=p),c>0&&!g(!n))break}var q=ze(a,b,h,i,!0);return L(h,q)&&(q.hitSide=!0),q}function $f(a,b,c,d){var e,f=a.doc,g=b.left;if("page"==d){var h=Math.min(a.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight),i=Math.max(h-.5*sc(a.display),3);e=(c>0?b.bottom:b.top)+c*i}else"line"==d&&(e=c>0?b.bottom+3:b.to
 p-3);for(var j;j=oc(a,g,e),j.outside;){if(c<0?e<=0:e>=f.height){j.hitSide=!0;break}e+=5*c}return j}function _f(a,b){var c=Yb(a,b.line);if(!c||c.hidden)return null;var d=B(a.doc,b.line),e=Vb(c,d,b.line),f=xa(d,a.doc.direction),g="left";if(f){var h=wa(f,b.ch);g=h%2?"right":"left"}var i=_b(e.map,b.ch,g);return i.offset="right"==i.collapse?i.end:i.start,i}function ag(a){for(var b=a;b;b=b.parentNode)if(/CodeMirror-gutter-wrapper/.test(b.className))return!0;return!1}function bg(a,b){return b&&(a.bad=!0),a}function cg(a,b,c,d,e){function f(a){return function(b){return b.id==a}}function g(){k&&(j+=l,k=!1)}function h(a){a&&(g(),j+=a)}function i(b){if(1==b.nodeType){var c=b.getAttribute("cm-text");if(null!=c)return void h(c||b.textContent.replace(/\u200b/g,""));var j,m=b.getAttribute("cm-marker");if(m){var n=a.findMarks(J(d,0),J(e+1,0),f(+m));return void(n.length&&(j=n[0].find(0))&am
 p;&h(C(a.doc,j.from,j.to).join(l)))}if("false"==b.getAttribute("contenteditable"))return;var o=/^(pre|div|p)$/i.test(b.nodeName);o&&g();for(var p=0;p<b.childNodes.length;p++)i(b.childNodes[p]);o&&(k=!0)}else 3==b.nodeType&&h(b.nodeValue)}for(var j="",k=!1,l=a.doc.lineSeparator();i(b),b!=c;)b=b.nextSibling;return j}function dg(a,b,c){var d;if(b==a.display.lineDiv){if(d=a.display.lineDiv.childNodes[c],!d)return bg(a.clipPos(J(a.display.viewTo-1)),!0);b=null,c=0}else for(d=b;;d=d.parentNode){if(!d||d==a.display.lineDiv)return null;if(d.parentNode&&d.parentNode==a.display.lineDiv)break}for(var e=0;e<a.display.view.length;e++){var f=a.display.view[e];if(f.node==d)return eg(f,b,c)}}function eg(a,b,c){function d(b,c,d){for(var e=-1;e<(l?l.length:0);e++)for(var f=e<0?k.map:l[e],g=0;g<f.length;g+=3){var h=f[g+2];if(h==b||h==c){var i=F(e<0?a.line:a.rest[e]),j=f[g]+d;return(d<0||h!=b)&&(j=f[g+(d?1:0)
 ]),J(i,j)}}}var e=a.text.firstChild,g=!1;if(!b||!f(e,b))return bg(J(F(a.line),0),!0);if(b==e&&(g=!0,b=e.childNodes[c],c=0,!b)){var h=a.rest?p(a.rest):a.line;return bg(J(F(h),h.text.length),g)}var i=3==b.nodeType?b:null,j=b;for(i||1!=b.childNodes.length||3!=b.firstChild.nodeType||(i=b.firstChild,c&&(c=i.nodeValue.length));j.parentNode!=e;)j=j.parentNode;var k=a.measure,l=k.maps,m=d(i,j,c);if(m)return bg(m,g);for(var n=j.nextSibling,o=i?i.nodeValue.length-c:0;n;n=n.nextSibling){if(m=d(n,n.firstChild,0))return bg(J(m.line,m.ch-o),g);o+=n.textContent.length}for(var q=j.previousSibling,r=c;q;q=q.previousSibling){if(m=d(q,q.firstChild,-1))return bg(J(m.line,m.ch+r),g);r+=q.textContent.length}}function fg(a,b){function c(){a.value=j.getValue()}if(b=b?k(b):{},b.value=a.value,!b.tabindex&&a.tabIndex&&(b.tabindex=a.tabIndex),!b.placeholder&&a.placeholder&&(b.placeholder=a.placeholder),null==b.autofocus){var d=g();b.autofocus=d==a||null!=a.getAtt
 ribute("autofocus")&&d==document.body}var e;if(a.form&&(Yg(a.form,"submit",c),!b.leaveSubmitMethodAlone)){var f=a.form;e=f.submit;try{var h=f.submit=function(){c(),f.submit=e,f.submit(),f.submit=h}}catch(i){}}b.finishInit=function(b){b.save=c,b.getTextArea=function(){return a},b.toTextArea=function(){b.toTextArea=isNaN,
+c(),a.parentNode.removeChild(b.getWrapperElement()),a.style.display="",a.form&&(Da(a.form,"submit",c),"function"==typeof a.form.submit&&(a.form.submit=e))}},a.style.display="none";var j=Pf(function(b){return a.parentNode.insertBefore(b,a.nextSibling)},b);return j}function gg(a){a.off=Da,a.on=Yg,a.wheelEventPixels=Kd,a.Doc=Eh,a.splitLines=$g,a.countColumn=l,a.findColumn=n,a.isWordChar=u,a.Pass=Mg,a.signal=Ea,a.Line=jh,a.changeEnd=Od,a.scrollbarModel=sh,a.Pos=J,a.cmpPos=K,a.modes=ch,a.mimeModes=dh,a.resolveMode=Ua,a.getMode=Va,a.modeExtensions=eh,a.extendMode=Wa,a.copyState=Xa,a.startState=Za,a.innerMode=Ya,a.commands=Mh,a.keyMap=Lh,a.keyName=jf,a.isModifierKey=gf,a.lookupKey=ff,a.normalizeKeyMap=ef,a.StringStream=fh,a.SharedTextMarker=Ch,a.TextMarker=Bh,a.LineWidget=zh,a.e_preventDefault=Ja,a.e_stopPropagation=Ka,a.e_stop=Ma,a.addClass=h,a.contains=f,a.rmClass=Gg,a.keyNames=Hh}var hg=navigator.userAgent,ig=navigator.platform,jg=
 /gecko\/\d/i.test(hg),kg=/MSIE \d/.test(hg),lg=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(hg),mg=/Edge\/(\d+)/.exec(hg),ng=kg||lg||mg,og=ng&&(kg?document.documentMode||6:+(mg||lg)[1]),pg=!mg&&/WebKit\//.test(hg),qg=pg&&/Qt\/\d+\.\d+/.test(hg),rg=!mg&&/Chrome\//.test(hg),sg=/Opera\//.test(hg),tg=/Apple Computer/.test(navigator.vendor),ug=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(hg),vg=/PhantomJS/.test(hg),wg=!mg&&/AppleWebKit/.test(hg)&&/Mobile\/\w+/.test(hg),xg=/Android/.test(hg),yg=wg||xg||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(hg),zg=wg||/Mac/.test(ig),Ag=/\bCrOS\b/.test(hg),Bg=/win/i.test(ig),Cg=sg&&hg.match(/Version\/(\d*\.\d*)/);Cg&&(Cg=Number(Cg[1])),Cg&&Cg>=15&&(sg=!1,pg=!0);var Dg,Eg=zg&&(qg||sg&&(null==Cg||Cg<12.11)),Fg=jg||ng&&og>=9,Gg=function(b,c){var d=b.className,e=a(c).exec(d);if(e){var f=d.slice(e.index+e[0].length);b.className=d.slice(0,e.in
 dex)+(f?e[1]+f:"")}};Dg=document.createRange?function(a,b,c,d){var e=document.createRange();return e.setEnd(d||a,c),e.setStart(a,b),e}:function(a,b,c){var d=document.body.createTextRange();try{d.moveToElementText(a.parentNode)}catch(e){return d}return d.collapse(!0),d.moveEnd("character",c),d.moveStart("character",b),d};var Hg=function(a){a.select()};wg?Hg=function(a){a.selectionStart=0,a.selectionEnd=a.value.length}:ng&&(Hg=function(a){try{a.select()}catch(b){}});var Ig=function(){this.id=null};Ig.prototype.set=function(a,b){clearTimeout(this.id),this.id=setTimeout(b,a)};var Jg,Kg,Lg=30,Mg={toString:function(){return"CodeMirror.Pass"}},Ng={scroll:!1},Og={origin:"*mouse"},Pg={origin:"+move"},Qg=[""],Rg=/[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/,Sg=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b
 -\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u
 1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/,Tg=!1,Ug=!1,Vg=null,Wg=function(){function a(a){return a<=247?c.charAt(a):1424<=a&&a<=1524?"R":1536<=a&&a<=1785?d.ch
 arAt(a-1536):1774<=a&&a<=2220?"r":8192<=a&&a<=8203?"w":8204==a?"b":"L"}function b(a,b,c){this.level=a,this.from=b,this.to=c}var c="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",d="nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111",e=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,f=/[stwN]/,g=/[LRr]/,h=/[Lb1n]/,i=/[1n]/;return function(c,d){var j="ltr"==d?"L":"R";if(0==c.length||"ltr"==d&&!e.test(c))return!1;for(var k=c.length,l=[],m=0;m<k;++m)l.push(a(
 c.charCodeAt(m)));for(var n=0,o=j;n<k;++n){var q=l[n];"m"==q?l[n]=o:o=q}for(var r=0,s=j;r<k;++r){var t=l[r];"1"==t&&"r"==s?l[r]="n":g.test(t)&&(s=t,"r"==t&&(l[r]="R"))}for(var u=1,v=l[0];u<k-1;++u){var w=l[u];"+"==w&&"1"==v&&"1"==l[u+1]?l[u]="1":","!=w||v!=l[u+1]||"1"!=v&&"n"!=v||(l[u]=v),v=w}for(var x=0;x<k;++x){var y=l[x];if(","==y)l[x]="N";else if("%"==y){var z=void 0;for(z=x+1;z<k&&"%"==l[z];++z);for(var A=x&&"!"==l[x-1]||z<k&&"1"==l[z]?"1":"N",B=x;B<z;++B)l[B]=A;x=z-1}}for(var C=0,D=j;C<k;++C){var E=l[C];"L"==D&&"1"==E?l[C]="L":g.test(E)&&(D=E)}for(var F=0;F<k;++F)if(f.test(l[F])){var G=void 0;for(G=F+1;G<k&&f.test(l[G
 ]);++G);for(var H="L"==(F?l[F-1]:j),I="L"==(G<k?l[G]:j),J=H==I?H?"L":"R":j,K=F;K<G;++K)l[K]=J;F=G-1}for(var L,M=[],N=0;N<k;)if(h.test(l[N])){var O=N;for(++N;N<k&&h.test(l[N]);++N);M.push(new b(0,O,N))}else{var P=N,Q=M.length;for(++N;N<k&&"L"!=l[N];++N);for(var R=P;R<N;)if(i.test(l[R])){P<R&&M.splice(Q,0,new b(1,P,R));var S=R;for(++R;R<N&&i.test(l[R]);++R);M.splice(Q,0,new b(2,S,R)),P=R}else++R;P<N&&M.splice(Q,0,new b(1,P,N))}return 1==M[0].level&&(L=c.match(/^\s+/))&&(M[0].from=L[0].length,M.unshift(new b(0,0,L[0].length))),1==p(M).level&&(L=c.match(/\s+$/))&&(p(M).to-=L[0].length,M.push(new b(0,k-L[0].length,k))),"rtl"==d?M.reverse():M}}(),Xg=[],Yg=function(a,b,c){if(a.addEventListener)a.addEventListener(b,c,!1);else if(a.attachEvent)a.attachEvent("on"+b,c);else{var d=a._handlers||(a._handlers={});d[b]=(d[b]||Xg).co
 ncat(c)}},Zg=function(){if(ng&&og<9)return!1;var a=d("div");return"draggable"in a||"dragDrop"in a}(),$g=3!="\n\nb".split(/\n/).length?function(a){for(var b=0,c=[],d=a.length;b<=d;){var e=a.indexOf("\n",b);e==-1&&(e=a.length);var f=a.slice(b,"\r"==a.charAt(e-1)?e-1:e),g=f.indexOf("\r");g!=-1?(c.push(f.slice(0,g)),b+=g+1):(c.push(f),b=e+1)}return c}:function(a){return a.split(/\r\n?|\n/)},_g=window.getSelection?function(a){try{return a.selectionStart!=a.selectionEnd}catch(b){return!1}}:function(a){var b;try{b=a.ownerDocument.selection.createRange()}catch(c){}return!(!b||b.parentElement()!=a)&&0!=b.compareEndPoints("StartToEnd",b)},ah=function(){var a=d("div");return"oncopy"in a||(a.setAttribute("oncopy","return;"),"function"==typeof a.oncopy)}(),bh=null,ch={},dh={},eh={},fh=function(a,b,c){this.pos=this.start=0,this.string=a,th
 is.tabSize=b||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=c};fh.prototype.eol=function(){return this.pos>=this.string.length},fh.prototype.sol=function(){return this.pos==this.lineStart},fh.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},fh.prototype.next=function(){if(this.pos<this.string.length)return this.string.charAt(this.pos++)},fh.prototype.eat=function(a){var b,c=this.string.charAt(this.pos);if(b="string"==typeof a?c==a:c&&(a.test?a.test(c):a(c)))return++this.pos,c},fh.prototype.eatWhile=function(a){for(var b=this.pos;this.eat(a););return this.pos>b},fh.prototype.eatSpace=function(){for(var a=this,b=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++a.pos;return this.pos>b},fh.prototype.skipToEnd=function(){this.pos=this.string.length},fh.prototype.skipTo=function(a){var b=this.string.indexOf(a,this.pos);if(b>-1)return this.pos=b,!0},fh.prototype.backUp=function(a){this.pos-=a},
 fh.prototype.column=function(){return this.lastColumnPos<this.start&&(this.lastColumnValue=l(this.string,this.start,this.tabSize,this.lastColumnPos,this.lastColumnValue),this.lastColumnPos=this.start),this.lastColumnValue-(this.lineStart?l(this.string,this.lineStart,this.tabSize):0)},fh.prototype.indentation=function(){return l(this.string,null,this.tabSize)-(this.lineStart?l(this.string,this.lineStart,this.tabSize):0)},fh.prototype.match=function(a,b,c){if("string"!=typeof a){var d=this.string.slice(this.pos).match(a);return d&&d.index>0?null:(d&&b!==!1&&(this.pos+=d[0].length),d)}var e=function(a){return c?a.toLowerCase():a},f=this.string.substr(this.pos,a.length);if(e(f)==e(a))return b!==!1&&(this.pos+=a.length),!0},fh.prototype.current=function(){return this.string.slice(this.start,this.pos)},fh.prototype.hideFirstChars=function(a,b){this.lineStart+=a;try{return b()}finally{this.lineStart-=a}},fh.prototype.lookAhead=functio
 n(a){var b=this.lineOracle;return b&&b.lookAhead(a)};var gh=function(a,b){this.state=a,this.lookAhead=b},hh=function(a,b,c,d){this.state=b,this.doc=a,this.line=c,this.maxLookAhead=d||0};hh.prototype.lookAhead=function(a){var b=this.doc.getLine(this.line+a);return null!=b&&a>this.maxLookAhead&&(this.maxLookAhead=a),b},hh.prototype.nextLine=function(){this.line++,this.maxLookAhead>0&&this.maxLookAhead--},hh.fromSaved=function(a,b,c){return b instanceof gh?new hh(a,Xa(a.mode,b.state),c,b.lookAhead):new hh(a,Xa(a.mode,b),c)},hh.prototype.save=function(a){var b=a!==!1?Xa(this.doc.mode,this.state):this.state;return this.maxLookAhead>0?new gh(b,this.maxLookAhead):b};var ih=function(a,b,c){this.start=a.start,this.end=a.pos,this.string=a.current(),this.type=b||null,this.state=c},jh=function(a,b,c){this.text=a,da(this,b),this.height=c?c(this):1};jh.prototype.lineNo=function(){return F(this)},Ia(jh);var kh,lh={},mh={},nh=null,oh=null,ph={left:0,right:0,
 top:0,bottom:0},qh=function(a,b,c){this.cm=c;var e=this.vert=d("div",[d("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),f=this.horiz=d("div",[d("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");a(e),a(f),Yg(e,"scroll",function(){e.clientHeight&&b(e.scrollTop,"vertical")}),Yg(f,"scroll",function(){f.clientWidth&&b(f.scrollLeft,"horizontal")}),this.checkedZeroWidth=!1,ng&&og<8&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")};qh.prototype.update=function(a){var b=a.scrollWidth>a.clientWidth+1,c=a.scrollHeight>a.clientHeight+1,d=a.nativeBarWidth;if(c){this.vert.style.display="block",this.vert.style.bottom=b?d+"px":"0";var e=a.viewHeight-(b?d:0);this.vert.firstChild.style.height=Math.max(0,a.scrollHeight-a.clientHeight+e)+"px"}els
 e this.vert.style.display="",this.vert.firstChild.style.height="0";if(b){this.horiz.style.display="block",this.horiz.style.right=c?d+"px":"0",this.horiz.style.left=a.barLeft+"px";var f=a.viewWidth-a.barLeft-(c?d:0);this.horiz.firstChild.style.width=Math.max(0,a.scrollWidth-a.clientWidth+f)+"px"}else this.horiz.style.display="",this.horiz.firstChild.style.width="0";return!this.checkedZeroWidth&&a.clientHeight>0&&(0==d&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:c?d:0,bottom:b?d:0}},qh.prototype.setScrollLeft=function(a){this.horiz.scrollLeft!=a&&(this.horiz.scrollLeft=a),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,"horiz")},qh.prototype.setScrollTop=function(a){this.vert.scrollTop!=a&&(this.vert.scrollTop=a),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,"vert&qu
 ot;)},qh.prototype.zeroWidthHack=function(){var a=zg&&!ug?"12px":"18px";this.horiz.style.height=this.vert.style.width=a,this.horiz.style.pointerEvents=this.vert.style.pointerEvents="none",this.disableHoriz=new Ig,this.disableVert=new Ig},qh.prototype.enableZeroWidthBar=function(a,b,c){function d(){var e=a.getBoundingClientRect(),f="vert"==c?document.elementFromPoint(e.right-1,(e.top+e.bottom)/2):document.elementFromPoint((e.right+e.left)/2,e.bottom-1);f!=a?a.style.pointerEvents="none":b.set(1e3,d)}a.style.pointerEvents="auto",b.set(1e3,d)},qh.prototype.clear=function(){var a=this.horiz.parentNode;a.removeChild(this.horiz),a.removeChild(this.vert)};var rh=function(){};rh.prototype.update=function(){return{bottom:0,right:0}},rh.prototype.setScrollLeft=function(){},rh.prototype.setScrollTop=function(){},rh.prototype.clear=function(){};var sh={"native":qh,"null":rh},th=0,uh=function(a,b,c){var d=a.di
 splay;this.viewport=b,this.visible=Mc(d,a.doc,b),this.editorIsHidden=!d.wrapper.offsetWidth,this.wrapperHeight=d.wrapper.clientHeight,this.wrapperWidth=d.wrapper.clientWidth,this.oldDisplayWidth=Sb(a),this.force=c,this.dims=uc(a),this.events=[]};uh.prototype.signal=function(a,b){Ha(a,b)&&this.events.push(arguments)},uh.prototype.finish=function(){for(var a=this,b=0;b<this.events.length;b++)Ea.apply(null,a.events[b])};var vh=0,wh=null;ng?wh=-.53:jg?wh=15:rg?wh=-.7:tg&&(wh=-1/3);var xh=function(a,b){this.ranges=a,this.primIndex=b};xh.prototype.primary=function(){return this.ranges[this.primIndex]},xh.prototype.equals=function(a){var b=this;if(a==this)return!0;if(a.primIndex!=this.primIndex||a.ranges.length!=this.ranges.length)return!1;for(var c=0;c<this.ranges.length;c++){var d=b.ranges[c],e=a.ranges[c];if(!L(d.anchor,e.anchor)||!L(d.head,e.head))return!1}return!0},xh.prototype.deepCopy=function(){for(var a=this,b=[],c=0;c<this.ranges.length;c++)b[c]=new yh(M(
 a.ranges[c].anchor),M(a.ranges[c].head));return new xh(b,this.primIndex)},xh.prototype.somethingSelected=function(){for(var a=this,b=0;b<this.ranges.length;b++)if(!a.ranges[b].empty())return!0;return!1},xh.prototype.contains=function(a,b){var c=this;b||(b=a);for(var d=0;d<this.ranges.length;d++){var e=c.ranges[d];if(K(b,e.from())>=0&&K(a,e.to())<=0)return d}return-1};var yh=function(a,b){this.anchor=a,this.head=b};yh.prototype.from=function(){return O(this.anchor,this.head)},yh.prototype.to=function(){return N(this.anchor,this.head)},yh.prototype.empty=function(){return this.head.line==this.anchor.line&&this.head.ch==this.anchor.ch},Oe.prototype={chunkSize:function(){return this.lines.length},removeInner:function(a,b){for(var c=this,d=a,e=a+b;d<e;++d){var f=c.lines[d];c.height-=f.height,kb(f),yb(f,"delete")}this.lines.splice(a,b)},collapse:function(a){a.push.apply(a,this.lines)},insertInner:function(a,b,c){var d=this;this.height+=c,this.lines
 =this.lines.slice(0,a).concat(b).concat(this.lines.slice(a));for(var e=0;e<b.length;++e)b[e].parent=d},iterN:function(a,b,c){for(var d=this,e=a+b;a<e;++a)if(c(d.lines[a]))return!0}},Pe.prototype={chunkSize:function(){return this.size},removeInner:function(a,b){var c=this;this.size-=b;for(var d=0;d<this.children.length;++d){var e=c.children[d],f=e.chunkSize();if(a<f){var g=Math.min(b,f-a),h=e.height;if(e.removeInner(a,g),c.height-=h-e.height,f==g&&(c.children.splice(d--,1),e.parent=null),0==(b-=g))break;a=0}else a-=f}if(this.size-b<25&&(this.children.length>1||!(this.children[0]instanceof Oe))){var i=[];this.collapse(i),this.children=[new Oe(i)],this.children[0].parent=this}},collapse:function(a){for(var b=this,c=0;c<this.children.length;++c)b.children[c].collapse(a)},insertInner:function(a,b,c){var d=this;this.size+=b.length,this.height+=c;for(var e=0;e<this.children.length;++e){var f=d.children[e],g=f.chunkSize();if(a<=g){if(f.insertInner(
 a,b,c),f.lines&&f.lines.length>50){for(var h=f.lines.length%25+25,i=h;i<f.lines.length;){var j=new Oe(f.lines.slice(i,i+=25));f.height-=j.height,d.children.splice(++e,0,j),j.parent=d}f.lines=f.lines.slice(0,h),d.maybeSpill()}break}a-=g}},maybeSpill:function(){if(!(this.children.length<=10)){var a=this;do{var b=a.children.splice(a.children.length-5,5),c=new Pe(b);if(a.parent){a.size-=c.size,a.height-=c.height;var d=m(a.parent.children,a);a.parent.children.splice(d+1,0,c)}else{var e=new Pe(a.children);e.parent=a,a.children=[e,c],a=e}c.parent=a.parent}while(a.children.length>10);a.parent.maybeSpill()}},iterN:function(a,b,c){for(var d=this,e=0;e<this.children.length;++e){var f=d.children[e],g=f.chunkSize();if(a<g){var h=Math.min(b,g-a);if(f.iterN(a,h,c))return!0;if(0==(b-=h))break;a=0}else a-=g}}};var zh=function(a,b,c){var d=this;if(c)for(var e in c)c.hasOwnProperty(e)&&(d[e]=c[e]);this.doc=a,this.node=b};zh.prototype.clear=function(){var a=this,b=this
 .doc.cm,c=this.line.widgets,d=this.line,e=F(d);if(null!=e&&c){for(var f=0;f<c.length;++f)c[f]==a&&c.splice(f--,1);c.length||(d.widgets=null);var g=Mb(this);E(d,Math.max(0,d.height-g)),b&&(md(b,function(){Qe(b,d,-g),rd(b,e,"widget")}),yb(b,"lineWidgetCleared",b,this,e))}},zh.prototype.changed=function(){var a=this,b=this.height,c=this.doc.cm,d=this.line;this.height=null;var e=Mb(this)-b;e&&(E(d,d.height+e),c&&md(c,function(){c.curOp.forceUpdate=!0,Qe(c,d,e),yb(c,"lineWidgetChanged",c,a,F(d))}))},Ia(zh);var Ah=0,Bh=function(a,b){this.lines=[],this.type=b,this.doc=a,this.id=++Ah};Bh.prototype.clear=function(){var a=this;if(!this.explicitlyCleared){var b=this.doc.cm,c=b&&!b.curOp;if(c&&ed(b),Ha(this,"clear")){var d=this.find();d&&yb(this,"clear",d.from,d.to)}for(var e=null,f=null,g=0;g<this.lines.length;++g){var h=a.lines[g],i=W(h.markedSpans,a);b&&!a.collapsed
 ?rd(b,F(h),"text"):b&&(null!=i.to&&(f=F(h)),null!=i.from&&(e=F(h))),h.markedSpans=X(h.markedSpans,i),null==i.from&&a.collapsed&&!qa(a.doc,h)&&b&&E(h,sc(b.display))}if(b&&this.collapsed&&!b.options.lineWrapping)for(var j=0;j<this.lines.length;++j){var k=la(a.lines[j]),l=ta(k);l>b.display.maxLineLength&&(b.display.maxLine=k,b.display.maxLineLength=l,b.display.maxLineChanged=!0)}null!=e&&b&&this.collapsed&&qd(b,e,f+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,b&&we(b.doc)),b&&yb(b,"markerCleared",b,this,e,f),c&&fd(b),this.parent&&this.parent.clear()}},Bh.prototype.find=function(a,b){var c=this;null==a&&"bookmark"==this.type&&(a=1);for(var d,e,f=0;f<this.lines.length;++f){var g=c.lines[f],h=W(g.markedSpans,c);if(null!=h.from&a
 mp;&(d=J(b?g:F(g),h.from),a==-1))return d;if(null!=h.to&&(e=J(b?g:F(g),h.to),1==a))return e}return d&&{from:d,to:e}},Bh.prototype.changed=function(){var a=this,b=this.find(-1,!0),c=this,d=this.doc.cm;b&&d&&md(d,function(){var e=b.line,f=F(b.line),g=Yb(d,f);if(g&&(dc(g),d.curOp.selectionChanged=d.curOp.forceUpdate=!0),d.curOp.updateMaxLine=!0,!qa(c.doc,e)&&null!=c.height){var h=c.height;c.height=null;var i=Mb(c)-h;i&&E(e,e.height+i)}yb(d,"markerChanged",d,a)})},Bh.prototype.attachLine=function(a){if(!this.lines.length&&this.doc.cm){var b=this.doc.cm.curOp;b.maybeHiddenMarkers&&m(b.maybeHiddenMarkers,this)!=-1||(b.maybeUnhiddenMarkers||(b.maybeUnhiddenMarkers=[])).push(this)}this.lines.push(a)},Bh.prototype.detachLine=function(a){if(this.lines.splice(m(this.lines,a),1),!this.lines.length&&this.doc.cm){var b=this.doc.cm.curOp;(b.maybeHiddenMarkers||(b.maybeHiddenMarkers=[])).push(this)}},Ia(Bh
 );var Ch=function(a,b){var c=this;this.markers=a,this.primary=b;for(var d=0;d<a.length;++d)a[d].parent=c};Ch.prototype.clear=function(){var a=this;if(!this.explicitlyCleared){this.explicitlyCleared=!0;for(var b=0;b<this.markers.length;++b)a.markers[b].clear();yb(this,"clear")}},Ch.prototype.find=function(a,b){return this.primary.find(a,b)},Ia(Ch);var Dh=0,Eh=function(a,b,c,d,e){if(!(this instanceof Eh))return new Eh(a,b,c,d,e);null==c&&(c=0),Pe.call(this,[new Oe([new jh("",null)])]),this.first=c,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.cleanGeneration=1,this.modeFrontier=this.highlightFrontier=c;var f=J(c,0);this.sel=Nd(f),this.history=new _d(null),this.id=++Dh,this.modeOption=b,this.lineSep=d,this.direction="rtl"==e?"rtl":"ltr",this.extend=!1,"string"==typeof a&&(a=this.splitLines(a)),Wd(this,{from:f,to:f,text:a}),te(this,Nd(f),Ng)};Eh.prototype=t(Pe.prototype,{constructor:Eh,iter:functi
 on(a,b,c){c?this.iterN(a-this.first,b-a,c):this.iterN(this.first,this.first+this.size,a)},insert:function(a,b){for(var c=0,d=0;d<b.length;++d)c+=b[d].height;this.insertInner(a-this.first,b,c)},remove:function(a,b){this.removeInner(a-this.first,b)},getValue:function(a){var b=D(this,this.first,this.first+this.size);return a===!1?b:b.join(a||this.lineSeparator())},setValue:pd(function(a){var b=J(this.first,0),c=this.first+this.size-1;De(this,{from:b,to:J(c,B(this,c).text.length),text:this.splitLines(a),origin:"setValue",full:!0},!0),this.cm&&Vc(this.cm,0,0),te(this,Nd(b),Ng)}),replaceRange:function(a,b,c,d){b=Q(this,b),c=c?Q(this,c):b,Je(this,a,b,c,d)},getRange:function(a,b,c){var d=C(this,Q(this,a),Q(this,b));return c===!1?d:d.join(c||this.lineSeparator())},getLine:function(a){var b=this.getLineHandle(a);return b&&b.text},getLineHandle:function(a){if(H(this,a))return B(this,a)},getLineNumber:function(a){return F(a)},getLineHandleVisualStart:function(a){ret
 urn"number"==typeof a&&(a=B(this,a)),la(a)},lineCount:function(){return this.size},firstLine:function(){return this.first},lastLine:function(){return this.first+this.size-1},clipPos:function(a){return Q(this,a)},getCursor:function(a){var b,c=this.sel.primary();return b=null==a||"head"==a?c.head:"anchor"==a?c.anchor:"end"==a||"to"==a||a===!1?c.to():c.from()},listSelections:function(){return this.sel.ranges},somethingSelected:function(){return this.sel.somethingSelected()},setCursor:pd(function(a,b,c){qe(this,Q(this,"number"==typeof a?J(a,b||0):a),null,c)}),setSelection:pd(function(a,b,c){qe(this,Q(this,a),Q(this,b||a),c)}),extendSelection:pd(function(a,b,c){ne(this,Q(this,a),b&&Q(this,b),c)}),extendSelections:pd(function(a,b){oe(this,S(this,a),b)}),extendSelectionsBy:pd(function(a,b){var c=q(this.sel.ranges,a);oe(this,S(this,c),b)}),setSelections:pd(function(a,b,c){var d=this;if(a.length){for(var e=[],f=0;f&l
 t;a.length;f++)e[f]=new yh(Q(d,a[f].anchor),Q(d,a[f].head));null==b&&(b=Math.min(a.length-1,this.sel.primIndex)),te(this,Md(e,b),c)}}),addSelection:pd(function(a,b,c){var d=this.sel.ranges.slice(0);d.push(new yh(Q(this,a),Q(this,b||a))),te(this,Md(d,d.length-1),c)}),getSelection:function(a){for(var b,c=this,d=this.sel.ranges,e=0;e<d.length;e++){var f=C(c,d[e].from(),d[e].to());b=b?b.concat(f):f}return a===!1?b:b.join(a||this.lineSeparator())},getSelections:function(a){for(var b=this,c=[],d=this.sel.ranges,e=0;e<d.length;e++){var f=C(b,d[e].from(),d[e].to());a!==!1&&(f=f.join(a||b.lineSeparator())),c[e]=f}return c},replaceSelection:function(a,b,c){for(var d=[],e=0;e<this.sel.ranges.length;e++)d[e]=a;this.replaceSelections(d,b,c||"+input")},replaceSelections:pd(function(a,b,c){for(var d=this,e=[],f=this.sel,g=0;g<f.ranges.length;g++){var h=f.ranges[g];e[g]={from:h.from(),to:h.to(),text:d.splitLines(a[g]),origin:c}}for(var i=b&&"end&qu
 ot;!=b&&Sd(this,e,b),j=e.length-1;j>=0;j--)De(d,e[j]);i?se(this,i):this.cm&&Uc(this.cm)}),undo:pd(function(){Fe(this,"undo")}),redo:pd(function(){Fe(this,"redo")}),undoSelection:pd(function(){Fe(this,"undo",!0)}),redoSelection:pd(function(){Fe(this,"redo",!0)}),setExtending:function(a){this.extend=a},getExtending:function(){return this.extend},historySize:function(){for(var a=this.history,b=0,c=0,d=0;d<a.done.length;d++)a.done[d].ranges||++b;for(var e=0;e<a.undone.length;e++)a.undone[e].ranges||++c;return{undo:b,redo:c}},clearHistory:function(){this.history=new _d(this.history.maxGeneration)},markClean:function(){this.cleanGeneration=this.changeGeneration(!0)},changeGeneration:function(a){return a&&(this.history.lastOp=this.history.lastSelOp=this.history.lastOrigin=null),this.history.generation},isClean:function(a){return this.history.generation==(a||this.cleanGeneration)},getHistory:function(){return{done:le(t
 his.history.done),undone:le(this.history.undone)}},setHistory:function(a){var b=this.history=new _d(this.history.maxGeneration);b.done=le(a.done.slice(0),null,!0),b.undone=le(a.undone.slice(0),null,!0)},setGutterMarker:pd(function(a,b,c){return Ne(this,a,"gutter",function(a){var d=a.gutterMarkers||(a.gutterMarkers={});return d[b]=c,!c&&w(d)&&(a.gutterMarkers=null),!0})}),clearGutter:pd(function(a){var b=this;this.iter(function(c){c.gutterMarkers&&c.gutterMarkers[a]&&Ne(b,c,"gutter",function(){return c.gutterMarkers[a]=null,w(c.gutterMarkers)&&(c.gutterMarkers=null),!0})})}),lineInfo:function(a){var b;if("number"==typeof a){if(!H(this,a))return null;if(b=a,a=B(this,a),!a)return null}else if(b=F(a),null==b)return null;return{line:b,handle:a,text:a.text,gutterMarkers:a.gutterMarkers,textClass:a.textClass,bgClass:a.bgClass,wrapClass:a.wrapClass,widgets:a.widgets}},addLineClass:pd(function(b,c,d){return Ne(this,b,&quot
 ;gutter"==c?"gutter":"class",function(b){var e="text"==c?"textClass":"background"==c?"bgClass":"gutter"==c?"gutterClass":"wrapClass";if(b[e]){if(a(d).test(b[e]))return!1;b[e]+=" "+d}else b[e]=d;return!0})}),removeLineClass:pd(function(b,c,d){return Ne(this,b,"gutter"==c?"gutter":"class",function(b){var e="text"==c?"textClass":"background"==c?"bgClass":"gutter"==c?"gutterClass":"wrapClass",f=b[e];if(!f)return!1;if(null==d)b[e]=null;else{var g=f.match(a(d));if(!g)return!1;var h=g.index+g[0].length;b[e]=f.slice(0,g.index)+(g.index&&h!=f.length?" ":"")+f.slice(h)||null}return!0})}),addLineWidget:pd(function(a,b,c){return Re(this,a,b,c)}),removeLineWidget:function(a){a.clear()},markText:function(a,b,c){return Se(this,Q(this,a),Q(this,b),c,c&&c.type||&
 quot;range")},setBookmark:function(a,b){var c={replacedWith:b&&(null==b.nodeType?b.widget:b),insertLeft:b&&b.insertLeft,clearWhenEmpty:!1,shared:b&&b.shared,handleMouseEvents:b&&b.handleMouseEvents};return a=Q(this,a),Se(this,a,a,c,"bookmark")},findMarksAt:function(a){a=Q(this,a);var b=[],c=B(this,a.line).markedSpans;if(c)for(var d=0;d<c.length;++d){var e=c[d];(null==e.from||e.from<=a.ch)&&(null==e.to||e.to>=a.ch)&&b.push(e.marker.parent||e.marker)}return b},findMarks:function(a,b,c){a=Q(this,a),b=Q(this,b);var d=[],e=a.line;return this.iter(a.line,b.line+1,function(f){var g=f.markedSpans;if(g)for(var h=0;h<g.length;h++){var i=g[h];null!=i.to&&e==a.line&&a.ch>=i.to||null==i.from&&e!=a.line||null!=i.from&&e==b.line&&i.from>=b.ch||c&&!c(i.marker)||d.push(i.marker.parent||i.marker)}++e}),d},getAllMarks:function(){var a=[];return this.iter(function(b){var c=b.
 markedSpans;if(c)for(var d=0;d<c.length;++d)null!=c[d].from&&a.push(c[d].marker)}),a},posFromIndex:function(a){var b,c=this.first,d=this.lineSeparator().length;return this.iter(function(e){var f=e.text.length+d;return f>a?(b=a,!0):(a-=f,void++c)}),Q(this,J(c,b))},indexFromPos:function(a){a=Q(this,a);var b=a.ch;if(a.line<this.first||a.ch<0)return 0;var c=this.lineSeparator().length;return this.iter(this.first,a.line,function(a){b+=a.text.length+c}),b},copy:function(a){var b=new Eh(D(this,this.first,this.first+this.size),this.modeOption,this.first,this.lineSep,this.direction);return b.scrollTop=this.scrollTop,b.scrollLeft=this.scrollLeft,b.sel=this.sel,b.extend=!1,a&&(b.history.undoDepth=this.history.undoDepth,b.setHistory(this.getHistory())),b},linkedDoc:function(a){a||(a={});var b=this.first,c=this.first+this.size;null!=a.from&&a.from>b&&(b=a.from),null!=a.to&&a.to<c&&(c=a.to);var d=new Eh(D(this,b,c),a.mode||this.mod
 eOption,b,this.lineSep,this.direction);return a.sharedHist&&(d.history=this.history),(this.linked||(this.linked=[])).push({doc:d,sharedHist:a.sharedHist}),d.linked=[{doc:this,isParent:!0,sharedHist:a.sharedHist}],Ve(d,Ue(this)),d},unlinkDoc:function(a){var b=this;if(a instanceof Pf&&(a=a.doc),this.linked)for(var c=0;c<this.linked.length;++c){var d=b.linked[c];if(d.doc==a){b.linked.splice(c,1),a.unlinkDoc(b),We(Ue(b));break}}if(a.history==this.history){var e=[a.id];Xd(a,function(a){return e.push(a.id)},!0),a.history=new _d(null),a.history.done=le(this.history.done,e),a.history.undone=le(this.history.undone,e)}},iterLinkedDocs:function(a){Xd(this,a)},getMode:function(){return this.mode},getEditor:function(){return this.cm},splitLines:function(a){return this.lineSep?a.split(this.lineSep):$g(a)},lineSeparator:function(){return this.lineSep||"\n"},setDirection:pd(function(a){"rtl"!=a&&(a="ltr"),a!=this.direction&&(this.dire
 ction=a,this.iter(function(a){return a.order=null}),this.cm&&$d(this.cm))})}),Eh.prototype.eachLine=Eh.prototype.iter;for(var Fh=0,Gh=!1,Hh={3:"Enter",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",61:"=",91:"Mod",92:"Mod",93:"Mod",106:"*",107:"=",109:"-",110:".",111:"/",127:"Delete",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",22
 1:"]",222:"'",63232:"Up",63233:"Down",63234:"Left",63235:"Right",63272:"Delete",63273:"Home",63275:"End",63276:"PageUp",63277:"PageDown",63302:"Insert"},Ih=0;Ih<10;Ih++)Hh[Ih+48]=Hh[Ih+96]=String(Ih);for(var Jh=65;Jh<=90;Jh++)Hh[Jh]=String.fromCharCode(Jh);for(var Kh=1;Kh<=12;Kh++)Hh[Kh+111]=Hh[Kh+63235]="F"+Kh;var Lh={};Lh.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"
 },Lh.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indent
 More","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},Lh.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Alt-F":"goWordRight","Alt-B":"goWordLeft","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-D":"delWordAfter","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars","Ctrl-O":"openLine"},Lh.macDefault={"Cmd-A":"selectAll","Cmd-D&quot
 ;:"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace&qu
 ot;:"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},Lh["default"]=zg?Lh.macDefault:Lh.pcDefault;var Mh={selectAll:Be,singleSelection:function(a){return a.setSelection(a.getCursor("anchor"),a.getCursor("head"),Ng)},killLine:function(a){return lf(a,function(b){if(b.empty()){var c=B(a.doc,b.head.line).text.length;
+return b.head.ch==c&&b.head.line<a.lastLine()?{from:b.head,to:J(b.head.line+1,0)}:{from:b.head,to:J(b.head.line,c)}}return{from:b.from(),to:b.to()}})},deleteLine:function(a){return lf(a,function(b){return{from:J(b.from().line,0),to:Q(a.doc,J(b.to().line+1,0))}})},delLineLeft:function(a){return lf(a,function(a){return{from:J(a.from().line,0),to:a.from()}})},delWrappedLineLeft:function(a){return lf(a,function(b){var c=a.charCoords(b.head,"div").top+5,d=a.coordsChar({left:0,top:c},"div");return{from:d,to:b.from()}})},delWrappedLineRight:function(a){return lf(a,function(b){var c=a.charCoords(b.head,"div").top+5,d=a.coordsChar({left:a.display.lineDiv.offsetWidth+100,top:c},"div");return{from:b.from(),to:d}})},undo:function(a){return a.undo()},redo:function(a){return a.redo()},undoSelection:function(a){return a.undoSelection()},redoSelection:function(a){return a.redoSelection()},goDocStart:function(a){return a.extendSelection(J(a.firstLin
 e(),0))},goDocEnd:function(a){return a.extendSelection(J(a.lastLine()))},goLineStart:function(a){return a.extendSelectionsBy(function(b){return mf(a,b.head.line)},{origin:"+move",bias:1})},goLineStartSmart:function(a){return a.extendSelectionsBy(function(b){return of(a,b.head)},{origin:"+move",bias:1})},goLineEnd:function(a){return a.extendSelectionsBy(function(b){return nf(a,b.head.line)},{origin:"+move",bias:-1})},goLineRight:function(a){return a.extendSelectionsBy(function(b){var c=a.cursorCoords(b.head,"div").top+5;return a.coordsChar({left:a.display.lineDiv.offsetWidth+100,top:c},"div")},Pg)},goLineLeft:function(a){return a.extendSelectionsBy(function(b){var c=a.cursorCoords(b.head,"div").top+5;return a.coordsChar({left:0,top:c},"div")},Pg)},goLineLeftSmart:function(a){return a.extendSelectionsBy(function(b){var c=a.cursorCoords(b.head,"div").top+5,d=a.coordsChar({left:0,top:c},"div");retu
 rn d.ch<a.getLine(d.line).search(/\S/)?of(a,b.head):d},Pg)},goLineUp:function(a){return a.moveV(-1,"line")},goLineDown:function(a){return a.moveV(1,"line")},goPageUp:function(a){return a.moveV(-1,"page")},goPageDown:function(a){return a.moveV(1,"page")},goCharLeft:function(a){return a.moveH(-1,"char")},goCharRight:function(a){return a.moveH(1,"char")},goColumnLeft:function(a){return a.moveH(-1,"column")},goColumnRight:function(a){return a.moveH(1,"column")},goWordLeft:function(a){return a.moveH(-1,"word")},goGroupRight:function(a){return a.moveH(1,"group")},goGroupLeft:function(a){return a.moveH(-1,"group")},goWordRight:function(a){return a.moveH(1,"word")},delCharBefore:function(a){return a.deleteH(-1,"char")},delCharAfter:function(a){return a.deleteH(1,"char")},delWordBefore:function(a){return a.deleteH(-1,"word")},delWordAfter:fu
 nction(a){return a.deleteH(1,"word")},delGroupBefore:function(a){return a.deleteH(-1,"group")},delGroupAfter:function(a){return a.deleteH(1,"group")},indentAuto:function(a){return a.indentSelection("smart")},indentMore:function(a){return a.indentSelection("add")},indentLess:function(a){return a.indentSelection("subtract")},insertTab:function(a){return a.replaceSelection("\t")},insertSoftTab:function(a){for(var b=[],c=a.listSelections(),d=a.options.tabSize,e=0;e<c.length;e++){var f=c[e].from(),g=l(a.getLine(f.line),f.ch,d);b.push(o(d-g%d))}a.replaceSelections(b)},defaultTab:function(a){a.somethingSelected()?a.indentSelection("add"):a.execCommand("insertTab")},transposeChars:function(a){return md(a,function(){for(var b=a.listSelections(),c=[],d=0;d<b.length;d++)if(b[d].empty()){var e=b[d].head,f=B(a.doc,e.line).text;if(f)if(e.ch==f.length&&(e=new J(e.line,e.ch-1)),e.ch>0)e=new J(
 e.line,e.ch+1),a.replaceRange(f.charAt(e.ch-1)+f.charAt(e.ch-2),J(e.line,e.ch-2),e,"+transpose");else if(e.line>a.doc.first){var g=B(a.doc,e.line-1).text;g&&(e=new J(e.line,1),a.replaceRange(f.charAt(0)+a.doc.lineSeparator()+g.charAt(g.length-1),J(e.line-1,g.length-1),e,"+transpose"))}c.push(new yh(e,e))}a.setSelections(c)})},newlineAndIndent:function(a){return md(a,function(){for(var b=a.listSelections(),c=b.length-1;c>=0;c--)a.replaceRange(a.doc.lineSeparator(),b[c].anchor,b[c].head,"+input");b=a.listSelections();for(var d=0;d<b.length;d++)a.indentLine(b[d].from().line,null,!0);Uc(a)})},openLine:function(a){return a.replaceSelection("\n","start")},toggleOverwrite:function(a){return a.toggleOverwrite()}},Nh=new Ig,Oh=null,Ph=400,Qh=function(a,b,c){this.time=a,this.pos=b,this.button=c};Qh.prototype.compare=function(a,b,c){return this.time+Ph>a&&0==K(b,this.pos)&&c==this.button};var Rh,Sh,Th={toStri
 ng:function(){return"CodeMirror.Init"}},Uh={},Vh={};Pf.defaults=Uh,Pf.optionHandlers=Vh;var Wh=[];Pf.defineInitHook=function(a){return Wh.push(a)};var Xh=null,Yh=function(a){var b=a.optionHandlers,c=a.helpers={};a.prototype={constructor:a,focus:function(){window.focus(),this.display.input.focus()},setOption:function(a,c){var d=this.options,e=d[a];d[a]==c&&"mode"!=a||(d[a]=c,b.hasOwnProperty(a)&&nd(this,b[a])(this,c,e),Ea(this,"optionChange",this,a))},getOption:function(a){return this.options[a]},getDoc:function(){return this.doc},addKeyMap:function(a,b){this.state.keyMaps[b?"push":"unshift"](kf(a))},removeKeyMap:function(a){for(var b=this.state.keyMaps,c=0;c<b.length;++c)if(b[c]==a||b[c].name==a)return b.splice(c,1),!0},addOverlay:od(function(b,c){var d=b.token?b:a.getMode(this.options,b);if(d.startState)throw new Error("Overlays may not be stateful.");r(this.state.overlays,{mode:d,modeSpec:b,opaque:c&amp
 ;&c.opaque,priority:c&&c.priority||0},function(a){return a.priority}),this.state.modeGen++,qd(this)}),removeOverlay:od(function(a){for(var b=this,c=this.state.overlays,d=0;d<c.length;++d){var e=c[d].modeSpec;if(e==a||"string"==typeof a&&e.name==a)return c.splice(d,1),b.state.modeGen++,void qd(b)}}),indentLine:od(function(a,b,c){"string"!=typeof b&&"number"!=typeof b&&(b=null==b?this.options.smartIndent?"smart":"prev":b?"add":"subtract"),H(this.doc,a)&&Rf(this,a,b,c)}),indentSelection:od(function(a){for(var b=this,c=this.doc.sel.ranges,d=-1,e=0;e<c.length;e++){var f=c[e];if(f.empty())f.head.line>d&&(Rf(b,f.head.line,a,!0),d=f.head.line,e==b.doc.sel.primIndex&&Uc(b));else{var g=f.from(),h=f.to(),i=Math.max(d,g.line);d=Math.min(b.lastLine(),h.line-(h.ch?0:1))+1;for(var j=i;j<d;++j)Rf(b,j,a);var k=b.doc.sel.ranges;0==g.ch&&c.length==k.leng
 th&&k[e].from().ch>0&&pe(b.doc,e,new yh(g,k[e].to()),Ng)}}}),getTokenAt:function(a,b){return eb(this,a,b)},getLineTokens:function(a,b){return eb(this,J(a),b,!0)},getTokenTypeAt:function(a){a=Q(this.doc,a);var b,c=_a(this,B(this.doc,a.line)),d=0,e=(c.length-1)/2,f=a.ch;if(0==f)b=c[2];else for(;;){var g=d+e>>1;if((g?c[2*g-1]:0)>=f)e=g;else{if(!(c[2*g+1]<f)){b=c[2*g+2];break}d=g+1}}var h=b?b.indexOf("overlay "):-1;return h<0?b:0==h?null:b.slice(0,h-1)},getModeAt:function(b){var c=this.doc.mode;return c.innerMode?a.innerMode(c,this.getTokenAt(b).state).mode:c},getHelper:function(a,b){return this.getHelpers(a,b)[0]},getHelpers:function(a,b){var d=this,e=[];if(!c.hasOwnProperty(b))return e;var f=c[b],g=this.getModeAt(a);if("string"==typeof g[b])f[g[b]]&&e.push(f[g[b]]);else if(g[b])for(var h=0;h<g[b].length;h++){var i=f[g[b][h]];i&&e.push(i)}else g.helperType&&f[g.helperType]?e.push(f[g.helperType]):f[g.name]
 &&e.push(f[g.name]);for(var j=0;j<f._global.length;j++){var k=f._global[j];k.pred(g,d)&&m(e,k.val)==-1&&e.push(k.val)}return e},getStateAfter:function(a,b){var c=this.doc;return a=P(c,null==a?c.first+c.size-1:a),ab(this,a+1,b).state},cursorCoords:function(a,b){var c,d=this.doc.sel.primary();return c=null==a?d.head:"object"==typeof a?Q(this.doc,a):a?d.from():d.to(),lc(this,c,b||"page")},charCoords:function(a,b){return kc(this,Q(this.doc,a),b||"page")},coordsChar:function(a,b){return a=jc(this,a,b||"page"),oc(this,a.left,a.top)},lineAtHeight:function(a,b){return a=jc(this,{top:a,left:0},b||"page").top,G(this.doc,a+this.display.viewOffset)},heightAtLine:function(a,b,c){var d,e=!1;if("number"==typeof a){var f=this.doc.first+this.doc.size-1;a<this.doc.first?a=this.doc.first:a>f&&(a=f,e=!0),d=B(this.doc,a)}else d=a;return ic(this,d,{top:0,left:0},b||"page",c||e).top+(e?this.doc.h
 eight-sa(d):0)},defaultTextHeight:function(){return sc(this.display)},defaultCharWidth:function(){return tc(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(a,b,c,d,e){var f=this.display;a=lc(this,Q(this.doc,a));var g=a.bottom,h=a.left;if(b.style.position="absolute",b.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(b),f.sizer.appendChild(b),"over"==d)g=a.top;else if("above"==d||"near"==d){var i=Math.max(f.wrapper.clientHeight,this.doc.height),j=Math.max(f.sizer.clientWidth,f.lineSpace.clientWidth);("above"==d||a.bottom+b.offsetHeight>i)&&a.top>b.offsetHeight?g=a.top-b.offsetHeight:a.bottom+b.offsetHeight<=i&&(g=a.bottom),h+b.offsetWidth>j&&(h=j-b.offsetWidth)}b.style.top=g+"px",b.style.left=b.style.right="","right"==e?(h=f.sizer.clientWidth-b.offsetWidth,b.st
 yle.right="0px"):("left"==e?h=0:"middle"==e&&(h=(f.sizer.clientWidth-b.offsetWidth)/2),b.style.left=h+"px"),c&&Rc(this,{left:h,top:g,right:h+b.offsetWidth,bottom:g+b.offsetHeight})},triggerOnKeyDown:od(uf),triggerOnKeyPress:od(xf),triggerOnKeyUp:wf,triggerOnMouseDown:od(zf),execCommand:function(a){if(Mh.hasOwnProperty(a))return Mh[a].call(null,this)},triggerElectric:od(function(a){Vf(this,a)}),findPosH:function(a,b,c,d){var e=this,f=1;b<0&&(f=-1,b=-b);for(var g=Q(this.doc,a),h=0;h<b&&(g=Zf(e.doc,g,f,c,d),!g.hitSide);++h);return g},moveH:od(function(a,b){var c=this;this.extendSelectionsBy(function(d){return c.display.shift||c.doc.extend||d.empty()?Zf(c.doc,d.head,a,b,c.options.rtlMoveVisually):a<0?d.from():d.to()},Pg)}),deleteH:od(function(a,b){var c=this.doc.sel,d=this.doc;c.somethingSelected()?d.replaceSelection("",null,"+delete"):lf(this,function(c){var e=Zf(d,c.head,a,b,!1);return
  a<0?{from:e,to:c.head}:{from:c.head,to:e}})}),findPosV:function(a,b,c,d){var e=this,f=1,g=d;b<0&&(f=-1,b=-b);for(var h=Q(this.doc,a),i=0;i<b;++i){var j=lc(e,h,"div");if(null==g?g=j.left:j.left=g,h=$f(e,j,f,c),h.hitSide)break}return h},moveV:od(function(a,b){var c=this,d=this.doc,e=[],f=!this.display.shift&&!d.extend&&d.sel.somethingSelected();if(d.extendSelectionsBy(function(g){if(f)return a<0?g.from():g.to();var h=lc(c,g.head,"div");null!=g.goalColumn&&(h.left=g.goalColumn),e.push(h.left);var i=$f(c,h,a,b);return"page"==b&&g==d.sel.primary()&&Tc(c,kc(c,i,"div").top-h.top),i},Pg),e.length)for(var g=0;g<d.sel.ranges.length;g++)d.sel.ranges[g].goalColumn=e[g]}),findWordAt:function(a){var b=this.doc,c=B(b,a.line).text,d=a.ch,e=a.ch;if(c){var f=this.getHelper(a,"wordChars");"before"!=a.sticky&&e!=c.length||!d?++e:--d;for(var g=c.charAt(d),h=v(g,f)?function(
 a){return v(a,f)}:/\s/.test(g)?function(a){return/\s/.test(a)}:function(a){return!/\s/.test(a)&&!v(a)};d>0&&h(c.charAt(d-1));)--d;for(;e<c.length&&h(c.charAt(e));)++e}return new yh(J(a.line,d),J(a.line,e))},toggleOverwrite:function(a){null!=a&&a==this.state.overwrite||((this.state.overwrite=!this.state.overwrite)?h(this.display.cursorDiv,"CodeMirror-overwrite"):Gg(this.display.cursorDiv,"CodeMirror-overwrite"),Ea(this,"overwriteToggle",this,this.state.overwrite))},hasFocus:function(){return this.display.input.getField()==g()},isReadOnly:function(){return!(!this.options.readOnly&&!this.doc.cantEdit)},scrollTo:od(function(a,b){Vc(this,a,b)}),getScrollInfo:function(){var a=this.display.scroller;return{left:a.scrollLeft,top:a.scrollTop,height:a.scrollHeight-Rb(this)-this.display.barHeight,width:a.scrollWidth-Rb(this)-this.display.barWidth,clientHeight:Tb(this),clientWidth:Sb(this)}},scrollIntoView:od(function(a,
 b){null==a?(a={from:this.doc.sel.primary().head,to:null},null==b&&(b=this.options.cursorScrollMargin)):"number"==typeof a?a={from:J(a,0),to:null}:null==a.from&&(a={from:a,to:null}),a.to||(a.to=a.from),a.margin=b||0,null!=a.from.line?Wc(this,a):Yc(this,a.from,a.to,a.margin)}),setSize:od(function(a,b){var c=this,d=function(a){return"number"==typeof a||/^\d+$/.test(String(a))?a+"px":a};null!=a&&(this.display.wrapper.style.width=d(a)),null!=b&&(this.display.wrapper.style.height=d(b)),this.options.lineWrapping&&ec(this);var e=this.display.viewFrom;this.doc.iter(e,this.display.viewTo,function(a){if(a.widgets)for(var b=0;b<a.widgets.length;b++)if(a.widgets[b].noHScroll){rd(c,e,"widget");break}++e}),this.curOp.forceUpdate=!0,Ea(this,"refresh",this)}),operation:function(a){return md(this,a)},startOperation:function(){return ed(this)},endOperation:function(){return fd(this)},refresh:od(function(){var 
 a=this.display.cachedTextHeight;qd(this),this.curOp.forceUpdate=!0,fc(this),Vc(this,this.doc.scrollLeft,this.doc.scrollTop),Fd(this),(null==a||Math.abs(a-sc(this.display))>.5)&&xc(this),Ea(this,"refresh",this)}),swapDoc:od(function(a){var b=this.doc;return b.cm=null,Yd(this,a),fc(this),this.display.input.reset(),Vc(this,a.scrollLeft,a.scrollTop),this.curOp.forceScroll=!0,yb(this,"swapDoc",this,b),b}),getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},Ia(a),a.registerHelper=function(b,d,e){c.hasOwnProperty(b)||(c[b]=a[b]={_global:[]}),c[b][d]=e},a.registerGlobalHelper=function(b,d,e,f){a.registerHelper(b,d,f),c[b]._global.push({pred:e,val:f})}},Zh=function(a){this.cm=a,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=n
 ew Ig,this.composing=null,this.gracePeriod=!1,this.readDOMTimeout=null};Zh.prototype.init=function(a){function b(a){if(!Fa(e,a)){if(e.somethingSelected())Sf({lineWise:!1,text:e.getSelections()}),"cut"==a.type&&e.replaceSelection("",null,"cut");else{if(!e.options.lineWiseCopyCut)return;var b=Wf(e);Sf({lineWise:!0,text:b.text}),"cut"==a.type&&e.operation(function(){e.setSelections(b.ranges,0,Ng),e.replaceSelection("",null,"cut")})}if(a.clipboardData){a.clipboardData.clearData();var c=Xh.text.join("\n");if(a.clipboardData.setData("Text",c),a.clipboardData.getData("Text")==c)return void a.preventDefault()}var g=Yf(),h=g.firstChild;e.display.lineSpace.insertBefore(g,e.display.lineSpace.firstChild),h.value=Xh.text.join("\n");var i=document.activeElement;Hg(h),setTimeout(function(){e.display.lineSpace.removeChild(g),i.focus(),i==f&&d.showPrimarySelection()},50)}}var c
 =this,d=this,e=d.cm,f=d.div=a.lineDiv;Xf(f,e.options.spellcheck),Yg(f,"paste",function(a){Fa(e,a)||Uf(a,e)||og<=11&&setTimeout(nd(e,function(){return c.updateFromDOM()}),20)}),Yg(f,"compositionstart",function(a){c.composing={data:a.data,done:!1}}),Yg(f,"compositionupdate",function(a){c.composing||(c.composing={data:a.data,done:!1})}),Yg(f,"compositionend",function(a){c.composing&&(a.data!=c.composing.data&&c.readFromDOMSoon(),c.composing.done=!0)}),Yg(f,"touchstart",function(){return d.forceCompositionEnd()}),Yg(f,"input",function(){c.composing||c.readFromDOMSoon()}),Yg(f,"copy",b),Yg(f,"cut",b)},Zh.prototype.prepareSelection=function(){var a=Bc(this.cm,!1);return a.focus=this.cm.state.focused,a},Zh.prototype.showSelection=function(a,b){a&&this.cm.display.view.length&&((a.focus||b)&&this.showPrimarySelection(),this.showMultipleSelections(a))},Zh.prototyp
 e.showPrimarySelection=function(){var a=window.getSelection(),b=this.cm,c=b.doc.sel.primary(),d=c.from(),e=c.to();if(b.display.viewTo==b.display.viewFrom||d.line>=b.display.viewTo||e.line<b.display.viewFrom)return void a.removeAllRanges();var f=dg(b,a.anchorNode,a.anchorOffset),g=dg(b,a.focusNode,a.focusOffset);if(!f||f.bad||!g||g.bad||0!=K(O(f,g),d)||0!=K(N(f,g),e)){var h=b.display.view,i=d.line>=b.display.viewFrom&&_f(b,d)||{node:h[0].measure.map[2],offset:0},j=e.line<b.display.viewTo&&_f(b,e);if(!j){var k=h[h.length-1].measure,l=k.maps?k.maps[k.maps.length-1]:k.map;j={node:l[l.length-1],offset:l[l.length-2]-l[l.length-3]}}if(!i||!j)return void a.removeAllRanges();var m,n=a.rangeCount&&a.getRangeAt(0);try{m=Dg(i.node,i.offset,j.offset,j.node)}catch(o){}m&&(!jg&&b.state.focused?(a.collapse(i.node,i.offset),m.collapsed||(a.removeAllRanges(),a.addRange(m))):(a.removeAllRanges(),a.addRange(m)),n&&null==a.anchorNode?a.addRange
 (n):jg&&this.startGracePeriod()),this.rememberSelection()}},Zh.prototype.startGracePeriod=function(){var a=this;clearTimeout(this.gracePeriod),this.gracePeriod=setTimeout(function(){a.gracePeriod=!1,a.selectionChanged()&&a.cm.operation(function(){return a.cm.curOp.selectionChanged=!0})},20)},Zh.prototype.showMultipleSelections=function(a){c(this.cm.display.cursorDiv,a.cursors),c(this.cm.display.selectionDiv,a.selection)},Zh.prototype.rememberSelection=function(){var a=window.getSelection();this.lastAnchorNode=a.anchorNode,this.lastAnchorOffset=a.anchorOffset,this.lastFocusNode=a.focusNode,this.lastFocusOffset=a.focusOffset},Zh.prototype.selectionInEditor=function(){var a=window.getSelection();if(!a.rangeCount)return!1;var b=a.getRangeAt(0).commonAncestorContainer;return f(this.div,b)},Zh.prototype.focus=function(){"nocursor"!=this.cm.options.readOnly&&(this.selectionInEditor()||this.showSelection(this.prepareSelection(),!0),this.div.focus())},Zh.pro
 totype.blur=function(){this.div.blur()},Zh.prototype.getField=function(){return this.div},Zh.prototype.supportsTouch=function(){return!0},Zh.prototype.receivedFocus=function(){function a(){b.cm.state.focused&&(b.pollSelection(),b.polling.set(b.cm.options.pollInterval,a))}var b=this;this.selectionInEditor()?this.pollSelection():md(this.cm,function(){return b.cm.curOp.selectionChanged=!0}),this.polling.set(this.cm.options.pollInterval,a)},Zh.prototype.selectionChanged=function(){var a=window.getSelection();return a.anchorNode!=this.lastAnchorNode||a.anchorOffset!=this.lastAnchorOffset||a.focusNode!=this.lastFocusNode||a.focusOffset!=this.lastFocusOffset},Zh.prototype.pollSelection=function(){if(null==this.readDOMTimeout&&!this.gracePeriod&&this.selectionChanged()){var a=window.getSelection(),b=this.cm;if(xg&&rg&&this.cm.options.gutters.length&&ag(a.anchorNode))return this.cm.triggerOnKeyDown({type:"keydown",keyCode:8,preventDef
 ault:Math.abs}),this.blur(),void this.focus();if(!this.composing){this.rememberSelection();var c=dg(b,a.anchorNode,a.anchorOffset),d=dg(b,a.focusNode,a.focusOffset);c&&d&&md(b,function(){te(b.doc,Nd(c,d),Ng),(c.bad||d.bad)&&(b.curOp.selectionChanged=!0)})}}},Zh.prototype.pollContent=function(){null!=this.readDOMTimeout&&(clearTimeout(this.readDOMTimeout),this.readDOMTimeout=null);var a=this.cm,b=a.display,c=a.doc.sel.primary(),d=c.from(),e=c.to();if(0==d.ch&&d.line>a.firstLine()&&(d=J(d.line-1,B(a.doc,d.line-1).length)),e.ch==B(a.doc,e.line).text.length&&e.line<a.lastLine()&&(e=J(e.line+1,0)),d.line<b.viewFrom||e.line>b.viewTo-1)return!1;var f,g,h;d.line==b.viewFrom||0==(f=zc(a,d.line))?(g=F(b.view[0].line),h=b.view[0].node):(g=F(b.view[f].line),h=b.view[f-1].node.nextSibling);var i,j,k=zc(a,e.line);if(k==b.view.length-1?(i=b.viewTo-1,j=b.lineDiv.lastChild):(i=F(b.view[k+1].line)-1,j=b.view[k+1].node.previou
 sSibling),!h)return!1;for(var l=a.doc.splitLines(cg(a,h,j,g,i)),m=C(a.doc,J(g,0),J(i,B(a.doc,i).text.length));l.length>1&&m.length>1;)if(p(l)==p(m))l.pop(),m.pop(),i--;else{if(l[0]!=m[0])break;l.shift(),m.shift(),g++}for(var n=0,o=0,q=l[0],r=m[0],s=Math.min(q.length,r.length);n<s&&q.charCodeAt(n)==r.charCodeAt(n);)++n;for(var t=p(l),u=p(m),v=Math.min(t.length-(1==l.length?n:0),u.length-(1==m.length?n:0));o<v&&t.charCodeAt(t.length-o-1)==u.charCodeAt(u.length-o-1);)++o;if(1==l.length&&1==m.length&&g==d.line)for(;n&&n>d.ch&&t.charCodeAt(t.length-o-1)==u.charCodeAt(u.length-o-1);)n--,o++;l[l.length-1]=t.slice(0,t.length-o).replace(/^\u200b+/,""),l[0]=l[0].slice(n).replace(/\u200b+$/,"");var w=J(g,n),x=J(i,m.length?p(m).length-o:0);return l.length>1||l[0]||K(w,x)?(Je(a.doc,l,w,x,"+input"),!0):void 0},Zh.prototype.ensurePolled=function(){this.forceCompositionEnd()},Zh.prototype.reset=f
 unction(){this.forceCompositionEnd()},Zh.prototype.forceCompositionEnd=function(){this.composing&&(clearTimeout(this.readDOMTimeout),this.composing=null,this.updateFromDOM(),this.div.blur(),this.div.focus())},Zh.prototype.readFromDOMSoon=function(){var a=this;null==this.readDOMTimeout&&(this.readDOMTimeout=setTimeout(function(){if(a.readDOMTimeout=null,a.composing){if(!a.composing.done)return;a.composing=null}a.updateFromDOM()},80))},Zh.prototype.updateFromDOM=function(){var a=this;!this.cm.isReadOnly()&&this.pollContent()||md(this.cm,function(){return qd(a.cm)})},Zh.prototype.setUneditable=function(a){a.contentEditable="false"},Zh.prototype.onKeyPress=function(a){0!=a.charCode&&(a.preventDefault(),this.cm.isReadOnly()||nd(this.cm,Tf)(this.cm,String.fromCharCode(null==a.charCode?a.keyCode:a.charCode),0))},Zh.prototype.readOnlyChanged=function(a){this.div.contentEditable=String("nocursor"!=a)},Zh.prototype.onContextMenu=function(){}
 ,Zh.prototype.resetPosition=function(){},Zh.prototype.needsContentAttribute=!0;var $h=function(a){this.cm=a,this.prevInput="",this.pollingFast=!1,this.polling=new Ig,this.hasSelection=!1,this.composing=null};$h.prototype.init=function(a){function b(a){if(!Fa(e,a)){if(e.somethingSelected())Sf({lineWise:!1,text:e.getSelections()});else{if(!e.options.lineWiseCopyCut)return;var b=Wf(e);Sf({lineWise:!0,text:b.text}),"cut"==a.type?e.setSelections(b.ranges,null,Ng):(d.prevInput="",g.value=b.text.join("\n"),Hg(g))}"cut"==a.type&&(e.state.cutIncoming=!0)}}var c=this,d=this,e=this.cm,f=this.wrapper=Yf(),g=this.textarea=f.firstChild;a.wrapper.insertBefore(f,a.wrapper.firstChild),wg&&(g.style.width="0px"),Yg(g,"input",function(){ng&&og>=9&&c.hasSelection&&(c.hasSelection=null),d.poll()}),Yg(g,"paste",function(a){Fa(e,a)||Uf(a,e)||(e.state.pasteIncoming=!0,d.fastPoll())}),Yg
 (g,"cut",b),Yg(g,"copy",b),Yg(a.scroller,"paste",function(b){Nb(a,b)||Fa(e,b)||(e.state.pasteIncoming=!0,d.focus())}),Yg(a.lineSpace,"selectstart",function(b){Nb(a,b)||Ja(b)}),Yg(g,"compositionstart",function(){var a=e.getCursor("from");d.composing&&d.composing.range.clear(),d.composing={start:a,range:e.markText(a,e.getCursor("to"),{className:"CodeMirror-composing"})}}),Yg(g,"compositionend",function(){d.composing&&(d.poll(),d.composing.range.clear(),d.composing=null)})},$h.prototype.prepareSelection=function(){var a=this.cm,b=a.display,c=a.doc,d=Bc(a);if(a.options.moveInputWithCursor){var e=lc(a,c.sel.primary().head,"div"),f=b.wrapper.getBoundingClientRect(),g=b.lineDiv.getBoundingClientRect();d.teTop=Math.max(0,Math.min(b.wrapper.clientHeight-10,e.top+g.top-f.top)),d.teLeft=Math.max(0,Math.min(b.wrapper.clientWidth-10,e.left+g.left-f.left))}return d},$h.prototype.sho
 wSelection=function(a){var b=this.cm,d=b.display;c(d.cursorDiv,a.cursors),c(d.selectionDiv,a.selection),null!=a.teTop&&(this.wrapper.style.top=a.teTop+"px",this.wrapper.style.left=a.teLeft+"px")},$h.prototype.reset=function(a){if(!this.contextMenuPending&&!this.composing){var b=this.cm;if(b.somethingSelected()){this.prevInput="";var c=b.getSelection();this.textarea.value=c,b.state.focused&&Hg(this.textarea),ng&&og>=9&&(this.hasSelection=c)}else a||(this.prevInput=this.textarea.value="",ng&&og>=9&&(this.hasSelection=null))}},$h.prototype.getField=function(){return this.textarea},$h.prototype.supportsTouch=function(){return!1},$h.prototype.focus=function(){if("nocursor"!=this.cm.options.readOnly&&(!yg||g()!=this.textarea))try{this.textarea.focus()}catch(a){}},$h.prototype.blur=function(){this.textarea.blur()},$h.prototype.resetPosition=function(){this.wrapper.style.t
 op=this.wrapper.style.left=0},$h.prototype.receivedFocus=function(){this.slowPoll()},$h.prototype.slowPoll=function(){var a=this;this.pollingFast||this.polling.set(this.cm.options.pollInterval,function(){a.poll(),a.cm.state.focused&&a.slowPoll()})},$h.prototype.fastPoll=function(){function a(){var d=c.poll();d||b?(c.pollingFast=!1,c.slowPoll()):(b=!0,c.polling.set(60,a))}var b=!1,c=this;c.pollingFast=!0,c.polling.set(20,a)},$h.prototype.poll=function(){var a=this,b=this.cm,c=this.textarea,d=this.prevInput;if(this.contextMenuPending||!b.state.focused||_g(c)&&!d&&!this.composing||b.isReadOnly()||b.options.disableInput||b.state.keySeq)return!1;var e=c.value;if(e==d&&!b.somethingSelected())return!1;if(ng&&og>=9&&this.hasSelection===e||zg&&/[\uf700-\uf7ff]/.test(e))return b.display.input.reset(),!1;if(b.doc.sel==b.display.selForContextMenu){var f=e.charCodeAt(0);if(8203!=f||d||(d="\u200b"),8666==f)return this.reset(),th
 is.cm.execCommand("undo")}for(var g=0,h=Math.min(d.length,e.length);g<h&&d.charCodeAt(g)==e.charCodeAt(g);)++g;return md(b,function(){Tf(b,e.slice(g),d.length-g,null,a.composing?"*compose":null),e.length>1e3||e.indexOf("\n")>-1?c.value=a.prevInput="":a.prevInput=e,a.composing&&(a.composing.range.clear(),a.composing.range=b.markText(a.composing.start,b.getCursor("to"),{className:"CodeMirror-composing"}))}),!0},$h.prototype.ensurePolled=function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},$h.prototype.onKeyPress=function(){ng&&og>=9&&(this.hasSelection=null),this.fastPoll()},$h.prototype.onContextMenu=function(a){function b(){if(null!=g.selectionStart){var a=e.somethingSelected(),b="\u200b"+(a?g.value:"");g.value="\u21da",g.value=b,d.prevInput=a?"":"\u200b",g.selectionStart=1,g.selectionEnd=b.length,f.selF
 orContextMenu=e.doc.sel}}function c(){if(d.contextMenuPending=!1,d.wrapper.style.cssText=l,g.style.cssText=k,ng&&og<9&&f.scrollbars.setScrollTop(f.scroller.scrollTop=i),null!=g.selectionStart){(!ng||ng&&og<9)&&b();var a=0,c=function(){f.selForContextMenu==e.doc.sel&&0==g.selectionStart&&g.selectionEnd>0&&"\u200b"==d.prevInput?nd(e,Be)(e):a++<10?f.detectingSelectAll=setTimeout(c,500):(f.selForContextMenu=null,f.input.reset())};f.detectingSelectAll=setTimeout(c,200)}}var d=this,e=d.cm,f=e.display,g=d.textarea,h=yc(e,a),i=f.scroller.scrollTop;if(h&&!sg){var j=e.options.resetSelectionOnContextMenu;j&&e.doc.sel.contains(h)==-1&&nd(e,te)(e.doc,Nd(h),Ng);var k=g.style.cssText,l=d.wrapper.style.cssText;d.wrapper.style.cssText="position: absolute";var m=d.wrapper.getBoundingClientRect();g.style.cssText="position: absolute; width: 30px; height: 30px;\n      top: "+(a.clien
 tY-m.top-5)+"px; left: "+(a.clientX-m.left-5)+"px;\n      z-index: 1000; background: "+(ng?"rgba(255, 255, 255, .05)":"transparent")+";\n      outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";var n;if(pg&&(n=window.scrollY),f.input.focus(),pg&&window.scrollTo(null,n),f.input.reset(),e.somethingSelected()||(g.value=d.prevInput=" "),d.contextMenuPending=!0,f.selForContextMenu=e.doc.sel,clearTimeout(f.detectingSelectAll),ng&&og>=9&&b(),Fg){Ma(a);var o=function(){Da(window,"mouseup",o),setTimeout(c,20)};Yg(window,"mouseup",o)}else setTimeout(c,50)}},$h.prototype.readOnlyChanged=function(a){a||this.reset(),this.textarea.disabled="nocursor"==a},$h.prototype.setUneditable=function(){},$h.prototype.needsContentAttribute=!1,Lf(Pf),Yh(Pf);var _h="iter insert remove copy getEditor constructor".split(&quot
 ; ");for(var ai in Eh.prototype)Eh.prototype.hasOwnProperty(ai)&&m(_h,ai)<0&&(Pf.prototype[ai]=function(a){return function(){return a.apply(this.doc,arguments)}}(Eh.prototype[ai]));return Ia(Eh),Pf.inputStyles={textarea:$h,contenteditable:Zh},Pf.defineMode=function(a){Pf.defaults.mode||"null"==a||(Pf.defaults.mode=a),Sa.apply(this,arguments)},Pf.defineMIME=Ta,Pf.defineMode("null",function(){return{token:function(a){return a.skipToEnd()}}}),Pf.defineMIME("text/plain","null"),Pf.defineExtension=function(a,b){Pf.prototype[a]=b},Pf.defineDocExtension=function(a,b){Eh.prototype[a]=b},Pf.fromTextArea=fg,gg(Pf),Pf.version="5.29.1",Pf})},{}],60:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use stri
 ct";function b(a,b,c,d,e,f){this.indented=a,this.column=b,this.type=c,this.info=d,this.align=e,this.prev=f}function c(a,c,d,e){var f=a.indented;return a.context&&"statement"==a.context.type&&"statement"!=d&&(f=a.context.indented),a.context=new b(f,c,d,e,null,a.context)}function d(a){var b=a.context.type;return")"!=b&&"]"!=b&&"}"!=b||(a.indented=a.context.indented),a.context=a.context.prev}function e(a,b,c){return"variable"==b.prevToken||"type"==b.prevToken||(!!/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(a.string.slice(0,c))||(!(!b.typeAtEndOfLine||a.column()!=a.indentation())||void 0))}function f(a){for(;;){if(!a||"top"==a.type)return!0;if("}"==a.type&&"namespace"!=a.prev.info)return!1;a=a.prev}}function g(a){for(var b={},c=a.split(" "),d=0;d<c.length;++d)b[c[d]]=!0;return b}function h(a,b){return"function"==typeof a
 ?a(b):a.propertyIsEnumerable(b)}function i(a,b){if(!b.startOfLine)return!1;for(var c,d=null;c=a.peek();){if("\\"==c&&a.match(/^.$/)){d=i;break}if("/"==c&&a.match(/^\/[\/\*]/,!1))break;a.next()}return b.tokenize=d,"meta"}function j(a,b){return"type"==b.prevToken&&"type"}function k(a){return a.eatWhile(/[\w\.']/),"number"}function l(a,b){if(a.backUp(1),a.match(/(R|u8R|uR|UR|LR)/)){var c=a.match(/"([^\s\\()]{0,16})\(/);return!!c&&(b.cpp11RawStringDelim=c[1],b.tokenize=o,o(a,b))}return a.match(/(u8|u|U|L)/)?!!a.match(/["']/,!1)&&"string":(a.next(),!1)}function m(a){var b=/(\w+)::~?(\w+)$/.exec(a);return b&&b[1]==b[2]}function n(a,b){for(var c;null!=(c=a.next());)if('"'==c&&!a.eat('"')){b.tokenize=null;break}return"string"}function o(a,b){var c=b.cpp11RawStringDelim.replace(/[^\w\s]/g,"\\$&"),d=a.match(new RegExp(".
 *?\\)"+c+'"'));return d?b.tokenize=null:a.skipToEnd(),"string"}function p(b,c){function d(a){if(a)for(var b in a)a.hasOwnProperty(b)&&e.push(b)}"string"==typeof b&&(b=[b]);var e=[];d(c.keywords),d(c.types),d(c.builtin),d(c.atoms),e.length&&(c.helperType=b[0],a.registerHelper("hintWords",b[0],e));for(var f=0;f<b.length;++f)a.defineMIME(b[f],c)}function q(a,b){for(var c=!1;!a.eol();){if(!c&&a.match('"""')){b.tokenize=null;break}c="\\"==a.next()&&!c}return"string"}function r(a){return function(b,c){for(var d,e=!1,f=!1;!b.eol();){if(!a&&!e&&b.match('"')){f=!0;break}if(a&&b.match('"""')){f=!0;break}d=b.next(),!e&&"$"==d&&b.match("{")&&b.skipTo("}"),e=!e&&"\\"==d&&!a}return!f&&a||(c.tokenize=null),"string"}}function s(a){return funct
 ion(b,c){for(var d,e=!1,f=!1;!b.eol();){if(!e&&b.match('"')&&("single"==a||b.match('""'))){f=!0;break}if(!e&&b.match("``")){v=s(a),f=!0;break}d=b.next(),e="single"==a&&!e&&"\\"==d}return f&&(c.tokenize=null),"string"}}a.defineMode("clike",function(g,i){function j(a,b){var c=a.next();if(y[c]){var d=y[c](a,b);if(d!==!1)return d}if('"'==c||"'"==c)return b.tokenize=k(c),b.tokenize(a,b);if(D.test(c))return n=c,null;if(E.test(c)){if(a.backUp(1),a.match(F))return"number";a.next()}if("/"==c){if(a.eat("*"))return b.tokenize=l,l(a,b);if(a.eat("/"))return a.skipToEnd(),"comment"}if(G.test(c)){for(;!a.match(/^\/[\/*]/,!1)&&a.eat(G););return"operator"}if(a.eatWhile(H),C)for(;a.match(C);)a.eatWhile(H);var e=a.current();return h(s,e)?(h(v,e)&&(n="newstatement"),h(w,e)&&
 (o=!0),"keyword"):h(t,e)?"type":h(u,e)?(h(v,e)&&(n="newstatement"),"builtin"):h(x,e)?"atom":"variable"}function k(a){return function(b,c){for(var d,e=!1,f=!1;null!=(d=b.next());){if(d==a&&!e){f=!0;break}e=!e&&"\\"==d}return(f||!e&&!z)&&(c.tokenize=null),"string"}}function l(a,b){for(var c,d=!1;c=a.next();){if("/"==c&&d){b.tokenize=null;break}d="*"==c}return"comment"}function m(a,b){i.typeFirstDefinitions&&a.eol()&&f(b.context)&&(b.typeAtEndOfLine=e(a,b,a.pos))}var n,o,p=g.indentUnit,q=i.statementIndentUnit||p,r=i.dontAlignCalls,s=i.keywords||{},t=i.types||{},u=i.builtin||{},v=i.blockKeywords||{},w=i.defKeywords||{},x=i.atoms||{},y=i.hooks||{},z=i.multiLineStrings,A=i.indentStatements!==!1,B=i.indentSwitch!==!1,C=i.namespaceSeparator,D=i.isPunctuationChar||/[\[\]{}\(\),;\:\.]/,E=i.numberStart||/[\d\.]/,F=
 i.number||/^(?:0x[a-f\d]+|0b[01]+|(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)(u|ll?|l|f)?/i,G=i.isOperatorChar||/[+\-*&%=<>!?|\/]/,H=i.isIdentifierChar||/[\w\$_\xa1-\uffff]/;return{startState:function(a){return{tokenize:null,context:new b((a||0)-p,0,"top",null,!1),indented:0,
+startOfLine:!0,prevToken:null}},token:function(a,b){var g=b.context;if(a.sol()&&(null==g.align&&(g.align=!1),b.indented=a.indentation(),b.startOfLine=!0),a.eatSpace())return m(a,b),null;n=o=null;var h=(b.tokenize||j)(a,b);if("comment"==h||"meta"==h)return h;if(null==g.align&&(g.align=!0),";"==n||":"==n||","==n&&a.match(/^\s*(?:\/\/.*)?$/,!1))for(;"statement"==b.context.type;)d(b);else if("{"==n)c(b,a.column(),"}");else if("["==n)c(b,a.column(),"]");else if("("==n)c(b,a.column(),")");else if("}"==n){for(;"statement"==g.type;)g=d(b);for("}"==g.type&&(g=d(b));"statement"==g.type;)g=d(b)}else n==g.type?d(b):A&&(("}"==g.type||"top"==g.type)&&";"!=n||"statement"==g.type&&"newstatement"==n)&&c(b,a.column(),"
 statement",a.current());if("variable"==h&&("def"==b.prevToken||i.typeFirstDefinitions&&e(a,b,a.start)&&f(b.context)&&a.match(/^\s*\(/,!1))&&(h="def"),y.token){var k=y.token(a,b,h);void 0!==k&&(h=k)}return"def"==h&&i.styleDefs===!1&&(h="variable"),b.startOfLine=!1,b.prevToken=o?"def":h||n,m(a,b),h},indent:function(b,c){if(b.tokenize!=j&&null!=b.tokenize||b.typeAtEndOfLine)return a.Pass;var d=b.context,e=c&&c.charAt(0);if("statement"==d.type&&"}"==e&&(d=d.prev),i.dontIndentStatements)for(;"statement"==d.type&&i.dontIndentStatements.test(d.info);)d=d.prev;if(y.indent){var f=y.indent(b,d,c);if("number"==typeof f)return f}var g=e==d.type,h=d.prev&&"switch"==d.prev.info;if(i.allmanIndentation&&/[{(]/.test(e)){for(;"top"!=d.type&&"}&quo
 t;!=d.type;)d=d.prev;return d.indented}return"statement"==d.type?d.indented+("{"==e?0:q):!d.align||r&&")"==d.type?")"!=d.type||g?d.indented+(g?0:p)+(g||!h||/^(?:case|default)\b/.test(c)?0:p):d.indented+q:d.column+(g?0:1)},electricInput:B?/^\s*(?:case .*?:|default:|\{\}?|\})$/:/^\s*[{}]$/,blockCommentStart:"/*",blockCommentEnd:"*/",lineComment:"//",fold:"brace"}});var t="auto if break case register continue return default do sizeof static else struct switch extern typedef union for goto while enum const volatile",u="int long char short double float unsigned signed void size_t ptrdiff_t";p(["text/x-csrc","text/x-c","text/x-chdr"],{name:"clike",keywords:g(t),types:g(u+" bool _Complex _Bool float_t double_t intptr_t intmax_t int8_t int16_t int32_t int64_t uintptr_t uintmax_t uint8_t uint16_t uint32_t uint64_t"),blockKeywords:g(&quo
 t;case do else for if switch while struct"),defKeywords:g("struct"),typeFirstDefinitions:!0,atoms:g("null true false"),hooks:{"#":i,"*":j},modeProps:{fold:["brace","include"]}}),p(["text/x-c++src","text/x-c++hdr"],{name:"clike",keywords:g(t+" asm dynamic_cast namespace reinterpret_cast try explicit new static_cast typeid catch operator template typename class friend private this using const_cast inline public throw virtual delete mutable protected alignas alignof constexpr decltype nullptr noexcept thread_local final static_assert override"),types:g(u+" bool wchar_t"),blockKeywords:g("catch class do else finally for if struct switch try while"),defKeywords:g("class namespace struct enum union"),typeFirstDefinitions:!0,atoms:g("true false null"),dontIndentStatements:/^template$/,isIdentifierChar:/[\w\$_~\xa1-\uffff]/,hooks:{"#":i,&
 quot;*":j,u:l,U:l,L:l,R:l,0:k,1:k,2:k,3:k,4:k,5:k,6:k,7:k,8:k,9:k,token:function(a,b,c){if("variable"==c&&"("==a.peek()&&(";"==b.prevToken||null==b.prevToken||"}"==b.prevToken)&&m(a.current()))return"def"}},namespaceSeparator:"::",modeProps:{fold:["brace","include"]}}),p("text/x-java",{name:"clike",keywords:g("abstract assert break case catch class const continue default do else enum extends final finally float for goto if implements import instanceof interface native new package private protected public return static strictfp super switch synchronized this throw throws transient try volatile while @interface"),types:g("byte short int long float double boolean char void Boolean Byte Character Double Float Integer Long Number Object Short String StringBuffer StringBuilder Void"),blockKeywords:g("catch class do else finally for if sw
 itch try while"),defKeywords:g("class interface package enum @interface"),typeFirstDefinitions:!0,atoms:g("true false null"),number:/^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+\.?\d*|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,hooks:{"@":function(a){return!a.match("interface",!1)&&(a.eatWhile(/[\w\$_]/),"meta")}},modeProps:{fold:["brace","import"]}}),p("text/x-csharp",{name:"clike",keywords:g("abstract as async await base break case catch checked class const continue default delegate do else enum event explicit extern finally fixed for foreach goto if implicit in interface internal is lock namespace new operator out override params private protected public readonly ref return sealed sizeof stackalloc static struct switch this throw try typeof unchecked unsafe using virtual void volatile while add alias ascending descending dynamic from get global group into join let orderby partial remove s
 elect set value var yield"),types:g("Action Boolean Byte Char DateTime DateTimeOffset Decimal Double Func Guid Int16 Int32 Int64 Object SByte Single String Task TimeSpan UInt16 UInt32 UInt64 bool byte char decimal double short int long object sbyte float string ushort uint ulong"),blockKeywords:g("catch class do else finally for foreach if struct switch try while"),defKeywords:g("class interface namespace struct var"),typeFirstDefinitions:!0,atoms:g("true false null"),hooks:{"@":function(a,b){return a.eat('"')?(b.tokenize=n,n(a,b)):(a.eatWhile(/[\w\$_]/),"meta")}}}),p("text/x-scala",{name:"clike",keywords:g("abstract case catch class def do else extends final finally for forSome if implicit import lazy match new null object override package private protected return sealed super this throw trait try type val var while with yield _ assert assume require print println printf readLine readBool
 ean readByte readShort readChar readInt readLong readFloat readDouble"),types:g("AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either Enumeration Equiv Error Exception Fractional Function IndexedSeq Int Integral Iterable Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable Compiler Double Exception Float Integer Long Math Number Object Package Pair Process Runtime Runnable SecurityManager Short StackTraceElement StrictMath String StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"),multiLineStrings:!0,blockKeywords:g("catch class enum do else finally for forSome if match switch try while"),defKeywords:g("class enum def object p
 ackage trait type val var"),atoms:g("true false null"),indentStatements:!1,indentSwitch:!1,isOperatorChar:/[+\-*&%=<>!?|\/#:@]/,hooks:{"@":function(a){return a.eatWhile(/[\w\$_]/),"meta"},'"':function(a,b){return!!a.match('""')&&(b.tokenize=q,b.tokenize(a,b))},"'":function(a){return a.eatWhile(/[\w\$_\xa1-\uffff]/),"atom"},"=":function(a,c){var d=c.context;return!("}"!=d.type||!d.align||!a.eat(">"))&&(c.context=new b(d.indented,d.column,d.type,d.info,null,d.prev),"operator")}},modeProps:{closeBrackets:{triples:'"'}}}),p("text/x-kotlin",{name:"clike",keywords:g("package as typealias class interface this super val var fun for is in This throw return break continue object if else while do try when !in !is as? file import where by get set abstract enum open inner override private public internal protected catch finally o
 ut final vararg reified dynamic companion constructor init sealed field property receiver param sparam lateinit data inline noinline tailrec external annotation crossinline const operator infix suspend"),types:g("Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable Compiler Double Exception Float Integer Long Math Number Object Package Pair Process Runtime Runnable SecurityManager Short StackTraceElement StrictMath String StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"),intendSwitch:!1,indentStatements:!1,multiLineStrings:!0,number:/^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+\.?\d*|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,blockKeywords:g("catch class do else finally for if where try while enum"),defKeywords:g("class val var object package interface fun"),atoms:g("true false null this"),hooks:{'"':function(a,b){return b.tokenize=r(a.match('""')),b.tokenize(a,b)}},modeProps:{closeBrackets:
 {triples:'"'}}}),p(["x-shader/x-vertex","x-shader/x-fragment"],{name:"clike",keywords:g("sampler1D sampler2D sampler3D samplerCube sampler1DShadow sampler2DShadow const attribute uniform varying break continue discard return for while do if else struct in out inout"),types:g("float int bool void vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 mat2 mat3 mat4"),blockKeywords:g("for while do if else struct"),builtin:g("radians degrees sin cos tan asin acos atan pow exp log exp2 sqrt inversesqrt abs sign floor ceil fract mod min max clamp mix step smoothstep length distance dot cross normalize ftransform faceforward reflect refract matrixCompMult lessThan lessThanEqual greaterThan greaterThanEqual equal notEqual any all not texture1D texture1DProj texture1DLod texture1DProjLod texture2D texture2DProj texture2DLod texture2DProjLod texture3D texture3DProj texture3DLod texture3DProjLod textureCube textureCubeLod shado
 w1D shadow2D shadow1DProj shadow2DProj shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod dFdx dFdy fwidth noise1 noise2 noise3 noise4"),atoms:g("true false gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 gl_FogCoord gl_PointCoord gl_Position gl_PointSize gl_ClipVertex gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor gl_TexCoord gl_FogFragCoord gl_FragCoord gl_FrontFacing gl_FragData gl_FragDepth gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose gl_ProjectionMatrixInverseTranspose gl_ModelViewProjectionMatrixInverseTranspose gl_TextureMatrixInverseTranspose gl_NormalScale gl_DepthRange gl_ClipPlane gl_Poi
 nt gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel gl_FrontLightModelProduct gl_BackLightModelProduct gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ gl_FogParameters gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits gl_MaxDrawBuffers"),indentSwitch:!1,hooks:{"#":i},modeProps:{fold:["brace","include"]}}),p("text/x-nesc",{name:"clike",keywords:g(t+"as atomic async call command component components configuration event generic implementation includes interface module new norace nx_struct nx_union post provides signal task uses abstract extends"),types:g(u),blockKeywords:g("case do else for if switch while struct"),atoms:g("null true false"),hooks:{"#":i},mo
 deProps:{fold:["brace","include"]}}),p("text/x-objectivec",{name:"clike",keywords:g(t+"inline restrict _Bool _Complex _Imaginary BOOL Class bycopy byref id IMP in inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),types:g(u),atoms:g("YES NO NULL NILL ON OFF true false"),hooks:{"@":function(a){return a.eatWhile(/[\w\$]/),"keyword"},"#":i,indent:function(a,b,c){if("statement"==b.type&&/^@\w/.test(c))return b.indented}},modeProps:{fold:"brace"}}),p("text/x-squirrel",{name:"clike",keywords:g("base break clone continue const default delete enum extends function in class foreach local resume return this throw typeof yield constructor instanceof static"),types:g(u),blockKeywords:g("case catch class else for foreach if switch try while"),defKeywords:g("function local class"),typeFir
 stDefinitions:!0,atoms:g("true false null"),hooks:{"#":i},modeProps:{fold:["brace","include"]}});var v=null;p("text/x-ceylon",{name:"clike",keywords:g("abstracts alias assembly assert assign break case catch class continue dynamic else exists extends finally for function given if import in interface is let module new nonempty object of out outer package return satisfies super switch then this throw try value void while"),types:function(a){var b=a.charAt(0);return b===b.toUpperCase()&&b!==b.toLowerCase()},blockKeywords:g("case catch class dynamic else finally for function if interface module new object switch try while"),defKeywords:g("class dynamic function interface module object package value"),builtin:g("abstract actual aliased annotation by default deprecated doc final formal late license native optional sealed see serializable shared suppressWarnings tagged throws variable&quo
 t;),isPunctuationChar:/[\[\]{}\(\),;\:\.`]/,isOperatorChar:/[+\-*&%=<>!?|^~:\/]/,numberStart:/[\d#$]/,number:/^(?:#[\da-fA-F_]+|\$[01_]+|[\d_]+[kMGTPmunpf]?|[\d_]+\.[\d_]+(?:[eE][-+]?\d+|[kMGTPmunpf]|)|)/i,multiLineStrings:!0,typeFirstDefinitions:!0,atoms:g("true false null larger smaller equal empty finished"),indentSwitch:!1,styleDefs:!1,hooks:{"@":function(a){return a.eatWhile(/[\w\$_]/),"meta"},'"':function(a,b){return b.tokenize=s(a.match('""')?"triple":"single"),b.tokenize(a,b)},"`":function(a,b){return!(!v||!a.match("`"))&&(b.tokenize=v,v=null,b.tokenize(a,b))},"'":function(a){return a.eatWhile(/[\w\$_\xa1-\uffff]/),"atom"},token:function(a,b,c){if(("variable"==c||"type"==c)&&"."==b.prevToken)return"variable-2"}},modeProps:{fold:["brace","import"],closeBrackets:{triples:'"'}}})})},{&
 quot;../../lib/codemirror":59}],61:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";function b(a){for(var b={},c=0;c<a.length;++c)b[a[c].toLowerCase()]=!0;return b}function c(a,b){for(var c,d=!1;null!=(c=a.next());){if(d&&"/"==c){b.tokenize=null;break}d="*"==c}return["comment","comment"]}a.defineMode("css",function(b,c){function d(a,b){return o=b,a}function e(a,b){var c=a.next();if(r[c]){var e=r[c](a,b);if(e!==!1)return e}return"@"==c?(a.eatWhile(/[\w\\\-]/),d("def",a.current())):"="==c||("~"==c||"|"==c)&&a.eat("=")?d(null,"compare"):'"'==c||"'"==c?(b.tokenize=f(c),b.tokenize(a,b)):"#&quo
 t;==c?(a.eatWhile(/[\w\\\-]/),d("atom","hash")):"!"==c?(a.match(/^\s*\w*/),d("keyword","important")):/\d/.test(c)||"."==c&&a.eat(/\d/)?(a.eatWhile(/[\w.%]/),d("number","unit")):"-"!==c?/[,+>*\/]/.test(c)?d(null,"select-op"):"."==c&&a.match(/^-?[_a-z][_a-z0-9-]*/i)?d("qualifier","qualifier"):/[:;{}\[\]\(\)]/.test(c)?d(null,c):"u"==c&&a.match(/rl(-prefix)?\(/)||"d"==c&&a.match("omain(")||"r"==c&&a.match("egexp(")?(a.backUp(1),b.tokenize=g,d("property","word")):/[\w\\\-]/.test(c)?(a.eatWhile(/[\w\\\-]/),d("property","word")):d(null,null):/[\d.]/.test(a.peek())?(a.eatWhile(/[\w.%]/),d("number","unit")):a.match(/^-[\w\\\-]+/)?(a.eatWhile(/[\w\\\-]/),a.match(/^\s*:/,!1)?d("variable-2","variable-d
 efinition"):d("variable-2","variable")):a.match(/^\w+-/)?d("meta","meta"):void 0}function f(a){return function(b,c){for(var e,f=!1;null!=(e=b.next());){if(e==a&&!f){")"==a&&b.backUp(1);break}f=!f&&"\\"==e}return(e==a||!f&&")"!=a)&&(c.tokenize=null),d("string","string")}}function g(a,b){return a.next(),a.match(/\s*[\"\')]/,!1)?b.tokenize=null:b.tokenize=f(")"),d(null,"(")}function h(a,b,c){this.type=a,this.indent=b,this.prev=c}function i(a,b,c,d){return a.context=new h(c,b.indentation()+(d===!1?0:q),a.context),c}function j(a){return a.context.prev&&(a.context=a.context.prev),a.context.type}function k(a,b,c){return F[c.context.type](a,b,c)}function l(a,b,c,d){for(var e=d||1;e>0;e--)c.context=c.context.prev;return k(a,b,c)}function m(a){var b=a.current().toLowerCase();p=B.hasOwnProperty(b)?"atom":A.hasOwnPro
 perty(b)?"keyword":"variable"}var n=c.inline;c.propertyKeywords||(c=a.resolveMode("text/css"));var o,p,q=b.indentUnit,r=c.tokenHooks,s=c.documentTypes||{},t=c.mediaTypes||{},u=c.mediaFeatures||{},v=c.mediaValueKeywords||{},w=c.propertyKeywords||{},x=c.nonStandardPropertyKeywords||{},y=c.fontProperties||{},z=c.counterDescriptors||{},A=c.colorKeywords||{},B=c.valueKeywords||{},C=c.allowNested,D=c.lineComment,E=c.supportsAtComponent===!0,F={};return F.top=function(a,b,c){if("{"==a)return i(c,b,"block");if("}"==a&&c.context.prev)return j(c);if(E&&/@component/.test(a))return i(c,b,"atComponentBlock");if(/^@(-moz-)?document$/.test(a))return i(c,b,"documentTypes");if(/^@(media|supports|(-moz-)?document|import)$/.test(a))return i(c,b,"atBlock");if(/^@(font-face|counter-style)/.test(a))return c.stateArg=a,"restricted_atBlock_before";if(/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(
 a))return"keyframes";if(a&&"@"==a.charAt(0))return i(c,b,"at");if("hash"==a)p="builtin";else if("word"==a)p="tag";else{if("variable-definition"==a)return"maybeprop";if("interpolation"==a)return i(c,b,"interpolation");if(":"==a)return"pseudo";if(C&&"("==a)return i(c,b,"parens")}return c.context.type},F.block=function(a,b,c){if("word"==a){var d=b.current().toLowerCase();return w.hasOwnProperty(d)?(p="property","maybeprop"):x.hasOwnProperty(d)?(p="string-2","maybeprop"):C?(p=b.match(/^\s*:(?:\s|$)/,!1)?"property":"tag","block"):(p+=" error","maybeprop")}return"meta"==a?"block":C||"hash"!=a&&"qualifier"!=a?F.top(a,b,c):(p="error","block")},F.maybeprop=functio
 n(a,b,c){return":"==a?i(c,b,"prop"):k(a,b,c)},F.prop=function(a,b,c){if(";"==a)return j(c);if("{"==a&&C)return i(c,b,"propBlock");if("}"==a||"{"==a)return l(a,b,c);if("("==a)return i(c,b,"parens");if("hash"!=a||/^#([0-9a-fA-f]{3,4}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8})$/.test(b.current())){if("word"==a)m(b);else if("interpolation"==a)return i(c,b,"interpolation")}else p+=" error";return"prop"},F.propBlock=function(a,b,c){return"}"==a?j(c):"word"==a?(p="property","maybeprop"):c.context.type},F.parens=function(a,b,c){return"{"==a||"}"==a?l(a,b,c):")"==a?j(c):"("==a?i(c,b,"parens"):"interpolation"==a?i(c,b,"interpolation"):("word"==a&&m(b),"parens")},F.pseudo=function(a,b,c){return"meta"==a?&
 quot;pseudo":"word"==a?(p="variable-3",c.context.type):k(a,b,c)},F.documentTypes=function(a,b,c){return"word"==a&&s.hasOwnProperty(b.current())?(p="tag",c.context.type):F.atBlock(a,b,c)},F.atBlock=function(a,b,c){if("("==a)return i(c,b,"atBlock_parens");if("}"==a||";"==a)return l(a,b,c);if("{"==a)return j(c)&&i(c,b,C?"block":"top");if("interpolation"==a)return i(c,b,"interpolation");if("word"==a){var d=b.current().toLowerCase();p="only"==d||"not"==d||"and"==d||"or"==d?"keyword":t.hasOwnProperty(d)?"attribute":u.hasOwnProperty(d)?"property":v.hasOwnProperty(d)?"keyword":w.hasOwnProperty(d)?"property":x.hasOwnProperty(d)?"string-2":B.hasOwnProperty(d)?"atom":A.hasOwnProperty(d)?"keyword":"error"}ret
 urn c.context.type},F.atComponentBlock=function(a,b,c){return"}"==a?l(a,b,c):"{"==a?j(c)&&i(c,b,C?"block":"top",!1):("word"==a&&(p="error"),c.context.type)},F.atBlock_parens=function(a,b,c){return")"==a?j(c):"{"==a||"}"==a?l(a,b,c,2):F.atBlock(a,b,c)},F.restricted_atBlock_before=function(a,b,c){return"{"==a?i(c,b,"restricted_atBlock"):"word"==a&&"@counter-style"==c.stateArg?(p="variable","restricted_atBlock_before"):k(a,b,c)},F.restricted_atBlock=function(a,b,c){return"}"==a?(c.stateArg=null,j(c)):"word"==a?(p="@font-face"==c.stateArg&&!y.hasOwnProperty(b.current().toLowerCase())||"@counter-style"==c.stateArg&&!z.hasOwnProperty(b.current().toLowerCase())?"error":"property","maybeprop"):"restricted_atBlock"},F.keyframe
 s=function(a,b,c){return"word"==a?(p="variable","keyframes"):"{"==a?i(c,b,"top"):k(a,b,c)},F.at=function(a,b,c){return";"==a?j(c):"{"==a||"}"==a?l(a,b,c):("word"==a?p="tag":"hash"==a&&(p="builtin"),"at")},F.interpolation=function(a,b,c){return"}"==a?j(c):"{"==a||";"==a?l(a,b,c):("word"==a?p="variable":"variable"!=a&&"("!=a&&")"!=a&&(p="error"),"interpolation")},{startState:function(a){return{tokenize:null,state:n?"block":"top",stateArg:null,context:new h(n?"block":"top",a||0,null)}},token:function(a,b){if(!b.tokenize&&a.eatSpace())return null;var c=(b.tokenize||e)(a,b);return c&&"object"==typeof c&&(o=c[1],c=c[0]),p=c,"comment"!=o&&(b.
 state=F[b.state](o,a,b)),p},indent:function(a,b){var c=a.context,d=b&&b.charAt(0),e=c.indent;return"prop"!=c.type||"}"!=d&&")"!=d||(c=c.prev),c.prev&&("}"!=d||"block"!=c.type&&"top"!=c.type&&"interpolation"!=c.type&&"restricted_atBlock"!=c.type?(")"!=d||"parens"!=c.type&&"atBlock_parens"!=c.type)&&("{"!=d||"at"!=c.type&&"atBlock"!=c.type)||(e=Math.max(0,c.indent-q)):(c=c.prev,e=c.indent)),e},electricChars:"}",blockCommentStart:"/*",blockCommentEnd:"*/",lineComment:D,fold:"brace"}});var d=["domain","regexp","url","url-prefix"],e=b(d),f=["all","aural","braille","handheld","print","projection","screen","tty","tv&quo
 t;,"embossed"],g=b(f),h=["width","min-width","max-width","height","min-height","max-height","device-width","min-device-width","max-device-width","device-height","min-device-height","max-device-height","aspect-ratio","min-aspect-ratio","max-aspect-ratio","device-aspect-ratio","min-device-aspect-ratio","max-device-aspect-ratio","color","min-color","max-color","color-index","min-color-index","max-color-index","monochrome","min-monochrome","max-monochrome","resolution","min-resolution","max-resolution","scan","grid","orientation","device-pixel-ratio","min-device-pixel-ratio","max-device-pixel-ratio","pointer",&quo
 t;any-pointer","hover","any-hover"],i=b(h),j=["landscape","portrait","none","coarse","fine","on-demand","hover","interlace","progressive"],k=b(j),l=["align-content","align-items","align-self","alignment-adjust","alignment-baseline","anchor-point","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","appearance","azimuth","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","backgr
 ound-position","background-repeat","background-size","baseline-shift","binding","bleed","bookmark-label","bookmark-level","bookmark-state","bookmark-target","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","
 border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","caret-color","clear","clip","color","color-profile","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","crop","cue","cue-after","cue-before","cursor","direction","display",&q
 uot;dominant-baseline","drop-initial-after-adjust","drop-initial-after-align","drop-initial-before-adjust","drop-initial-before-align","drop-initial-size","drop-initial-value","elevation","empty-cells","fit","fit-position","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","float-offset","flow-from","flow-into","font","font-feature-settings","font-family","font-kerning","font-language-override","font-size","font-size-adjust","font-stretch","font-style","font-synthesis","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-ligatures",&q
 uot;font-variant-numeric","font-variant-position","font-weight","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-column","grid-column-end","grid-column-gap","grid-column-start","grid-gap","grid-row","grid-row-end","grid-row-gap","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","inline-box-align","justify-content","justify-items","justify-self","left","letter-spacing","line-break","line-height","line-stacking","line-stacking-ruby",&q
 uot;line-stacking-shift","line-stacking-strategy","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marks","marquee-direction","marquee-loop","marquee-play-count","marquee-speed","marquee-style","max-height","max-width","min-height","min-width","move-to","nav-down","nav-index","nav-left","nav-right","nav-up","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-style","overflow-wrap","overflow-x",&
 quot;overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","page-policy","pause","pause-after","pause-before","perspective","perspective-origin","pitch","pitch-range","place-content","place-items","place-self","play-during","position","presentation-level","punctuation-trim","quotes","region-break-after","region-break-before","region-break-inside","region-fragment","rendering-intent","resize","rest","rest-after","rest-before","richness","right","rotation","rotation-point","ruby-align","ruby-overha
 ng","ruby-position","ruby-span","shape-image-threshold","shape-inside","shape-margin","shape-outside","size","speak","speak-as","speak-header","speak-numeral","speak-punctuation","speech-rate","stress","string-set","tab-size","table-layout","target","target-name","target-new","target-position","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-style","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-height","text-indent","text-justify","text-outline","text-overflow","text-shadow",&
 quot;text-size-adjust","text-space-collapse","text-transform","text-underline-position","text-wrap","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","user-select","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","volume","white-space","widows","width","will-change","word-break","word-spacing","word-wrap","z-index","clip-path","clip-rule","mask","enable-background","filter",
 "flood-color","flood-opacity","lighting-color","stop-color","stop-opacity","pointer-events","color-interpolation","color-interpolation-filters","color-rendering","fill","fill-opacity","fill-rule","image-rendering","marker","marker-end","marker-mid","marker-start","shape-rendering","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-rendering","baseline-shift","dominant-baseline","glyph-orientation-horizontal","glyph-orientation-vertical","text-anchor","writing-mode"],m=b(l),n=["scrollbar-arrow-color","scrollbar-base-color","scrollbar-dark-shadow-c
 olor","scrollbar-face-color","scrollbar-highlight-color","scrollbar-shadow-color","scrollbar-3d-light-color","scrollbar-track-color","shape-inside","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","zoom"],o=b(n),p=["font-family","src","unicode-range","font-variant","font-feature-settings","font-stretch","font-weight","font-style"],q=b(p),r=["additive-symbols","fallback","negative","pad","prefix","range","speak-as","suffix","symbols","system"],s=b(r),t=["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmon
 d","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow",&q
 uot;honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy&quo
 t;,"oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"],u=b(t),v=["above","absolute","active
 border","additive","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alphabetic","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","attr","auto","auto-flow","avoid","avoid-column","avoid-page","avoid-region","background","backwards","baseline","below","bidi-override","binary","bengali","blink","block","block-axis","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","bullets","button","button-be
 vel","buttonface","buttonhighlight","buttonshadow","buttontext","calc","cambodian","capitalize","caps-lock-indicator","caption","captiontext","caret","cell","center","checkbox","circle","cjk-decimal","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","color","color-burn","color-dodge","column","column-reverse","compact","condensed","contain","content","contents","content-box","context-menu","continuous","copy","counter","counters","cover","crop","cross","crosshair","currentcolor&qu
 ot;,"cursive","cyclic","darken","dashed","decimal","decimal-leading-zero","default","default-button","dense","destination-atop","destination-in","destination-out","destination-over","devanagari","difference","disc","discard","disclosure-closed","disclosure-open","document","dot-dash","dot-dot-dash","dotted","double","down","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er",
 "ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ethiopic-numeric","ew-resize","exclusion","expanded","extends","extra-condensed","extra-expanded","fantasy","fast","fill","fixed","flat","flex","flex-end","flex-start","footnotes","forwards","from","geometricPrecision","georgian","graytext","grid","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hard-light","hebrew","help","hidden",&qu
 ot;hide","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","hue","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-flex","inline-grid","inline-table","inset","inside","intrinsic","invert","italic","japanese-formal","japanese-informal","justify","kannada","katakana","katakana-iroha","keep-all","khmer","korean-hangul-formal","korean-hanja-formal","korean-hanja-informal","landscape","lao",&quo
 t;large","larger","left","level","lighter","lighten","line-through","linear","linear-gradient","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","luminosity","malayalam","match","matrix","matrix3d","media-controls-background","media-current-time-display","media-fullscreen-button","media-mute-button","media-play-button","media-return-to-realtime-button","media-rewind-button","media-seek-back-button","media-seek-forward-button","media-slider&
 quot;,"media-sliderthumb","media-time-remaining-display","media-volume-slider","media-volume-slider-container","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menulist-text","menulist-textfield","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","multiply","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","numbers","numeric","nw-resize","nwse-resize","oblique","octal","opacity","open
 -quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","persian","perspective","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radial-gradient","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeating-linear-gradient","repeating-radial-gradient","repeat-x","repeat-y","reset","reverse","rgb","rgba",&quot
 ;ridge","right","rotate","rotate3d","rotateX","rotateY","rotateZ","round","row","row-resize","row-reverse","rtl","run-in","running","s-resize","sans-serif","saturation","scale","scale3d","scaleX","scaleY","scaleZ","screen","scroll","scrollbar","scroll-position","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","self-start","self-end","semi-condensed","semi-expanded","separate","serif","show","sidama","simp-chinese-formal","simp-chinese-informal","single","skew",&quot
 ;skewX","skewY","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small","small-caps","small-caption","smaller","soft-light","solid","somali","source-atop","source-in","source-out","source-over","space","space-around","space-between","space-evenly","spell-out","square","square-button","start","static","status-bar","stretch","stroke","sub","subpixel-antialiased","super","sw-resize","symbolic","symbols","system-ui","table","table-caption","table-cell","table-column","table-column-group",&
 quot;table-footer-group","table-header-group","table-row","table-row-group","tamil","telugu","text","text-bottom","text-top","textarea","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","trad-chinese-formal","trad-chinese-informal","transform","translate","translate3d","translateX","translateY","translateZ","transparent","ultra-condensed","ultra-expanded","underline","unset","up","upper-alpha","upper-arm
 enian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","var","vertical","vertical-text","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","words","wrap","wrap-reverse","x-large","x-small","xor","xx-large","xx-small"],w=b(v),x=d.concat(f).concat(h).concat(j).concat(l).concat(n).concat(t).concat(v);
+a.registerHelper("hintWords","css",x),a.defineMIME("text/css",{documentTypes:e,mediaTypes:g,mediaFeatures:i,mediaValueKeywords:k,propertyKeywords:m,nonStandardPropertyKeywords:o,fontProperties:q,counterDescriptors:s,colorKeywords:u,valueKeywords:w,tokenHooks:{"/":function(a,b){return!!a.eat("*")&&(b.tokenize=c,c(a,b))}},name:"css"}),a.defineMIME("text/x-scss",{mediaTypes:g,mediaFeatures:i,mediaValueKeywords:k,propertyKeywords:m,nonStandardPropertyKeywords:o,colorKeywords:u,valueKeywords:w,fontProperties:q,allowNested:!0,lineComment:"//",tokenHooks:{"/":function(a,b){return a.eat("/")?(a.skipToEnd(),["comment","comment"]):a.eat("*")?(b.tokenize=c,c(a,b)):["operator","operator"]},":":function(a){return!!a.match(/\s*\{/,!1)&&[null,null]},$:function(a){return a.match(/^[\w-]+/),a.match(/^\s*:/,!1)?["variable-
 2","variable-definition"]:["variable-2","variable"]},"#":function(a){return!!a.eat("{")&&[null,"interpolation"]}},name:"css",helperType:"scss"}),a.defineMIME("text/x-less",{mediaTypes:g,mediaFeatures:i,mediaValueKeywords:k,propertyKeywords:m,nonStandardPropertyKeywords:o,colorKeywords:u,valueKeywords:w,fontProperties:q,allowNested:!0,lineComment:"//",tokenHooks:{"/":function(a,b){return a.eat("/")?(a.skipToEnd(),["comment","comment"]):a.eat("*")?(b.tokenize=c,c(a,b)):["operator","operator"]},"@":function(a){return a.eat("{")?[null,"interpolation"]:!a.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/,!1)&&(a.eatWhile(/[\w\\\-]/),a.match(/^\s*:/,!1)?["variable-2","variable-definition"]:[&qu
 ot;variable-2","variable"])},"&":function(){return["atom","atom"]}},name:"css",helperType:"less"}),a.defineMIME("text/x-gss",{documentTypes:e,mediaTypes:g,mediaFeatures:i,propertyKeywords:m,nonStandardPropertyKeywords:o,fontProperties:q,counterDescriptors:s,colorKeywords:u,valueKeywords:w,supportsAtComponent:!0,tokenHooks:{"/":function(a,b){return!!a.eat("*")&&(b.tokenize=c,c(a,b))}},name:"css",helperType:"gss"})})},{"../../lib/codemirror":59}],62:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";a.defineMode("diff",function(){var a={"+":"positive","-":"negative",&qu
 ot;@":"meta"};return{token:function(b){var c=b.string.search(/[\t ]+?$/);if(!b.sol()||0===c)return b.skipToEnd(),("error "+(a[b.string.charAt(0)]||"")).replace(/ $/,"");var d=a[b.peek()]||b.skipToEnd();return c===-1?b.skipToEnd():b.pos=c,d}}}),a.defineMIME("text/x-diff","diff")})},{"../../lib/codemirror":59}],63:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror"),a("../markdown/markdown"),a("../../addon/mode/overlay")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../markdown/markdown","../../addon/mode/overlay"],d):d(CodeMirror)}(function(a){"use strict";var b=/^((?:(?:aaas?|about|acap|adiumxtra|af[ps]|aim|apt|attachment|aw|beshare|bitcoin|bolo|callto|cap|chrome(?:-extension)?|cid|coap|com-eventbrite-attendee|content|crid|cvs|
 data|dav|dict|dlna-(?:playcontainer|playsingle)|dns|doi|dtn|dvb|ed2k|facetime|feed|file|finger|fish|ftp|geo|gg|git|gizmoproject|go|gopher|gtalk|h323|hcp|https?|iax|icap|icon|im|imap|info|ipn|ipp|irc[6s]?|iris(?:\.beep|\.lwz|\.xpc|\.xpcs)?|itms|jar|javascript|jms|keyparc|lastfm|ldaps?|magnet|mailto|maps|market|message|mid|mms|ms-help|msnim|msrps?|mtqp|mumble|mupdate|mvn|news|nfs|nih?|nntp|notes|oid|opaquelocktoken|palm|paparazzi|platform|pop|pres|proxy|psyc|query|res(?:ource)?|rmi|rsync|rtmp|rtsp|secondlife|service|session|sftp|sgn|shttp|sieve|sips?|skype|sm[bs]|snmp|soap\.beeps?|soldat|spotify|ssh|steam|svn|tag|teamspeak|tel(?:net)?|tftp|things|thismessage|tip|tn3270|tv|udp|unreal|urn|ut2004|vemmi|ventrilo|view-source|webcal|wss?|wtai|wyciwyg|xcon(?:-userid)?|xfire|xmlrpc\.beeps?|xmpp|xri|ymsgr|z39\.50[rs]?):(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]|\([^\s()<>]*\))+(?:\([^\s()<>]*\)|[^\s`*!()\[\]{};:'".,<>?\xab\xbb\u201
 c\u201d\u2018\u2019]))/i;a.defineMode("gfm",function(c,d){function e(a){return a.code=!1,null}var f=0,g={startState:function(){return{code:!1,codeBlock:!1,ateSpace:!1}},copyState:function(a){return{code:a.code,codeBlock:a.codeBlock,ateSpace:a.ateSpace}},token:function(a,c){if(c.combineTokens=null,c.codeBlock)return a.match(/^```+/)?(c.codeBlock=!1,null):(a.skipToEnd(),null);if(a.sol()&&(c.code=!1),a.sol()&&a.match(/^```+/))return a.skipToEnd(),c.codeBlock=!0,null;if("`"===a.peek()){a.next();var e=a.pos;a.eatWhile("`");var g=1+a.pos-e;return c.code?g===f&&(c.code=!1):(f=g,c.code=!0),null}if(c.code)return a.next(),null;if(a.eatSpace())return c.ateSpace=!0,null;if((a.sol()||c.ateSpace)&&(c.ateSpace=!1,d.gitHubSpice!==!1)){if(a.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+@)?(?:[a-f0-9]{7,40}\b)/))return c.combineTokens=!0,"link";if(a.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+)?#[0-9]+\b/))return c.combineT
 okens=!0,"link"}return a.match(b)&&"]("!=a.string.slice(a.start-2,a.start)&&(0==a.start||/\W/.test(a.string.charAt(a.start-1)))?(c.combineTokens=!0,"link"):(a.next(),null)},blankLine:e},h={taskLists:!0,strikethrough:!0,emoji:!0};for(var i in d)h[i]=d[i];return h.name="markdown",a.overlayMode(a.getMode(c,h),g)},"markdown"),a.defineMIME("text/x-gfm","gfm")})},{"../../addon/mode/overlay":37,"../../lib/codemirror":59,"../markdown/markdown":68}],64:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror"),a("../xml/xml"),a("../javascript/javascript"),a("../css/css")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../xml/xml","../javascript/javascript","../css/css"],d):d(CodeMirror)}(functi
 on(a){"use strict";function b(a,b,c){var d=a.current(),e=d.search(b);return e>-1?a.backUp(d.length-e):d.match(/<\/?$/)&&(a.backUp(d.length),a.match(b,!1)||a.match(d)),c}function c(a){var b=i[a];return b?b:i[a]=new RegExp("\\s+"+a+"\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*")}function d(a,b){var d=a.match(c(b));return d?/^\s*(.*?)\s*$/.exec(d[2])[1]:""}function e(a,b){return new RegExp((b?"^":"")+"</s*"+a+"s*>","i")}function f(a,b){for(var c in a)for(var d=b[c]||(b[c]=[]),e=a[c],f=e.length-1;f>=0;f--)d.unshift(e[f])}function g(a,b){for(var c=0;c<a.length;c++){var e=a[c];if(!e[0]||e[1].test(d(b,e[0])))return e[2]}}var h={script:[["lang",/(javascript|babel)/i,"javascript"],["type",/^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^module$|^$/i,"javascript"],["type",/./,"text/plain"],[null,null,"ja
 vascript"]],style:[["lang",/^css$/i,"css"],["type",/^(text\/)?(x-)?(stylesheet|css)$/i,"css"],["type",/./,"text/plain"],[null,null,"css"]]},i={};a.defineMode("htmlmixed",function(c,d){function i(d,f){var h,l=j.token(d,f.htmlState),m=/\btag\b/.test(l);if(m&&!/[<>\s\/]/.test(d.current())&&(h=f.htmlState.tagName&&f.htmlState.tagName.toLowerCase())&&k.hasOwnProperty(h))f.inTag=h+" ";else if(f.inTag&&m&&/>$/.test(d.current())){var n=/^([\S]+) (.*)/.exec(f.inTag);f.inTag=null;var o=">"==d.current()&&g(k[n[1]],n[2]),p=a.getMode(c,o),q=e(n[1],!0),r=e(n[1],!1);f.token=function(a,c){return a.match(q,!1)?(c.token=i,c.localState=c.localMode=null,null):b(a,r,c.localMode.token(a,c.localState))},f.localMode=p,f.localState=a.startState(p,j.indent(f.htmlState,""))}else f.inTag&&(f.inTag+=d.current(),d.eol()&
 &(f.inTag+=" "));return l}var j=a.getMode(c,{name:"xml",htmlMode:!0,multilineTagIndentFactor:d.multilineTagIndentFactor,multilineTagIndentPastTag:d.multilineTagIndentPastTag}),k={},l=d&&d.tags,m=d&&d.scriptTypes;if(f(h,k),l&&f(l,k),m)for(var n=m.length-1;n>=0;n--)k.script.unshift(["type",m[n].matches,m[n].mode]);return{startState:function(){var b=a.startState(j);return{token:i,inTag:null,localMode:null,localState:null,htmlState:b}},copyState:function(b){var c;return b.localState&&(c=a.copyState(b.localMode,b.localState)),{token:b.token,inTag:b.inTag,localMode:b.localMode,localState:c,htmlState:a.copyState(j,b.htmlState)}},token:function(a,b){return b.token(a,b)},indent:function(b,c,d){return!b.localMode||/^\s*<\//.test(c)?j.indent(b.htmlState,c):b.localMode.indent?b.localMode.indent(b.localState,c,d):a.Pass},innerMode:function(a){return{state:a.localState||a.htmlState,mode:a.localMode||j}}}},"xml",&quo
 t;javascript","css"),a.defineMIME("text/html","htmlmixed")})},{"../../lib/codemirror":59,"../css/css":61,"../javascript/javascript":66,"../xml/xml":75}],65:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";a.defineMode("http",function(){function a(a,b){return a.skipToEnd(),b.cur=g,"error"}function b(b,d){return b.match(/^HTTP\/\d\.\d/)?(d.cur=c,"keyword"):b.match(/^[A-Z]+/)&&/[ \t]/.test(b.peek())?(d.cur=e,"keyword"):a(b,d)}function c(b,c){var e=b.match(/^\d+/);if(!e)return a(b,c);c.cur=d;var f=Number(e[0]);return f>=100&&f<200?"positive informational":f>=200&&f<300?"positive success&quo
 t;:f>=300&&f<400?"positive redirect":f>=400&&f<500?"negative client-error":f>=500&&f<600?"negative server-error":"error"}function d(a,b){return a.skipToEnd(),b.cur=g,null}function e(a,b){return a.eatWhile(/\S/),b.cur=f,"string-2"}function f(b,c){return b.match(/^HTTP\/\d\.\d$/)?(c.cur=g,"keyword"):a(b,c)}function g(a){return a.sol()&&!a.eat(/[ \t]/)?a.match(/^.*?:/)?"atom":(a.skipToEnd(),"error"):(a.skipToEnd(),"string")}function h(a){return a.skipToEnd(),null}return{token:function(a,b){var c=b.cur;return c!=g&&c!=h&&a.eatSpace()?null:c(a,b)},blankLine:function(a){a.cur=h},startState:function(){return{cur:b}}}}),a.defineMIME("message/http","http")})},{"../../lib/codemirror":59}],66:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/cod
 emirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";a.defineMode("javascript",function(b,c){function d(a){for(var b,c=!1,d=!1;null!=(b=a.next());){if(!c){if("/"==b&&!d)return;"["==b?d=!0:d&&"]"==b&&(d=!1)}c=!c&&"\\"==b}}function e(a,b,c){return Aa=a,Ba=c,b}function f(a,b){var c=a.next();if('"'==c||"'"==c)return b.tokenize=g(c),b.tokenize(a,b);if("."==c&&a.match(/^\d+(?:[eE][+\-]?\d+)?/))return e("number","number");if("."==c&&a.match(".."))return e("spread","meta");if(/[\[\]{}\(\),;\:\.]/.test(c))return e(c);if("="==c&&a.eat(">"))return e("=>","operator");if("0"==c&&a.eat(/x/i))return a.eatWhile(/[\da-f]/i),e("numbe
 r","number");if("0"==c&&a.eat(/o/i))return a.eatWhile(/[0-7]/i),e("number","number");if("0"==c&&a.eat(/b/i))return a.eatWhile(/[01]/i),e("number","number");if(/\d/.test(c))return a.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/),e("number","number");if("/"==c)return a.eat("*")?(b.tokenize=h,h(a,b)):a.eat("/")?(a.skipToEnd(),e("comment","comment")):za(a,b,1)?(d(a),a.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/),e("regexp","string-2")):(a.eatWhile(Ja),e("operator","operator",a.current()));if("`"==c)return b.tokenize=i,i(a,b);if("#"==c)return a.skipToEnd(),e("error","error");if(Ja.test(c))return">"==c&&b.lexical&&">"==b.lexical.type||a.eatWhile(Ja),e("operator","operator",a.current());if(Ha.test(c))
 {a.eatWhile(Ha);var f=a.current();if("."!=b.lastType){if(Ia.propertyIsEnumerable(f)){var j=Ia[f];return e(j.type,j.style,f)}if("async"==f&&a.match(/^\s*[\(\w]/,!1))return e("async","keyword",f)}return e("variable","variable",f)}}function g(a){return function(b,c){var d,g=!1;if(Ea&&"@"==b.peek()&&b.match(Ka))return c.tokenize=f,e("jsonld-keyword","meta");for(;null!=(d=b.next())&&(d!=a||g);)g=!g&&"\\"==d;return g||(c.tokenize=f),e("string","string")}}function h(a,b){for(var c,d=!1;c=a.next();){if("/"==c&&d){b.tokenize=f;break}d="*"==c}return e("comment","comment")}function i(a,b){for(var c,d=!1;null!=(c=a.next());){if(!d&&("`"==c||"$"==c&&a.eat("{"))){b.tokenize=f;break}d=!d&&"\\"==c}return e("quasi","s
 tring-2",a.current())}function j(a,b){b.fatArrowAt&&(b.fatArrowAt=null);var c=a.string.indexOf("=>",a.start);if(!(c<0)){if(Ga){var d=/:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(a.string.slice(a.start,c));d&&(c=d.index)}for(var e=0,f=!1,g=c-1;g>=0;--g){var h=a.string.charAt(g),i=La.indexOf(h);if(i>=0&&i<3){if(!e){++g;break}if(0==--e){"("==h&&(f=!0);break}}else if(i>=3&&i<6)++e;else if(Ha.test(h))f=!0;else{if(/["'\/]/.test(h))return;if(f&&!e){++g;break}}}f&&!e&&(b.fatArrowAt=g)}}function k(a,b,c,d,e,f){this.indented=a,this.column=b,this.type=c,this.prev=e,this.info=f,null!=d&&(this.align=d)}function l(a,b){for(var c=a.localVars;c;c=c.next)if(c.name==b)return!0;for(var d=a.context;d;d=d.prev)for(var c=d.vars;c;c=c.next)if(c.name==b)return!0}function m(a,b,c,d,e){var f=a.cc;for(Na.state=a,Na.stream=e,Na.marked=null,Na.cc=f,Na.style=b,a.lexical.hasOwnP
 roperty("align")||(a.lexical.align=!0);;){var g=f.length?f.pop():Fa?w:v;if(g(c,d)){for(;f.length&&f[f.length-1].lex;)f.pop()();return Na.marked?Na.marked:"variable"==c&&l(a,d)?"variable-2":b}}}function n(){for(var a=arguments.length-1;a>=0;a--)Na.cc.push(arguments[a])}function o(){return n.apply(null,arguments),!0}function p(a){function b(b){for(var c=b;c;c=c.next)if(c.name==a)return!0;return!1}var d=Na.state;if(Na.marked="def",d.context){if(b(d.localVars))return;d.localVars={name:a,next:d.localVars}}else{if(b(d.globalVars))return;c.globalVars&&(d.globalVars={name:a,next:d.globalVars})}}function q(){Na.state.context={prev:Na.state.context,vars:Na.state.localVars},Na.state.localVars=Oa}function r(){Na.state.localVars=Na.state.context.vars,Na.state.context=Na.state.context.prev}function s(a,b){var c=function(){var c=Na.state,d=c.indented;if("stat"==c.lexical.type)d=c.lexical.indented;else for(var e=c.lexical;
 e&&")"==e.type&&e.align;e=e.prev)d=e.indented;c.lexical=new k(d,Na.stream.column(),a,null,c.lexical,b)};return c.lex=!0,c}function t(){var a=Na.state;a.lexical.prev&&(")"==a.lexical.type&&(a.indented=a.lexical.indented),a.lexical=a.lexical.prev)}function u(a){function b(c){return c==a?o():";"==a?n():o(b)}return b}function v(a,b){return"var"==a?o(s("vardef",b.length),$,u(";"),t):"keyword a"==a?o(s("form"),y,v,t):"keyword b"==a?o(s("form"),v,t):"{"==a?o(s("}"),S,t):";"==a?o():"if"==a?("else"==Na.state.lexical.info&&Na.state.cc[Na.state.cc.length-1]==t&&Na.state.cc.pop()(),o(s("form"),y,v,t,da)):"function"==a?o(ja):"for"==a?o(s("form"),ea,v,t):"variable"==a?Ga&&"type"==b?(Na.marked="keyword",o(U,u("operator&qu
 ot;),U,u(";"))):Ga&&"declare"==b?(Na.marked="keyword",o(v)):o(s("stat"),L):"switch"==a?o(s("form"),y,u("{"),s("}","switch"),S,t,t):"case"==a?o(w,u(":")):"default"==a?o(u(":")):"catch"==a?o(s("form"),q,u("("),ka,u(")"),v,t,r):"class"==a?o(s("form"),ma,t):"export"==a?o(s("stat"),qa,t):"import"==a?o(s("stat"),sa,t):"module"==a?o(s("form"),_,u("{"),s("}"),S,t,t):"async"==a?o(v):"@"==b?o(w,v):n(s("stat"),w,u(";"),t)}function w(a){return z(a,!1)}function x(a){return z(a,!0)}function y(a){return"("!=a?n():o(s(")"),w,u(")"),t)}function z(a,b){if(Na.state.fatArrowAt==Na.stream.start){var c=b?H:G;if("("==a)return o(q,s(")"),Q(ka,&q
 uot;)"),t,u("=>"),c,r);if("variable"==a)return n(q,_,u("=>"),c,r)}var d=b?D:C;return Ma.hasOwnProperty(a)?o(d):"function"==a?o(ja,d):"class"==a?o(s("form"),la,t):"keyword c"==a||"async"==a?o(b?B:A):"("==a?o(s(")"),A,u(")"),t,d):"operator"==a||"spread"==a?o(b?x:w):"["==a?o(s("]"),xa,t,d):"{"==a?R(N,"}",null,d):"quasi"==a?n(E,d):"new"==a?o(I(b)):o()}function A(a){return a.match(/[;\}\)\],]/)?n():n(w)}function B(a){return a.match(/[;\}\)\],]/)?n():n(x)}function C(a,b){return","==a?o(w):D(a,b,!1)}function D(a,b,c){var d=0==c?C:D,e=0==c?w:x;return"=>"==a?o(q,c?H:G,r):"operator"==a?/\+\+|--/.test(b)||Ga&&"!"==b?o(d):"?"==b?o(w,u(":"),e):o(e):"quasi"==a?n(E,d):";"!=a?"("==a?R(x,")",&
 quot;call",d):"."==a?o(M,d):"["==a?o(s("]"),A,u("]"),t,d):Ga&&"as"==b?(Na.marked="keyword",o(U,d)):void 0:void 0}function E(a,b){return"quasi"!=a?n():"${"!=b.slice(b.length-2)?o(E):o(w,F)}function F(a){if("}"==a)return Na.marked="string-2",Na.state.tokenize=i,o(E)}function G(a){return j(Na.stream,Na.state),n("{"==a?v:w)}function H(a){return j(Na.stream,Na.state),n("{"==a?v:x)}function I(a){return function(b){return"."==b?o(a?K:J):"variable"==b&&Ga?o(Z,a?D:C):n(a?x:w)}}function J(a,b){if("target"==b)return Na.marked="keyword",o(C)}function K(a,b){if("target"==b)return Na.marked="keyword",o(D)}function L(a){return":"==a?o(t,v):n(C,u(";"),t)}function M(a){if("variable"==a)return Na.marked="property",o()}function N(a,b){if("async"==a)return
  Na.marked="property",o(N);if("variable"==a||"keyword"==Na.style){if(Na.marked="property","get"==b||"set"==b)return o(O);var c;return Ga&&Na.state.fatArrowAt==Na.stream.start&&(c=Na.stream.match(/^\s*:\s*/,!1))&&(Na.state.fatArrowAt=Na.stream.pos+c[0].length),o(P)}return"number"==a||"string"==a?(Na.marked=Ea?"property":Na.style+" property",o(P)):"jsonld-keyword"==a?o(P):"modifier"==a?o(N):"["==a?o(w,u("]"),P):"spread"==a?o(w,P):":"==a?n(P):void 0}function O(a){return"variable"!=a?n(P):(Na.marked="property",o(ja))}function P(a){return":"==a?o(x):"("==a?n(ja):void 0}function Q(a,b,c){function d(e,f){if(c?c.indexOf(e)>-1:","==e){var g=Na.state.lexical;return"call"==g.info&&(g.pos=(g.pos||0)+1),o(function(c,d){return c==b||d==b?n():n(a)
 },d)}return e==b||f==b?o():o(u(b))}return function(c,e){return c==b||e==b?o():n(a,d)}}function R(a,b,c){for(var d=3;d<arguments.length;d++)Na.cc.push(arguments[d]);return o(s(b,c),Q(a,b),t)}function S(a){return"}"==a?o():n(v,S)}function T(a,b){if(Ga){if(":"==a)return o(U);if("?"==b)return o(T)}}function U(a,b){return"variable"==a?"keyof"==b?(Na.marked="keyword",o(U)):(Na.marked="type",o(Y)):"string"==a||"number"==a||"atom"==a?o(Y):"["==a?o(s("]"),Q(U,"]",","),t,Y):"{"==a?o(s("}"),Q(W,"}",",;"),t,Y):"("==a?o(Q(X,")"),V):void 0}function V(a){if("=>"==a)return o(U)}function W(a,b){return"variable"==a||"keyword"==Na.style?(Na.marked="property",o(W)):"?"==b?o(W):":"==a?o(U):"["==a?o(w,T,u("]"),W):void 0}fun
 ction X(a){return"variable"==a?o(X):":"==a?o(U):void 0}function Y(a,b){return"<"==b?o(s(">"),Q(U,">"),t,Y):"|"==b||"."==a?o(U):"["==a?o(u("]"),Y):"extends"==b?o(U):void 0}function Z(a,b){if("<"==b)return o(s(">"),Q(U,">"),t,Y)}function $(){return n(_,T,ba,ca)}function _(a,b){return"modifier"==a?o(_):"variable"==a?(p(b),o()):"spread"==a?o(_):"["==a?R(_,"]"):"{"==a?R(aa,"}"):void 0}function aa(a,b){return"variable"!=a||Na.stream.match(/^\s*:/,!1)?("variable"==a&&(Na.marked="property"),"spread"==a?o(_):"}"==a?n():o(u(":"),_,ba)):(p(b),o(ba))}function ba(a,b){if("="==b)return o(x)}function ca(a){if(","==a)return o($)}function da(a,b){if("keyword b"==a&&"else"
 ==b)return o(s("form","else"),v,t)}function ea(a){if("("==a)return o(s(")"),fa,u(")"),t)}function fa(a){return"var"==a?o($,u(";"),ha):";"==a?o(ha):"variable"==a?o(ga):n(w,u(";"),ha)}function ga(a,b){return"in"==b||"of"==b?(Na.marked="keyword",o(w)):o(C,ha)}function ha(a,b){return";"==a?o(ia):"in"==b||"of"==b?(Na.marked="keyword",o(w)):n(w,u(";"),ia)}function ia(a){")"!=a&&o(w)}function ja(a,b){return"*"==b?(Na.marked="keyword",o(ja)):"variable"==a?(p(b),o(ja)):"("==a?o(q,s(")"),Q(ka,")"),t,T,v,r):Ga&&"<"==b?o(s(">"),Q(U,">"),t,ja):void 0}function ka(a){return"spread"==a||"modifier"==a?o(ka):n(_,T,ba)}function la(a,b){return"variable"==a?ma(a,b):na(a,b)}f
 unction ma(a,b){if("variable"==a)return p(b),o(na)}function na(a,b){return"<"==b?o(s(">"),Q(U,">"),t,na):"extends"==b||"implements"==b||Ga&&","==a?o(Ga?U:w,na):"{"==a?o(s("}"),oa,t):void 0}function oa(a,b){return"modifier"==a||"async"==a||"variable"==a&&("static"==b||"get"==b||"set"==b)&&Na.stream.match(/^\s+[\w$\xa1-\uffff]/,!1)?(Na.marked="keyword",o(oa)):"variable"==a||"keyword"==Na.style?(Na.marked="property",o(Ga?pa:ja,oa)):"["==a?o(w,u("]"),Ga?pa:ja,oa):"*"==b?(Na.marked="keyword",o(oa)):";"==a?o(oa):"}"==a?o():"@"==b?o(w,oa):void 0}function pa(a,b){return"?"==b?o(pa):":"==a?o(U,ba):"="==b?o(x):n(ja)}function qa(a,b){return"*"==b?(Na.marked="key
 word",o(wa,u(";"))):"default"==b?(Na.marked="keyword",o(w,u(";"))):"{"==a?o(Q(ra,"}"),wa,u(";")):n(v)}function ra(a,b){return"as"==b?(Na.marked="keyword",o(u("variable"))):"variable"==a?n(x,ra):void 0}function sa(a){return"string"==a?o():n(ta,ua,wa)}function ta(a,b){return"{"==a?R(ta,"}"):("variable"==a&&p(b),"*"==b&&(Na.marked="keyword"),o(va))}function ua(a){if(","==a)return o(ta,ua)}function va(a,b){if("as"==b)return Na.marked="keyword",o(ta)}function wa(a,b){if("from"==b)return Na.marked="keyword",o(w)}function xa(a){return"]"==a?o():n(Q(x,"]"))}function ya(a,b){return"operator"==a.lastType||","==a.lastType||Ja.test(b.charAt(0))||/[,.]/.test(b.charAt(0))}function za(a,b,c){return b.tokenize==f&&
 /^(?:operator|sof|keyword c|case|new|export|default|[\[{}\(,;:]|=>)$/.test(b.lastType)||"quasi"==b.lastType&&/\{\s*$/.test(a.string.slice(0,a.pos-(c||0)))}var Aa,Ba,Ca=b.indentUnit,Da=c.statementIndent,Ea=c.jsonld,Fa=c.json||Ea,Ga=c.typescript,Ha=c.wordCharacters||/[\w$\xa1-\uffff]/,Ia=function(){function a(a){return{type:a,style:"keyword"}}var b=a("keyword a"),c=a("keyword b"),d=a("keyword c"),e=a("operator"),f={type:"atom",style:"atom"},g={"if":a("if"),"while":b,"with":b,"else":c,"do":c,"try":c,"finally":c,"return":d,"break":d,"continue":d,"new":a("new"),"delete":d,"throw":d,"debugger":d,"var":a("var"),"const":a("var"),"let":a("var"),"function":a("function&quot
 ;),"catch":a("catch"),"for":a("for"),"switch":a("switch"),"case":a("case"),"default":a("default"),"in":e,"typeof":e,"instanceof":e,"true":f,"false":f,"null":f,undefined:f,NaN:f,Infinity:f,"this":a("this"),"class":a("class"),"super":a("atom"),"yield":d,"export":a("export"),"import":a("import"),"extends":d,await:d};if(Ga){var h={type:"variable",style:"type"},i={"interface":a("class"),"implements":d,namespace:d,module:a("module"),"enum":a("module"),"public":a("modifier"),"private":a("modifier"),"protected":a("modifier"),"abstract":a("modifier"),readonly:
 a("modifier"),string:h,number:h,"boolean":h,any:h};for(var j in i)g[j]=i[j]}return g}(),Ja=/[+\-*&%=<>!?|~^@]/,Ka=/^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/,La="([{}])",Ma={atom:!0,number:!0,variable:!0,string:!0,regexp:!0,"this":!0,"jsonld-keyword":!0},Na={state:null,column:null,marked:null,cc:null},Oa={name:"this",next:{name:"arguments"}};return t.lex=!0,{startState:function(a){var b={tokenize:f,lastType:"sof",cc:[],lexical:new k((a||0)-Ca,0,"block",!1),localVars:c.localVars,context:c.localVars&&{vars:c.localVars},indented:a||0};return c.globalVars&&"object"==typeof c.globalVars&&(b.globalVars=c.globalVars),b},token:function(a,b){if(a.sol()&&(b.lexical.hasOwnProperty("align")||(b.lexical.align=!1),b.indented=a.indentation(),j(a,b)),b.tokenize!=h&&a.eatSpace())return null;var
  c=b.tokenize(a,b);return"comment"==Aa?c:(b.lastType="operator"!=Aa||"++"!=Ba&&"--"!=Ba?Aa:"incdec",m(b,c,Aa,Ba,a))},indent:function(b,d){if(b.tokenize==h)return a.Pass;if(b.tokenize!=f)return 0;var e,g=d&&d.charAt(0),i=b.lexical;if(!/^\s*else\b/.test(d))for(var j=b.cc.length-1;j>=0;--j){var k=b.cc[j];if(k==t)i=i.prev;else if(k!=da)break}for(;("stat"==i.type||"form"==i.type)&&("}"==g||(e=b.cc[b.cc.length-1])&&(e==C||e==D)&&!/^[,\.=+\-*:?[\(]/.test(d));)i=i.prev;Da&&")"==i.type&&"stat"==i.prev.type&&(i=i.prev);var l=i.type,m=g==l;return"vardef"==l?i.indented+("operator"==b.lastType||","==b.lastType?i.info+1:0):"form"==l&&"{"==g?i.indented:"form"==l?i.indented+Ca:"stat"==l?i.indented+(ya(b,d)?Da||Ca:0):"switch"!=i.info||m||0==c.double
 IndentSwitch?i.align?i.column+(m?0:1):i.indented+(m?0:Ca):i.indented+(/^(?:case|default)\b/.test(d)?Ca:2*Ca)},electricInput:/^\s*(?:case .*?:|default:|\{|\})$/,blockCommentStart:Fa?null:"/*",blockCommentEnd:Fa?null:"*/",lineComment:Fa?null:"//",fold:"brace",closeBrackets:"()[]{}''\"\"``",helperType:Fa?"json":"javascript",jsonldMode:Ea,jsonMode:Fa,expressionAllowed:za,skipExpression:function(a){var b=a.cc[a.cc.length-1];b!=w&&b!=x||a.cc.pop()}}}),a.registerHelper("wordChars","javascript",/[\w$]/),a.defineMIME("text/javascript","javascript"),a.defineMIME("text/ecmascript","javascript"),a.defineMIME("application/javascript","javascript"),a.defineMIME("application/x-javascript","javascript"),a.defineMIME("application/ecmascript","javascript"),a.defineMIME("application/json&quot
 ;,{name:"javascript",json:!0}),a.defineMIME("application/x-json",{name:"javascript",json:!0}),a.defineMIME("application/ld+json",{name:"javascript",jsonld:!0}),a.defineMIME("text/typescript",{name:"javascript",typescript:!0}),a.defineMIME("application/typescript",{name:"javascript",typescript:!0})})},{"../../lib/codemirror":59}],67:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror"),a("../xml/xml"),a("../javascript/javascript")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../xml/xml","../javascript/javascript"],d):d(CodeMirror)}(function(a){"use strict";function b(a,b,c,d){this.state=a,this.mode=b,this.depth=c,this.prev=d}function c(d){return new b(a.copyState(d.mode,d.state),d.mode,d.depth,d.prev&amp
 ;&c(d.prev))}a.defineMode("jsx",function(d,e){function f(a){var b=a.tagName;a.tagName=null;var c=j.indent(a,"");return a.tagName=b,c}function g(a,b){return b.context.mode==j?h(a,b,b.context):i(a,b,b.context)}function h(c,e,h){if(2==h.depth)return c.match(/^.*?\*\//)?h.depth=1:c.skipToEnd(),"comment";if("{"==c.peek()){j.skipAttribute(h.state);var i=f(h.state),l=h.state.context;if(l&&c.match(/^[^>]*>\s*$/,!1)){for(;l.prev&&!l.startOfLine;)l=l.prev;l.startOfLine?i-=d.indentUnit:h.prev.state.lexical&&(i=h.prev.state.lexical.indented)}else 1==h.depth&&(i+=d.indentUnit);return e.context=new b(a.startState(k,i),k,0,e.context),null}if(1==h.depth){if("<"==c.peek())return j.skipAttribute(h.state),e.context=new b(a.startState(j,f(h.state)),j,0,e.context),null;if(c.match("//"))return c.skipToEnd(),"comment";if(c.match("/*"))return h.depth=2,g(c,e)}var m,n=j.token(c,h.stat
 e),o=c.current();return/\btag\b/.test(n)?/>$/.test(o)?h.state.context?h.depth=0:e.context=e.context.prev:/^</.test(o)&&(h.depth=1):!n&&(m=o.indexOf("{"))>-1&&c.backUp(o.length-m),n}function i(c,d,e){if("<"==c.peek()&&k.expressionAllowed(c,e.state))return k.skipExpression(e.state),d.context=new b(a.startState(j,k.indent(e.state,"")),j,0,d.context),null;var f=k.token(c,e.state);if(!f&&null!=e.depth){var g=c.current();"{"==g?e.depth++:"}"==g&&0==--e.depth&&(d.context=d.context.prev)}return f}var j=a.getMode(d,{name:"xml",allowMissing:!0,multilineTagIndentPastTag:!1}),k=a.getMode(d,e&&e.base||"javascript");return{startState:function(){return{context:new b(a.startState(k),k)}},copyState:function(a){return{context:c(a.context)}},token:g,indent:function(a,b,c){return a.context.mode.indent(a.context.state,b,c)},innerMode:function(a){return a.conte
 xt}}},"xml","javascript"),a.defineMIME("text/jsx","jsx"),a.defineMIME("text/typescript-jsx",{name:"jsx",base:{name:"javascript",typescript:!0}})})},{"../../lib/codemirror":59,"../javascript/javascript":66,"../xml/xml":75}],68:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror"),a("../xml/xml"),a("../meta")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../xml/xml","../meta"],d):d(CodeMirror)}(function(a){"use strict";a.defineMode("markdown",function(b,c){function d(c){if(a.findModeByName){var d=a.findModeByName(c);d&&(c=d.mime||d.mimes[0])}var e=a.getMode(b,c);return"null"==e.name?null:e}function e(a,b,c){return b.f=b.inline=c,c(a,b)}function f(a,b,c){return b.f=b.block=c,c(a,
 b)}function g(a){return!a||!/\S/.test(a.string)}function h(a){return a.linkTitle=!1,a.em=!1,a.strong=!1,a.strikethrough=!1,a.quote=0,a.indentedCode=!1,a.f==j&&(a.f=n,a.block=i),a.trailingSpace=0,a.trailingSpaceNewLine=!1,a.prevLine=a.thisLine,a.thisLine={stream:null},null}function i(b,f){var h=b.column()===f.indentation,i=g(f.prevLine.stream),j=f.indentedCode,m=f.prevLine.hr,n=f.list!==!1,o=(f.listStack[f.listStack.length-1]||0)+3;f.indentedCode=!1;var p=f.indentation;if(null===f.indentationDiff&&(f.indentationDiff=f.indentation,n)){for(f.list=null;p<f.listStack[f.listStack.length-1];)f.listStack.pop(),f.listStack.length?f.indentation=f.listStack[f.listStack.length-1]:f.list=!1;f.list!==!1&&(f.indentationDiff=p-f.listStack[f.listStack.length-1])}var q=!(i||m||f.prevLine.header||n&&j||f.prevLine.fencedCodeEnd),s=(f.list===!1||m||i)&&f.indentation<=o&&b.match(y),t=null;if(f.indentationDiff>=4&&(j||f.prevLine.fencedCodeEn
 d||f.prevLine.header||i))return b.skipToEnd(),f.indentedCode=!0,w.code;if(b.eatSpace())return null;if(h&&f.indentation<=o&&(t=b.match(B))&&t[1].length<=6)return f.quote=0,f.header=t[1].length,f.thisLine.header=!0,c.highlightFormatting&&(f.formatting="header"),f.f=f.inline,l(f);if(f.indentation<=o&&b.eat(">"))return f.quote=h?1:f.quote+1,c.highlightFormatting&&(f.formatting="quote"),b.eatSpace(),l(f);if(!s&&!f.setext&&h&&f.indentation<=o&&(t=b.match(z))){var u=t[1]?"ol":"ul";return f.indentation=p+b.current().length,f.list=!0,f.quote=0,f.listStack.push(f.indentation),c.taskLists&&b.match(A,!1)&&(f.taskList=!0),f.f=f.inline,c.highlightFormatting&&(f.formatting=["list","list-"+u]),l(f)}return h&&f.indentation<=o&&(t=b.match(E,!0))?(f.quote=0,f.fencedEndRE=new RegExp(t[1]+"+ *$
 "),f.localMode=c.fencedCodeBlockHighlighting&&d(t[2]),f.localMode&&(f.localState=a.startState(f.localMode)),f.f=f.block=k,c.highlightFormatting&&(f.formatting="code-block"),f.code=-1,l(f)):f.setext||!(q&&n||f.quote||f.list!==!1||f.code||s||F.test(b.string))&&(t=b.lookAhead(1))&&(t=t.match(C))?(f.setext?(f.header=f.setext,f.setext=0,b.skipToEnd(),c.highlightFormatting&&(f.formatting="header")):(f.header="="==t[0].charAt(0)?1:2,f.setext=f.header),f.thisLine.header=!0,f.f=f.inline,l(f)):s?(b.skipToEnd(),f.hr=!0,f.thisLine.hr=!0,w.hr):"["===b.peek()?e(b,f,r):e(b,f,f.inline)}function j(b,c){var d=u.token(b,c.htmlState);if(!v){var e=a.innerMode(u,c.htmlState);("xml"==e.mode.name&&null===e.state.tagStart&&!e.state.context&&e.state.tokenize.isInText||c.md_inside&&b.current().indexOf(">")>-1)&&(c.f=n,c.block=i,c.htmlState=null)
 }return d}function k(a,b){var d=b.listStack[b.listStack.length-1]||0,e=b.indentation<d,g=d+3;if(b.fencedEndRE&&b.indentation<=g&&(e||a.match(b.fencedEndRE))){c.highlightFormatting&&(b.formatting="code-block");var h;return e||(h=l(b)),b.localMode=b.localState=null,b.block=i,b.f=n,b.fencedEndRE=null,b.code=0,b.thisLine.fencedCodeEnd=!0,e?f(a,b,b.block):h}return b.localMode?b.localMode.token(a,b.localState):(a.skipToEnd(),w.code)}function l(a){var b=[];if(a.formatting){b.push(w.formatting),"string"==typeof a.formatting&&(a.formatting=[a.formatting]);for(var d=0;d<a.formatting.length;d++)b.push(w.formatting+"-"+a.formatting[d]),"header"===a.formatting[d]&&b.push(w.formatting+"-"+a.formatting[d]+"-"+a.header),"quote"===a.formatting[d]&&(!c.maxBlockquoteDepth||c.maxBlockquoteDepth>=a.quote?b.push(w.formatting+"-"+a.formatting[d]+"-"+a.quote)
 :b.push("error"))}if(a.taskOpen)return b.push("meta"),b.length?b.join(" "):null;if(a.taskClosed)return b.push("property"),b.length?b.join(" "):null;if(a.linkHref?b.push(w.linkHref,"url"):(a.strong&&b.push(w.strong),a.em&&b.push(w.em),a.strikethrough&&b.push(w.strikethrough),a.emoji&&b.push(w.emoji),a.linkText&&b.push(w.linkText),a.code&&b.push(w.code),a.image&&b.push(w.image),a.imageAltText&&b.push(w.imageAltText,"link"),a.imageMarker&&b.push(w.imageMarker)),a.header&&b.push(w.header,w.header+"-"+a.header),a.quote&&(b.push(w.quote),!c.maxBlockquoteDepth||c.maxBlockquoteDepth>=a.quote?b.push(w.quote+"-"+a.quote):b.push(w.quote+"-"+c.maxBlockquoteDepth)),a.list!==!1){var e=(a.listStack.length-1)%3;e?1===e?b.push(w.list2):b.push(w.list3):b.push(w.list1)}return a.trailingSpaceNewLine?b.push("tr
 ailing-space-new-line"):a.trailingSpace&&b.push("trailing-space-"+(a.trailingSpace%2?"a":"b")),b.length?b.join(" "):null}function m(a,b){if(a.match(D,!0))return l(b)}function n(b,d){var e=d.text(b,d);if("undefined"!=typeof e)return e;if(d.list)return d.list=null,l(d);if(d.taskList){var g=" "===b.match(A,!0)[1];return g?d.taskOpen=!0:d.taskClosed=!0,c.highlightFormatting&&(d.formatting="task"),d.taskList=!1,
+l(d)}if(d.taskOpen=!1,d.taskClosed=!1,d.header&&b.match(/^#+$/,!0))return c.highlightFormatting&&(d.formatting="header"),l(d);var h=b.next();if(d.linkTitle){d.linkTitle=!1;var i=h;"("===h&&(i=")"),i=(i+"").replace(/([.?*+^\[\]\\(){}|-])/g,"\\$1");var k="^\\s*(?:[^"+i+"\\\\]+|\\\\\\\\|\\\\.)"+i;if(b.match(new RegExp(k),!0))return w.linkHref}if("`"===h){var m=d.formatting;c.highlightFormatting&&(d.formatting="code"),b.eatWhile("`");var q=b.current().length;if(0!=d.code||d.quote&&1!=q){if(q==d.code){var r=l(d);return d.code=0,r}return d.formatting=m,l(d)}return d.code=q,l(d)}if(d.code)return l(d);if("\\"===h&&(b.next(),c.highlightFormatting)){var s=l(d),t=w.formatting+"-escape";return s?s+" "+t:t}if("!"===h&&b.match(/\[[^\]]*\] ?(?:\(|\[)/,!1))return d.imageMarker=!0,d.image=!0,c.highlightForm
 atting&&(d.formatting="image"),l(d);if("["===h&&d.imageMarker&&b.match(/[^\]]*\](\(.*?\)| ?\[.*?\])/,!1))return d.imageMarker=!1,d.imageAltText=!0,c.highlightFormatting&&(d.formatting="image"),l(d);if("]"===h&&d.imageAltText){c.highlightFormatting&&(d.formatting="image");var s=l(d);return d.imageAltText=!1,d.image=!1,d.inline=d.f=p,s}if("["===h&&!d.image)return d.linkText=!0,c.highlightFormatting&&(d.formatting="link"),l(d);if("]"===h&&d.linkText){c.highlightFormatting&&(d.formatting="link");var s=l(d);return d.linkText=!1,d.inline=d.f=b.match(/\(.*?\)| ?\[.*?\]/,!1)?p:n,s}if("<"===h&&b.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/,!1)){d.f=d.inline=o,c.highlightFormatting&&(d.formatting="link");var s=l(d);return s?s+=" ":s="",s+w.linkInline}if("&l
 t;"===h&&b.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/,!1)){d.f=d.inline=o,c.highlightFormatting&&(d.formatting="link");var s=l(d);return s?s+=" ":s="",s+w.linkEmail}if(c.xml&&"<"===h&&b.match(/^(!--|[a-z]+(?:\s+[a-z_:.\-]+(?:\s*=\s*[^ >]+)?)*\s*>)/i,!1)){var v=b.string.indexOf(">",b.pos);if(v!=-1){var x=b.string.substring(b.start,v);/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(x)&&(d.md_inside=!0)}return b.backUp(1),d.htmlState=a.startState(u),f(b,d,j)}if(c.xml&&"<"===h&&b.match(/^\/\w*?>/))return d.md_inside=!1,"tag";if("*"===h||"_"===h){for(var y=1,z=1==b.pos?" ":b.string.charAt(b.pos-2);y<3&&b.eat(h);)y++;var B=b.peek()||" ",C=!/\s/.test(B)&&(!G.test(B)||/\s/.test(z)||G.test(z)),D=!/\s/.test(z)&&(!G.test(z)||/\s/.test(B)||G.test(B)),E=null,F=null;if(y%2&
 &(d.em||!C||"*"!==h&&D&&!G.test(z)?d.em!=h||!D||"*"!==h&&C&&!G.test(B)||(E=!1):E=!0),y>1&&(d.strong||!C||"*"!==h&&D&&!G.test(z)?d.strong!=h||!D||"*"!==h&&C&&!G.test(B)||(F=!1):F=!0),null!=F||null!=E){c.highlightFormatting&&(d.formatting=null==E?"strong":null==F?"em":"strong em"),E===!0&&(d.em=h),F===!0&&(d.strong=h);var r=l(d);return E===!1&&(d.em=!1),F===!1&&(d.strong=!1),r}}else if(" "===h&&(b.eat("*")||b.eat("_"))){if(" "===b.peek())return l(d);b.backUp(1)}if(c.strikethrough)if("~"===h&&b.eatWhile(h)){if(d.strikethrough){c.highlightFormatting&&(d.formatting="strikethrough");var r=l(d);return d.strikethrough=!1,r}if(b.match(/^[^\s]/,!1))return d.strikethrough=!0,c.highlightFormatting&&(d.formatting="
 strikethrough"),l(d)}else if(" "===h&&b.match(/^~~/,!0)){if(" "===b.peek())return l(d);b.backUp(2)}if(c.emoji&&":"===h&&b.match(/^[a-z_\d+-]+:/)){d.emoji=!0,c.highlightFormatting&&(d.formatting="emoji");var H=l(d);return d.emoji=!1,H}return" "===h&&(b.match(/ +$/,!1)?d.trailingSpace++:d.trailingSpace&&(d.trailingSpaceNewLine=!0)),l(d)}function o(a,b){var d=a.next();if(">"===d){b.f=b.inline=n,c.highlightFormatting&&(b.formatting="link");var e=l(b);return e?e+=" ":e="",e+w.linkInline}return a.match(/^[^>]+/,!0),w.linkInline}function p(a,b){if(a.eatSpace())return null;var d=a.next();return"("===d||"["===d?(b.f=b.inline=q("("===d?")":"]"),c.highlightFormatting&&(b.formatting="link-string"),b.linkHref=!0,l(b)):"error"}function q(a){return function(b,d){var 
 e=b.next();if(e===a){d.f=d.inline=n,c.highlightFormatting&&(d.formatting="link-string");var f=l(d);return d.linkHref=!1,f}return b.match(I[a]),d.linkHref=!0,l(d)}}function r(a,b){return a.match(/^([^\]\\]|\\.)*\]:/,!1)?(b.f=s,a.next(),c.highlightFormatting&&(b.formatting="link"),b.linkText=!0,l(b)):e(a,b,n)}function s(a,b){if(a.match(/^\]:/,!0)){b.f=b.inline=t,c.highlightFormatting&&(b.formatting="link");var d=l(b);return b.linkText=!1,d}return a.match(/^([^\]\\]|\\.)+/,!0),w.linkText}function t(a,b){return a.eatSpace()?null:(a.match(/^[^\s]+/,!0),void 0===a.peek()?b.linkTitle=!0:a.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/,!0),b.f=b.inline=n,w.linkHref+" url")}var u=a.getMode(b,"text/html"),v="null"==u.name;void 0===c.highlightFormatting&&(c.highlightFormatting=!1),void 0===c.maxBlockquoteDepth&&(c.maxBlockquoteDepth=0),
 void 0===c.taskLists&&(c.taskLists=!1),void 0===c.strikethrough&&(c.strikethrough=!1),void 0===c.emoji&&(c.emoji=!1),void 0===c.fencedCodeBlockHighlighting&&(c.fencedCodeBlockHighlighting=!0),void 0===c.xml&&(c.xml=!0),void 0===c.tokenTypeOverrides&&(c.tokenTypeOverrides={});var w={header:"header",code:"comment",quote:"quote",list1:"variable-2",list2:"variable-3",list3:"keyword",hr:"hr",image:"image",imageAltText:"image-alt-text",imageMarker:"image-marker",formatting:"formatting",linkInline:"link",linkEmail:"link",linkText:"link",linkHref:"string",em:"em",strong:"strong",strikethrough:"strikethrough",emoji:"builtin"};for(var x in w)w.hasOwnProperty(x)&&c.tokenTypeOverrides[x]&&(w[x]=c.tokenTypeOverrides[x]);var y=/^([*\-_])(?:\s*\1){
 2,}\s*$/,z=/^(?:[*\-+]|^[0-9]+([.)]))\s+/,A=/^\[(x| )\](?=\s)/i,B=c.allowAtxHeaderWithoutSpace?/^(#+)/:/^(#+)(?: |$)/,C=/^ *(?:\={1,}|-{1,})\s*$/,D=/^[^#!\[\]*_\\<>` "'(~:]+/,E=/^(~~~+|```+)[ \t]*([\w+#-]*)[^\n`]*$/,F=/^\s*\[[^\]]+?\]:\s*\S+(\s*\S*\s*)?$/,G=/[!\"#$%&\'()*+,\-\.\/:;<=>?@\[\\\]^_`{|}~\u2014]/,H="    ",I={")":/^(?:[^\\\(\)]|\\.|\((?:[^\\\(\)]|\\.)*\))*?(?=\))/,"]":/^(?:[^\\\[\]]|\\.|\[(?:[^\\\[\]]|\\.)*\])*?(?=\])/},J={startState:function(){return{f:i,prevLine:{stream:null},thisLine:{stream:null},block:i,htmlState:null,indentation:0,inline:n,text:m,formatting:!1,linkText:!1,linkHref:!1,linkTitle:!1,code:0,em:!1,strong:!1,header:0,setext:0,hr:!1,taskList:!1,list:!1,listStack:[],quote:0,trailingSpace:0,trailingSpaceNewLine:!1,strikethrough:!1,emoji:!1,fencedEndRE:null}},copyState:function(b){return{f:b.f,prevLine:b.prevLine,thisLine:b.thisLine,block:b.block,htmlState:b.htmlState&&a.copyState(u,b.htmlState),i
 ndentation:b.indentation,localMode:b.localMode,localState:b.localMode?a.copyState(b.localMode,b.localState):null,inline:b.inline,text:b.text,formatting:!1,linkText:b.linkText,linkTitle:b.linkTitle,code:b.code,em:b.em,strong:b.strong,strikethrough:b.strikethrough,emoji:b.emoji,header:b.header,setext:b.setext,hr:b.hr,taskList:b.taskList,list:b.list,listStack:b.listStack.slice(0),quote:b.quote,indentedCode:b.indentedCode,trailingSpace:b.trailingSpace,trailingSpaceNewLine:b.trailingSpaceNewLine,md_inside:b.md_inside,fencedEndRE:b.fencedEndRE}},token:function(a,b){if(b.formatting=!1,a!=b.thisLine.stream){if(b.header=0,b.hr=!1,a.match(/^\s*$/,!0))return h(b),null;if(b.prevLine=b.thisLine,b.thisLine={stream:a},b.taskList=!1,b.trailingSpace=0,b.trailingSpaceNewLine=!1,b.f=b.block,b.f!=j){var c=a.match(/^\s*/,!0)[0].replace(/\t/g,H).length;if(b.indentation=c,b.indentationDiff=null,c>0)return null}}return b.f(a,b)},innerMode:function(a){return a.block==j?{state:a.htmlState,mode:u}:a.localS
 tate?{state:a.localState,mode:a.localMode}:{state:a,mode:J}},indent:function(b,c,d){return b.block==j&&u.indent?u.indent(b.htmlState,c,d):b.localState&&b.localMode.indent?b.localMode.indent(b.localState,c,d):a.Pass},blankLine:h,getType:l,closeBrackets:"()[]{}''\"\"``",fold:"markdown"};return J},"xml"),a.defineMIME("text/x-markdown","markdown")})},{"../../lib/codemirror":59,"../meta":69,"../xml/xml":75}],69:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../lib/codemirror")):"function"==typeof define&&define.amd?define(["../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";a.modeInfo=[{name:"APL",mime:"text/apl",mode:"apl",ext:["dyalog","apl"]},{name:"PGP",mimes:["application/pgp","application/pg
 p-encrypted","application/pgp-keys","application/pgp-signature"],mode:"asciiarmor",ext:["asc","pgp","sig"]},{name:"ASN.1",mime:"text/x-ttcn-asn",mode:"asn.1",ext:["asn","asn1"]},{name:"Asterisk",mime:"text/x-asterisk",mode:"asterisk",file:/^extensions\.conf$/i},{name:"Brainfuck",mime:"text/x-brainfuck",mode:"brainfuck",ext:["b","bf"]},{name:"C",mime:"text/x-csrc",mode:"clike",ext:["c","h"]},{name:"C++",mime:"text/x-c++src",mode:"clike",ext:["cpp","c++","cc","cxx","hpp","h++","hh","hxx"],alias:["cpp"]},{name:"Cobol",mime:"text/x-cobol",mode:"cobol",ext:["cob","cpy"]},{name:&qu
 ot;C#",mime:"text/x-csharp",mode:"clike",ext:["cs"],alias:["csharp"]},{name:"Clojure",mime:"text/x-clojure",mode:"clojure",ext:["clj","cljc","cljx"]},{name:"ClojureScript",mime:"text/x-clojurescript",mode:"clojure",ext:["cljs"]},{name:"Closure Stylesheets (GSS)",mime:"text/x-gss",mode:"css",ext:["gss"]},{name:"CMake",mime:"text/x-cmake",mode:"cmake",ext:["cmake","cmake.in"],file:/^CMakeLists.txt$/},{name:"CoffeeScript",mimes:["application/vnd.coffeescript","text/coffeescript","text/x-coffeescript"],mode:"coffeescript",ext:["coffee"],alias:["coffee","coffee-script"]},{name:"Common Lisp",mime:"text/x-common-lisp",mode:"commonlisp",ext:["cl&q
 uot;,"lisp","el"],alias:["lisp"]},{name:"Cypher",mime:"application/x-cypher-query",mode:"cypher",ext:["cyp","cypher"]},{name:"Cython",mime:"text/x-cython",mode:"python",ext:["pyx","pxd","pxi"]},{name:"Crystal",mime:"text/x-crystal",mode:"crystal",ext:["cr"]},{name:"CSS",mime:"text/css",mode:"css",ext:["css"]},{name:"CQL",mime:"text/x-cassandra",mode:"sql",ext:["cql"]},{name:"D",mime:"text/x-d",mode:"d",ext:["d"]},{name:"Dart",mimes:["application/dart","text/x-dart"],mode:"dart",ext:["dart"]},{name:"diff",mime:"text/x-diff",mode:"diff",ext:["diff","patch"]},{name:"Django",mime:&quo
 t;text/x-django",mode:"django"},{name:"Dockerfile",mime:"text/x-dockerfile",mode:"dockerfile",file:/^Dockerfile$/},{name:"DTD",mime:"application/xml-dtd",mode:"dtd",ext:["dtd"]},{name:"Dylan",mime:"text/x-dylan",mode:"dylan",ext:["dylan","dyl","intr"]},{name:"EBNF",mime:"text/x-ebnf",mode:"ebnf"},{name:"ECL",mime:"text/x-ecl",mode:"ecl",ext:["ecl"]},{name:"edn",mime:"application/edn",mode:"clojure",ext:["edn"]},{name:"Eiffel",mime:"text/x-eiffel",mode:"eiffel",ext:["e"]},{name:"Elm",mime:"text/x-elm",mode:"elm",ext:["elm"]},{name:"Embedded Javascript",mime:"application/x-ejs",mode:"htmlembedded",ext:["ejs"]},{name:
 "Embedded Ruby",mime:"application/x-erb",mode:"htmlembedded",ext:["erb"]},{name:"Erlang",mime:"text/x-erlang",mode:"erlang",ext:["erl"]},{name:"Factor",mime:"text/x-factor",mode:"factor",ext:["factor"]},{name:"FCL",mime:"text/x-fcl",mode:"fcl"},{name:"Forth",mime:"text/x-forth",mode:"forth",ext:["forth","fth","4th"]},{name:"Fortran",mime:"text/x-fortran",mode:"fortran",ext:["f","for","f77","f90"]},{name:"F#",mime:"text/x-fsharp",mode:"mllike",ext:["fs"],alias:["fsharp"]},{name:"Gas",mime:"text/x-gas",mode:"gas",ext:["s"]},{name:"Gherkin",mime:"text/x-feature",mode:"gherkin",ext:["featu
 re"]},{name:"GitHub Flavored Markdown",mime:"text/x-gfm",mode:"gfm",file:/^(readme|contributing|history).md$/i},{name:"Go",mime:"text/x-go",mode:"go",ext:["go"]},{name:"Groovy",mime:"text/x-groovy",mode:"groovy",ext:["groovy","gradle"],file:/^Jenkinsfile$/},{name:"HAML",mime:"text/x-haml",mode:"haml",ext:["haml"]},{name:"Haskell",mime:"text/x-haskell",mode:"haskell",ext:["hs"]},{name:"Haskell (Literate)",mime:"text/x-literate-haskell",mode:"haskell-literate",ext:["lhs"]},{name:"Haxe",mime:"text/x-haxe",mode:"haxe",ext:["hx"]},{name:"HXML",mime:"text/x-hxml",mode:"haxe",ext:["hxml"]},{name:"ASP.NET",mime:"application/x-aspx",mode:"htmlembed
 ded",ext:["aspx"],alias:["asp","aspx"]},{name:"HTML",mime:"text/html",mode:"htmlmixed",ext:["html","htm"],alias:["xhtml"]},{name:"HTTP",mime:"message/http",mode:"http"},{name:"IDL",mime:"text/x-idl",mode:"idl",ext:["pro"]},{name:"Pug",mime:"text/x-pug",mode:"pug",ext:["jade","pug"],alias:["jade"]},{name:"Java",mime:"text/x-java",mode:"clike",ext:["java"]},{name:"Java Server Pages",mime:"application/x-jsp",mode:"htmlembedded",ext:["jsp"],alias:["jsp"]},{name:"JavaScript",mimes:["text/javascript","text/ecmascript","application/javascript","application/x-javascript","application/ecmascript"],mode:"javascript&quot
 ;,ext:["js"],alias:["ecmascript","js","node"]},{name:"JSON",mimes:["application/json","application/x-json"],mode:"javascript",ext:["json","map"],alias:["json5"]},{name:"JSON-LD",mime:"application/ld+json",mode:"javascript",ext:["jsonld"],alias:["jsonld"]},{name:"JSX",mime:"text/jsx",mode:"jsx",ext:["jsx"]},{name:"Jinja2",mime:"null",mode:"jinja2"},{name:"Julia",mime:"text/x-julia",mode:"julia",ext:["jl"]},{name:"Kotlin",mime:"text/x-kotlin",mode:"clike",ext:["kt"]},{name:"LESS",mime:"text/x-less",mode:"css",ext:["less"]},{name:"LiveScript",mime:"text/x-livescript",mode:"livescript",ext:["ls"],alias:[
 "ls"]},{name:"Lua",mime:"text/x-lua",mode:"lua",ext:["lua"]},{name:"Markdown",mime:"text/x-markdown",mode:"markdown",ext:["markdown","md","mkd"]},{name:"mIRC",mime:"text/mirc",mode:"mirc"},{name:"MariaDB SQL",mime:"text/x-mariadb",mode:"sql"},{name:"Mathematica",mime:"text/x-mathematica",mode:"mathematica",ext:["m","nb"]},{name:"Modelica",mime:"text/x-modelica",mode:"modelica",ext:["mo"]},{name:"MUMPS",mime:"text/x-mumps",mode:"mumps",ext:["mps"]},{name:"MS SQL",mime:"text/x-mssql",mode:"sql"},{name:"mbox",mime:"application/mbox",mode:"mbox",ext:["mbox"]},{name:"MySQL",mime:"text/x-mysql",mode:"
 sql"},{name:"Nginx",mime:"text/x-nginx-conf",mode:"nginx",file:/nginx.*\.conf$/i},{name:"NSIS",mime:"text/x-nsis",mode:"nsis",ext:["nsh","nsi"]},{name:"NTriples",mimes:["application/n-triples","application/n-quads","text/n-triples"],mode:"ntriples",ext:["nt","nq"]},{name:"Objective C",mime:"text/x-objectivec",mode:"clike",ext:["m","mm"],alias:["objective-c","objc"]},{name:"OCaml",mime:"text/x-ocaml",mode:"mllike",ext:["ml","mli","mll","mly"]},{name:"Octave",mime:"text/x-octave",mode:"octave",ext:["m"]},{name:"Oz",mime:"text/x-oz",mode:"oz",ext:["oz"]},{name:"Pascal",mime:"text/x-pascal",mode:&qu
 ot;pascal",ext:["p","pas"]},{name:"PEG.js",mime:"null",mode:"pegjs",ext:["jsonld"]},{name:"Perl",mime:"text/x-perl",mode:"perl",ext:["pl","pm"]},{name:"PHP",mime:"application/x-httpd-php",mode:"php",ext:["php","php3","php4","php5","php7","phtml"]},{name:"Pig",mime:"text/x-pig",mode:"pig",ext:["pig"]},{name:"Plain Text",mime:"text/plain",mode:"null",ext:["txt","text","conf","def","list","log"]},{name:"PLSQL",mime:"text/x-plsql",mode:"sql",ext:["pls"]},{name:"PowerShell",mime:"application/x-powershell",mode:"powershell",ext:["ps1","psd1","psm1"]},{name:&quot
 ;Properties files",mime:"text/x-properties",mode:"properties",ext:["properties","ini","in"],alias:["ini","properties"]},{name:"ProtoBuf",mime:"text/x-protobuf",mode:"protobuf",ext:["proto"]},{name:"Python",mime:"text/x-python",mode:"python",ext:["BUILD","bzl","py","pyw"],file:/^(BUCK|BUILD)$/},{name:"Puppet",mime:"text/x-puppet",mode:"puppet",ext:["pp"]},{name:"Q",mime:"text/x-q",mode:"q",ext:["q"]},{name:"R",mime:"text/x-rsrc",mode:"r",ext:["r","R"],alias:["rscript"]},{name:"reStructuredText",mime:"text/x-rst",mode:"rst",ext:["rst"],alias:["rst"]},{name:"RPM Changes",mime:"text/x-rpm-changes",m
 ode:"rpm"},{name:"RPM Spec",mime:"text/x-rpm-spec",mode:"rpm",ext:["spec"]},{name:"Ruby",mime:"text/x-ruby",mode:"ruby",ext:["rb"],alias:["jruby","macruby","rake","rb","rbx"]},{name:"Rust",mime:"text/x-rustsrc",mode:"rust",ext:["rs"]},{name:"SAS",mime:"text/x-sas",mode:"sas",ext:["sas"]},{name:"Sass",mime:"text/x-sass",mode:"sass",ext:["sass"]},{name:"Scala",mime:"text/x-scala",mode:"clike",ext:["scala"]},{name:"Scheme",mime:"text/x-scheme",mode:"scheme",ext:["scm","ss"]},{name:"SCSS",mime:"text/x-scss",mode:"css",ext:["scss"]},{name:"Shell",mimes:["text/x-sh","application/x-
 sh"],mode:"shell",ext:["sh","ksh","bash"],alias:["bash","sh","zsh"],file:/^PKGBUILD$/},{name:"Sieve",mime:"application/sieve",mode:"sieve",ext:["siv","sieve"]},{name:"Slim",mimes:["text/x-slim","application/x-slim"],mode:"slim",ext:["slim"]},{name:"Smalltalk",mime:"text/x-stsrc",mode:"smalltalk",ext:["st"]},{name:"Smarty",mime:"text/x-smarty",mode:"smarty",ext:["tpl"]},{name:"Solr",mime:"text/x-solr",mode:"solr"},{name:"Soy",mime:"text/x-soy",mode:"soy",ext:["soy"],alias:["closure template"]},{name:"SPARQL",mime:"application/sparql-query",mode:"sparql",ext:["rq","sparql"],alias:["sparul"]},{name
 :"Spreadsheet",mime:"text/x-spreadsheet",mode:"spreadsheet",alias:["excel","formula"]},{name:"SQL",mime:"text/x-sql",mode:"sql",ext:["sql"]},{name:"SQLite",mime:"text/x-sqlite",mode:"sql"},{name:"Squirrel",mime:"text/x-squirrel",mode:"clike",ext:["nut"]},{name:"Stylus",mime:"text/x-styl",mode:"stylus",ext:["styl"]},{name:"Swift",mime:"text/x-swift",mode:"swift",ext:["swift"]},{name:"sTeX",mime:"text/x-stex",mode:"stex"},{name:"LaTeX",mime:"text/x-latex",mode:"stex",ext:["text","ltx"],alias:["tex"]},{name:"SystemVerilog",mime:"text/x-systemverilog",mode:"verilog",ext:["v","sv","svh"]},{name:"Tcl&
 quot;,mime:"text/x-tcl",mode:"tcl",ext:["tcl"]},{name:"Textile",mime:"text/x-textile",mode:"textile",ext:["textile"]},{name:"TiddlyWiki ",mime:"text/x-tiddlywiki",mode:"tiddlywiki"},{name:"Tiki wiki",mime:"text/tiki",mode:"tiki"},{name:"TOML",mime:"text/x-toml",mode:"toml",ext:["toml"]},{name:"Tornado",mime:"text/x-tornado",mode:"tornado"},{name:"troff",mime:"text/troff",mode:"troff",ext:["1","2","3","4","5","6","7","8","9"]},{name:"TTCN",mime:"text/x-ttcn",mode:"ttcn",ext:["ttcn","ttcn3","ttcnpp"]},{name:"TTCN_CFG",mime:"text/x-ttcn-cfg",mode:"ttcn-cfg",ext:["cfg"]},{na
 me:"Turtle",mime:"text/turtle",mode:"turtle",ext:["ttl"]},{name:"TypeScript",mime:"application/typescript",mode:"javascript",ext:["ts"],alias:["ts"]},{name:"TypeScript-JSX",mime:"text/typescript-jsx",mode:"jsx",ext:["tsx"],alias:["tsx"]},{name:"Twig",mime:"text/x-twig",mode:"twig"},{name:"Web IDL",mime:"text/x-webidl",mode:"webidl",ext:["webidl"]},{name:"VB.NET",mime:"text/x-vb",mode:"vb",ext:["vb"]},{name:"VBScript",mime:"text/vbscript",mode:"vbscript",ext:["vbs"]},{name:"Velocity",mime:"text/velocity",mode:"velocity",ext:["vtl"]},{name:"Verilog",mime:"text/x-verilog",mode:"verilog",ext:["v"]},{name:"VHDL",mi
 me:"text/x-vhdl",mode:"vhdl",ext:["vhd","vhdl"]},{name:"Vue.js Component",mimes:["script/x-vue","text/x-vue"],mode:"vue",ext:["vue"]},{name:"XML",mimes:["application/xml","text/xml"],mode:"xml",ext:["xml","xsl","xsd","svg"],alias:["rss","wsdl","xsd"]},{name:"XQuery",mime:"application/xquery",mode:"xquery",ext:["xy","xquery"]},{name:"Yacas",mime:"text/x-yacas",mode:"yacas",ext:["ys"]},{name:"YAML",mimes:["text/x-yaml","text/yaml"],mode:"yaml",ext:["yaml","yml"],alias:["yml"]},{name:"Z80",mime:"text/x-z80",mode:"z80",ext:["z80"]},{name:"mscgen",mime:"text/x-mscgen",mode:&q
 uot;mscgen",ext:["mscgen","mscin","msc"]},{name:"xu",mime:"text/x-xu",mode:"mscgen",ext:["xu"]},{name:"msgenny",mime:"text/x-msgenny",mode:"mscgen",ext:["msgenny"]}];for(var b=0;b<a.modeInfo.length;b++){var c=a.modeInfo[b];c.mimes&&(c.mime=c.mimes[0])}a.findModeByMIME=function(b){b=b.toLowerCase();for(var c=0;c<a.modeInfo.length;c++){var d=a.modeInfo[c];if(d.mime==b)return d;if(d.mimes)for(var e=0;e<d.mimes.length;e++)if(d.mimes[e]==b)return d}return/\+xml$/.test(b)?a.findModeByMIME("application/xml"):/\+json$/.test(b)?a.findModeByMIME("application/json"):void 0},a.findModeByExtension=function(b){for(var c=0;c<a.modeInfo.length;c++){var d=a.modeInfo[c];if(d.ext)for(var e=0;e<d.ext.length;e++)if(d.ext[e]==b)return d}},a.findModeByFileName=function(b){for(var c=0;c<a.modeInfo.length;c++){var d=a.modeInfo[c];if(d.file&&
 d.file.test(b))return d}var e=b.lastIndexOf("."),f=e>-1&&b.substring(e+1,b.length);if(f)return a.findModeByExtension(f)},a.findModeByName=function(b){b=b.toLowerCase();for(var c=0;c<a.modeInfo.length;c++){var d=a.modeInfo[c];if(d.name.toLowerCase()==b)return d;if(d.alias)for(var e=0;e<d.alias.length;e++)if(d.alias[e].toLowerCase()==b)return d}}})},{"../lib/codemirror":59}],70:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";a.defineMode("nginx",function(a){function b(a){for(var b={},c=a.split(" "),d=0;d<c.length;++d)b[c[d]]=!0;return b}function c(a,b){return h=b,a}function d(a,b){a.eatWhile(/[\w\$_]/);var d=a.current();if(i.propertyIsEnumerable(d))return"keyword";if(j.propertyIsEn
 umerable(d))return"variable-2";if(k.propertyIsEnumerable(d))return"string-2";var h=a.next();return"@"==h?(a.eatWhile(/[\w\\\-]/),c("meta",a.current())):"/"==h&&a.eat("*")?(b.tokenize=e,e(a,b)):"<"==h&&a.eat("!")?(b.tokenize=f,f(a,b)):"="!=h?"~"!=h&&"|"!=h||!a.eat("=")?'"'==h||"'"==h?(b.tokenize=g(h),b.tokenize(a,b)):"#"==h?(a.skipToEnd(),c("comment","comment")):"!"==h?(a.match(/^\s*\w*/),c("keyword","important")):/\d/.test(h)?(a.eatWhile(/[\w.%]/),c("number","unit")):/[,.+>*\/]/.test(h)?c(null,"select-op"):/[;{}:\[\]]/.test(h)?c(null,h):(a.eatWhile(/[\w\\\-]/),c("variable","variable")):c(null,"compare"):void c(null,"compare")}function e(a,b){for(var e,f=!1;null!=(e=a.next());){if(f&&&q
 uot;/"==e){b.tokenize=d;break}f="*"==e}return c("comment","comment")}function f(a,b){for(var e,f=0;null!=(e=a.next());){if(f>=2&&">"==e){b.tokenize=d;break}f="-"==e?f+1:0}return c("comment","comment")}function g(a){return function(b,e){for(var f,g=!1;null!=(f=b.next())&&(f!=a||g);)g=!g&&"\\"==f;return g||(e.tokenize=d),c("string","string")}}var h,i=b("break return rewrite set accept_mutex accept_mutex_delay access_log add_after_body add_before_body add_header addition_types aio alias allow ancient_browser ancient_browser_value auth_basic auth_basic_user_file auth_http auth_http_header auth_http_timeout autoindex autoindex_exact_size autoindex_localtime charset charset_types client_body_buffer_size client_body_in_file_only client_body_in_single_buffer client_body_temp_path client_body_timeout client_header_buffer_size client_header_timeout client
 _max_body_size connection_pool_size create_full_put_path daemon dav_access dav_methods debug_connection debug_points default_type degradation degrade deny devpoll_changes devpoll_events directio directio_alignment empty_gif env epoll_events error_log eventport_events expires fastcgi_bind fastcgi_buffer_size fastcgi_buffers fastcgi_busy_buffers_size fastcgi_cache fastcgi_cache_key fastcgi_cache_methods fastcgi_cache_min_uses fastcgi_cache_path fastcgi_cache_use_stale fastcgi_cache_valid fastcgi_catch_stderr fastcgi_connect_timeout fastcgi_hide_header fastcgi_ignore_client_abort fastcgi_ignore_headers fastcgi_index fastcgi_intercept_errors fastcgi_max_temp_file_size fastcgi_next_upstream fastcgi_param fastcgi_pass_header fastcgi_pass_request_body fastcgi_pass_request_headers fastcgi_read_timeout fastcgi_send_lowat fastcgi_send_timeout fastcgi_split_path_info fastcgi_store fastcgi_store_access fastcgi_temp_file_write_size fastcgi_temp_path fastcgi_upstream_fail_timeout fastcgi_upstream
 _max_fails flv geoip_city geoip_country google_perftools_profiles gzip gzip_buffers gzip_comp_level gzip_disable gzip_hash gzip_http_version gzip_min_length gzip_no_buffer gzip_proxied gzip_static gzip_types gzip_vary gzip_window if_modified_since ignore_invalid_headers image_filter image_filter_buffer image_filter_jpeg_quality image_filter_transparency imap_auth imap_capabilities imap_client_buffer index ip_hash keepalive_requests keepalive_timeout kqueue_changes kqueue_events large_client_header_buffers limit_conn limit_conn_log_level limit_rate limit_rate_after limit_req limit_req_log_level limit_req_zone limit_zone lingering_time lingering_timeout lock_file log_format log_not_found log_subrequest map_hash_bucket_size map_hash_max_size master_process memcached_bind memcached_buffer_size memcached_connect_timeout memcached_next_upstream memcached_read_timeout memcached_send_timeout memcached_upstream_fail_timeout memcached_upstream_max_fails merge_slashes min_delete_depth modern_b
 rowser modern_browser_value msie_padding msie_refresh multi_accept open_file_cache open_file_cache_errors open_file_cache_events open_file_cache_min_uses open_file_cache_valid open_log_file_cache output_buffers override_charset perl perl_modules perl_require perl_set pid pop3_auth pop3_capabilities port_in_redirect postpone_gzipping postpone_output protocol proxy proxy_bind proxy_buffer proxy_buffer_size proxy_buffering proxy_buffers proxy_busy_buffers_size proxy_cache proxy_cache_key proxy_cache_methods proxy_cache_min_uses proxy_cache_path proxy_cache_use_stale proxy_cache_valid proxy_connect_timeout proxy_headers_hash_bucket_size proxy_headers_hash_max_size proxy_hide_header proxy_ignore_client_abort proxy_ignore_headers proxy_intercept_errors proxy_max_temp_file_size proxy_method proxy_next_upstream proxy_pass_error_message proxy_pass_header proxy_pass_request_body proxy_pass_request_headers proxy_read_timeout proxy_redirect proxy_send_lowat proxy_send_timeout proxy_set_body pro
 xy_set_header proxy_ssl_session_reuse proxy_store proxy_store_access proxy_temp_file_write_size proxy_temp_path proxy_timeout proxy_upstream_fail_timeout proxy_upstream_max_fails random_index read_ahead real_ip_header recursive_error_pages request_pool_size reset_timedout_connection resolver resolver_timeout rewrite_log rtsig_overflow_events rtsig_overflow_test rtsig_overflow_threshold rtsig_signo satisfy secure_link_secret send_lowat send_timeout sendfile sendfile_max_chunk server_name_in_redirect server_names_hash_bucket_size server_names_hash_max_size server_tokens set_real_ip_from smtp_auth smtp_capabilities smtp_client_buffer smtp_greeting_delay so_keepalive source_charset ssi ssi_ignore_recycled_buffers ssi_min_file_chunk ssi_silent_errors ssi_types ssi_value_length ssl ssl_certificate ssl_certificate_key ssl_ciphers ssl_client_certificate ssl_crl ssl_dhparam ssl_engine ssl_prefer_server_ciphers ssl_protocols ssl_session_cache ssl_session_timeout ssl_verify_client ssl_verify_d
 epth starttls stub_status sub_filter sub_filter_once sub_filter_types tcp_nodelay tcp_nopush thread_stack_size timeout timer_resolution types_hash_bucket_size types_hash_max_size underscores_in_headers uninitialized_variable_warn use user userid userid_domain userid_expires userid_mark userid_name userid_p3p userid_path userid_service valid_referers variables_hash_bucket_size variables_hash_max_size worker_connections worker_cpu_affinity worker_priority worker_processes worker_rlimit_core worker_rlimit_nofile worker_rlimit_sigpending worker_threads working_directory xclient xml_entities xslt_stylesheet xslt_typesdrew@li229-23"),j=b("http mail events server types location upstream charset_map limit_except if geo map"),k=b("include root server server_name listen internal proxy_pass memcached_pass fastcgi_pass try_files"),l=a.indentUnit;return{startState:function(a){return{tokenize:d,baseIndent:a||0,stack:[]}},token:function(a,b){if(a.eatSpace())return null;h=n
 ull;var c=b.tokenize(a,b),d=b.stack[b.stack.length-1];return"hash"==h&&"rule"==d?c="atom":"variable"==c&&("rule"==d?c="number":d&&"@media{"!=d||(c="tag")),"rule"==d&&/^[\{\};]$/.test(h)&&b.stack.pop(),"{"==h?"@media"==d?b.stack[b.stack.length-1]="@media{":b.stack.push("{"):"}"==h?b.stack.pop():"@media"==h?b.stack.push("@media"):"{"==d&&"comment"!=h&&b.stack.push("rule"),c},indent:function(a,b){var c=a.stack.length;return/^\}/.test(b)&&(c-="rule"==a.stack[a.stack.length-1]?2:1),a.baseIndent+c*l},electricChars:"}"}}),a.defineMIME("text/x-nginx-conf","nginx")})},{"../../lib/codemirror":59}],71:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof 
 b?d(a("../../lib/codemirror"),a("../htmlmixed/htmlmixed"),a("../clike/clike")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../htmlmixed/htmlmixed","../clike/clike"],d):d(CodeMirror)}(function(a){"use strict";function b(a){for(var b={},c=a.split(" "),d=0;d<c.length;++d)b[c[d]]=!0;return b}function c(a,b,e){return 0==a.length?d(b):function(f,g){for(var h=a[0],i=0;i<h.length;i++)if(f.match(h[i][0]))return g.tokenize=c(a.slice(1),b),h[i][1];return g.tokenize=d(b,e),"string"}}function d(a,b){return function(c,d){return e(c,d,a,b)}}function e(a,b,d,e){if(e!==!1&&a.match("${",!1)||a.match("{$",!1))return b.tokenize=null,"string";if(e!==!1&&a.match(/^\$[a-zA-Z_][a-zA-Z0-9_]*/))return a.match("[",!1)&&(b.tokenize=c([[["[",null]],[[/\d[\w\.]*/,"number"],[/\$[a-zA-Z_][a-zA-
 Z0-9_]*/,"variable-2"],[/[\w\$]+/,"variable"]],[["]",null]]],d,e)),a.match(/\-\>\w/,!1)&&(b.tokenize=c([[["->",null]],[[/[\w]+/,"variable"]]],d,e)),"variable-2";for(var f=!1;!a.eol()&&(f||e===!1||!a.match("{$",!1)&&!a.match(/^(\$[a-zA-Z_][a-zA-Z0-9_]*|\$\{)/,!1));){if(!f&&a.match(d)){b.tokenize=null,b.tokStack.pop(),b.tokStack.pop();break}f="\\"==a.next()&&!f}return"string"}var f="abstract and array as break case catch class clone const continue declare default do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final for foreach function global goto if implements interface instanceof namespace new or private protected public static switch throw trait try use var while xor die echo empty exit eval include include_once isset list require require_once return print unset __halt_compiler self static parent yield insteadof f
 inally",g="true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__ __TRAIT__",h="func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords s
 trtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_
 get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents file_put_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_met
 a_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_rever
 se array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists array_intersect_key array_combine array_column pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri ap
 ache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_nu
 mfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg
 _insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once json_decode json_encode json_last_error json_last_error_msg curl_close curl_copy_handle curl_errno curl_error curl_escape curl_exec curl_file_create curl_getinfo curl_init curl_multi_add_handle curl_multi_close curl_multi_exec curl_multi_getcontent curl_multi_info_read curl_multi_init curl_multi_remove_handle curl_multi_select curl_multi_setopt curl_multi_strerror curl_paus
 e curl_reset curl_setopt_array curl_setopt curl_share_close curl_share_init curl_share_setopt curl_strerror curl_unescape curl_version mysqli_affected_rows mysqli_autocommit mysqli_change_user mysqli_character_set_name mysqli_close mysqli_commit mysqli_connect_errno mysqli_connect_error mysqli_connect mysqli_data_seek mysqli_debug mysqli_dump_debug_info mysqli_errno mysqli_error_list mysqli_error mysqli_fetch_all mysqli_fetch_array mysqli_fetch_assoc mysqli_fetch_field_direct mysqli_fetch_field mysqli_fetch_fields mysqli_fetch_lengths mysqli_fetch_object mysqli_fetch_row mysqli_field_count mysqli_field_seek mysqli_field_tell mysqli_free_result mysqli_get_charset mysqli_get_client_info mysqli_get_client_stats mysqli_get_client_version mysqli_get_connection_stats mysqli_get_host_info mysqli_get_proto_info mysqli_get_server_info mysqli_get_server_version mysqli_info mysqli_init mysqli_insert_id mysqli_kill mysqli_more_results mysqli_multi_query mysqli_next_result mysqli_num_fields mysq
 li_num_rows mysqli_options mysqli_ping mysqli_prepare mysqli_query mysqli_real_connect mysqli_real_escape_string mysqli_real_query mysqli_reap_async_query mysqli_refresh mysqli_rollback mysqli_select_db mysqli_set_charset mysqli_set_local_infile_default mysqli_set_local_infile_handler mysqli_sqlstate mysqli_ssl_set mysqli_stat mysqli_stmt_init mysqli_store_result mysqli_thread_id mysqli_thread_safe mysqli_use_result mysqli_warning_count";
+a.registerHelper("hintWords","php",[f,g,h].join(" ").split(" ")),a.registerHelper("wordChars","php",/[\w$]/);var i={name:"clike",helperType:"php",keywords:b(f),blockKeywords:b("catch do else elseif for foreach if switch try while finally"),defKeywords:b("class function interface namespace trait"),atoms:b(g),builtin:b(h),multiLineStrings:!0,hooks:{$:function(a){return a.eatWhile(/[\w\$_]/),"variable-2"},"<":function(a,b){var c;if(c=a.match(/<<\s*/)){var e=a.eat(/['"]/);a.eatWhile(/[\w\.]/);var f=a.current().slice(c[0].length+(e?2:1));if(e&&a.eat(e),f)return(b.tokStack||(b.tokStack=[])).push(f,0),b.tokenize=d(f,"'"!=e),"string"}return!1},"#":function(a){for(;!a.eol()&&!a.match("?>",!1);)a.next();return"comment"},"/":function(a){if(a.eat("/")){for(;!a.eol()&&
 !a.match("?>",!1);)a.next();return"comment"}return!1},'"':function(a,b){return(b.tokStack||(b.tokStack=[])).push('"',0),b.tokenize=d('"'),"string"},"{":function(a,b){return b.tokStack&&b.tokStack.length&&b.tokStack[b.tokStack.length-1]++,!1},"}":function(a,b){return b.tokStack&&b.tokStack.length>0&&!--b.tokStack[b.tokStack.length-1]&&(b.tokenize=d(b.tokStack[b.tokStack.length-2])),!1}}};a.defineMode("php",function(b,c){function d(b,c){var d=c.curMode==f;if(b.sol()&&c.pending&&'"'!=c.pending&&"'"!=c.pending&&(c.pending=null),d)return d&&null==c.php.tokenize&&b.match("?>")?(c.curMode=e,c.curState=c.html,c.php.context.prev||(c.php=null),"meta"):f.token(b,c.curState);if(b.match(/^<\?\w*/))return c.curMode=f,c.php||(c.php=a.startState(f,e.indent(c.html,""))),c.curState=c.
 php,"meta";if('"'==c.pending||"'"==c.pending){for(;!b.eol()&&b.next()!=c.pending;);var g="string"}else if(c.pending&&b.pos<c.pending.end){b.pos=c.pending.end;var g=c.pending.style}else var g=e.token(b,c.curState);c.pending&&(c.pending=null);var h,i=b.current(),j=i.search(/<\?/);return j!=-1&&("string"==g&&(h=i.match(/[\'\"]$/))&&!/\?>/.test(i)?c.pending=h[0]:c.pending={end:b.pos,style:g},b.backUp(i.length-j)),g}var e=a.getMode(b,"text/html"),f=a.getMode(b,i);return{startState:function(){var b=a.startState(e),d=c.startOpen?a.startState(f):null;return{html:b,php:d,curMode:c.startOpen?f:e,curState:c.startOpen?d:b,pending:null}},copyState:function(b){var c,d=b.html,g=a.copyState(e,d),h=b.php,i=h&&a.copyState(f,h);return c=b.curMode==e?g:i,{html:g,php:i,curMode:b.curMode,curState:c,pending:b.pending}},token:d,indent:function(a,b){return a.curMode!=f&&/^\s*&
 lt;\//.test(b)||a.curMode==f&&/^\?>/.test(b)?e.indent(a.html,b):a.curMode.indent(a.curState,b)},blockCommentStart:"/*",blockCommentEnd:"*/",lineComment:"//",innerMode:function(a){return{state:a.curState,mode:a.curMode}}}},"htmlmixed","clike"),a.defineMIME("application/x-httpd-php","php"),a.defineMIME("application/x-httpd-php-open",{name:"php",startOpen:!0}),a.defineMIME("text/x-php",i)})},{"../../lib/codemirror":59,"../clike/clike":60,"../htmlmixed/htmlmixed":64}],72:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror"),a("../css/css")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../css/css"],d):d(CodeMirror)}(function(a){"use strict";a.defineMode("sass",function(b){functi
 on c(a){return new RegExp("^"+a.join("|"))}function d(a){return!a.peek()||a.match(/\s+$/,!1)}function e(a,b){var c=a.peek();return")"===c?(a.next(),b.tokenizer=k,"operator"):"("===c?(a.next(),a.eatSpace(),"operator"):"'"===c||'"'===c?(b.tokenizer=g(a.next()),"string"):(b.tokenizer=g(")",!1),"string")}function f(a,b){return function(c,d){return c.sol()&&c.indentation()<=a?(d.tokenizer=k,k(c,d)):(b&&c.skipTo("*/")?(c.next(),c.next(),d.tokenizer=k):c.skipToEnd(),"comment")}}function g(a,b){function c(e,f){var g=e.next(),i=e.peek(),j=e.string.charAt(e.pos-2),l="\\"!==g&&i===a||g===a&&"\\"!==j;return l?(g!==a&&b&&e.next(),d(e)&&(f.cursorHalf=0),f.tokenizer=k,"string"):"#"===g&&"{"===i?(f.tokenizer=h(c),e.next(),"operator"):"string&quot
 ;}return null==b&&(b=!0),c}function h(a){return function(b,c){return"}"===b.peek()?(b.next(),c.tokenizer=a,"operator"):k(b,c)}}function i(a){if(0==a.indentCount){a.indentCount++;var c=a.scopes[0].offset,d=c+b.indentUnit;a.scopes.unshift({offset:d})}}function j(a){1!=a.scopes.length&&a.scopes.shift()}function k(a,b){var c=a.peek();if(a.match("/*"))return b.tokenizer=f(a.indentation(),!0),b.tokenizer(a,b);if(a.match("//"))return b.tokenizer=f(a.indentation(),!1),b.tokenizer(a,b);if(a.match("#{"))return b.tokenizer=h(k),"operator";if('"'===c||"'"===c)return a.next(),b.tokenizer=g(c),"string";if(b.cursorHalf){if("#"===c&&(a.next(),a.match(/[0-9a-fA-F]{6}|[0-9a-fA-F]{3}/)))return d(a)&&(b.cursorHalf=0),"number";if(a.match(/^-?[0-9\.]+/))return d(a)&&(b.cursorHalf=0),"number";if(a.match(/^(px|em|in)\b/))return d(a)&&(b.cursorHal
 f=0),"unit";if(a.match(t))return d(a)&&(b.cursorHalf=0),"keyword";if(a.match(/^url/)&&"("===a.peek())return b.tokenizer=e,d(a)&&(b.cursorHalf=0),"atom";if("$"===c)return a.next(),a.eatWhile(/[\w-]/),d(a)&&(b.cursorHalf=0),"variable-2";if("!"===c)return a.next(),b.cursorHalf=0,a.match(/^[\w]+/)?"keyword":"operator";if(a.match(v))return d(a)&&(b.cursorHalf=0),"operator";if(a.eatWhile(/[\w-]/))return d(a)&&(b.cursorHalf=0),m=a.current().toLowerCase(),q.hasOwnProperty(m)?"atom":p.hasOwnProperty(m)?"keyword":o.hasOwnProperty(m)?(b.prevProp=a.current().toLowerCase(),"property"):"tag";if(d(a))return b.cursorHalf=0,null}else{if("-"===c&&a.match(/^-\w+-/))return"meta";if("."===c){if(a.next(),a.match(/^[\w-]+/))return i(b),"qualifier";if("#"===a.peek(
 ))return i(b),"tag"}if("#"===c){if(a.next(),a.match(/^[\w-]+/))return i(b),"builtin";if("#"===a.peek())return i(b),"tag"}if("$"===c)return a.next(),a.eatWhile(/[\w-]/),"variable-2";if(a.match(/^-?[0-9\.]+/))return"number";if(a.match(/^(px|em|in)\b/))return"unit";if(a.match(t))return"keyword";if(a.match(/^url/)&&"("===a.peek())return b.tokenizer=e,"atom";if("="===c&&a.match(/^=[\w-]+/))return i(b),"meta";if("+"===c&&a.match(/^\+[\w-]+/))return"variable-3";if("@"===c&&a.match(/@extend/)&&(a.match(/\s*[\w]/)||j(b)),a.match(/^@(else if|if|media|else|for|each|while|mixin|function)/))return i(b),"def";if("@"===c)return a.next(),a.eatWhile(/[\w-]/),"def";if(a.eatWhile(/[\w-]/)){if(a.match(/ *: *[\w-\+\$#!\("']/,!1)){m=a.current().toLowerCase();var l
 =b.prevProp+"-"+m;return o.hasOwnProperty(l)?"property":o.hasOwnProperty(m)?(b.prevProp=m,"property"):r.hasOwnProperty(m)?"property":"tag"}return a.match(/ *:/,!1)?(i(b),b.cursorHalf=1,b.prevProp=a.current().toLowerCase(),"property"):a.match(/ *,/,!1)?"tag":(i(b),"tag")}if(":"===c)return a.match(w)?"variable-3":(a.next(),b.cursorHalf=1,"operator")}return a.match(v)?"operator":(a.next(),null)}function l(a,c){a.sol()&&(c.indentCount=0);var d=c.tokenizer(a,c),e=a.current();if("@return"!==e&&"}"!==e||j(c),null!==d){for(var f=a.pos-e.length,g=f+b.indentUnit*c.indentCount,h=[],i=0;i<c.scopes.length;i++){var k=c.scopes[i];k.offset<=g&&h.push(k)}c.scopes=h}return d}var m,n=a.mimeModes["text/css"],o=n.propertyKeywords||{},p=n.colorKeywords||{},q=n.valueKeywords||{},r=n.fontProperties||{},s=["true","f
 alse","null","auto"],t=new RegExp("^"+s.join("|")),u=["\\(","\\)","=",">","<","==",">=","<=","\\+","-","\\!=","/","\\*","%","and","or","not",";","\\{","\\}",":"],v=c(u),w=/^::?[a-zA-Z_][\w\-]*/;return{startState:function(){return{tokenizer:k,scopes:[{offset:0,type:"sass"}],indentCount:0,cursorHalf:0,definedVars:[],definedMixins:[]}},token:function(a,b){var c=l(a,b);return b.lastToken={style:c,content:a.current()},c},indent:function(a){return a.scopes[0].offset}}},"css"),a.defineMIME("text/x-sass","sass")})},{"../../lib/codemirror":59,"../css/css":61}],73:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("..
 /../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";a.defineMode("shell",function(){function a(a,b){for(var c=b.split(" "),d=0;d<c.length;d++)e[c[d]]=a}function b(a,b){if(a.eatSpace())return null;var g=a.sol(),h=a.next();if("\\"===h)return a.next(),null;if("'"===h||'"'===h||"`"===h)return b.tokens.unshift(c(h,"`"===h?"quote":"string")),d(a,b);if("#"===h)return g&&a.eat("!")?(a.skipToEnd(),"meta"):(a.skipToEnd(),"comment");if("$"===h)return b.tokens.unshift(f),d(a,b);if("+"===h||"="===h)return"operator";if("-"===h)return a.eat("-"),a.eatWhile(/\w/),"attribute";if(/\d/.test(h)&&(a.eatWhile(/\d/),a.eol()||!/\w/.test(a.peek())))return"number";
 a.eatWhile(/[\w-]/);var i=a.current();return"="===a.peek()&&/\w+/.test(i)?"def":e.hasOwnProperty(i)?e[i]:null}function c(a,b){var e="("==a?")":"{"==a?"}":a;return function(g,h){for(var i,j=!1,k=!1;null!=(i=g.next());){if(i===e&&!k){j=!0;break}if("$"===i&&!k&&"'"!==a){k=!0,g.backUp(1),h.tokens.unshift(f);break}if(!k&&i===a&&a!==e)return h.tokens.unshift(c(a,b)),d(g,h);k=!k&&"\\"===i}return j&&h.tokens.shift(),b}}function d(a,c){return(c.tokens[0]||b)(a,c)}var e={};a("atom","true false"),a("keyword","if then do else elif while until for in esac fi fin fil done exit set unset export function"),a("builtin","ab awk bash beep cat cc cd chown chmod chroot clear cp curl cut diff echo find gawk gcc get git grep hg kill killall ln ls make mkdir openssl mv nc node npm ping ps restart rm r
 mdir sed service sh shopt shred source sort sleep ssh start stop su sudo svn tee telnet top touch vi vim wall wc wget who write yes zsh");var f=function(a,b){b.tokens.length>1&&a.eat("$");var e=a.next();return/['"({]/.test(e)?(b.tokens[0]=c(e,"("==e?"quote":"{"==e?"def":"string"),d(a,b)):(/\d/.test(e)||a.eatWhile(/\w/),b.tokens.shift(),"def")};return{startState:function(){return{tokens:[]}},token:function(a,b){return d(a,b)},closeBrackets:"()[]{}''\"\"``",lineComment:"#",fold:"brace"}}),a.defineMIME("text/x-sh","shell"),a.defineMIME("application/x-sh","shell")})},{"../../lib/codemirror":59}],74:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../li
 b/codemirror"],d):d(CodeMirror)}(function(a){"use strict";a.defineMode("sql",function(b,c){function d(a,b){var c=a.next();if(o[c]){var d=o[c](a,b);if(d!==!1)return d}if(n.hexNumber&&("0"==c&&a.match(/^[xX][0-9a-fA-F]+/)||("x"==c||"X"==c)&&a.match(/^'[0-9a-fA-F]+'/)))return"number";if(n.binaryNumber&&(("b"==c||"B"==c)&&a.match(/^'[01]+'/)||"0"==c&&a.match(/^b[01]+/)))return"number";if(c.charCodeAt(0)>47&&c.charCodeAt(0)<58)return a.match(/^[0-9]*(\.[0-9]+)?([eE][-+]?[0-9]+)?/),n.decimallessFloat&&a.match(/^\.(?!\.)/),"number";if("?"==c&&(a.eatSpace()||a.eol()||a.eat(";")))return"variable-3";if("'"==c||'"'==c&&n.doubleQuote)return b.tokenize=e(c),b.tokenize(a,b);if((n.nCharCast&&("n"==c||"N"==c)||n.charsetCast&&
 amp;"_"==c&&a.match(/[a-z][a-z0-9]*/i))&&("'"==a.peek()||'"'==a.peek()))return"keyword";if(/^[\(\),\;\[\]]/.test(c))return null;if(n.commentSlashSlash&&"/"==c&&a.eat("/"))return a.skipToEnd(),"comment";if(n.commentHash&&"#"==c||"-"==c&&a.eat("-")&&(!n.commentSpaceRequired||a.eat(" ")))return a.skipToEnd(),"comment";if("/"==c&&a.eat("*"))return b.tokenize=f(1),b.tokenize(a,b);if("."!=c){if(m.test(c))return a.eatWhile(m),null;if("{"==c&&(a.match(/^( )*(d|D|t|T|ts|TS)( )*'[^']*'( )*}/)||a.match(/^( )*(d|D|t|T|ts|TS)( )*"[^"]*"( )*}/)))return"number";a.eatWhile(/^[_\w\d]/);var g=a.current().toLowerCase();return p.hasOwnProperty(g)&&(a.match(/^( )+'[^']*'/)||a.match(/^( )+"[^"]*"/))?"number":j.hasOwnProperty
 (g)?"atom":k.hasOwnProperty(g)?"builtin":l.hasOwnProperty(g)?"keyword":i.hasOwnProperty(g)?"string-2":null}return n.zerolessFloat&&a.match(/^(?:\d+(?:e[+-]?\d+)?)/i)?"number":a.match(/^\.+/)?null:n.ODBCdotTable&&a.match(/^[\w\d_]+/)?"variable-2":void 0}function e(a){return function(b,c){for(var e,f=!1;null!=(e=b.next());){if(e==a&&!f){c.tokenize=d;break}f=!f&&"\\"==e}return"string"}}function f(a){return function(b,c){var e=b.match(/^.*?(\/\*|\*\/)/);return e?"/*"==e[1]?c.tokenize=f(a+1):a>1?c.tokenize=f(a-1):c.tokenize=d:b.skipToEnd(),"comment"}}function g(a,b,c){b.context={prev:b.context,indent:a.indentation(),col:a.column(),type:c}}function h(a){a.indent=a.context.indent,a.context=a.context.prev}var i=c.client||{},j=c.atoms||{"false":!0,"true":!0,"null":!0},k=c.builtin||{},l=c.keywords||{},m=c.operatorChars||/^[*+\-%&l
 t;>!=&|~^]/,n=c.support||{},o=c.hooks||{},p=c.dateSQL||{date:!0,time:!0,timestamp:!0};return{startState:function(){return{tokenize:d,context:null}},token:function(a,b){if(a.sol()&&b.context&&null==b.context.align&&(b.context.align=!1),b.tokenize==d&&a.eatSpace())return null;var c=b.tokenize(a,b);if("comment"==c)return c;b.context&&null==b.context.align&&(b.context.align=!0);var e=a.current();return"("==e?g(a,b,")"):"["==e?g(a,b,"]"):b.context&&b.context.type==e&&h(b),c},indent:function(c,d){var e=c.context;if(!e)return a.Pass;var f=d.charAt(0)==e.type;return e.align?e.col+(f?0:1):e.indent+(f?0:b.indentUnit)},blockCommentStart:"/*",blockCommentEnd:"*/",lineComment:n.commentSlashSlash?"//":n.commentHash?"#":"--"}}),function(){function b(a){for(var b;null!=(b=a.next());)if("`"==b&&!a.eat("`&quot
 ;))return"variable-2";return a.backUp(a.current().length-1),a.eatWhile(/\w/)?"variable-2":null}function c(a){for(var b;null!=(b=a.next());)if('"'==b&&!a.eat('"'))return"variable-2";return a.backUp(a.current().length-1),a.eatWhile(/\w/)?"variable-2":null}function d(a){return a.eat("@")&&(a.match(/^session\./),a.match(/^local\./),a.match(/^global\./)),a.eat("'")?(a.match(/^.*'/),"variable-2"):a.eat('"')?(a.match(/^.*"/),"variable-2"):a.eat("`")?(a.match(/^.*`/),"variable-2"):a.match(/^[0-9a-zA-Z$\.\_]+/)?"variable-2":null}function e(a){return a.eat("N")?"atom":a.match(/^[a-zA-Z.#!?]/)?"variable-2":null}function f(a){for(var b={},c=a.split(" "),d=0;d<c.length;++d)b[c[d]]=!0;return b}var g="alter and as asc between by count create delete desc distinct drop from group having in insert into is join
  like not on or order select set table union update values where limit ";a.defineMIME("text/x-sql",{name:"sql",keywords:f(g+"begin"),builtin:f("bool boolean bit blob enum long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision real date datetime year unsigned signed decimal numeric"),atoms:f("false true null unknown"),operatorChars:/^[*+\-%<>!=]/,dateSQL:f("date time timestamp"),support:f("ODBCdotTable doubleQuote binaryNumber hexNumber")}),a.defineMIME("text/x-mssql",{name:"sql",client:f("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"),keywords:f(g+"begin trigger proc view index for add constraint key primary foreign collate 
 clustered nonclustered declare exec"),builtin:f("bigint numeric bit smallint decimal smallmoney int tinyint money float real char varchar text nchar nvarchar ntext binary varbinary image cursor timestamp hierarchyid uniqueidentifier sql_variant xml table "),atoms:f("false true null unknown"),operatorChars:/^[*+\-%<>!=]/,dateSQL:f("date datetimeoffset datetime2 smalldatetime datetime time"),hooks:{"@":d}}),a.defineMIME("text/x-mysql",{name:"sql",client:f("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"),keywords:f(g+"accessible action add after algorithm all analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate c
 ollation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general get global grant grants group group_concat handler hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invo
 ker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable
  server session share show signal slave slow smallint snapshot soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"),builtin:f("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varchara
 cter precision date datetime year unsigned signed numeric"),atoms:f("false true null unknown"),operatorChars:/^[*+\-%<>!=&|^]/,dateSQL:f("date time timestamp"),support:f("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber doubleQuote nCharCast charsetCast commentHash commentSpaceRequired"),hooks:{"@":d,"`":b,"\\":e}}),a.defineMIME("text/x-mariadb",{name:"sql",client:f("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"),keywords:f(g+"accessible action add after algorithm all always analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comme
 nt commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general generated get global grant grants group groupby_concat handler hard hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate k
 ey keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password persistent phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server sess
 ion share show shutdown signal slave slow smallint snapshot soft soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views virtual warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"),builtin:f("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varcha
 r varcharacter precision date datetime year unsigned signed numeric"),atoms:f("false true null unknown"),operatorChars:/^[*+\-%<>!=&|^]/,dateSQL:f("date time timestamp"),support:f("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber doubleQuote nCharCast charsetCast commentHash commentSpaceRequired"),hooks:{"@":d,"`":b,"\\":e}}),a.defineMIME("text/x-sqlite",{name:"sql",client:f("auth backup bail binary changes check clone databases dbinfo dump echo eqp exit explain fullschema headers help import imposter indexes iotrace limit lint load log mode nullvalue once open output print prompt quit read restore save scanstats schema separator session shell show stats system tables testcase timeout timer trace vfsinfo vfslist vfsname width"),keywords:f(g+"abort action add after all analyze attach autoincrement before begin cascade case cast check collate column commit co
 nflict constraint cross current_date current_time current_timestamp database default deferrable deferred detach each else end escape except exclusive exists explain fail for foreign full glob if ignore immediate index indexed initially inner instead intersect isnull key left limit match natural no notnull null of offset outer plan pragma primary query raise recursive references regexp reindex release rename replace restrict right rollback row savepoint temp temporary then to transaction trigger unique using vacuum view virtual when with without"),builtin:f("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text clob bigint int int2 int8 integer float double char varchar date datetime year unsigned signed numeric real"),atoms:f("null current_date current_time current_timestamp"),operatorChars:/^[*+\-%<>!=&|\/~]/,dateSQL:f("date time timestamp datetim
 e"),support:f("decimallessFloat zerolessFloat"),identifierQuote:'"',hooks:{"@":d,":":d,"?":d,$:d,'"':c,"`":b}}),a.defineMIME("text/x-cassandra",{name:"sql",client:{},keywords:f("add all allow alter and any apply as asc authorize batch begin by clustering columnfamily compact consistency count create custom delete desc distinct drop each_quorum exists filtering from grant if in index insert into key keyspace keyspaces level limit local_one local_quorum modify nan norecursive nosuperuser not of on one order password permission permissions primary quorum rename revoke schema select set storage superuser table three to token truncate ttl two type unlogged update use user users using values where with writetime"),builtin:f("ascii bigint blob boolean counter decimal double float frozen inet int list map static text timestamp timeuuid tuple uuid varchar varint"),atoms:f("false true
  infinity NaN"),operatorChars:/^[<>=]/,dateSQL:{},support:f("commentSlashSlash decimallessFloat"),hooks:{}}),a.defineMIME("text/x-plsql",{name:"sql",client:f("appinfo arraysize autocommit autoprint autorecovery autotrace blockterminator break btitle cmdsep colsep compatibility compute concat copycommit copytypecheck define describe echo editfile embedded escape exec execute feedback flagger flush heading headsep instance linesize lno loboffset logsource long longchunksize markup native newpage numformat numwidth pagesize pause pno recsep recsepchar release repfooter repheader serveroutput shiftinout show showmode size spool sqlblanklines sqlcase sqlcode sqlcontinue sqlnumber sqlpluscompatibility sqlprefix sqlprompt sqlterminator suffix tab term termout time timing trimout trimspool ttitle underline verify version wrap"),keywords:f("abort accept access add all alter and any array arraylen as asc assert assign at attributes audit
  authorization avg base_table begin between binary_integer body boolean by case cast char char_base check close cluster clusters colauth column comment commit compress connect connected constant constraint crash create current currval cursor data_base database date dba deallocate debugoff debugon decimal declare default definition delay delete desc digits dispose distinct do drop else elseif elsif enable end entry escape exception exception_init exchange exclusive exists exit external fast fetch file for force form from function generic goto grant group having identified if immediate in increment index indexes indicator initial initrans insert interface intersect into is key level library like limited local lock log logging long loop master maxextents maxtrans member minextents minus mislabel mode modify multiset new next no noaudit nocompress nologging noparallel not nowait number_base object of off offline on online only open option or order out package parallel partition pctfree 
 pctincrease pctused pls_integer positive positiven pragma primary prior private privileges procedure public raise range raw read rebuild record ref references refresh release rename replace resource restrict return returning returns reverse revoke rollback row rowid rowlabel rownum rows run savepoint schema segment select separate session set share snapshot some space split sql start statement storage subtype successful synonym tabauth table tables tablespace task terminate then to trigger truncate type union unique unlimited unrecoverable unusable update use using validate value values variable view views when whenever where while with work"),builtin:f("abs acos add_months ascii asin atan atan2 average bfile bfilename bigserial bit blob ceil character chartorowid chr clob concat convert cos cosh count dec decode deref dual dump dup_val_on_index empty error exp false float floor found glb greatest hextoraw initcap instr instrb int integer isopen last_day least length lengt
 hb ln lower lpad ltrim lub make_ref max min mlslabel mod months_between natural naturaln nchar nclob new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_sort nls_upper nlssort no_data_found notfound null number numeric nvarchar2 nvl others power rawtohex real reftohex round rowcount rowidtochar rowtype rpad rtrim serial sign signtype sin sinh smallint soundex sqlcode sqlerrm sqrt stddev string substr substrb sum sysdate tan tanh to_char text to_date to_label to_multi_byte to_number to_single_byte translate true trunc uid unlogged upper user userenv varchar varchar2 variance varying vsize xml"),operatorChars:/^[*+\-%<>!=~]/,dateSQL:f("date time timestamp"),support:f("doubleQuote nCharCast zerolessFloat binaryNumber hexNumber")}),a.defineMIME("text/x-hive",{name:"sql",keywords:f("select alter $elem$ $key$ $value$ add after all analyze and archive as asc before between binary bo
 th bucket buckets by cascade case cast change cluster clustered clusterstatus collection column columns comment compute concatenate continue create cross cursor data database databases dbproperties deferred delete delimited desc describe directory disable distinct distribute drop else enable end escaped exclusive exists explain export extended external false fetch fields fileformat first format formatted from full function functions grant group having hold_ddltime idxproperties if import in index indexes inpath inputdriver inputformat insert intersect into is items join keys lateral left like limit lines load local location lock locks mapjoin materialized minus msck no_drop nocompress not of offline on option or order out outer outputdriver outputformat overwrite partition partitioned partitions percent plus preserve procedure purge range rcfile read readonly reads rebuild recordreader recordwriter recover reduce regexp rename repair replace restrict revoke right rlike row schema sc
 hemas semi sequencefile serde serdeproperties set shared show show_database sort sorted ssl statistics stored streamtable table tables tablesample tblproperties temporary terminated textfile then tmp to touch transform trigger true unarchive undo union uniquejoin unlock update use using utc utc_tmestamp view when where while with"),builtin:f("bool boolean long timestamp tinyint smallint bigint int float double date datetime unsigned string array struct map uniontype"),atoms:f("false true null unknown"),operatorChars:/^[*+\-%<>!=]/,dateSQL:f("date timestamp"),support:f("ODBCdotTable doubleQuote binaryNumber hexNumber")}),a.defineMIME("text/x-pgsql",{name:"sql",client:f("source"),keywords:f(g+"a abort abs absent absolute access according action ada add admin after aggregate all allocate also always analyse analyze any are array array_agg array_max_cardinality asensitive assertion assignment asymmetri
 c at atomic attribute attributes authorization avg backward base64 before begin begin_frame begin_partition bernoulli binary bit_length blob blocked bom both breadth c cache call called cardinality cascade cascaded case cast catalog catalog_name ceil ceiling chain characteristics characters character_length character_set_catalog character_set_name character_set_schema char_length check checkpoint class class_origin clob close cluster coalesce cobol collate collation collation_catalog collation_name collation_schema collect column columns column_name command_function command_function_code comment comments commit committed concurrently condition condition_number configuration conflict connect connection connection_name constraint constraints constraint_catalog constraint_name constraint_schema constructor contains content continue control conversion convert copy corr corresponding cost covar_pop covar_samp cross csv cube cume_dist current current_catalog current_date current_default_t
 ransform_group current_path current_role current_row current_schema current_time current_timestamp current_transform_group_for_type current_user cursor cursor_name cycle data database datalink datetime_interval_code datetime_interval_precision day db deallocate dec declare default defaults deferrable deferred defined definer degree delimiter delimiters dense_rank depth deref derived describe descriptor deterministic diagnostics dictionary disable discard disconnect dispatch dlnewcopy dlpreviouscopy dlurlcomplete dlurlcompleteonly dlurlcompletewrite dlurlpath dlurlpathonly dlurlpathwrite dlurlscheme dlurlserver dlvalue do document domain dynamic dynamic_function dynamic_function_code each element else empty enable encoding encrypted end end-exec end_frame end_partition enforced enum equals escape event every except exception exclude excluding exclusive exec execute exists exp explain expression extension external extract false family fetch file filter final first first_value flag flo
 at floor following for force foreign fortran forward found frame_row free freeze fs full function functions fusion g general generated get global go goto grant granted greatest grouping groups handler header hex hierarchy hold hour id identity if ignore ilike immediate immediately immutable implementation implicit import including increment indent index indexes indicator inherit inherits initially inline inner inout input insensitive instance instantiable instead integrity intersect intersection invoker isnull isolation k key key_member key_type label lag language large last last_value lateral lead leading leakproof least left length level library like_regex link listen ln load local localtime localtimestamp location locator lock locked logged lower m map mapping match matched materialized max maxvalue max_cardinality member merge message_length message_octet_length message_text method min minute minvalue mod mode modifies module month more move multiset mumps name names namespace n
 ational natural nchar nclob nesting new next nfc nfd nfkc nfkd nil no none normalize normalized nothing notify notnull nowait nth_value ntile null nullable nullif nulls number object occurrences_regex octets octet_length of off offset oids old only open operator option options ordering ordinality others out outer output over overlaps overlay overriding owned owner p pad parallel parameter parameter_mode parameter_name parameter_ordinal_position parameter_specific_catalog parameter_specific_name parameter_specific_schema parser partial partition pascal passing passthrough password percent percentile_cont percentile_disc percent_rank period permission placing plans pli policy portion position position_regex power precedes preceding prepare prepared preserve primary prior privileges procedural procedure program public quote range rank read reads reassign recheck recovery recursive ref references referencing refresh regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_s
 xx regr_sxy regr_syy reindex relative release rename repeatable replace replica requiring reset respect restart restore restrict restricted result return returned_cardinality returned_length returned_octet_length returned_sqlstate returning returns revoke right role rollback rollup routine routine_catalog routine_name routine_schema row rows row_count row_number rule savepoint scale schema schema_name scope scope_catalog scope_name scope_schema scroll search second section security selective self sensitive sequence sequences serializable server server_name session session_user setof sets share show similar simple size skip snapshot some source space specific specifictype specific_name sql sqlcode sqlerror sqlexception sqlstate sqlwarning sqrt stable standalone start state statement static statistics stddev_pop stddev_samp stdin stdout storage strict strip structure style subclass_origin submultiset substring substring_regex succeeds sum symmetric sysid system system_time system_user
  t tables tablesample tablespace table_name temp template temporary then ties timezone_hour timezone_minute to token top_level_count trailing transaction transactions_committed transactions_rolled_back transaction_active transform transforms translate translate_regex translation treat trigger trigger_catalog trigger_name trigger_schema trim trim_array true truncate trusted type types uescape unbounded uncommitted under unencrypted unique unknown unlink unlisten unlogged unnamed unnest until untyped upper uri usage user user_defined_type_catalog user_defined_type_code user_defined_type_name user_defined_type_schema using vacuum valid validate validator value value_of varbinary variadic var_pop var_samp verbose version versioning view views volatile when whenever whitespace width_bucket window within work wrapper write xmlagg xmlattributes xmlbinary xmlcast xmlcomment xmlconcat xmldeclaration xmldocument xmlelement xmlexists xmlforest xmliterate xmlnamespaces xmlparse xmlpi xmlquery x
 mlroot xmlschema xmlserialize xmltable xmltext xmlvalidate year yes loop repeat attach path depends detach zone"),
+builtin:f("bigint int8 bigserial serial8 bit varying varbit boolean bool box bytea character char varchar cidr circle date double precision float8 inet integer int int4 interval json jsonb line lseg macaddr macaddr8 money numeric decimal path pg_lsn point polygon real float4 smallint int2 smallserial serial2 serial serial4 text time without zone with timetz timestamp timestamptz tsquery tsvector txid_snapshot uuid xml"),atoms:f("false true null unknown"),operatorChars:/^[*+\-%<>!=&|^\/#@?~]/,dateSQL:f("date time timestamp"),support:f("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber nCharCast charsetCast")}),a.defineMIME("text/x-gql",{name:"sql",keywords:f("ancestor and asc by contains desc descendant distinct from group has in is limit offset on order select superset where"),atoms:f("false true"),builtin:f("blob datetime first key __key__ string integer double boolean nu
 ll"),operatorChars:/^[*+\-%<>!=]/}),a.defineMIME("text/x-gpsql",{name:"sql",client:f("source"),keywords:f("abort absolute access action active add admin after aggregate all also alter always analyse analyze and any array as asc assertion assignment asymmetric at authorization backward before begin between bigint binary bit boolean both by cache called cascade cascaded case cast chain char character characteristics check checkpoint class close cluster coalesce codegen collate column comment commit committed concurrency concurrently configuration connection constraint constraints contains content continue conversion copy cost cpu_rate_limit create createdb createexttable createrole createuser cross csv cube current current_catalog current_date current_role current_schema current_time current_timestamp current_user cursor cycle data database day deallocate dec decimal declare decode default defaults deferrable deferred definer delete delimi
 ter delimiters deny desc dictionary disable discard distinct distributed do document domain double drop dxl each else enable encoding encrypted end enum errors escape every except exchange exclude excluding exclusive execute exists explain extension external extract false family fetch fields filespace fill filter first float following for force foreign format forward freeze from full function global grant granted greatest group group_id grouping handler hash having header hold host hour identity if ignore ilike immediate immutable implicit in including inclusive increment index indexes inherit inherits initially inline inner inout input insensitive insert instead int integer intersect interval into invoker is isnull isolation join key language large last leading least left level like limit list listen load local localtime localtimestamp location lock log login mapping master match maxvalue median merge minute minvalue missing mode modifies modify month move name names national natur
 al nchar new newline next no nocreatedb nocreateexttable nocreaterole nocreateuser noinherit nologin none noovercommit nosuperuser not nothing notify notnull nowait null nullif nulls numeric object of off offset oids old on only operator option options or order ordered others out outer over overcommit overlaps overlay owned owner parser partial partition partitions passing password percent percentile_cont percentile_disc placing plans position preceding precision prepare prepared preserve primary prior privileges procedural procedure protocol queue quote randomly range read readable reads real reassign recheck recursive ref references reindex reject relative release rename repeatable replace replica reset resource restart restrict returning returns revoke right role rollback rollup rootpartition row rows rule savepoint scatter schema scroll search second security segment select sequence serializable session session_user set setof sets share show similar simple smallint some split sq
 l stable standalone start statement statistics stdin stdout storage strict strip subpartition subpartitions substring superuser symmetric sysid system table tablespace temp template temporary text then threshold ties time timestamp to trailing transaction treat trigger trim true truncate trusted type unbounded uncommitted unencrypted union unique unknown unlisten until update user using vacuum valid validation validator value values varchar variadic varying verbose version view volatile web when where whitespace window with within without work writable write xml xmlattributes xmlconcat xmlelement xmlexists xmlforest xmlparse xmlpi xmlroot xmlserialize year yes zone"),builtin:f("bigint int8 bigserial serial8 bit varying varbit boolean bool box bytea character char varchar cidr circle date double precision float float8 inet integer int int4 interval json jsonb line lseg macaddr macaddr8 money numeric decimal path pg_lsn point polygon real float4 smallint int2 smallserial ser
 ial2 serial serial4 text time without zone with timetz timestamp timestamptz tsquery tsvector txid_snapshot uuid xml"),atoms:f("false true null unknown"),operatorChars:/^[*+\-%<>!=&|^\/#@?~]/,dateSQL:f("date time timestamp"),support:f("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber nCharCast charsetCast")}),a.defineMIME("text/x-sparksql",{name:"sql",keywords:f("add after all alter analyze and anti archive array as asc at between bucket buckets by cache cascade case cast change clear cluster clustered codegen collection column columns comment commit compact compactions compute concatenate cost create cross cube current current_date current_timestamp database databases datata dbproperties defined delete delimited desc describe dfs directories distinct distribute drop else end escaped except exchange exists explain export extended external false fields fileformat first following for format formatt
 ed from full function functions global grant group grouping having if ignore import in index indexes inner inpath inputformat insert intersect interval into is items join keys last lateral lazy left like limit lines list load local location lock locks logical macro map minus msck natural no not null nulls of on option options or order out outer outputformat over overwrite partition partitioned partitions percent preceding principals purge range recordreader recordwriter recover reduce refresh regexp rename repair replace reset restrict revoke right rlike role roles rollback rollup row rows schema schemas select semi separated serde serdeproperties set sets show skewed sort sorted start statistics stored stratify struct table tables tablesample tblproperties temp temporary terminated then to touch transaction transactions transform true truncate unarchive unbounded uncache union unlock unset use using values view when where window with"),builtin:f("tinyint smallint int bigi
 nt boolean float double string binary timestamp decimal array map struct uniontype delimited serde sequencefile textfile rcfile inputformat outputformat"),atoms:f("false true null"),operatorChars:/^[*+\-%<>!=~&|^]/,dateSQL:f("date time timestamp"),support:f("ODBCdotTable doubleQuote zerolessFloat")})}()})},{"../../lib/codemirror":59}],75:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";var b={autoSelfClosers:{area:!0,base:!0,br:!0,col:!0,command:!0,embed:!0,frame:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0,menuitem:!0},implicitlyClosed:{dd:!0,li:!0,optgroup:!0,option:!0,p:!0,rp:!0,rt:!0,tbody:!0,td:!0,tfoot:!0,th:!0,tr:!0},contextGrabbers:{dd:{dd:!0,dt:!
 0},dt:{dd:!0,dt:!0},li:{li:!0},option:{option:!0,optgroup:!0},optgroup:{optgroup:!0},p:{address:!0,article:!0,aside:!0,blockquote:!0,dir:!0,div:!0,dl:!0,fieldset:!0,footer:!0,form:!0,h1:!0,h2:!0,h3:!0,h4:!0,h5:!0,h6:!0,header:!0,hgroup:!0,hr:!0,menu:!0,nav:!0,ol:!0,p:!0,pre:!0,section:!0,table:!0,ul:!0},rp:{rp:!0,rt:!0},rt:{rp:!0,rt:!0},tbody:{tbody:!0,tfoot:!0},td:{td:!0,th:!0},tfoot:{tbody:!0},th:{td:!0,th:!0},thead:{tbody:!0,tfoot:!0},tr:{tr:!0}},doNotIndent:{pre:!0},allowUnquoted:!0,allowMissing:!0,caseFold:!0},c={autoSelfClosers:{},implicitlyClosed:{},contextGrabbers:{},doNotIndent:{},allowUnquoted:!1,allowMissing:!1,caseFold:!1};a.defineMode("xml",function(d,e){function f(a,b){function c(c){return b.tokenize=c,c(a,b)}var d=a.next();if("<"==d)return a.eat("!")?a.eat("[")?a.match("CDATA[")?c(i("atom","]]>")):null:a.match("--")?c(i("comment","-->")):a.match("DOCTYPE&q
 uot;,!0,!0)?(a.eatWhile(/[\w\._\-]/),c(j(1))):null:a.eat("?")?(a.eatWhile(/[\w\._\-]/),b.tokenize=i("meta","?>"),"meta"):(A=a.eat("/")?"closeTag":"openTag",b.tokenize=g,"tag bracket");if("&"==d){var e;return e=a.eat("#")?a.eat("x")?a.eatWhile(/[a-fA-F\d]/)&&a.eat(";"):a.eatWhile(/[\d]/)&&a.eat(";"):a.eatWhile(/[\w\.\-:]/)&&a.eat(";"),e?"atom":"error"}return a.eatWhile(/[^&<]/),null}function g(a,b){var c=a.next();if(">"==c||"/"==c&&a.eat(">"))return b.tokenize=f,A=">"==c?"endTag":"selfcloseTag","tag bracket";if("="==c)return A="equals",null;if("<"==c){b.tokenize=f,b.state=n,b.tagName=b.tagStart=null;var d=b.tokenize(a,b);return d?d+" tag error":"tag error&q
 uot;}return/[\'\"]/.test(c)?(b.tokenize=h(c),b.stringStartCol=a.column(),b.tokenize(a,b)):(a.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/),"word")}function h(a){var b=function(b,c){for(;!b.eol();)if(b.next()==a){c.tokenize=g;break}return"string"};return b.isInAttribute=!0,b}function i(a,b){return function(c,d){for(;!c.eol();){if(c.match(b)){d.tokenize=f;break}c.next()}return a}}function j(a){return function(b,c){for(var d;null!=(d=b.next());){if("<"==d)return c.tokenize=j(a+1),c.tokenize(b,c);if(">"==d){if(1==a){c.tokenize=f;break}return c.tokenize=j(a-1),c.tokenize(b,c)}}return"meta"}}function k(a,b,c){this.prev=a.context,this.tagName=b,this.indent=a.indented,this.startOfLine=c,(x.doNotIndent.hasOwnProperty(b)||a.context&&a.context.noIndent)&&(this.noIndent=!0)}function l(a){a.context&&(a.context=a.context.prev)}function m(a,b){for(var c;;){if(!a.context)return;if(c=a.cont
 ext.tagName,!x.contextGrabbers.hasOwnProperty(c)||!x.contextGrabbers[c].hasOwnProperty(b))return;l(a)}}function n(a,b,c){return"openTag"==a?(c.tagStart=b.column(),o):"closeTag"==a?p:n}function o(a,b,c){return"word"==a?(c.tagName=b.current(),B="tag",s):(B="error",o)}function p(a,b,c){if("word"==a){var d=b.current();return c.context&&c.context.tagName!=d&&x.implicitlyClosed.hasOwnProperty(c.context.tagName)&&l(c),c.context&&c.context.tagName==d||x.matchClosing===!1?(B="tag",q):(B="tag error",r)}return B="error",r}function q(a,b,c){return"endTag"!=a?(B="error",q):(l(c),n)}function r(a,b,c){return B="error",q(a,b,c)}function s(a,b,c){if("word"==a)return B="attribute",t;if("endTag"==a||"selfcloseTag"==a){var d=c.tagName,e=c.tagStart;return c.tagName=c.tagStart=null,"selfcloseTag"==a||x.aut
 oSelfClosers.hasOwnProperty(d)?m(c,d):(m(c,d),c.context=new k(c,d,e==c.indented)),n}return B="error",s}function t(a,b,c){return"equals"==a?u:(x.allowMissing||(B="error"),s(a,b,c))}function u(a,b,c){return"string"==a?v:"word"==a&&x.allowUnquoted?(B="string",s):(B="error",s(a,b,c))}function v(a,b,c){return"string"==a?v:s(a,b,c)}var w=d.indentUnit,x={},y=e.htmlMode?b:c;for(var z in y)x[z]=y[z];for(var z in e)x[z]=e[z];var A,B;return f.isInText=!0,{startState:function(a){var b={tokenize:f,state:n,indented:a||0,tagName:null,tagStart:null,context:null};return null!=a&&(b.baseIndent=a),b},token:function(a,b){if(!b.tagName&&a.sol()&&(b.indented=a.indentation()),a.eatSpace())return null;A=null;var c=b.tokenize(a,b);return(c||A)&&"comment"!=c&&(B=null,b.state=b.state(A||c,a,b),B&&(c="error"==B?c+" error":B)),c},indent:function(b,
 c,d){var e=b.context;if(b.tokenize.isInAttribute)return b.tagStart==b.indented?b.stringStartCol+1:b.indented+w;if(e&&e.noIndent)return a.Pass;if(b.tokenize!=g&&b.tokenize!=f)return d?d.match(/^(\s*)/)[0].length:0;if(b.tagName)return x.multilineTagIndentPastTag!==!1?b.tagStart+b.tagName.length+2:b.tagStart+w*(x.multilineTagIndentFactor||1);if(x.alignCDATA&&/<!\[CDATA\[/.test(c))return 0;var h=c&&/^<(\/)?([\w_:\.-]*)/.exec(c);if(h&&h[1])for(;e;){if(e.tagName==h[2]){e=e.prev;break}if(!x.implicitlyClosed.hasOwnProperty(e.tagName))break;e=e.prev}else if(h)for(;e;){var i=x.contextGrabbers[e.tagName];if(!i||!i.hasOwnProperty(h[2]))break;e=e.prev}for(;e&&e.prev&&!e.startOfLine;)e=e.prev;return e?e.indent+w:b.baseIndent||0},electricInput:/<\/[\s\w:]+>$/,blockCommentStart:"<!--",blockCommentEnd:"-->",configuration:x.htmlMode?"html":"xml",helperType:x.htmlMode?"html":&quo
 t;xml",skipAttribute:function(a){a.state==u&&(a.state=s)}}}),a.defineMIME("text/xml","xml"),a.defineMIME("application/xml","xml"),a.mimeModes.hasOwnProperty("text/html")||a.defineMIME("text/html",{name:"xml",htmlMode:!0})})},{"../../lib/codemirror":59}],76:[function(a,b,c){!function(d){"object"==typeof c&&"object"==typeof b?d(a("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],d):d(CodeMirror)}(function(a){"use strict";a.defineMode("yaml",function(){var a=["true","false","on","off","yes","no"],b=new RegExp("\\b(("+a.join(")|(")+"))$","i");return{token:function(a,c){var d=a.peek(),e=c.escaped;if(c.escaped=!1,"#"==d&&(0==a.pos||/\s/.test(a.string.ch
 arAt(a.pos-1))))return a.skipToEnd(),"comment";if(a.match(/^('([^']|\\.)*'?|"([^"]|\\.)*"?)/))return"string";if(c.literal&&a.indentation()>c.keyCol)return a.skipToEnd(),"string";if(c.literal&&(c.literal=!1),a.sol()){if(c.keyCol=0,c.pair=!1,c.pairStart=!1,a.match(/---/))return"def";if(a.match(/\.\.\./))return"def";if(a.match(/\s*-\s+/))return"meta"}if(a.match(/^(\{|\}|\[|\])/))return"{"==d?c.inlinePairs++:"}"==d?c.inlinePairs--:"["==d?c.inlineList++:c.inlineList--,"meta";if(c.inlineList>0&&!e&&","==d)return a.next(),"meta";if(c.inlinePairs>0&&!e&&","==d)return c.keyCol=0,c.pair=!1,c.pairStart=!1,a.next(),"meta";if(c.pairStart){if(a.match(/^\s*(\||\>)\s*/))return c.literal=!0,"meta";if(a.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i))return"variable-2";if(0==c
 .inlinePairs&&a.match(/^\s*-?[0-9\.\,]+\s?$/))return"number";if(c.inlinePairs>0&&a.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/))return"number";if(a.match(b))return"keyword"}return!c.pair&&a.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^,\[\]{}#&*!|>'"%@`])[^#]*?(?=\s*:($|\s))/)?(c.pair=!0,c.keyCol=a.indentation(),"atom"):c.pair&&a.match(/^:\s*/)?(c.pairStart=!0,"meta"):(c.pairStart=!1,c.escaped="\\"==d,a.next(),null)},startState:function(){return{pair:!1,pairStart:!1,keyCol:0,inlinePairs:0,inlineList:0,literal:!1,escaped:!1}}}}),a.defineMIME("text/x-yaml","yaml"),a.defineMIME("text/yaml","yaml")})},{"../../lib/codemirror":59}],77:[function(a,b,c){var d=a("../../../node_modules/codemirror/lib/codemirror");a("../../../node_modules/codemirror/lib/codemirror.js"),a("../../../node_modules/codemirror/k
 eymap/emacs.js"),a("../../../node_modules/codemirror/keymap/sublime.js"),a("../../../node_modules/codemirror/keymap/vim.js"),a("../../../node_modules/codemirror/addon/hint/show-hint.js"),a("../../../node_modules/codemirror/addon/hint/anyword-hint.js"),a("../../../node_modules/codemirror/addon/hint/css-hint.js"),a("../../../node_modules/codemirror/addon/hint/html-hint.js"),a("../../../node_modules/codemirror/addon/hint/javascript-hint.js"),a("../../../node_modules/codemirror/addon/hint/sql-hint.js"),a("../../../node_modules/codemirror/addon/hint/xml-hint.js"),a("../../../node_modules/codemirror/addon/lint/lint.js"),a("../../../node_modules/codemirror/addon/lint/css-lint.js"),a("../../../node_modules/codemirror/addon/lint/html-lint.js"),a("../../../node_modules/codemirror/addon/lint/javascript-lint.js"),a("../../../node_modules/codemirror/addon/li
 nt/json-lint.js"),a("../../../node_modules/codemirror/addon/comment/comment.js"),a("../../../node_modules/codemirror/addon/comment/continuecomment.js"),a("../../../node_modules/codemirror/addon/fold/xml-fold.js"),a("../../../node_modules/codemirror/addon/mode/overlay.js"),a("../../../node_modules/codemirror/addon/edit/closebrackets.js"),a("../../../node_modules/codemirror/addon/edit/closetag.js"),a("../../../node_modules/codemirror/addon/edit/continuelist.js"),a("../../../node_modules/codemirror/addon/edit/matchbrackets.js"),a("../../../node_modules/codemirror/addon/edit/matchtags.js"),a("../../../node_modules/codemirror/addon/edit/trailingspace.js"),a("../../../node_modules/codemirror/addon/dialog/dialog.js"),a("../../../node_modules/codemirror/addon/display/autorefresh.js"),a("../../../node_modules/codemirror/addon/display/fullscreen.js"),a(".
 ./../../node_modules/codemirror/addon/display/panel.js"),a("../../../node_modules/codemirror/addon/display/placeholder.js"),a("../../../node_modules/codemirror/addon/display/rulers.js"),a("../../../node_modules/codemirror/addon/fold/brace-fold.js"),a("../../../node_modules/codemirror/addon/fold/comment-fold.js"),a("../../../node_modules/codemirror/addon/fold/foldcode.js"),a("../../../node_modules/codemirror/addon/fold/foldgutter.js"),a("../../../node_modules/codemirror/addon/fold/indent-fold.js"),a("../../../node_modules/codemirror/addon/fold/markdown-fold.js"),a("../../../node_modules/codemirror/addon/merge/merge.js"),a("../../../node_modules/codemirror/addon/mode/loadmode.js"),a("../../../node_modules/codemirror/addon/mode/multiplex.js"),a("../../../node_modules/codemirror/addon/mode/simple.js"),a("../../../node_modules/codemirror/addon/runmode/runmode.
 js"),a("../../../node_modules/codemirror/addon/runmode/colorize.js"),a("../../../node_modules/codemirror/addon/runmode/runmode-standalone.js"),a("../../../node_modules/codemirror/addon/scroll/annotatescrollbar.js"),a("../../../node_modules/codemirror/addon/scroll/scrollpastend.js"),a("../../../node_modules/codemirror/addon/scroll/simplescrollbars.js"),a("../../../node_modules/codemirror/addon/search/search.js"),a("../../../node_modules/codemirror/addon/search/jump-to-line.js"),a("../../../node_modules/codemirror/addon/search/match-highlighter.js"),a("../../../node_modules/codemirror/addon/search/matchesonscrollbar.js"),a("../../../node_modules/codemirror/addon/search/searchcursor.js"),a("../../../node_modules/codemirror/addon/tern/tern.js"),a("../../../node_modules/codemirror/addon/tern/worker.js"),a("../../../node_modules/codemirror/addon/wrap/hardwrap.j
 s"),a("../../../node_modules/codemirror/addon/selection/active-line.js"),a("../../../node_modules/codemirror/addon/selection/mark-selection.js"),a("../../../node_modules/codemirror/addon/selection/selection-pointer.js"),a("../../../node_modules/codemirror/mode/meta.js"),a("../../../node_modules/codemirror/mode/clike/clike.js"),a("../../../node_modules/codemirror/mode/css/css.js"),a("../../../node_modules/codemirror/mode/diff/diff.js"),a("../../../node_modules/codemirror/mode/htmlmixed/htmlmixed.js"),a("../../../node_modules/codemirror/mode/http/http.js"),a("../../../node_modules/codemirror/mode/javascript/javascript.js"),a("../../../node_modules/codemirror/mode/jsx/jsx.js"),a("../../../node_modules/codemirror/mode/markdown/markdown.js"),a("../../../node_modules/codemirror/mode/gfm/gfm.js"),a("../../../node_modules/codemirror/mode/nginx/nginx.js&
 quot;),a("../../../node_modules/codemirror/mode/php/php.js"),a("../../../node_modules/codemirror/mode/sass/sass.js"),a("../../../node_modules/codemirror/mode/shell/shell.js"),a("../../../node_modules/codemirror/mode/sql/sql.js"),a("../../../node_modules/codemirror/mode/xml/xml.js"),a("../../../node_modules/codemirror/mode/yaml/yaml.js"),window.wp||(window.wp={}),window.wp.CodeMirror=d},{"../../../node_modules/codemirror/addon/comment/comment.js":1,"../../../node_modules/codemirror/addon/comment/continuecomment.js":2,"../../../node_modules/codemirror/addon/dialog/dialog.js":3,"../../../node_modules/codemirror/addon/display/autorefresh.js":4,"../../../node_modules/codemirror/addon/display/fullscreen.js":5,"../../../node_modules/codemirror/addon/display/panel.js":6,"../../../node_modules/codemirror/addon/display/placeholder.js":7,"../../../node_modules/
 codemirror/addon/display/rulers.js":8,"../../../node_modules/codemirror/addon/edit/closebrackets.js":9,"../../../node_modules/codemirror/addon/edit/closetag.js":10,"../../../node_modules/codemirror/addon/edit/continuelist.js":11,"../../../node_modules/codemirror/addon/edit/matchbrackets.js":12,"../../../node_modules/codemirror/addon/edit/matchtags.js":13,"../../../node_modules/codemirror/addon/edit/trailingspace.js":14,"../../../node_modules/codemirror/addon/fold/brace-fold.js":15,"../../../node_modules/codemirror/addon/fold/comment-fold.js":16,"../../../node_modules/codemirror/addon/fold/foldcode.js":17,"../../../node_modules/codemirror/addon/fold/foldgutter.js":18,"../../../node_modules/codemirror/addon/fold/indent-fold.js":19,"../../../node_modules/codemirror/addon/fold/markdown-fold.js":20,"../../../node_modules/codemirror/addon/fold/xml-fold.js"
 :21,"../../../node_modules/codemirror/addon/hint/anyword-hint.js":22,"../../../node_modules/codemirror/addon/hint/css-hint.js":23,"../../../node_modules/codemirror/addon/hint/html-hint.js":24,"../../../node_modules/codemirror/addon/hint/javascript-hint.js":25,"../../../node_modules/codemirror/addon/hint/show-hint.js":26,"../../../node_modules/codemirror/addon/hint/sql-hint.js":27,"../../../node_modules/codemirror/addon/hint/xml-hint.js":28,"../../../node_modules/codemirror/addon/lint/css-lint.js":29,"../../../node_modules/codemirror/addon/lint/html-lint.js":30,"../../../node_modules/codemirror/addon/lint/javascript-lint.js":31,"../../../node_modules/codemirror/addon/lint/json-lint.js":32,"../../../node_modules/codemirror/addon/lint/lint.js":33,"../../../node_modules/codemirror/addon/merge/merge.js":34,"../../../node_modules/codemirror/addon/mode/load
 mode.js":35,"../../../node_modules/codemirror/addon/mode/multiplex.js":36,"../../../node_modules/codemirror/addon/mode/overlay.js":37,"../../../node_modules/codemirror/addon/mode/simple.js":38,"../../../node_modules/codemirror/addon/runmode/colorize.js":39,"../../../node_modules/codemirror/addon/runmode/runmode-standalone.js":40,"../../../node_modules/codemirror/addon/runmode/runmode.js":41,"../../../node_modules/codemirror/addon/scroll/annotatescrollbar.js":42,"../../../node_modules/codemirror/addon/scroll/scrollpastend.js":43,"../../../node_modules/codemirror/addon/scroll/simplescrollbars.js":44,"../../../node_modules/codemirror/addon/search/jump-to-line.js":45,"../../../node_modules/codemirror/addon/search/match-highlighter.js":46,"../../../node_modules/codemirror/addon/search/matchesonscrollbar.js":47,"../../../node_modules/codemirror/addon/search/sea
 rch.js":48,"../../../node_modules/codemirror/addon/search/searchcursor.js":49,"../../../node_modules/codemirror/addon/selection/active-line.js":50,"../../../node_modules/codemirror/addon/selection/mark-selection.js":51,"../../../node_modules/codemirror/addon/selection/selection-pointer.js":52,"../../../node_modules/codemirror/addon/tern/tern.js":53,"../../../node_modules/codemirror/addon/tern/worker.js":54,"../../../node_modules/codemirror/addon/wrap/hardwrap.js":55,"../../../node_modules/codemirror/keymap/emacs.js":56,"../../../node_modules/codemirror/keymap/sublime.js":57,"../../../node_modules/codemirror/keymap/vim.js":58,"../../../node_modules/codemirror/lib/codemirror":59,"../../../node_modules/codemirror/lib/codemirror.js":59,"../../../node_modules/codemirror/mode/clike/clike.js":60,"../../../node_modules/codemirror/mode/css/css.js":6
 1,"../../../node_modules/codemirror/mode/diff/diff.js":62,"../../../node_modules/codemirror/mode/gfm/gfm.js":63,"../../../node_modules/codemirror/mode/htmlmixed/htmlmixed.js":64,"../../../node_modules/codemirror/mode/http/http.js":65,"../../../node_modules/codemirror/mode/javascript/javascript.js":66,"../../../node_modules/codemirror/mode/jsx/jsx.js":67,"../../../node_modules/codemirror/mode/markdown/markdown.js":68,"../../../node_modules/codemirror/mode/meta.js":69,"../../../node_modules/codemirror/mode/nginx/nginx.js":70,"../../../node_modules/codemirror/mode/php/php.js":71,"../../../node_modules/codemirror/mode/sass/sass.js":72,"../../../node_modules/codemirror/mode/shell/shell.js":73,"../../../node_modules/codemirror/mode/sql/sql.js":74,"../../../node_modules/codemirror/mode/xml/xml.js":75,"../../../node_modules/codemirror/mode/yaml/yam
 l.js":76}]},{},[77]);
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjscodemirrorcsslintjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/src/wp-includes/js/codemirror/csslint.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/codemirror/csslint.js                            (rev 0)
+++ trunk/src/wp-includes/js/codemirror/csslint.js      2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,10859 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/*!
+CSSLint v1.0.4
+Copyright (c) 2016 Nicole Sullivan and Nicholas C. Zakas. All rights reserved.
+
+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 CSSLint = (function(){
+  var module = module || {},
+      exports = exports || {};
+
+/*!
+Parser-Lib
+Copyright (c) 2009-2016 Nicholas C. Zakas. All rights reserved.
+
+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.
+*/
+/* Version v1.1.0, Build time: 6-December-2016 10:31:29 */
+var parserlib = (function () {
+var require;
+require=(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){
+"use strict";
+
+/* exported Colors */
+
+var Colors = module.exports = {
+    __proto__       :null,
+    aliceblue       :"#f0f8ff",
+    antiquewhite    :"#faebd7",
+    aqua            :"#00ffff",
+    aquamarine      :"#7fffd4",
+    azure           :"#f0ffff",
+    beige           :"#f5f5dc",
+    bisque          :"#ffe4c4",
+    black           :"#000000",
+    blanchedalmond  :"#ffebcd",
+    blue            :"#0000ff",
+    blueviolet      :"#8a2be2",
+    brown           :"#a52a2a",
+    burlywood       :"#deb887",
+    cadetblue       :"#5f9ea0",
+    chartreuse      :"#7fff00",
+    chocolate       :"#d2691e",
+    coral           :"#ff7f50",
+    cornflowerblue  :"#6495ed",
+    cornsilk        :"#fff8dc",
+    crimson         :"#dc143c",
+    cyan            :"#00ffff",
+    darkblue        :"#00008b",
+    darkcyan        :"#008b8b",
+    darkgoldenrod   :"#b8860b",
+    darkgray        :"#a9a9a9",
+    darkgrey        :"#a9a9a9",
+    darkgreen       :"#006400",
+    darkkhaki       :"#bdb76b",
+    darkmagenta     :"#8b008b",
+    darkolivegreen  :"#556b2f",
+    darkorange      :"#ff8c00",
+    darkorchid      :"#9932cc",
+    darkred         :"#8b0000",
+    darksalmon      :"#e9967a",
+    darkseagreen    :"#8fbc8f",
+    darkslateblue   :"#483d8b",
+    darkslategray   :"#2f4f4f",
+    darkslategrey   :"#2f4f4f",
+    darkturquoise   :"#00ced1",
+    darkviolet      :"#9400d3",
+    deeppink        :"#ff1493",
+    deepskyblue     :"#00bfff",
+    dimgray         :"#696969",
+    dimgrey         :"#696969",
+    dodgerblue      :"#1e90ff",
+    firebrick       :"#b22222",
+    floralwhite     :"#fffaf0",
+    forestgreen     :"#228b22",
+    fuchsia         :"#ff00ff",
+    gainsboro       :"#dcdcdc",
+    ghostwhite      :"#f8f8ff",
+    gold            :"#ffd700",
+    goldenrod       :"#daa520",
+    gray            :"#808080",
+    grey            :"#808080",
+    green           :"#008000",
+    greenyellow     :"#adff2f",
+    honeydew        :"#f0fff0",
+    hotpink         :"#ff69b4",
+    indianred       :"#cd5c5c",
+    indigo          :"#4b0082",
+    ivory           :"#fffff0",
+    khaki           :"#f0e68c",
+    lavender        :"#e6e6fa",
+    lavenderblush   :"#fff0f5",
+    lawngreen       :"#7cfc00",
+    lemonchiffon    :"#fffacd",
+    lightblue       :"#add8e6",
+    lightcoral      :"#f08080",
+    lightcyan       :"#e0ffff",
+    lightgoldenrodyellow  :"#fafad2",
+    lightgray       :"#d3d3d3",
+    lightgrey       :"#d3d3d3",
+    lightgreen      :"#90ee90",
+    lightpink       :"#ffb6c1",
+    lightsalmon     :"#ffa07a",
+    lightseagreen   :"#20b2aa",
+    lightskyblue    :"#87cefa",
+    lightslategray  :"#778899",
+    lightslategrey  :"#778899",
+    lightsteelblue  :"#b0c4de",
+    lightyellow     :"#ffffe0",
+    lime            :"#00ff00",
+    limegreen       :"#32cd32",
+    linen           :"#faf0e6",
+    magenta         :"#ff00ff",
+    maroon          :"#800000",
+    mediumaquamarine:"#66cdaa",
+    mediumblue      :"#0000cd",
+    mediumorchid    :"#ba55d3",
+    mediumpurple    :"#9370d8",
+    mediumseagreen  :"#3cb371",
+    mediumslateblue :"#7b68ee",
+    mediumspringgreen   :"#00fa9a",
+    mediumturquoise :"#48d1cc",
+    mediumvioletred :"#c71585",
+    midnightblue    :"#191970",
+    mintcream       :"#f5fffa",
+    mistyrose       :"#ffe4e1",
+    moccasin        :"#ffe4b5",
+    navajowhite     :"#ffdead",
+    navy            :"#000080",
+    oldlace         :"#fdf5e6",
+    olive           :"#808000",
+    olivedrab       :"#6b8e23",
+    orange          :"#ffa500",
+    orangered       :"#ff4500",
+    orchid          :"#da70d6",
+    palegoldenrod   :"#eee8aa",
+    palegreen       :"#98fb98",
+    paleturquoise   :"#afeeee",
+    palevioletred   :"#d87093",
+    papayawhip      :"#ffefd5",
+    peachpuff       :"#ffdab9",
+    peru            :"#cd853f",
+    pink            :"#ffc0cb",
+    plum            :"#dda0dd",
+    powderblue      :"#b0e0e6",
+    purple          :"#800080",
+    red             :"#ff0000",
+    rosybrown       :"#bc8f8f",
+    royalblue       :"#4169e1",
+    saddlebrown     :"#8b4513",
+    salmon          :"#fa8072",
+    sandybrown      :"#f4a460",
+    seagreen        :"#2e8b57",
+    seashell        :"#fff5ee",
+    sienna          :"#a0522d",
+    silver          :"#c0c0c0",
+    skyblue         :"#87ceeb",
+    slateblue       :"#6a5acd",
+    slategray       :"#708090",
+    slategrey       :"#708090",
+    snow            :"#fffafa",
+    springgreen     :"#00ff7f",
+    steelblue       :"#4682b4",
+    tan             :"#d2b48c",
+    teal            :"#008080",
+    thistle         :"#d8bfd8",
+    tomato          :"#ff6347",
+    turquoise       :"#40e0d0",
+    violet          :"#ee82ee",
+    wheat           :"#f5deb3",
+    white           :"#ffffff",
+    whitesmoke      :"#f5f5f5",
+    yellow          :"#ffff00",
+    yellowgreen     :"#9acd32",
+    //'currentColor' color keyword https://www.w3.org/TR/css3-color/#currentcolor
+    currentColor        :"The value of the 'color' property.",
+    //CSS2 system colors https://www.w3.org/TR/css3-color/#css2-system
+    activeBorder        :"Active window border.",
+    activecaption       :"Active window caption.",
+    appworkspace        :"Background color of multiple document interface.",
+    background          :"Desktop background.",
+    buttonface          :"The face background color for 3-D elements that appear 3-D due to one layer of surrounding border.",
+    buttonhighlight     :"The color of the border facing the light source for 3-D elements that appear 3-D due to one layer of surrounding border.",
+    buttonshadow        :"The color of the border away from the light source for 3-D elements that appear 3-D due to one layer of surrounding border.",
+    buttontext          :"Text on push buttons.",
+    captiontext         :"Text in caption, size box, and scrollbar arrow box.",
+    graytext            :"Grayed (disabled) text. This color is set to #000 if the current display driver does not support a solid gray color.",
+    greytext            :"Greyed (disabled) text. This color is set to #000 if the current display driver does not support a solid grey color.",
+    highlight           :"Item(s) selected in a control.",
+    highlighttext       :"Text of item(s) selected in a control.",
+    inactiveborder      :"Inactive window border.",
+    inactivecaption     :"Inactive window caption.",
+    inactivecaptiontext :"Color of text in an inactive caption.",
+    infobackground      :"Background color for tooltip controls.",
+    infotext            :"Text color for tooltip controls.",
+    menu                :"Menu background.",
+    menutext            :"Text in menus.",
+    scrollbar           :"Scroll bar gray area.",
+    threeddarkshadow    :"The color of the darker (generally outer) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",
+    threedface          :"The face background color for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",
+    threedhighlight     :"The color of the lighter (generally outer) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",
+    threedlightshadow   :"The color of the darker (generally inner) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",
+    threedshadow        :"The color of the lighter (generally inner) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.",
+    window              :"Window background.",
+    windowframe         :"Window frame.",
+    windowtext          :"Text in windows."
+};
+
+},{}],2:[function(require,module,exports){
+"use strict";
+
+module.exports = Combinator;
+
+var SyntaxUnit = require("../util/SyntaxUnit");
+
+var Parser = require("./Parser");
+
+/**
+ * Represents a selector combinator (whitespace, +, >).
+ * @namespace parserlib.css
+ * @class Combinator
+ * @extends parserlib.util.SyntaxUnit
+ * @constructor
+ * @param {String} text The text representation of the unit.
+ * @param {int} line The line of text on which the unit resides.
+ * @param {int} col The column of text on which the unit resides.
+ */
+function Combinator(text, line, col) {
+
+    SyntaxUnit.call(this, text, line, col, Parser.COMBINATOR_TYPE);
+
+    /**
+     * The type of modifier.
+     * @type String
+     * @property type
+     */
+    this.type = "unknown";
+
+    //pretty simple
+    if (/^\s+$/.test(text)) {
+        this.type = "descendant";
+    } else if (text === ">") {
+        this.type = "child";
+    } else if (text === "+") {
+        this.type = "adjacent-sibling";
+    } else if (text === "~") {
+        this.type = "sibling";
+    }
+
+}
+
+Combinator.prototype = new SyntaxUnit();
+Combinator.prototype.constructor = Combinator;
+
+
+},{"../util/SyntaxUnit":26,"./Parser":6}],3:[function(require,module,exports){
+"use strict";
+
+module.exports = Matcher;
+
+var StringReader = require("../util/StringReader");
+var SyntaxError = require("../util/SyntaxError");
+
+/**
+ * This class implements a combinator library for matcher functions.
+ * The combinators are described at:
+ * https://developer.mozilla.org/en-US/docs/Web/CSS/Value_definition_syntax#Component_value_combinators
+ */
+function Matcher(matchFunc, toString) {
+    this.match = function(expression) {
+        // Save/restore marks to ensure that failed matches always restore
+        // the original location in the expression.
+        var result;
+        expression.mark();
+        result = matchFunc(expression);
+        if (result) {
+            expression.drop();
+        } else {
+            expression.restore();
+        }
+        return result;
+    };
+    this.toString = typeof toString === "function" ? toString : function() {
+        return toString;
+    };
+}
+
+/** Precedence table of combinators. */
+Matcher.prec = {
+    MOD:    5,
+    SEQ:    4,
+    ANDAND: 3,
+    OROR:   2,
+    ALT:    1
+};
+
+/** Simple recursive-descent grammar to build matchers from strings. */
+Matcher.parse = function(str) {
+    var reader, eat, expr, oror, andand, seq, mod, term, result;
+    reader = new StringReader(str);
+    eat = function(matcher) {
+        var result = reader.readMatch(matcher);
+        if (result === null) {
+            throw new SyntaxError(
+                "Expected "+matcher, reader.getLine(), reader.getCol());
+        }
+        return result;
+    };
+    expr = function() {
+        // expr = oror (" | " oror)*
+        var m = [ oror() ];
+        while (reader.readMatch(" | ") !== null) {
+            m.push(oror());
+        }
+        return m.length === 1 ? m[0] : Matcher.alt.apply(Matcher, m);
+    };
+    oror = function() {
+        // oror = andand ( " || " andand)*
+        var m = [ andand() ];
+        while (reader.readMatch(" || ") !== null) {
+            m.push(andand());
+        }
+        return m.length === 1 ? m[0] : Matcher.oror.apply(Matcher, m);
+    };
+    andand = function() {
+        // andand = seq ( " && " seq)*
+        var m = [ seq() ];
+        while (reader.readMatch(" && ") !== null) {
+            m.push(seq());
+        }
+        return m.length === 1 ? m[0] : Matcher.andand.apply(Matcher, m);
+    };
+    seq = function() {
+        // seq = mod ( " " mod)*
+        var m = [ mod() ];
+        while (reader.readMatch(/^ (?![&|\]])/) !== null) {
+            m.push(mod());
+        }
+        return m.length === 1 ? m[0] : Matcher.seq.apply(Matcher, m);
+    };
+    mod = function() {
+        // mod = term ( "?" | "*" | "+" | "#" | "{<num>,<num>}" )?
+        var m = term();
+        if (reader.readMatch("?") !== null) {
+            return m.question();
+        } else if (reader.readMatch("*") !== null) {
+            return m.star();
+        } else if (reader.readMatch("+") !== null) {
+            return m.plus();
+        } else if (reader.readMatch("#") !== null) {
+            return m.hash();
+        } else if (reader.readMatch(/^\{\s*/) !== null) {
+            var min = eat(/^\d+/);
+            eat(/^\s*,\s*/);
+            var max = eat(/^\d+/);
+            eat(/^\s*\}/);
+            return m.braces(+min, +max);
+        }
+        return m;
+    };
+    term = function() {
+        // term = <nt> | literal | "[ " expression " ]"
+        if (reader.readMatch("[ ") !== null) {
+            var m = expr();
+            eat(" ]");
+            return m;
+        }
+        return Matcher.fromType(eat(/^[^ ?*+#{]+/));
+    };
+    result = expr();
+    if (!reader.eof()) {
+        throw new SyntaxError(
+            "Expected end of string", reader.getLine(), reader.getCol());
+    }
+    return result;
+};
+
+/**
+ * Convert a string to a matcher (parsing simple alternations),
+ * or do nothing if the argument is already a matcher.
+ */
+Matcher.cast = function(m) {
+    if (m instanceof Matcher) {
+        return m;
+    }
+    return Matcher.parse(m);
+};
+
+/**
+ * Create a matcher for a single type.
+ */
+Matcher.fromType = function(type) {
+    // Late require of ValidationTypes to break a dependency cycle.
+    var ValidationTypes = require("./ValidationTypes");
+    return new Matcher(function(expression) {
+        return expression.hasNext() && ValidationTypes.isType(expression, type);
+    }, type);
+};
+
+/**
+ * Create a matcher for one or more juxtaposed words, which all must
+ * occur, in the given order.
+ */
+Matcher.seq = function() {
+    var ms = Array.prototype.slice.call(arguments).map(Matcher.cast);
+    if (ms.length === 1) {
+        return ms[0];
+    }
+    return new Matcher(function(expression) {
+        var i, result = true;
+        for (i = 0; result && i < ms.length; i++) {
+            result = ms[i].match(expression);
+        }
+        return result;
+    }, function(prec) {
+        var p = Matcher.prec.SEQ;
+        var s = ms.map(function(m) {
+            return m.toString(p);
+        }).join(" ");
+        if (prec > p) {
+            s = "[ " + s + " ]";
+        }
+        return s;
+    });
+};
+
+/**
+ * Create a matcher for one or more alternatives, where exactly one
+ * must occur.
+ */
+Matcher.alt = function() {
+    var ms = Array.prototype.slice.call(arguments).map(Matcher.cast);
+    if (ms.length === 1) {
+        return ms[0];
+    }
+    return new Matcher(function(expression) {
+        var i, result = false;
+        for (i = 0; !result && i < ms.length; i++) {
+            result = ms[i].match(expression);
+        }
+        return result;
+    }, function(prec) {
+        var p = Matcher.prec.ALT;
+        var s = ms.map(function(m) {
+            return m.toString(p);
+        }).join(" | ");
+        if (prec > p) {
+            s = "[ " + s + " ]";
+        }
+        return s;
+    });
+};
+
+/**
+ * Create a matcher for two or more options.  This implements the
+ * double bar (||) and double ampersand (&&) operators, as well as
+ * variants of && where some of the alternatives are optional.
+ * This will backtrack through even successful matches to try to
+ * maximize the number of items matched.
+ */
+Matcher.many = function(required) {
+    var ms = Array.prototype.slice.call(arguments, 1).reduce(function(acc, v) {
+        if (v.expand) {
+            // Insert all of the options for the given complex rule as
+            // individual options.
+            var ValidationTypes = require("./ValidationTypes");
+            acc.push.apply(acc, ValidationTypes.complex[v.expand].options);
+        } else {
+            acc.push(Matcher.cast(v));
+        }
+        return acc;
+    }, []);
+
+    if (required === true) {
+        required = ms.map(function() {
+            return true;
+        });
+    }
+
+    var result = new Matcher(function(expression) {
+        var seen = [], max = 0, pass = 0;
+        var success = function(matchCount) {
+            if (pass === 0) {
+                max = Math.max(matchCount, max);
+                return matchCount === ms.length;
+            } else {
+                return matchCount === max;
+            }
+        };
+        var tryMatch = function(matchCount) {
+            for (var i = 0; i < ms.length; i++) {
+                if (seen[i]) {
+                    continue;
+                }
+                expression.mark();
+                if (ms[i].match(expression)) {
+                    seen[i] = true;
+                    // Increase matchCount iff this was a required element
+                    // (or if all the elements are optional)
+                    if (tryMatch(matchCount + ((required === false || required[i]) ? 1 : 0))) {
+                        expression.drop();
+                        return true;
+                    }
+                    // Backtrack: try *not* matching using this rule, and
+                    // let's see if it leads to a better overall match.
+                    expression.restore();
+                    seen[i] = false;
+                } else {
+                    expression.drop();
+                }
+            }
+            return success(matchCount);
+        };
+        if (!tryMatch(0)) {
+            // Couldn't get a complete match, retrace our steps to make the
+            // match with the maximum # of required elements.
+            pass++;
+            tryMatch(0);
+        }
+
+        if (required === false) {
+            return max > 0;
+        }
+        // Use finer-grained specification of which matchers are required.
+        for (var i = 0; i < ms.length; i++) {
+            if (required[i] && !seen[i]) {
+                return false;
+            }
+        }
+        return true;
+    }, function(prec) {
+        var p = required === false ? Matcher.prec.OROR : Matcher.prec.ANDAND;
+        var s = ms.map(function(m, i) {
+            if (required !== false && !required[i]) {
+                return m.toString(Matcher.prec.MOD) + "?";
+            }
+            return m.toString(p);
+        }).join(required === false ? " || " : " && ");
+        if (prec > p) {
+            s = "[ " + s + " ]";
+        }
+        return s;
+    });
+    result.options = ms;
+    return result;
+};
+
+/**
+ * Create a matcher for two or more options, where all options are
+ * mandatory but they may appear in any order.
+ */
+Matcher.andand = function() {
+    var args = Array.prototype.slice.call(arguments);
+    args.unshift(true);
+    return Matcher.many.apply(Matcher, args);
+};
+
+/**
+ * Create a matcher for two or more options, where options are
+ * optional and may appear in any order, but at least one must be
+ * present.
+ */
+Matcher.oror = function() {
+    var args = Array.prototype.slice.call(arguments);
+    args.unshift(false);
+    return Matcher.many.apply(Matcher, args);
+};
+
+/** Instance methods on Matchers. */
+Matcher.prototype = {
+    constructor: Matcher,
+    // These are expected to be overridden in every instance.
+    match: function() { throw new Error("unimplemented"); },
+    toString: function() { throw new Error("unimplemented"); },
+    // This returns a standalone function to do the matching.
+    func: function() { return this.match.bind(this); },
+    // Basic combinators
+    then: function(m) { return Matcher.seq(this, m); },
+    or: function(m) { return Matcher.alt(this, m); },
+    andand: function(m) { return Matcher.many(true, this, m); },
+    oror: function(m) { return Matcher.many(false, this, m); },
+    // Component value multipliers
+    star: function() { return this.braces(0, Infinity, "*"); },
+    plus: function() { return this.braces(1, Infinity, "+"); },
+    question: function() { return this.braces(0, 1, "?"); },
+    hash: function() {
+        return this.braces(1, Infinity, "#", Matcher.cast(","));
+    },
+    braces: function(min, max, marker, optSep) {
+        var m1 = this, m2 = optSep ? optSep.then(this) : this;
+        if (!marker) {
+            marker = "{" + min + "," + max + "}";
+        }
+        return new Matcher(function(expression) {
+            var result = true, i;
+            for (i = 0; i < max; i++) {
+                if (i > 0 && optSep) {
+                    result = m2.match(expression);
+                } else {
+                    result = m1.match(expression);
+                }
+                if (!result) {
+                    break;
+                }
+            }
+            return i >= min;
+        }, function() {
+            return m1.toString(Matcher.prec.MOD) + marker;
+        });
+    }
+};
+
+},{"../util/StringReader":24,"../util/SyntaxError":25,"./ValidationTypes":21}],4:[function(require,module,exports){
+"use strict";
+
+module.exports = MediaFeature;
+
+var SyntaxUnit = require("../util/SyntaxUnit");
+
+var Parser = require("./Parser");
+
+/**
+ * Represents a media feature, such as max-width:500.
+ * @namespace parserlib.css
+ * @class MediaFeature
+ * @extends parserlib.util.SyntaxUnit
+ * @constructor
+ * @param {SyntaxUnit} name The name of the feature.
+ * @param {SyntaxUnit} value The value of the feature or null if none.
+ */
+function MediaFeature(name, value) {
+
+    SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol, Parser.MEDIA_FEATURE_TYPE);
+
+    /**
+     * The name of the media feature
+     * @type String
+     * @property name
+     */
+    this.name = name;
+
+    /**
+     * The value for the feature or null if there is none.
+     * @type SyntaxUnit
+     * @property value
+     */
+    this.value = value;
+}
+
+MediaFeature.prototype = new SyntaxUnit();
+MediaFeature.prototype.constructor = MediaFeature;
+
+
+},{"../util/SyntaxUnit":26,"./Parser":6}],5:[function(require,module,exports){
+"use strict";
+
+module.exports = MediaQuery;
+
+var SyntaxUnit = require("../util/SyntaxUnit");
+
+var Parser = require("./Parser");
+
+/**
+ * Represents an individual media query.
+ * @namespace parserlib.css
+ * @class MediaQuery
+ * @extends parserlib.util.SyntaxUnit
+ * @constructor
+ * @param {String} modifier The modifier "not" or "only" (or null).
+ * @param {String} mediaType The type of media (i.e., "print").
+ * @param {Array} parts Array of selectors parts making up this selector.
+ * @param {int} line The line of text on which the unit resides.
+ * @param {int} col The column of text on which the unit resides.
+ */
+function MediaQuery(modifier, mediaType, features, line, col) {
+
+    SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType : "") + (mediaType && features.length > 0 ? " and " : "") + features.join(" and "), line, col, Parser.MEDIA_QUERY_TYPE);
+
+    /**
+     * The media modifier ("not" or "only")
+     * @type String
+     * @property modifier
+     */
+    this.modifier = modifier;
+
+    /**
+     * The mediaType (i.e., "print")
+     * @type String
+     * @property mediaType
+     */
+    this.mediaType = mediaType;
+
+    /**
+     * The parts that make up the selector.
+     * @type Array
+     * @property features
+     */
+    this.features = features;
+
+}
+
+MediaQuery.prototype = new SyntaxUnit();
+MediaQuery.prototype.constructor = MediaQuery;
+
+
+},{"../util/SyntaxUnit":26,"./Parser":6}],6:[function(require,module,exports){
+"use strict";
+
+module.exports = Parser;
+
+var EventTarget = require("../util/EventTarget");
+var SyntaxError = require("../util/SyntaxError");
+var SyntaxUnit = require("../util/SyntaxUnit");
+
+var Combinator = require("./Combinator");
+var MediaFeature = require("./MediaFeature");
+var MediaQuery = require("./MediaQuery");
+var PropertyName = require("./PropertyName");
+var PropertyValue = require("./PropertyValue");
+var PropertyValuePart = require("./PropertyValuePart");
+var Selector = require("./Selector");
+var SelectorPart = require("./SelectorPart");
+var SelectorSubPart = require("./SelectorSubPart");
+var TokenStream = require("./TokenStream");
+var Tokens = require("./Tokens");
+var Validation = require("./Validation");
+
+/**
+ * A CSS3 parser.
+ * @namespace parserlib.css
+ * @class Parser
+ * @constructor
+ * @param {Object} options (Optional) Various options for the parser:
+ *      starHack (true|false) to allow IE6 star hack as valid,
+ *      underscoreHack (true|false) to interpret leading underscores
+ *      as IE6-7 targeting for known properties, ieFilters (true|false)
+ *      to indicate that IE < 8 filters should be accepted and not throw
+ *      syntax errors.
+ */
+function Parser(options) {
+
+    //inherit event functionality
+    EventTarget.call(this);
+
+
+    this.options = options || {};
+
+    this._tokenStream = null;
+}
+
+//Static constants
+Parser.DEFAULT_TYPE = 0;
+Parser.COMBINATOR_TYPE = 1;
+Parser.MEDIA_FEATURE_TYPE = 2;
+Parser.MEDIA_QUERY_TYPE = 3;
+Parser.PROPERTY_NAME_TYPE = 4;
+Parser.PROPERTY_VALUE_TYPE = 5;
+Parser.PROPERTY_VALUE_PART_TYPE = 6;
+Parser.SELECTOR_TYPE = 7;
+Parser.SELECTOR_PART_TYPE = 8;
+Parser.SELECTOR_SUB_PART_TYPE = 9;
+
+Parser.prototype = function() {
+
+    var proto = new EventTarget(),  //new prototype
+        prop,
+        additions =  {
+            __proto__: null,
+
+            //restore constructor
+            constructor: Parser,
+
+            //instance constants - yuck
+            DEFAULT_TYPE : 0,
+            COMBINATOR_TYPE : 1,
+            MEDIA_FEATURE_TYPE : 2,
+            MEDIA_QUERY_TYPE : 3,
+            PROPERTY_NAME_TYPE : 4,
+            PROPERTY_VALUE_TYPE : 5,
+            PROPERTY_VALUE_PART_TYPE : 6,
+            SELECTOR_TYPE : 7,
+            SELECTOR_PART_TYPE : 8,
+            SELECTOR_SUB_PART_TYPE : 9,
+
+            //-----------------------------------------------------------------
+            // Grammar
+            //-----------------------------------------------------------------
+
+            _stylesheet: function() {
+
+                /*
+                 * stylesheet
+                 *  : [ CHARSET_SYM S* STRING S* ';' ]?
+                 *    [S|CDO|CDC]* [ import [S|CDO|CDC]* ]*
+                 *    [ namespace [S|CDO|CDC]* ]*
+                 *    [ [ ruleset | media | page | font_face | keyframes_rule | supports_rule ] [S|CDO|CDC]* ]*
+                 *  ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    count,
+                    token,
+                    tt;
+
+                this.fire("startstylesheet");
+
+                //try to read character set
+                this._charset();
+
+                this._skipCruft();
+
+                //try to read imports - may be more than one
+                while (tokenStream.peek() === Tokens.IMPORT_SYM) {
+                    this._import();
+                    this._skipCruft();
+                }
+
+                //try to read namespaces - may be more than one
+                while (tokenStream.peek() === Tokens.NAMESPACE_SYM) {
+                    this._namespace();
+                    this._skipCruft();
+                }
+
+                //get the next token
+                tt = tokenStream.peek();
+
+                //try to read the rest
+                while (tt > Tokens.EOF) {
+
+                    try {
+
+                        switch (tt) {
+                            case Tokens.MEDIA_SYM:
+                                this._media();
+                                this._skipCruft();
+                                break;
+                            case Tokens.PAGE_SYM:
+                                this._page();
+                                this._skipCruft();
+                                break;
+                            case Tokens.FONT_FACE_SYM:
+                                this._font_face();
+                                this._skipCruft();
+                                break;
+                            case Tokens.KEYFRAMES_SYM:
+                                this._keyframes();
+                                this._skipCruft();
+                                break;
+                            case Tokens.VIEWPORT_SYM:
+                                this._viewport();
+                                this._skipCruft();
+                                break;
+                            case Tokens.DOCUMENT_SYM:
+                                this._document();
+                                this._skipCruft();
+                                break;
+                            case Tokens.SUPPORTS_SYM:
+                                this._supports();
+                                this._skipCruft();
+                                break;
+                            case Tokens.UNKNOWN_SYM:  //unknown @ rule
+                                tokenStream.get();
+                                if (!this.options.strict) {
+
+                                    //fire error event
+                                    this.fire({
+                                        type:       "error",
+                                        error:      null,
+                                        message:    "Unknown @ rule: " + tokenStream.LT(0).value + ".",
+                                        line:       tokenStream.LT(0).startLine,
+                                        col:        tokenStream.LT(0).startCol
+                                    });
+
+                                    //skip braces
+                                    count=0;
+                                    while (tokenStream.advance([Tokens.LBRACE, Tokens.RBRACE]) === Tokens.LBRACE) {
+                                        count++;    //keep track of nesting depth
+                                    }
+
+                                    while (count) {
+                                        tokenStream.advance([Tokens.RBRACE]);
+                                        count--;
+                                    }
+
+                                } else {
+                                    //not a syntax error, rethrow it
+                                    throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol);
+                                }
+                                break;
+                            case Tokens.S:
+                                this._readWhitespace();
+                                break;
+                            default:
+                                if (!this._ruleset()) {
+
+                                    //error handling for known issues
+                                    switch (tt) {
+                                        case Tokens.CHARSET_SYM:
+                                            token = tokenStream.LT(1);
+                                            this._charset(false);
+                                            throw new SyntaxError("@charset not allowed here.", token.startLine, token.startCol);
+                                        case Tokens.IMPORT_SYM:
+                                            token = tokenStream.LT(1);
+                                            this._import(false);
+                                            throw new SyntaxError("@import not allowed here.", token.startLine, token.startCol);
+                                        case Tokens.NAMESPACE_SYM:
+                                            token = tokenStream.LT(1);
+                                            this._namespace(false);
+                                            throw new SyntaxError("@namespace not allowed here.", token.startLine, token.startCol);
+                                        default:
+                                            tokenStream.get();  //get the last token
+                                            this._unexpectedToken(tokenStream.token());
+                                    }
+
+                                }
+                        }
+                    } catch (ex) {
+                        if (ex instanceof SyntaxError && !this.options.strict) {
+                            this.fire({
+                                type:       "error",
+                                error:      ex,
+                                message:    ex.message,
+                                line:       ex.line,
+                                col:        ex.col
+                            });
+                        } else {
+                            throw ex;
+                        }
+                    }
+
+                    tt = tokenStream.peek();
+                }
+
+                if (tt !== Tokens.EOF) {
+                    this._unexpectedToken(tokenStream.token());
+                }
+
+                this.fire("endstylesheet");
+            },
+
+            _charset: function(emit) {
+                var tokenStream = this._tokenStream,
+                    charset,
+                    token,
+                    line,
+                    col;
+
+                if (tokenStream.match(Tokens.CHARSET_SYM)) {
+                    line = tokenStream.token().startLine;
+                    col = tokenStream.token().startCol;
+
+                    this._readWhitespace();
+                    tokenStream.mustMatch(Tokens.STRING);
+
+                    token = tokenStream.token();
+                    charset = token.value;
+
+                    this._readWhitespace();
+                    tokenStream.mustMatch(Tokens.SEMICOLON);
+
+                    if (emit !== false) {
+                        this.fire({
+                            type:   "charset",
+                            charset:charset,
+                            line:   line,
+                            col:    col
+                        });
+                    }
+                }
+            },
+
+            _import: function(emit) {
+                /*
+                 * import
+                 *   : IMPORT_SYM S*
+                 *    [STRING|URI] S* media_query_list? ';' S*
+                 */
+
+                var tokenStream = this._tokenStream,
+                    uri,
+                    importToken,
+                    mediaList   = [];
+
+                //read import symbol
+                tokenStream.mustMatch(Tokens.IMPORT_SYM);
+                importToken = tokenStream.token();
+                this._readWhitespace();
+
+                tokenStream.mustMatch([Tokens.STRING, Tokens.URI]);
+
+                //grab the URI value
+                uri = tokenStream.token().value.replace(/^(?:url\()?["']?([^"']+?)["']?\)?$/, "$1");
+
+                this._readWhitespace();
+
+                mediaList = this._media_query_list();
+
+                //must end with a semicolon
+                tokenStream.mustMatch(Tokens.SEMICOLON);
+                this._readWhitespace();
+
+                if (emit !== false) {
+                    this.fire({
+                        type:   "import",
+                        uri:    uri,
+                        media:  mediaList,
+                        line:   importToken.startLine,
+                        col:    importToken.startCol
+                    });
+                }
+
+            },
+
+            _namespace: function(emit) {
+                /*
+                 * namespace
+                 *   : NAMESPACE_SYM S* [namespace_prefix S*]? [STRING|URI] S* ';' S*
+                 */
+
+                var tokenStream = this._tokenStream,
+                    line,
+                    col,
+                    prefix,
+                    uri;
+
+                //read import symbol
+                tokenStream.mustMatch(Tokens.NAMESPACE_SYM);
+                line = tokenStream.token().startLine;
+                col = tokenStream.token().startCol;
+                this._readWhitespace();
+
+                //it's a namespace prefix - no _namespace_prefix() method because it's just an IDENT
+                if (tokenStream.match(Tokens.IDENT)) {
+                    prefix = tokenStream.token().value;
+                    this._readWhitespace();
+                }
+
+                tokenStream.mustMatch([Tokens.STRING, Tokens.URI]);
+                /*if (!tokenStream.match(Tokens.STRING)){
+                    tokenStream.mustMatch(Tokens.URI);
+                }*/
+
+                //grab the URI value
+                uri = tokenStream.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/, "$1");
+
+                this._readWhitespace();
+
+                //must end with a semicolon
+                tokenStream.mustMatch(Tokens.SEMICOLON);
+                this._readWhitespace();
+
+                if (emit !== false) {
+                    this.fire({
+                        type:   "namespace",
+                        prefix: prefix,
+                        uri:    uri,
+                        line:   line,
+                        col:    col
+                    });
+                }
+
+            },
+
+            _supports: function(emit) {
+                /*
+                 * supports_rule
+                 *  : SUPPORTS_SYM S* supports_condition S* group_rule_body
+                 *  ;
+                 */
+                var tokenStream = this._tokenStream,
+                    line,
+                    col;
+
+                if (tokenStream.match(Tokens.SUPPORTS_SYM)) {
+                    line = tokenStream.token().startLine;
+                    col = tokenStream.token().startCol;
+
+                    this._readWhitespace();
+                    this._supports_condition();
+                    this._readWhitespace();
+
+                    tokenStream.mustMatch(Tokens.LBRACE);
+                    this._readWhitespace();
+
+                    if (emit !== false) {
+                        this.fire({
+                            type:   "startsupports",
+                            line:   line,
+                            col:    col
+                        });
+                    }
+
+                    while (true) {
+                        if (!this._ruleset()) {
+                            break;
+                        }
+                    }
+
+                    tokenStream.mustMatch(Tokens.RBRACE);
+                    this._readWhitespace();
+
+                    this.fire({
+                        type:   "endsupports",
+                        line:   line,
+                        col:    col
+                    });
+                }
+            },
+
+            _supports_condition: function() {
+                /*
+                 * supports_condition
+                 *  : supports_negation | supports_conjunction | supports_disjunction |
+                 *    supports_condition_in_parens
+                 *  ;
+                 */
+                var tokenStream = this._tokenStream,
+                    ident;
+
+                if (tokenStream.match(Tokens.IDENT)) {
+                    ident = tokenStream.token().value.toLowerCase();
+
+                    if (ident === "not") {
+                        tokenStream.mustMatch(Tokens.S);
+                        this._supports_condition_in_parens();
+                    } else {
+                        tokenStream.unget();
+                    }
+                } else {
+                    this._supports_condition_in_parens();
+                    this._readWhitespace();
+
+                    while (tokenStream.peek() === Tokens.IDENT) {
+                        ident = tokenStream.LT(1).value.toLowerCase();
+                        if (ident === "and" || ident === "or") {
+                            tokenStream.mustMatch(Tokens.IDENT);
+                            this._readWhitespace();
+                            this._supports_condition_in_parens();
+                            this._readWhitespace();
+                        }
+                    }
+                }
+            },
+
+            _supports_condition_in_parens: function() {
+                /*
+                 * supports_condition_in_parens
+                 *  : ( '(' S* supports_condition S* ')' ) | supports_declaration_condition |
+                 *    general_enclosed
+                 *  ;
+                 */
+                var tokenStream = this._tokenStream,
+                    ident;
+
+                if (tokenStream.match(Tokens.LPAREN)) {
+                    this._readWhitespace();
+                    if (tokenStream.match(Tokens.IDENT)) {
+                        // look ahead for not keyword, if not given, continue with declaration condition.
+                        ident = tokenStream.token().value.toLowerCase();
+                        if (ident === "not") {
+                            this._readWhitespace();
+                            this._supports_condition();
+                            this._readWhitespace();
+                            tokenStream.mustMatch(Tokens.RPAREN);
+                        } else {
+                            tokenStream.unget();
+                            this._supports_declaration_condition(false);
+                        }
+                    } else {
+                        this._supports_condition();
+                        this._readWhitespace();
+                        tokenStream.mustMatch(Tokens.RPAREN);
+                    }
+                } else {
+                    this._supports_declaration_condition();
+                }
+            },
+
+            _supports_declaration_condition: function(requireStartParen) {
+                /*
+                 * supports_declaration_condition
+                 *  : '(' S* declaration ')'
+                 *  ;
+                 */
+                var tokenStream = this._tokenStream;
+
+                if (requireStartParen !== false) {
+                    tokenStream.mustMatch(Tokens.LPAREN);
+                }
+                this._readWhitespace();
+                this._declaration();
+                tokenStream.mustMatch(Tokens.RPAREN);
+            },
+
+            _media: function() {
+                /*
+                 * media
+                 *   : MEDIA_SYM S* media_query_list S* '{' S* ruleset* '}' S*
+                 *   ;
+                 */
+                var tokenStream     = this._tokenStream,
+                    line,
+                    col,
+                    mediaList;//       = [];
+
+                //look for @media
+                tokenStream.mustMatch(Tokens.MEDIA_SYM);
+                line = tokenStream.token().startLine;
+                col = tokenStream.token().startCol;
+
+                this._readWhitespace();
+
+                mediaList = this._media_query_list();
+
+                tokenStream.mustMatch(Tokens.LBRACE);
+                this._readWhitespace();
+
+                this.fire({
+                    type:   "startmedia",
+                    media:  mediaList,
+                    line:   line,
+                    col:    col
+                });
+
+                while (true) {
+                    if (tokenStream.peek() === Tokens.PAGE_SYM) {
+                        this._page();
+                    } else if (tokenStream.peek() === Tokens.FONT_FACE_SYM) {
+                        this._font_face();
+                    } else if (tokenStream.peek() === Tokens.VIEWPORT_SYM) {
+                        this._viewport();
+                    } else if (tokenStream.peek() === Tokens.DOCUMENT_SYM) {
+                        this._document();
+                    } else if (tokenStream.peek() === Tokens.SUPPORTS_SYM) {
+                        this._supports();
+                    } else if (tokenStream.peek() === Tokens.MEDIA_SYM) {
+                        this._media();
+                    } else if (!this._ruleset()) {
+                        break;
+                    }
+                }
+
+                tokenStream.mustMatch(Tokens.RBRACE);
+                this._readWhitespace();
+
+                this.fire({
+                    type:   "endmedia",
+                    media:  mediaList,
+                    line:   line,
+                    col:    col
+                });
+            },
+
+
+            //CSS3 Media Queries
+            _media_query_list: function() {
+                /*
+                 * media_query_list
+                 *   : S* [media_query [ ',' S* media_query ]* ]?
+                 *   ;
+                 */
+                var tokenStream = this._tokenStream,
+                    mediaList   = [];
+
+
+                this._readWhitespace();
+
+                if (tokenStream.peek() === Tokens.IDENT || tokenStream.peek() === Tokens.LPAREN) {
+                    mediaList.push(this._media_query());
+                }
+
+                while (tokenStream.match(Tokens.COMMA)) {
+                    this._readWhitespace();
+                    mediaList.push(this._media_query());
+                }
+
+                return mediaList;
+            },
+
+            /*
+             * Note: "expression" in the grammar maps to the _media_expression
+             * method.
+
+             */
+            _media_query: function() {
+                /*
+                 * media_query
+                 *   : [ONLY | NOT]? S* media_type S* [ AND S* expression ]*
+                 *   | expression [ AND S* expression ]*
+                 *   ;
+                 */
+                var tokenStream = this._tokenStream,
+                    type        = null,
+                    ident       = null,
+                    token       = null,
+                    expressions = [];
+
+                if (tokenStream.match(Tokens.IDENT)) {
+                    ident = tokenStream.token().value.toLowerCase();
+
+                    //since there's no custom tokens for these, need to manually check
+                    if (ident !== "only" && ident !== "not") {
+                        tokenStream.unget();
+                        ident = null;
+                    } else {
+                        token = tokenStream.token();
+                    }
+                }
+
+                this._readWhitespace();
+
+                if (tokenStream.peek() === Tokens.IDENT) {
+                    type = this._media_type();
+                    if (token === null) {
+                        token = tokenStream.token();
+                    }
+                } else if (tokenStream.peek() === Tokens.LPAREN) {
+                    if (token === null) {
+                        token = tokenStream.LT(1);
+                    }
+                    expressions.push(this._media_expression());
+                }
+
+                if (type === null && expressions.length === 0) {
+                    return null;
+                } else {
+                    this._readWhitespace();
+                    while (tokenStream.match(Tokens.IDENT)) {
+                        if (tokenStream.token().value.toLowerCase() !== "and") {
+                            this._unexpectedToken(tokenStream.token());
+                        }
+
+                        this._readWhitespace();
+                        expressions.push(this._media_expression());
+                    }
+                }
+
+                return new MediaQuery(ident, type, expressions, token.startLine, token.startCol);
+            },
+
+            //CSS3 Media Queries
+            _media_type: function() {
+                /*
+                 * media_type
+                 *   : IDENT
+                 *   ;
+                 */
+                return this._media_feature();
+            },
+
+            /**
+             * Note: in CSS3 Media Queries, this is called "expression".
+             * Renamed here to avoid conflict with CSS3 Selectors
+             * definition of "expression". Also note that "expr" in the
+             * grammar now maps to "expression" from CSS3 selectors.
+             * @method _media_expression
+             * @private
+             */
+            _media_expression: function() {
+                /*
+                 * expression
+                 *  : '(' S* media_feature S* [ ':' S* expr ]? ')' S*
+                 *  ;
+                 */
+                var tokenStream = this._tokenStream,
+                    feature     = null,
+                    token,
+                    expression  = null;
+
+                tokenStream.mustMatch(Tokens.LPAREN);
+
+                feature = this._media_feature();
+                this._readWhitespace();
+
+                if (tokenStream.match(Tokens.COLON)) {
+                    this._readWhitespace();
+                    token = tokenStream.LT(1);
+                    expression = this._expression();
+                }
+
+                tokenStream.mustMatch(Tokens.RPAREN);
+                this._readWhitespace();
+
+                return new MediaFeature(feature, expression ? new SyntaxUnit(expression, token.startLine, token.startCol) : null);
+            },
+
+            //CSS3 Media Queries
+            _media_feature: function() {
+                /*
+                 * media_feature
+                 *   : IDENT
+                 *   ;
+                 */
+                var tokenStream = this._tokenStream;
+
+                this._readWhitespace();
+
+                tokenStream.mustMatch(Tokens.IDENT);
+
+                return SyntaxUnit.fromToken(tokenStream.token());
+            },
+
+            //CSS3 Paged Media
+            _page: function() {
+                /*
+                 * page:
+                 *    PAGE_SYM S* IDENT? pseudo_page? S*
+                 *    '{' S* [ declaration | margin ]? [ ';' S* [ declaration | margin ]? ]* '}' S*
+                 *    ;
+                 */
+                var tokenStream = this._tokenStream,
+                    line,
+                    col,
+                    identifier  = null,
+                    pseudoPage  = null;
+
+                //look for @page
+                tokenStream.mustMatch(Tokens.PAGE_SYM);
+                line = tokenStream.token().startLine;
+                col = tokenStream.token().startCol;
+
+                this._readWhitespace();
+
+                if (tokenStream.match(Tokens.IDENT)) {
+                    identifier = tokenStream.token().value;
+
+                    //The value 'auto' may not be used as a page name and MUST be treated as a syntax error.
+                    if (identifier.toLowerCase() === "auto") {
+                        this._unexpectedToken(tokenStream.token());
+                    }
+                }
+
+                //see if there's a colon upcoming
+                if (tokenStream.peek() === Tokens.COLON) {
+                    pseudoPage = this._pseudo_page();
+                }
+
+                this._readWhitespace();
+
+                this.fire({
+                    type:   "startpage",
+                    id:     identifier,
+                    pseudo: pseudoPage,
+                    line:   line,
+                    col:    col
+                });
+
+                this._readDeclarations(true, true);
+
+                this.fire({
+                    type:   "endpage",
+                    id:     identifier,
+                    pseudo: pseudoPage,
+                    line:   line,
+                    col:    col
+                });
+
+            },
+
+            //CSS3 Paged Media
+            _margin: function() {
+                /*
+                 * margin :
+                 *    margin_sym S* '{' declaration [ ';' S* declaration? ]* '}' S*
+                 *    ;
+                 */
+                var tokenStream = this._tokenStream,
+                    line,
+                    col,
+                    marginSym   = this._margin_sym();
+
+                if (marginSym) {
+                    line = tokenStream.token().startLine;
+                    col = tokenStream.token().startCol;
+
+                    this.fire({
+                        type: "startpagemargin",
+                        margin: marginSym,
+                        line:   line,
+                        col:    col
+                    });
+
+                    this._readDeclarations(true);
+
+                    this.fire({
+                        type: "endpagemargin",
+                        margin: marginSym,
+                        line:   line,
+                        col:    col
+                    });
+                    return true;
+                } else {
+                    return false;
+                }
+            },
+
+            //CSS3 Paged Media
+            _margin_sym: function() {
+
+                /*
+                 * margin_sym :
+                 *    TOPLEFTCORNER_SYM |
+                 *    TOPLEFT_SYM |
+                 *    TOPCENTER_SYM |
+                 *    TOPRIGHT_SYM |
+                 *    TOPRIGHTCORNER_SYM |
+                 *    BOTTOMLEFTCORNER_SYM |
+                 *    BOTTOMLEFT_SYM |
+                 *    BOTTOMCENTER_SYM |
+                 *    BOTTOMRIGHT_SYM |
+                 *    BOTTOMRIGHTCORNER_SYM |
+                 *    LEFTTOP_SYM |
+                 *    LEFTMIDDLE_SYM |
+                 *    LEFTBOTTOM_SYM |
+                 *    RIGHTTOP_SYM |
+                 *    RIGHTMIDDLE_SYM |
+                 *    RIGHTBOTTOM_SYM
+                 *    ;
+                 */
+
+                var tokenStream = this._tokenStream;
+
+                if (tokenStream.match([Tokens.TOPLEFTCORNER_SYM, Tokens.TOPLEFT_SYM,
+                        Tokens.TOPCENTER_SYM, Tokens.TOPRIGHT_SYM, Tokens.TOPRIGHTCORNER_SYM,
+                        Tokens.BOTTOMLEFTCORNER_SYM, Tokens.BOTTOMLEFT_SYM,
+                        Tokens.BOTTOMCENTER_SYM, Tokens.BOTTOMRIGHT_SYM,
+                        Tokens.BOTTOMRIGHTCORNER_SYM, Tokens.LEFTTOP_SYM,
+                        Tokens.LEFTMIDDLE_SYM, Tokens.LEFTBOTTOM_SYM, Tokens.RIGHTTOP_SYM,
+                        Tokens.RIGHTMIDDLE_SYM, Tokens.RIGHTBOTTOM_SYM])) {
+                    return SyntaxUnit.fromToken(tokenStream.token());
+                } else {
+                    return null;
+                }
+
+            },
+
+            _pseudo_page: function() {
+                /*
+                 * pseudo_page
+                 *   : ':' IDENT
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream;
+
+                tokenStream.mustMatch(Tokens.COLON);
+                tokenStream.mustMatch(Tokens.IDENT);
+
+                //TODO: CSS3 Paged Media says only "left", "center", and "right" are allowed
+
+                return tokenStream.token().value;
+            },
+
+            _font_face: function() {
+                /*
+                 * font_face
+                 *   : FONT_FACE_SYM S*
+                 *     '{' S* declaration [ ';' S* declaration ]* '}' S*
+                 *   ;
+                 */
+                var tokenStream = this._tokenStream,
+                    line,
+                    col;
+
+                //look for @page
+                tokenStream.mustMatch(Tokens.FONT_FACE_SYM);
+                line = tokenStream.token().startLine;
+                col = tokenStream.token().startCol;
+
+                this._readWhitespace();
+
+                this.fire({
+                    type:   "startfontface",
+                    line:   line,
+                    col:    col
+                });
+
+                this._readDeclarations(true);
+
+                this.fire({
+                    type:   "endfontface",
+                    line:   line,
+                    col:    col
+                });
+            },
+
+            _viewport: function() {
+                /*
+                 * viewport
+                 *   : VIEWPORT_SYM S*
+                 *     '{' S* declaration? [ ';' S* declaration? ]* '}' S*
+                 *   ;
+                 */
+                var tokenStream = this._tokenStream,
+                    line,
+                    col;
+
+                tokenStream.mustMatch(Tokens.VIEWPORT_SYM);
+                line = tokenStream.token().startLine;
+                col = tokenStream.token().startCol;
+
+                this._readWhitespace();
+
+                this.fire({
+                    type:   "startviewport",
+                    line:   line,
+                    col:    col
+                });
+
+                this._readDeclarations(true);
+
+                this.fire({
+                    type:   "endviewport",
+                    line:   line,
+                    col:    col
+                });
+
+            },
+
+            _document: function() {
+                /*
+                 * document
+                 *   : DOCUMENT_SYM S*
+                 *     _document_function [ ',' S* _document_function ]* S*
+                 *     '{' S* ruleset* '}'
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    token,
+                    functions = [],
+                    prefix = "";
+
+                tokenStream.mustMatch(Tokens.DOCUMENT_SYM);
+                token = tokenStream.token();
+                if (/^@\-([^\-]+)\-/.test(token.value)) {
+                    prefix = RegExp.$1;
+                }
+
+                this._readWhitespace();
+                functions.push(this._document_function());
+
+                while (tokenStream.match(Tokens.COMMA)) {
+                    this._readWhitespace();
+                    functions.push(this._document_function());
+                }
+
+                tokenStream.mustMatch(Tokens.LBRACE);
+                this._readWhitespace();
+
+                this.fire({
+                    type:      "startdocument",
+                    functions: functions,
+                    prefix:    prefix,
+                    line:      token.startLine,
+                    col:       token.startCol
+                });
+
+                var ok = true;
+                while (ok) {
+                    switch (tokenStream.peek()) {
+                        case Tokens.PAGE_SYM:
+                            this._page();
+                            break;
+                        case Tokens.FONT_FACE_SYM:
+                            this._font_face();
+                            break;
+                        case Tokens.VIEWPORT_SYM:
+                            this._viewport();
+                            break;
+                        case Tokens.MEDIA_SYM:
+                            this._media();
+                            break;
+                        case Tokens.KEYFRAMES_SYM:
+                            this._keyframes();
+                            break;
+                        case Tokens.DOCUMENT_SYM:
+                            this._document();
+                            break;
+                        default:
+                            ok = Boolean(this._ruleset());
+                    }
+                }
+
+                tokenStream.mustMatch(Tokens.RBRACE);
+                token = tokenStream.token();
+                this._readWhitespace();
+
+                this.fire({
+                    type:      "enddocument",
+                    functions: functions,
+                    prefix:    prefix,
+                    line:      token.startLine,
+                    col:       token.startCol
+                });
+            },
+
+            _document_function: function() {
+                /*
+                 * document_function
+                 *   : function | URI S*
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    value;
+
+                if (tokenStream.match(Tokens.URI)) {
+                    value = tokenStream.token().value;
+                    this._readWhitespace();
+                } else {
+                    value = this._function();
+                }
+
+                return value;
+            },
+
+            _operator: function(inFunction) {
+
+                /*
+                 * operator (outside function)
+                 *  : '/' S* | ',' S* | /( empty )/
+                 * operator (inside function)
+                 *  : '/' S* | '+' S* | '*' S* | '-' S* /( empty )/
+                 *  ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    token       = null;
+
+                if (tokenStream.match([Tokens.SLASH, Tokens.COMMA]) ||
+                    (inFunction && tokenStream.match([Tokens.PLUS, Tokens.STAR, Tokens.MINUS]))) {
+                    token =  tokenStream.token();
+                    this._readWhitespace();
+                }
+                return token ? PropertyValuePart.fromToken(token) : null;
+
+            },
+
+            _combinator: function() {
+
+                /*
+                 * combinator
+                 *  : PLUS S* | GREATER S* | TILDE S* | S+
+                 *  ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    value       = null,
+                    token;
+
+                if (tokenStream.match([Tokens.PLUS, Tokens.GREATER, Tokens.TILDE])) {
+                    token = tokenStream.token();
+                    value = new Combinator(token.value, token.startLine, token.startCol);
+                    this._readWhitespace();
+                }
+
+                return value;
+            },
+
+            _unary_operator: function() {
+
+                /*
+                 * unary_operator
+                 *  : '-' | '+'
+                 *  ;
+                 */
+
+                var tokenStream = this._tokenStream;
+
+                if (tokenStream.match([Tokens.MINUS, Tokens.PLUS])) {
+                    return tokenStream.token().value;
+                } else {
+                    return null;
+                }
+            },
+
+            _property: function() {
+
+                /*
+                 * property
+                 *   : IDENT S*
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    value       = null,
+                    hack        = null,
+                    tokenValue,
+                    token,
+                    line,
+                    col;
+
+                //check for star hack - throws error if not allowed
+                if (tokenStream.peek() === Tokens.STAR && this.options.starHack) {
+                    tokenStream.get();
+                    token = tokenStream.token();
+                    hack = token.value;
+                    line = token.startLine;
+                    col = token.startCol;
+                }
+
+                if (tokenStream.match(Tokens.IDENT)) {
+                    token = tokenStream.token();
+                    tokenValue = token.value;
+
+                    //check for underscore hack - no error if not allowed because it's valid CSS syntax
+                    if (tokenValue.charAt(0) === "_" && this.options.underscoreHack) {
+                        hack = "_";
+                        tokenValue = tokenValue.substring(1);
+                    }
+
+                    value = new PropertyName(tokenValue, hack, (line||token.startLine), (col||token.startCol));
+                    this._readWhitespace();
+                }
+
+                return value;
+            },
+
+            //Augmented with CSS3 Selectors
+            _ruleset: function() {
+                /*
+                 * ruleset
+                 *   : selectors_group
+                 *     '{' S* declaration? [ ';' S* declaration? ]* '}' S*
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    tt,
+                    selectors;
+
+
+                /*
+                 * Error Recovery: If even a single selector fails to parse,
+                 * then the entire ruleset should be thrown away.
+                 */
+                try {
+                    selectors = this._selectors_group();
+                } catch (ex) {
+                    if (ex instanceof SyntaxError && !this.options.strict) {
+
+                        //fire error event
+                        this.fire({
+                            type:       "error",
+                            error:      ex,
+                            message:    ex.message,
+                            line:       ex.line,
+                            col:        ex.col
+                        });
+
+                        //skip over everything until closing brace
+                        tt = tokenStream.advance([Tokens.RBRACE]);
+                        if (tt === Tokens.RBRACE) {
+                            //if there's a right brace, the rule is finished so don't do anything
+                        } else {
+                            //otherwise, rethrow the error because it wasn't handled properly
+                            throw ex;
+                        }
+
+                    } else {
+                        //not a syntax error, rethrow it
+                        throw ex;
+                    }
+
+                    //trigger parser to continue
+                    return true;
+                }
+
+                //if it got here, all selectors parsed
+                if (selectors) {
+
+                    this.fire({
+                        type:       "startrule",
+                        selectors:  selectors,
+                        line:       selectors[0].line,
+                        col:        selectors[0].col
+                    });
+
+                    this._readDeclarations(true);
+
+                    this.fire({
+                        type:       "endrule",
+                        selectors:  selectors,
+                        line:       selectors[0].line,
+                        col:        selectors[0].col
+                    });
+
+                }
+
+                return selectors;
+
+            },
+
+            //CSS3 Selectors
+            _selectors_group: function() {
+
+                /*
+                 * selectors_group
+                 *   : selector [ COMMA S* selector ]*
+                 *   ;
+                 */
+                var tokenStream = this._tokenStream,
+                    selectors   = [],
+                    selector;
+
+                selector = this._selector();
+                if (selector !== null) {
+
+                    selectors.push(selector);
+                    while (tokenStream.match(Tokens.COMMA)) {
+                        this._readWhitespace();
+                        selector = this._selector();
+                        if (selector !== null) {
+                            selectors.push(selector);
+                        } else {
+                            this._unexpectedToken(tokenStream.LT(1));
+                        }
+                    }
+                }
+
+                return selectors.length ? selectors : null;
+            },
+
+            //CSS3 Selectors
+            _selector: function() {
+                /*
+                 * selector
+                 *   : simple_selector_sequence [ combinator simple_selector_sequence ]*
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    selector    = [],
+                    nextSelector = null,
+                    combinator  = null,
+                    ws          = null;
+
+                //if there's no simple selector, then there's no selector
+                nextSelector = this._simple_selector_sequence();
+                if (nextSelector === null) {
+                    return null;
+                }
+
+                selector.push(nextSelector);
+
+                do {
+
+                    //look for a combinator
+                    combinator = this._combinator();
+
+                    if (combinator !== null) {
+                        selector.push(combinator);
+                        nextSelector = this._simple_selector_sequence();
+
+                        //there must be a next selector
+                        if (nextSelector === null) {
+                            this._unexpectedToken(tokenStream.LT(1));
+                        } else {
+
+                            //nextSelector is an instance of SelectorPart
+                            selector.push(nextSelector);
+                        }
+                    } else {
+
+                        //if there's not whitespace, we're done
+                        if (this._readWhitespace()) {
+
+                            //add whitespace separator
+                            ws = new Combinator(tokenStream.token().value, tokenStream.token().startLine, tokenStream.token().startCol);
+
+                            //combinator is not required
+                            combinator = this._combinator();
+
+                            //selector is required if there's a combinator
+                            nextSelector = this._simple_selector_sequence();
+                            if (nextSelector === null) {
+                                if (combinator !== null) {
+                                    this._unexpectedToken(tokenStream.LT(1));
+                                }
+                            } else {
+
+                                if (combinator !== null) {
+                                    selector.push(combinator);
+                                } else {
+                                    selector.push(ws);
+                                }
+
+                                selector.push(nextSelector);
+                            }
+                        } else {
+                            break;
+                        }
+
+                    }
+                } while (true);
+
+                return new Selector(selector, selector[0].line, selector[0].col);
+            },
+
+            //CSS3 Selectors
+            _simple_selector_sequence: function() {
+                /*
+                 * simple_selector_sequence
+                 *   : [ type_selector | universal ]
+                 *     [ HASH | class | attrib | pseudo | negation ]*
+                 *   | [ HASH | class | attrib | pseudo | negation ]+
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+
+                    //parts of a simple selector
+                    elementName = null,
+                    modifiers   = [],
+
+                    //complete selector text
+                    selectorText= "",
+
+                    //the different parts after the element name to search for
+                    components  = [
+                        //HASH
+                        function() {
+                            return tokenStream.match(Tokens.HASH) ?
+                                    new SelectorSubPart(tokenStream.token().value, "id", tokenStream.token().startLine, tokenStream.token().startCol) :
+                                    null;
+                        },
+                        this._class,
+                        this._attrib,
+                        this._pseudo,
+                        this._negation
+                    ],
+                    i           = 0,
+                    len         = components.length,
+                    component   = null,
+                    line,
+                    col;
+
+
+                //get starting line and column for the selector
+                line = tokenStream.LT(1).startLine;
+                col = tokenStream.LT(1).startCol;
+
+                elementName = this._type_selector();
+                if (!elementName) {
+                    elementName = this._universal();
+                }
+
+                if (elementName !== null) {
+                    selectorText += elementName;
+                }
+
+                while (true) {
+
+                    //whitespace means we're done
+                    if (tokenStream.peek() === Tokens.S) {
+                        break;
+                    }
+
+                    //check for each component
+                    while (i < len && component === null) {
+                        component = components[i++].call(this);
+                    }
+
+                    if (component === null) {
+
+                        //we don't have a selector
+                        if (selectorText === "") {
+                            return null;
+                        } else {
+                            break;
+                        }
+                    } else {
+                        i = 0;
+                        modifiers.push(component);
+                        selectorText += component.toString();
+                        component = null;
+                    }
+                }
+
+
+                return selectorText !== "" ?
+                        new SelectorPart(elementName, modifiers, selectorText, line, col) :
+                        null;
+            },
+
+            //CSS3 Selectors
+            _type_selector: function() {
+                /*
+                 * type_selector
+                 *   : [ namespace_prefix ]? element_name
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    ns          = this._namespace_prefix(),
+                    elementName = this._element_name();
+
+                if (!elementName) {
+                    /*
+                     * Need to back out the namespace that was read due to both
+                     * type_selector and universal reading namespace_prefix
+                     * first. Kind of hacky, but only way I can figure out
+                     * right now how to not change the grammar.
+                     */
+                    if (ns) {
+                        tokenStream.unget();
+                        if (ns.length > 1) {
+                            tokenStream.unget();
+                        }
+                    }
+
+                    return null;
+                } else {
+                    if (ns) {
+                        elementName.text = ns + elementName.text;
+                        elementName.col -= ns.length;
+                    }
+                    return elementName;
+                }
+            },
+
+            //CSS3 Selectors
+            _class: function() {
+                /*
+                 * class
+                 *   : '.' IDENT
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    token;
+
+                if (tokenStream.match(Tokens.DOT)) {
+                    tokenStream.mustMatch(Tokens.IDENT);
+                    token = tokenStream.token();
+                    return new SelectorSubPart("." + token.value, "class", token.startLine, token.startCol - 1);
+                } else {
+                    return null;
+                }
+
+            },
+
+            //CSS3 Selectors
+            _element_name: function() {
+                /*
+                 * element_name
+                 *   : IDENT
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    token;
+
+                if (tokenStream.match(Tokens.IDENT)) {
+                    token = tokenStream.token();
+                    return new SelectorSubPart(token.value, "elementName", token.startLine, token.startCol);
+
+                } else {
+                    return null;
+                }
+            },
+
+            //CSS3 Selectors
+            _namespace_prefix: function() {
+                /*
+                 * namespace_prefix
+                 *   : [ IDENT | '*' ]? '|'
+                 *   ;
+                 */
+                var tokenStream = this._tokenStream,
+                    value       = "";
+
+                //verify that this is a namespace prefix
+                if (tokenStream.LA(1) === Tokens.PIPE || tokenStream.LA(2) === Tokens.PIPE) {
+
+                    if (tokenStream.match([Tokens.IDENT, Tokens.STAR])) {
+                        value += tokenStream.token().value;
+                    }
+
+                    tokenStream.mustMatch(Tokens.PIPE);
+                    value += "|";
+
+                }
+
+                return value.length ? value : null;
+            },
+
+            //CSS3 Selectors
+            _universal: function() {
+                /*
+                 * universal
+                 *   : [ namespace_prefix ]? '*'
+                 *   ;
+                 */
+                var tokenStream = this._tokenStream,
+                    value       = "",
+                    ns;
+
+                ns = this._namespace_prefix();
+                if (ns) {
+                    value += ns;
+                }
+
+                if (tokenStream.match(Tokens.STAR)) {
+                    value += "*";
+                }
+
+                return value.length ? value : null;
+
+            },
+
+            //CSS3 Selectors
+            _attrib: function() {
+                /*
+                 * attrib
+                 *   : '[' S* [ namespace_prefix ]? IDENT S*
+                 *         [ [ PREFIXMATCH |
+                 *             SUFFIXMATCH |
+                 *             SUBSTRINGMATCH |
+                 *             '=' |
+                 *             INCLUDES |
+                 *             DASHMATCH ] S* [ IDENT | STRING ] S*
+                 *         ]? ']'
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    value       = null,
+                    ns,
+                    token;
+
+                if (tokenStream.match(Tokens.LBRACKET)) {
+                    token = tokenStream.token();
+                    value = token.value;
+                    value += this._readWhitespace();
+
+                    ns = this._namespace_prefix();
+
+                    if (ns) {
+                        value += ns;
+                    }
+
+                    tokenStream.mustMatch(Tokens.IDENT);
+                    value += tokenStream.token().value;
+                    value += this._readWhitespace();
+
+                    if (tokenStream.match([Tokens.PREFIXMATCH, Tokens.SUFFIXMATCH, Tokens.SUBSTRINGMATCH,
+                            Tokens.EQUALS, Tokens.INCLUDES, Tokens.DASHMATCH])) {
+
+                        value += tokenStream.token().value;
+                        value += this._readWhitespace();
+
+                        tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]);
+                        value += tokenStream.token().value;
+                        value += this._readWhitespace();
+                    }
+
+                    tokenStream.mustMatch(Tokens.RBRACKET);
+
+                    return new SelectorSubPart(value + "]", "attribute", token.startLine, token.startCol);
+                } else {
+                    return null;
+                }
+            },
+
+            //CSS3 Selectors
+            _pseudo: function() {
+
+                /*
+                 * pseudo
+                 *   : ':' ':'? [ IDENT | functional_pseudo ]
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    pseudo      = null,
+                    colons      = ":",
+                    line,
+                    col;
+
+                if (tokenStream.match(Tokens.COLON)) {
+
+                    if (tokenStream.match(Tokens.COLON)) {
+                        colons += ":";
+                    }
+
+                    if (tokenStream.match(Tokens.IDENT)) {
+                        pseudo = tokenStream.token().value;
+                        line = tokenStream.token().startLine;
+                        col = tokenStream.token().startCol - colons.length;
+                    } else if (tokenStream.peek() === Tokens.FUNCTION) {
+                        line = tokenStream.LT(1).startLine;
+                        col = tokenStream.LT(1).startCol - colons.length;
+                        pseudo = this._functional_pseudo();
+                    }
+
+                    if (pseudo) {
+                        pseudo = new SelectorSubPart(colons + pseudo, "pseudo", line, col);
+                    } else {
+                        var startLine = tokenStream.LT(1).startLine,
+                            startCol  = tokenStream.LT(0).startCol;
+                        throw new SyntaxError("Expected a `FUNCTION` or `IDENT` after colon at line " + startLine + ", col " + startCol + ".", startLine, startCol);
+                    }
+                }
+
+                return pseudo;
+            },
+
+            //CSS3 Selectors
+            _functional_pseudo: function() {
+                /*
+                 * functional_pseudo
+                 *   : FUNCTION S* expression ')'
+                 *   ;
+                */
+
+                var tokenStream = this._tokenStream,
+                    value = null;
+
+                if (tokenStream.match(Tokens.FUNCTION)) {
+                    value = tokenStream.token().value;
+                    value += this._readWhitespace();
+                    value += this._expression();
+                    tokenStream.mustMatch(Tokens.RPAREN);
+                    value += ")";
+                }
+
+                return value;
+            },
+
+            //CSS3 Selectors
+            _expression: function() {
+                /*
+                 * expression
+                 *   : [ [ PLUS | '-' | DIMENSION | NUMBER | STRING | IDENT ] S* ]+
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    value       = "";
+
+                while (tokenStream.match([Tokens.PLUS, Tokens.MINUS, Tokens.DIMENSION,
+                        Tokens.NUMBER, Tokens.STRING, Tokens.IDENT, Tokens.LENGTH,
+                        Tokens.FREQ, Tokens.ANGLE, Tokens.TIME,
+                        Tokens.RESOLUTION, Tokens.SLASH])) {
+
+                    value += tokenStream.token().value;
+                    value += this._readWhitespace();
+                }
+
+                return value.length ? value : null;
+
+            },
+
+            //CSS3 Selectors
+            _negation: function() {
+                /*
+                 * negation
+                 *   : NOT S* negation_arg S* ')'
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    line,
+                    col,
+                    value       = "",
+                    arg,
+                    subpart     = null;
+
+                if (tokenStream.match(Tokens.NOT)) {
+                    value = tokenStream.token().value;
+                    line = tokenStream.token().startLine;
+                    col = tokenStream.token().startCol;
+                    value += this._readWhitespace();
+                    arg = this._negation_arg();
+                    value += arg;
+                    value += this._readWhitespace();
+                    tokenStream.match(Tokens.RPAREN);
+                    value += tokenStream.token().value;
+
+                    subpart = new SelectorSubPart(value, "not", line, col);
+                    subpart.args.push(arg);
+                }
+
+                return subpart;
+            },
+
+            //CSS3 Selectors
+            _negation_arg: function() {
+                /*
+                 * negation_arg
+                 *   : type_selector | universal | HASH | class | attrib | pseudo
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    args        = [
+                        this._type_selector,
+                        this._universal,
+                        function() {
+                            return tokenStream.match(Tokens.HASH) ?
+                                    new SelectorSubPart(tokenStream.token().value, "id", tokenStream.token().startLine, tokenStream.token().startCol) :
+                                    null;
+                        },
+                        this._class,
+                        this._attrib,
+                        this._pseudo
+                    ],
+                    arg         = null,
+                    i           = 0,
+                    len         = args.length,
+                    line,
+                    col,
+                    part;
+
+                line = tokenStream.LT(1).startLine;
+                col = tokenStream.LT(1).startCol;
+
+                while (i < len && arg === null) {
+
+                    arg = args[i].call(this);
+                    i++;
+                }
+
+                //must be a negation arg
+                if (arg === null) {
+                    this._unexpectedToken(tokenStream.LT(1));
+                }
+
+                //it's an element name
+                if (arg.type === "elementName") {
+                    part = new SelectorPart(arg, [], arg.toString(), line, col);
+                } else {
+                    part = new SelectorPart(null, [arg], arg.toString(), line, col);
+                }
+
+                return part;
+            },
+
+            _declaration: function() {
+
+                /*
+                 * declaration
+                 *   : property ':' S* expr prio?
+                 *   | /( empty )/
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    property    = null,
+                    expr        = null,
+                    prio        = null,
+                    invalid     = null,
+                    propertyName= "";
+
+                property = this._property();
+                if (property !== null) {
+
+                    tokenStream.mustMatch(Tokens.COLON);
+                    this._readWhitespace();
+
+                    expr = this._expr();
+
+                    //if there's no parts for the value, it's an error
+                    if (!expr || expr.length === 0) {
+                        this._unexpectedToken(tokenStream.LT(1));
+                    }
+
+                    prio = this._prio();
+
+                    /*
+                     * If hacks should be allowed, then only check the root
+                     * property. If hacks should not be allowed, treat
+                     * _property or *property as invalid properties.
+                     */
+                    propertyName = property.toString();
+                    if (this.options.starHack && property.hack === "*" ||
+                            this.options.underscoreHack && property.hack === "_") {
+
+                        propertyName = property.text;
+                    }
+
+                    try {
+                        this._validateProperty(propertyName, expr);
+                    } catch (ex) {
+                        invalid = ex;
+                    }
+
+                    this.fire({
+                        type:       "property",
+                        property:   property,
+                        value:      expr,
+                        important:  prio,
+                        line:       property.line,
+                        col:        property.col,
+                        invalid:    invalid
+                    });
+
+                    return true;
+                } else {
+                    return false;
+                }
+            },
+
+            _prio: function() {
+                /*
+                 * prio
+                 *   : IMPORTANT_SYM S*
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    result      = tokenStream.match(Tokens.IMPORTANT_SYM);
+
+                this._readWhitespace();
+                return result;
+            },
+
+            _expr: function(inFunction) {
+                /*
+                 * expr
+                 *   : term [ operator term ]*
+                 *   ;
+                 */
+
+                var values      = [],
+                    //valueParts    = [],
+                    value       = null,
+                    operator    = null;
+
+                value = this._term(inFunction);
+                if (value !== null) {
+
+                    values.push(value);
+
+                    do {
+                        operator = this._operator(inFunction);
+
+                        //if there's an operator, keep building up the value parts
+                        if (operator) {
+                            values.push(operator);
+                        } /*else {
+                            //if there's not an operator, you have a full value
+                            values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col));
+                            valueParts = [];
+                        }*/
+
+                        value = this._term(inFunction);
+
+                        if (value === null) {
+                            break;
+                        } else {
+                            values.push(value);
+                        }
+                    } while (true);
+                }
+
+                //cleanup
+                /*if (valueParts.length) {
+                    values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col));
+                }*/
+
+                return values.length > 0 ? new PropertyValue(values, values[0].line, values[0].col) : null;
+            },
+
+            _term: function(inFunction) {
+
+                /*
+                 * term
+                 *   : unary_operator?
+                 *     [ NUMBER S* | PERCENTAGE S* | LENGTH S* | ANGLE S* |
+                 *       TIME S* | FREQ S* | function | ie_function ]
+                 *   | STRING S* | IDENT S* | URI S* | UNICODERANGE S* | hexcolor
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    unary       = null,
+                    value       = null,
+                    endChar     = null,
+                    part        = null,
+                    token,
+                    line,
+                    col;
+
+                //returns the operator or null
+                unary = this._unary_operator();
+                if (unary !== null) {
+                    line = tokenStream.token().startLine;
+                    col = tokenStream.token().startCol;
+                }
+
+                //exception for IE filters
+                if (tokenStream.peek() === Tokens.IE_FUNCTION && this.options.ieFilters) {
+
+                    value = this._ie_function();
+                    if (unary === null) {
+                        line = tokenStream.token().startLine;
+                        col = tokenStream.token().startCol;
+                    }
+
+                //see if it's a simple block
+                } else if (inFunction && tokenStream.match([Tokens.LPAREN, Tokens.LBRACE, Tokens.LBRACKET])) {
+
+                    token = tokenStream.token();
+                    endChar = token.endChar;
+                    value = token.value + this._expr(inFunction).text;
+                    if (unary === null) {
+                        line = tokenStream.token().startLine;
+                        col = tokenStream.token().startCol;
+                    }
+                    tokenStream.mustMatch(Tokens.type(endChar));
+                    value += endChar;
+                    this._readWhitespace();
+
+                //see if there's a simple match
+                } else if (tokenStream.match([Tokens.NUMBER, Tokens.PERCENTAGE, Tokens.LENGTH,
+                        Tokens.ANGLE, Tokens.TIME,
+                        Tokens.FREQ, Tokens.STRING, Tokens.IDENT, Tokens.URI, Tokens.UNICODE_RANGE])) {
+
+                    value = tokenStream.token().value;
+                    if (unary === null) {
+                        line = tokenStream.token().startLine;
+                        col = tokenStream.token().startCol;
+                        // Correct potentially-inaccurate IDENT parsing in
+                        // PropertyValuePart constructor.
+                        part = PropertyValuePart.fromToken(tokenStream.token());
+                    }
+                    this._readWhitespace();
+                } else {
+
+                    //see if it's a color
+                    token = this._hexcolor();
+                    if (token === null) {
+
+                        //if there's no unary, get the start of the next token for line/col info
+                        if (unary === null) {
+                            line = tokenStream.LT(1).startLine;
+                            col = tokenStream.LT(1).startCol;
+                        }
+
+                        //has to be a function
+                        if (value === null) {
+
+                            /*
+                             * This checks for alpha(opacity=0) style of IE
+                             * functions. IE_FUNCTION only presents progid: style.
+                             */
+                            if (tokenStream.LA(3) === Tokens.EQUALS && this.options.ieFilters) {
+                                value = this._ie_function();
+                            } else {
+                                value = this._function();
+                            }
+                        }
+
+                        /*if (value === null) {
+                            return null;
+                            //throw new Error("Expected identifier at line " + tokenStream.token().startLine + ", character " +  tokenStream.token().startCol + ".");
+                        }*/
+
+                    } else {
+                        value = token.value;
+                        if (unary === null) {
+                            line = token.startLine;
+                            col = token.startCol;
+                        }
+                    }
+
+                }
+
+                return part !== null ? part : value !== null ?
+                        new PropertyValuePart(unary !== null ? unary + value : value, line, col) :
+                        null;
+
+            },
+
+            _function: function() {
+
+                /*
+                 * function
+                 *   : FUNCTION S* expr ')' S*
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    functionText = null,
+                    expr        = null,
+                    lt;
+
+                if (tokenStream.match(Tokens.FUNCTION)) {
+                    functionText = tokenStream.token().value;
+                    this._readWhitespace();
+                    expr = this._expr(true);
+                    functionText += expr;
+
+                    //START: Horrible hack in case it's an IE filter
+                    if (this.options.ieFilters && tokenStream.peek() === Tokens.EQUALS) {
+                        do {
+
+                            if (this._readWhitespace()) {
+                                functionText += tokenStream.token().value;
+                            }
+
+                            //might be second time in the loop
+                            if (tokenStream.LA(0) === Tokens.COMMA) {
+                                functionText += tokenStream.token().value;
+                            }
+
+                            tokenStream.match(Tokens.IDENT);
+                            functionText += tokenStream.token().value;
+
+                            tokenStream.match(Tokens.EQUALS);
+                            functionText += tokenStream.token().value;
+
+                            //functionText += this._term();
+                            lt = tokenStream.peek();
+                            while (lt !== Tokens.COMMA && lt !== Tokens.S && lt !== Tokens.RPAREN) {
+                                tokenStream.get();
+                                functionText += tokenStream.token().value;
+                                lt = tokenStream.peek();
+                            }
+                        } while (tokenStream.match([Tokens.COMMA, Tokens.S]));
+                    }
+
+                    //END: Horrible Hack
+
+                    tokenStream.match(Tokens.RPAREN);
+                    functionText += ")";
+                    this._readWhitespace();
+                }
+
+                return functionText;
+            },
+
+            _ie_function: function() {
+
+                /* (My own extension)
+                 * ie_function
+                 *   : IE_FUNCTION S* IDENT '=' term [S* ','? IDENT '=' term]+ ')' S*
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    functionText = null,
+                    lt;
+
+                //IE function can begin like a regular function, too
+                if (tokenStream.match([Tokens.IE_FUNCTION, Tokens.FUNCTION])) {
+                    functionText = tokenStream.token().value;
+
+                    do {
+
+                        if (this._readWhitespace()) {
+                            functionText += tokenStream.token().value;
+                        }
+
+                        //might be second time in the loop
+                        if (tokenStream.LA(0) === Tokens.COMMA) {
+                            functionText += tokenStream.token().value;
+                        }
+
+                        tokenStream.match(Tokens.IDENT);
+                        functionText += tokenStream.token().value;
+
+                        tokenStream.match(Tokens.EQUALS);
+                        functionText += tokenStream.token().value;
+
+                        //functionText += this._term();
+                        lt = tokenStream.peek();
+                        while (lt !== Tokens.COMMA && lt !== Tokens.S && lt !== Tokens.RPAREN) {
+                            tokenStream.get();
+                            functionText += tokenStream.token().value;
+                            lt = tokenStream.peek();
+                        }
+                    } while (tokenStream.match([Tokens.COMMA, Tokens.S]));
+
+                    tokenStream.match(Tokens.RPAREN);
+                    functionText += ")";
+                    this._readWhitespace();
+                }
+
+                return functionText;
+            },
+
+            _hexcolor: function() {
+                /*
+                 * There is a constraint on the color that it must
+                 * have either 3 or 6 hex-digits (i.e., [0-9a-fA-F])
+                 * after the "#"; e.g., "#000" is OK, but "#abcd" is not.
+                 *
+                 * hexcolor
+                 *   : HASH S*
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    token = null,
+                    color;
+
+                if (tokenStream.match(Tokens.HASH)) {
+
+                    //need to do some validation here
+
+                    token = tokenStream.token();
+                    color = token.value;
+                    if (!/#[a-f0-9]{3,6}/i.test(color)) {
+                        throw new SyntaxError("Expected a hex color but found '" + color + "' at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol);
+                    }
+                    this._readWhitespace();
+                }
+
+                return token;
+            },
+
+            //-----------------------------------------------------------------
+            // Animations methods
+            //-----------------------------------------------------------------
+
+            _keyframes: function() {
+
+                /*
+                 * keyframes:
+                 *   : KEYFRAMES_SYM S* keyframe_name S* '{' S* keyframe_rule* '}' {
+                 *   ;
+                 */
+                var tokenStream = this._tokenStream,
+                    token,
+                    tt,
+                    name,
+                    prefix = "";
+
+                tokenStream.mustMatch(Tokens.KEYFRAMES_SYM);
+                token = tokenStream.token();
+                if (/^@\-([^\-]+)\-/.test(token.value)) {
+                    prefix = RegExp.$1;
+                }
+
+                this._readWhitespace();
+                name = this._keyframe_name();
+
+                this._readWhitespace();
+                tokenStream.mustMatch(Tokens.LBRACE);
+
+                this.fire({
+                    type:   "startkeyframes",
+                    name:   name,
+                    prefix: prefix,
+                    line:   token.startLine,
+                    col:    token.startCol
+                });
+
+                this._readWhitespace();
+                tt = tokenStream.peek();
+
+                //check for key
+                while (tt === Tokens.IDENT || tt === Tokens.PERCENTAGE) {
+                    this._keyframe_rule();
+                    this._readWhitespace();
+                    tt = tokenStream.peek();
+                }
+
+                this.fire({
+                    type:   "endkeyframes",
+                    name:   name,
+                    prefix: prefix,
+                    line:   token.startLine,
+                    col:    token.startCol
+                });
+
+                this._readWhitespace();
+                tokenStream.mustMatch(Tokens.RBRACE);
+                this._readWhitespace();
+
+            },
+
+            _keyframe_name: function() {
+
+                /*
+                 * keyframe_name:
+                 *   : IDENT
+                 *   | STRING
+                 *   ;
+                 */
+                var tokenStream = this._tokenStream;
+
+                tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]);
+                return SyntaxUnit.fromToken(tokenStream.token());
+            },
+
+            _keyframe_rule: function() {
+
+                /*
+                 * keyframe_rule:
+                 *   : key_list S*
+                 *     '{' S* declaration [ ';' S* declaration ]* '}' S*
+                 *   ;
+                 */
+                var keyList = this._key_list();
+
+                this.fire({
+                    type:   "startkeyframerule",
+                    keys:   keyList,
+                    line:   keyList[0].line,
+                    col:    keyList[0].col
+                });
+
+                this._readDeclarations(true);
+
+                this.fire({
+                    type:   "endkeyframerule",
+                    keys:   keyList,
+                    line:   keyList[0].line,
+                    col:    keyList[0].col
+                });
+
+            },
+
+            _key_list: function() {
+
+                /*
+                 * key_list:
+                 *   : key [ S* ',' S* key]*
+                 *   ;
+                 */
+                var tokenStream = this._tokenStream,
+                    keyList = [];
+
+                //must be least one key
+                keyList.push(this._key());
+
+                this._readWhitespace();
+
+                while (tokenStream.match(Tokens.COMMA)) {
+                    this._readWhitespace();
+                    keyList.push(this._key());
+                    this._readWhitespace();
+                }
+
+                return keyList;
+            },
+
+            _key: function() {
+                /*
+                 * There is a restriction that IDENT can be only "from" or "to".
+                 *
+                 * key
+                 *   : PERCENTAGE
+                 *   | IDENT
+                 *   ;
+                 */
+
+                var tokenStream = this._tokenStream,
+                    token;
+
+                if (tokenStream.match(Tokens.PERCENTAGE)) {
+                    return SyntaxUnit.fromToken(tokenStream.token());
+                } else if (tokenStream.match(Tokens.IDENT)) {
+                    token = tokenStream.token();
+
+                    if (/from|to/i.test(token.value)) {
+                        return SyntaxUnit.fromToken(token);
+                    }
+
+                    tokenStream.unget();
+                }
+
+                //if it gets here, there wasn't a valid token, so time to explode
+                this._unexpectedToken(tokenStream.LT(1));
+            },
+
+            //-----------------------------------------------------------------
+            // Helper methods
+            //-----------------------------------------------------------------
+
+            /**
+             * Not part of CSS grammar, but useful for skipping over
+             * combination of white space and HTML-style comments.
+             * @return {void}
+             * @method _skipCruft
+             * @private
+             */
+            _skipCruft: function() {
+                while (this._tokenStream.match([Tokens.S, Tokens.CDO, Tokens.CDC])) {
+                    //noop
+                }
+            },
+
+            /**
+             * Not part of CSS grammar, but this pattern occurs frequently
+             * in the official CSS grammar. Split out here to eliminate
+             * duplicate code.
+             * @param {Boolean} checkStart Indicates if the rule should check
+             *      for the left brace at the beginning.
+             * @param {Boolean} readMargins Indicates if the rule should check
+             *      for margin patterns.
+             * @return {void}
+             * @method _readDeclarations
+             * @private
+             */
+            _readDeclarations: function(checkStart, readMargins) {
+                /*
+                 * Reads the pattern
+                 * S* '{' S* declaration [ ';' S* declaration ]* '}' S*
+                 * or
+                 * S* '{' S* [ declaration | margin ]? [ ';' S* [ declaration | margin ]? ]* '}' S*
+                 * Note that this is how it is described in CSS3 Paged Media, but is actually incorrect.
+                 * A semicolon is only necessary following a declaration if there's another declaration
+                 * or margin afterwards.
+                 */
+                var tokenStream = this._tokenStream,
+                    tt;
+
+
+                this._readWhitespace();
+
+                if (checkStart) {
+                    tokenStream.mustMatch(Tokens.LBRACE);
+                }
+
+                this._readWhitespace();
+
+                try {
+
+                    while (true) {
+
+                        if (tokenStream.match(Tokens.SEMICOLON) || (readMargins && this._margin())) {
+                            //noop
+                        } else if (this._declaration()) {
+                            if (!tokenStream.match(Tokens.SEMICOLON)) {
+                                break;
+                            }
+                        } else {
+                            break;
+                        }
+
+                        //if ((!this._margin() && !this._declaration()) || !tokenStream.match(Tokens.SEMICOLON)){
+                        //    break;
+                        //}
+                        this._readWhitespace();
+                    }
+
+                    tokenStream.mustMatch(Tokens.RBRACE);
+                    this._readWhitespace();
+
+                } catch (ex) {
+                    if (ex instanceof SyntaxError && !this.options.strict) {
+
+                        //fire error event
+                        this.fire({
+                            type:       "error",
+                            error:      ex,
+                            message:    ex.message,
+                            line:       ex.line,
+                            col:        ex.col
+                        });
+
+                        //see if there's another declaration
+                        tt = tokenStream.advance([Tokens.SEMICOLON, Tokens.RBRACE]);
+                        if (tt === Tokens.SEMICOLON) {
+                            //if there's a semicolon, then there might be another declaration
+                            this._readDeclarations(false, readMargins);
+                        } else if (tt !== Tokens.RBRACE) {
+                            //if there's a right brace, the rule is finished so don't do anything
+                            //otherwise, rethrow the error because it wasn't handled properly
+                            throw ex;
+                        }
+
+                    } else {
+                        //not a syntax error, rethrow it
+                        throw ex;
+                    }
+                }
+
+            },
+
+            /**
+             * In some cases, you can end up with two white space tokens in a
+             * row. Instead of making a change in every function that looks for
+             * white space, this function is used to match as much white space
+             * as necessary.
+             * @method _readWhitespace
+             * @return {String} The white space if found, empty string if not.
+             * @private
+             */
+            _readWhitespace: function() {
+
+                var tokenStream = this._tokenStream,
+                    ws = "";
+
+                while (tokenStream.match(Tokens.S)) {
+                    ws += tokenStream.token().value;
+                }
+
+                return ws;
+            },
+
+
+            /**
+             * Throws an error when an unexpected token is found.
+             * @param {Object} token The token that was found.
+             * @method _unexpectedToken
+             * @return {void}
+             * @private
+             */
+            _unexpectedToken: function(token) {
+                throw new SyntaxError("Unexpected token '" + token.value + "' at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol);
+            },
+
+            /**
+             * Helper method used for parsing subparts of a style sheet.
+             * @return {void}
+             * @method _verifyEnd
+             * @private
+             */
+            _verifyEnd: function() {
+                if (this._tokenStream.LA(1) !== Tokens.EOF) {
+                    this._unexpectedToken(this._tokenStream.LT(1));
+                }
+            },
+
+            //-----------------------------------------------------------------
+            // Validation methods
+            //-----------------------------------------------------------------
+            _validateProperty: function(property, value) {
+                Validation.validate(property, value);
+            },
+
+            //-----------------------------------------------------------------
+            // Parsing methods
+            //-----------------------------------------------------------------
+
+            parse: function(input) {
+                this._tokenStream = new TokenStream(input, Tokens);
+                this._stylesheet();
+            },
+
+            parseStyleSheet: function(input) {
+                //just passthrough
+                return this.parse(input);
+            },
+
+            parseMediaQuery: function(input) {
+                this._tokenStream = new TokenStream(input, Tokens);
+                var result = this._media_query();
+
+                //if there's anything more, then it's an invalid selector
+                this._verifyEnd();
+
+                //otherwise return result
+                return result;
+            },
+
+            /**
+             * Parses a property value (everything after the semicolon).
+             * @return {parserlib.css.PropertyValue} The property value.
+             * @throws parserlib.util.SyntaxError If an unexpected token is found.
+             * @method parserPropertyValue
+             */
+            parsePropertyValue: function(input) {
+
+                this._tokenStream = new TokenStream(input, Tokens);
+                this._readWhitespace();
+
+                var result = this._expr();
+
+                //okay to have a trailing white space
+                this._readWhitespace();
+
+                //if there's anything more, then it's an invalid selector
+                this._verifyEnd();
+
+                //otherwise return result
+                return result;
+            },
+
+            /**
+             * Parses a complete CSS rule, including selectors and
+             * properties.
+             * @param {String} input The text to parser.
+             * @return {Boolean} True if the parse completed successfully, false if not.
+             * @method parseRule
+             */
+            parseRule: function(input) {
+                this._tokenStream = new TokenStream(input, Tokens);
+
+                //skip any leading white space
+                this._readWhitespace();
+
+                var result = this._ruleset();
+
+                //skip any trailing white space
+                this._readWhitespace();
+
+                //if there's anything more, then it's an invalid selector
+                this._verifyEnd();
+
+                //otherwise return result
+                return result;
+            },
+
+            /**
+             * Parses a single CSS selector (no comma)
+             * @param {String} input The text to parse as a CSS selector.
+             * @return {Selector} An object representing the selector.
+             * @throws parserlib.util.SyntaxError If an unexpected token is found.
+             * @method parseSelector
+             */
+            parseSelector: function(input) {
+
+                this._tokenStream = new TokenStream(input, Tokens);
+
+                //skip any leading white space
+                this._readWhitespace();
+
+                var result = this._selector();
+
+                //skip any trailing white space
+                this._readWhitespace();
+
+                //if there's anything more, then it's an invalid selector
+                this._verifyEnd();
+
+                //otherwise return result
+                return result;
+            },
+
+            /**
+             * Parses an HTML style attribute: a set of CSS declarations
+             * separated by semicolons.
+             * @param {String} input The text to parse as a style attribute
+             * @return {void}
+             * @method parseStyleAttribute
+             */
+            parseStyleAttribute: function(input) {
+                input += "}"; // for error recovery in _readDeclarations()
+                this._tokenStream = new TokenStream(input, Tokens);
+                this._readDeclarations();
+            }
+        };
+
+    //copy over onto prototype
+    for (prop in additions) {
+        if (Object.prototype.hasOwnProperty.call(additions, prop)) {
+            proto[prop] = additions[prop];
+        }
+    }
+
+    return proto;
+}();
+
+
+/*
+nth
+  : S* [ ['-'|'+']? INTEGER? {N} [ S* ['-'|'+'] S* INTEGER ]? |
+         ['-'|'+']? INTEGER | {O}{D}{D} | {E}{V}{E}{N} ] S*
+  ;
+*/
+
+},{"../util/EventTarget":23,"../util/SyntaxError":25,"../util/SyntaxUnit":26,"./Combinator":2,"./MediaFeature":4,"./MediaQuery":5,"./PropertyName":8,"./PropertyValue":9,"./PropertyValuePart":11,"./Selector":13,"./SelectorPart":14,"./SelectorSubPart":15,"./TokenStream":17,"./Tokens":18,"./Validation":19}],7:[function(require,module,exports){
+"use strict";
+
+/* exported Properties */
+
+var Properties = module.exports = {
+    __proto__: null,
+
+    //A
+    "align-items"                   : "flex-start | flex-end | center | baseline | stretch",
+    "align-content"                 : "flex-start | flex-end | center | space-between | space-around | stretch",
+    "align-self"                    : "auto | flex-start | flex-end | center | baseline | stretch",
+    "all"                           : "initial | inherit | unset",
+    "-webkit-align-items"           : "flex-start | flex-end | center | baseline | stretch",
+    "-webkit-align-content"         : "flex-start | flex-end | center | space-between | space-around | stretch",
+    "-webkit-align-self"            : "auto | flex-start | flex-end | center | baseline | stretch",
+    "alignment-adjust"              : "auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical | <percentage> | <length>",
+    "alignment-baseline"            : "auto | baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical",
+    "animation"                     : 1,
+    "animation-delay"               : "<time>#",
+    "animation-direction"           : "<single-animation-direction>#",
+    "animation-duration"            : "<time>#",
+    "animation-fill-mode"           : "[ none | forwards | backwards | both ]#",
+    "animation-iteration-count"     : "[ <number> | infinite ]#",
+    "animation-name"                : "[ none | <single-animation-name> ]#",
+    "animation-play-state"          : "[ running | paused ]#",
+    "animation-timing-function"     : 1,
+
+    //vendor prefixed
+    "-moz-animation-delay"               : "<time>#",
+    "-moz-animation-direction"           : "[ normal | alternate ]#",
+    "-moz-animation-duration"            : "<time>#",
+    "-moz-animation-iteration-count"     : "[ <number> | infinite ]#",
+    "-moz-animation-name"                : "[ none | <single-animation-name> ]#",
+    "-moz-animation-play-state"          : "[ running | paused ]#",
+
+    "-ms-animation-delay"               : "<time>#",
+    "-ms-animation-direction"           : "[ normal | alternate ]#",
+    "-ms-animation-duration"            : "<time>#",
+    "-ms-animation-iteration-count"     : "[ <number> | infinite ]#",
+    "-ms-animation-name"                : "[ none | <single-animation-name> ]#",
+    "-ms-animation-play-state"          : "[ running | paused ]#",
+
+    "-webkit-animation-delay"               : "<time>#",
+    "-webkit-animation-direction"           : "[ normal | alternate ]#",
+    "-webkit-animation-duration"            : "<time>#",
+    "-webkit-animation-fill-mode"           : "[ none | forwards | backwards | both ]#",
+    "-webkit-animation-iteration-count"     : "[ <number> | infinite ]#",
+    "-webkit-animation-name"                : "[ none | <single-animation-name> ]#",
+    "-webkit-animation-play-state"          : "[ running | paused ]#",
+
+    "-o-animation-delay"               : "<time>#",
+    "-o-animation-direction"           : "[ normal | alternate ]#",
+    "-o-animation-duration"            : "<time>#",
+    "-o-animation-iteration-count"     : "[ <number> | infinite ]#",
+    "-o-animation-name"                : "[ none | <single-animation-name> ]#",
+    "-o-animation-play-state"          : "[ running | paused ]#",
+
+    "appearance"                    : "none | auto",
+    "-moz-appearance"               : "none | button | button-arrow-down | button-arrow-next | button-arrow-previous | button-arrow-up | button-bevel | button-focus | caret | checkbox | checkbox-container | checkbox-label | checkmenuitem | dualbutton | groupbox | listbox | listitem | menuarrow | menubar | menucheckbox | menuimage | menuitem | menuitemtext | menulist | menulist-button | menulist-text | menulist-textfield | menupopup | menuradio | menuseparator | meterbar | meterchunk | progressbar | progressbar-vertical | progresschunk | progresschunk-vertical | radio | radio-container | radio-label | radiomenuitem | range | range-thumb | resizer | resizerpanel | scale-horizontal | scalethumbend | scalethumb-horizontal | scalethumbstart | scalethumbtick | scalethumb-vertical | scale-vertical | scrollbarbutton-down | scrollbarbutton-left | scrollbarbutton-right | scrollbarbutton-up | scrollbarthumb-horizontal | scrollbarthumb-vertical | scrollbartrack-horizontal | scrol
 lbartrack-vertical | searchfield | separator | sheet | spinner | spinner-downbutton | spinner-textfield | spinner-upbutton | splitter | statusbar | statusbarpanel | tab | tabpanel | tabpanels | tab-scroll-arrow-back | tab-scroll-arrow-forward | textfield | textfield-multiline | toolbar | toolbarbutton | toolbarbutton-dropdown | toolbargripper | toolbox | tooltip | treeheader | treeheadercell | treeheadersortarrow | treeitem | treeline | treetwisty | treetwistyopen | treeview | -moz-mac-unified-toolbar | -moz-win-borderless-glass | -moz-win-browsertabbar-toolbox | -moz-win-communicationstext | -moz-win-communications-toolbox | -moz-win-exclude-glass | -moz-win-glass | -moz-win-mediatext | -moz-win-media-toolbox | -moz-window-button-box | -moz-window-button-box-maximized | -moz-window-button-close | -moz-window-button-maximize | -moz-window-button-minimize | -moz-window-button-restore | -moz-window-frame-bottom | -moz-window-frame-left | -moz-window-frame-right | -moz-window-titlebar 
 | -moz-window-titlebar-maximized",
+    "-ms-appearance"                : "none | icon | window | desktop | workspace | document | tooltip | dialog | button | push-button | hyperlink | radio | radio-button | checkbox | menu-item | tab | menu | menubar | pull-down-menu | pop-up-menu | list-menu | radio-group | checkbox-group | outline-tree | range | field | combo-box | signature | password | normal",
+    "-webkit-appearance"            : "none | button | button-bevel | caps-lock-indicator | caret | checkbox | default-button | listbox | listitem | media-fullscreen-button | media-mute-button | media-play-button | media-seek-back-button   | media-seek-forward-button     | media-slider | media-sliderthumb | menulist   | menulist-button       | menulist-text | menulist-textfield | push-button      | radio | searchfield   | searchfield-cancel-button     | searchfield-decoration | searchfield-results-button | searchfield-results-decoration | slider-horizontal | slider-vertical | sliderthumb-horizontal | sliderthumb-vertical    | square-button | textarea      | textfield     | scrollbarbutton-down | scrollbarbutton-left | scrollbarbutton-right | scrollbarbutton-up | scrollbargripper-horizontal | scrollbargripper-vertical | scrollbarthumb-horizontal | scrollbarthumb-vertical | scrollbartrack-horizontal | scrollbartrack-vertical",
+    "-o-appearance"                 : "none | window | desktop | workspace | document | tooltip | dialog | button | push-button | hyperlink | radio | radio-button | checkbox | menu-item | tab | menu | menubar | pull-down-menu | pop-up-menu | list-menu | radio-group | checkbox-group | outline-tree | range | field | combo-box | signature | password | normal",
+
+    "azimuth"                       : "<azimuth>",
+
+    //B
+    "backface-visibility"           : "visible | hidden",
+    "background"                    : 1,
+    "background-attachment"         : "<attachment>#",
+    "background-clip"               : "<box>#",
+    "background-color"              : "<color>",
+    "background-image"              : "<bg-image>#",
+    "background-origin"             : "<box>#",
+    "background-position"           : "<bg-position>",
+    "background-repeat"             : "<repeat-style>#",
+    "background-size"               : "<bg-size>#",
+    "baseline-shift"                : "baseline | sub | super | <percentage> | <length>",
+    "behavior"                      : 1,
+    "binding"                       : 1,
+    "bleed"                         : "<length>",
+    "bookmark-label"                : "<content> | <attr> | <string>",
+    "bookmark-level"                : "none | <integer>",
+    "bookmark-state"                : "open | closed",
+    "bookmark-target"               : "none | <uri> | <attr>",
+    "border"                        : "<border-width> || <border-style> || <color>",
+    "border-bottom"                 : "<border-width> || <border-style> || <color>",
+    "border-bottom-color"           : "<color>",
+    "border-bottom-left-radius"     :  "<x-one-radius>",
+    "border-bottom-right-radius"    :  "<x-one-radius>",
+    "border-bottom-style"           : "<border-style>",
+    "border-bottom-width"           : "<border-width>",
+    "border-collapse"               : "collapse | separate",
+    "border-color"                  : "<color>{1,4}",
+    "border-image"                  : 1,
+    "border-image-outset"           : "[ <length> | <number> ]{1,4}",
+    "border-image-repeat"           : "[ stretch | repeat | round ]{1,2}",
+    "border-image-slice"            : "<border-image-slice>",
+    "border-image-source"           : "<image> | none",
+    "border-image-width"            : "[ <length> | <percentage> | <number> | auto ]{1,4}",
+    "border-left"                   : "<border-width> || <border-style> || <color>",
+    "border-left-color"             : "<color>",
+    "border-left-style"             : "<border-style>",
+    "border-left-width"             : "<border-width>",
+    "border-radius"                 : "<border-radius>",
+    "border-right"                  : "<border-width> || <border-style> || <color>",
+    "border-right-color"            : "<color>",
+    "border-right-style"            : "<border-style>",
+    "border-right-width"            : "<border-width>",
+    "border-spacing"                : "<length>{1,2}",
+    "border-style"                  : "<border-style>{1,4}",
+    "border-top"                    : "<border-width> || <border-style> || <color>",
+    "border-top-color"              : "<color>",
+    "border-top-left-radius"        : "<x-one-radius>",
+    "border-top-right-radius"       : "<x-one-radius>",
+    "border-top-style"              : "<border-style>",
+    "border-top-width"              : "<border-width>",
+    "border-width"                  : "<border-width>{1,4}",
+    "bottom"                        : "<margin-width>",
+    "-moz-box-align"                : "start | end | center | baseline | stretch",
+    "-moz-box-decoration-break"     : "slice | clone",
+    "-moz-box-direction"            : "normal | reverse",
+    "-moz-box-flex"                 : "<number>",
+    "-moz-box-flex-group"           : "<integer>",
+    "-moz-box-lines"                : "single | multiple",
+    "-moz-box-ordinal-group"        : "<integer>",
+    "-moz-box-orient"               : "horizontal | vertical | inline-axis | block-axis",
+    "-moz-box-pack"                 : "start | end | center | justify",
+    "-o-box-decoration-break"       : "slice | clone",
+    "-webkit-box-align"             : "start | end | center | baseline | stretch",
+    "-webkit-box-decoration-break"  : "slice | clone",
+    "-webkit-box-direction"         : "normal | reverse",
+    "-webkit-box-flex"              : "<number>",
+    "-webkit-box-flex-group"        : "<integer>",
+    "-webkit-box-lines"             : "single | multiple",
+    "-webkit-box-ordinal-group"     : "<integer>",
+    "-webkit-box-orient"            : "horizontal | vertical | inline-axis | block-axis",
+    "-webkit-box-pack"              : "start | end | center | justify",
+    "box-decoration-break"          : "slice | clone",
+    "box-shadow"                    : "<box-shadow>",
+    "box-sizing"                    : "content-box | border-box",
+    "break-after"                   : "auto | always | avoid | left | right | page | column | avoid-page | avoid-column",
+    "break-before"                  : "auto | always | avoid | left | right | page | column | avoid-page | avoid-column",
+    "break-inside"                  : "auto | avoid | avoid-page | avoid-column",
+
+    //C
+    "caption-side"                  : "top | bottom",
+    "clear"                         : "none | right | left | both",
+    "clip"                          : "<shape> | auto",
+    "-webkit-clip-path"             : "<clip-source> | <clip-path> | none",
+    "clip-path"                     : "<clip-source> | <clip-path> | none",
+    "clip-rule"                     : "nonzero | evenodd",
+    "color"                         : "<color>",
+    "color-interpolation"           : "auto | sRGB | linearRGB",
+    "color-interpolation-filters"   : "auto | sRGB | linearRGB",
+    "color-profile"                 : 1,
+    "color-rendering"               : "auto | optimizeSpeed | optimizeQuality",
+    "column-count"                  : "<integer> | auto",                      //https://www.w3.org/TR/css3-multicol/
+    "column-fill"                   : "auto | balance",
+    "column-gap"                    : "<length> | normal",
+    "column-rule"                   : "<border-width> || <border-style> || <color>",
+    "column-rule-color"             : "<color>",
+    "column-rule-style"             : "<border-style>",
+    "column-rule-width"             : "<border-width>",
+    "column-span"                   : "none | all",
+    "column-width"                  : "<length> | auto",
+    "columns"                       : 1,
+    "content"                       : 1,
+    "counter-increment"             : 1,
+    "counter-reset"                 : 1,
+    "crop"                          : "<shape> | auto",
+    "cue"                           : "cue-after | cue-before",
+    "cue-after"                     : 1,
+    "cue-before"                    : 1,
+    "cursor"                        : 1,
+
+    //D
+    "direction"                     : "ltr | rtl",
+    "display"                       : "inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | grid | inline-grid | run-in | ruby | ruby-base | ruby-text | ruby-base-container | ruby-text-container | contents | none | -moz-box | -moz-inline-block | -moz-inline-box | -moz-inline-grid | -moz-inline-stack | -moz-inline-table | -moz-grid | -moz-grid-group | -moz-grid-line | -moz-groupbox | -moz-deck | -moz-popup | -moz-stack | -moz-marker | -webkit-box | -webkit-inline-box | -ms-flexbox | -ms-inline-flexbox | flex | -webkit-flex | inline-flex | -webkit-inline-flex",
+    "dominant-baseline"             : "auto | use-script | no-change | reset-size | ideographic | alphabetic | hanging | mathematical | central | middle | text-after-edge | text-before-edge",
+    "drop-initial-after-adjust"     : "central | middle | after-edge | text-after-edge | ideographic | alphabetic | mathematical | <percentage> | <length>",
+    "drop-initial-after-align"      : "baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical",
+    "drop-initial-before-adjust"    : "before-edge | text-before-edge | central | middle | hanging | mathematical | <percentage> | <length>",
+    "drop-initial-before-align"     : "caps-height | baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical",
+    "drop-initial-size"             : "auto | line | <length> | <percentage>",
+    "drop-initial-value"            : "<integer>",
+
+    //E
+    "elevation"                     : "<angle> | below | level | above | higher | lower",
+    "empty-cells"                   : "show | hide",
+    "enable-background"             : 1,
+
+    //F
+    "fill"                          : "<paint>",
+    "fill-opacity"                  : "<opacity-value>",
+    "fill-rule"                     : "nonzero | evenodd",
+    "filter"                        : "<filter-function-list> | none",
+    "fit"                           : "fill | hidden | meet | slice",
+    "fit-position"                  : 1,
+    "flex"                          : "<flex>",
+    "flex-basis"                    : "<width>",
+    "flex-direction"                : "row | row-reverse | column | column-reverse",
+    "flex-flow"                     : "<flex-direction> || <flex-wrap>",
+    "flex-grow"                     : "<number>",
+    "flex-shrink"                   : "<number>",
+    "flex-wrap"                     : "nowrap | wrap | wrap-reverse",
+    "-webkit-flex"                  : "<flex>",
+    "-webkit-flex-basis"            : "<width>",
+    "-webkit-flex-direction"        : "row | row-reverse | column | column-reverse",
+    "-webkit-flex-flow"             : "<flex-direction> || <flex-wrap>",
+    "-webkit-flex-grow"             : "<number>",
+    "-webkit-flex-shrink"           : "<number>",
+    "-webkit-flex-wrap"             : "nowrap | wrap | wrap-reverse",
+    "-ms-flex"                      : "<flex>",
+    "-ms-flex-align"                : "start | end | center | stretch | baseline",
+    "-ms-flex-direction"            : "row | row-reverse | column | column-reverse",
+    "-ms-flex-order"                : "<number>",
+    "-ms-flex-pack"                 : "start | end | center | justify",
+    "-ms-flex-wrap"                 : "nowrap | wrap | wrap-reverse",
+    "float"                         : "left | right | none",
+    "float-offset"                  : 1,
+    "flood-color"                   : 1,
+    "flood-opacity"                 : "<opacity-value>",
+    "font"                          : "<font-shorthand> | caption | icon | menu | message-box | small-caption | status-bar",
+    "font-family"                   : "<font-family>",
+    "font-feature-settings"         : "<feature-tag-value> | normal",
+    "font-kerning"                  : "auto | normal | none",
+    "font-size"                     : "<font-size>",
+    "font-size-adjust"              : "<number> | none",
+    "font-stretch"                  : "<font-stretch>",
+    "font-style"                    : "<font-style>",
+    "font-variant"                  : "<font-variant> | normal | none",
+    "font-variant-alternates"       : "<font-variant-alternates> | normal",
+    "font-variant-caps"             : "<font-variant-caps> | normal",
+    "font-variant-east-asian"       : "<font-variant-east-asian> | normal",
+    "font-variant-ligatures"        : "<font-variant-ligatures> | normal | none",
+    "font-variant-numeric"          : "<font-variant-numeric> | normal",
+    "font-variant-position"         : "normal | sub | super",
+    "font-weight"                   : "<font-weight>",
+
+    //G
+    "glyph-orientation-horizontal"  : "<glyph-angle>",
+    "glyph-orientation-vertical"    : "auto | <glyph-angle>",
+    "grid"                          : 1,
+    "grid-area"                     : 1,
+    "grid-auto-columns"             : 1,
+    "grid-auto-flow"                : 1,
+    "grid-auto-position"            : 1,
+    "grid-auto-rows"                : 1,
+    "grid-cell-stacking"            : "columns | rows | layer",
+    "grid-column"                   : 1,
+    "grid-columns"                  : 1,
+    "grid-column-align"             : "start | end | center | stretch",
+    "grid-column-sizing"            : 1,
+    "grid-column-start"             : 1,
+    "grid-column-end"               : 1,
+    "grid-column-span"              : "<integer>",
+    "grid-flow"                     : "none | rows | columns",
+    "grid-layer"                    : "<integer>",
+    "grid-row"                      : 1,
+    "grid-rows"                     : 1,
+    "grid-row-align"                : "start | end | center | stretch",
+    "grid-row-start"                : 1,
+    "grid-row-end"                  : 1,
+    "grid-row-span"                 : "<integer>",
+    "grid-row-sizing"               : 1,
+    "grid-template"                 : 1,
+    "grid-template-areas"           : 1,
+    "grid-template-columns"         : 1,
+    "grid-template-rows"            : 1,
+
+    //H
+    "hanging-punctuation"           : 1,
+    "height"                        : "<margin-width> | <content-sizing>",
+    "hyphenate-after"               : "<integer> | auto",
+    "hyphenate-before"              : "<integer> | auto",
+    "hyphenate-character"           : "<string> | auto",
+    "hyphenate-lines"               : "no-limit | <integer>",
+    "hyphenate-resource"            : 1,
+    "hyphens"                       : "none | manual | auto",
+
+    //I
+    "icon"                          : 1,
+    "image-orientation"             : "angle | auto",
+    "image-rendering"               : "auto | optimizeSpeed | optimizeQuality",
+    "image-resolution"              : 1,
+    "ime-mode"                      : "auto | normal | active | inactive | disabled",
+    "inline-box-align"              : "last | <integer>",
+
+    //J
+    "justify-content"               : "flex-start | flex-end | center | space-between | space-around",
+    "-webkit-justify-content"       : "flex-start | flex-end | center | space-between | space-around",
+
+    //K
+    "kerning"                       : "auto | <length>",
+
+    //L
+    "left"                          : "<margin-width>",
+    "letter-spacing"                : "<length> | normal",
+    "line-height"                   : "<line-height>",
+    "line-break"                    : "auto | loose | normal | strict",
+    "line-stacking"                 : 1,
+    "line-stacking-ruby"            : "exclude-ruby | include-ruby",
+    "line-stacking-shift"           : "consider-shifts | disregard-shifts",
+    "line-stacking-strategy"        : "inline-line-height | block-line-height | max-height | grid-height",
+    "list-style"                    : 1,
+    "list-style-image"              : "<uri> | none",
+    "list-style-position"           : "inside | outside",
+    "list-style-type"               : "disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none",
+
+    //M
+    "margin"                        : "<margin-width>{1,4}",
+    "margin-bottom"                 : "<margin-width>",
+    "margin-left"                   : "<margin-width>",
+    "margin-right"                  : "<margin-width>",
+    "margin-top"                    : "<margin-width>",
+    "mark"                          : 1,
+    "mark-after"                    : 1,
+    "mark-before"                   : 1,
+    "marker"                        : 1,
+    "marker-end"                    : 1,
+    "marker-mid"                    : 1,
+    "marker-start"                  : 1,
+    "marks"                         : 1,
+    "marquee-direction"             : 1,
+    "marquee-play-count"            : 1,
+    "marquee-speed"                 : 1,
+    "marquee-style"                 : 1,
+    "mask"                          : 1,
+    "max-height"                    : "<length> | <percentage> | <content-sizing> | none",
+    "max-width"                     : "<length> | <percentage> | <content-sizing> | none",
+    "min-height"                    : "<length> | <percentage> | <content-sizing> | contain-floats | -moz-contain-floats | -webkit-contain-floats",
+    "min-width"                     : "<length> | <percentage> | <content-sizing> | contain-floats | -moz-contain-floats | -webkit-contain-floats",
+    "move-to"                       : 1,
+
+    //N
+    "nav-down"                      : 1,
+    "nav-index"                     : 1,
+    "nav-left"                      : 1,
+    "nav-right"                     : 1,
+    "nav-up"                        : 1,
+
+    //O
+    "object-fit"                    : "fill | contain | cover | none | scale-down",
+    "object-position"               : "<position>",
+    "opacity"                       : "<opacity-value>",
+    "order"                         : "<integer>",
+    "-webkit-order"                 : "<integer>",
+    "orphans"                       : "<integer>",
+    "outline"                       : 1,
+    "outline-color"                 : "<color> | invert",
+    "outline-offset"                : 1,
+    "outline-style"                 : "<border-style>",
+    "outline-width"                 : "<border-width>",
+    "overflow"                      : "visible | hidden | scroll | auto",
+    "overflow-style"                : 1,
+    "overflow-wrap"                 : "normal | break-word",
+    "overflow-x"                    : 1,
+    "overflow-y"                    : 1,
+
+    //P
+    "padding"                       : "<padding-width>{1,4}",
+    "padding-bottom"                : "<padding-width>",
+    "padding-left"                  : "<padding-width>",
+    "padding-right"                 : "<padding-width>",
+    "padding-top"                   : "<padding-width>",
+    "page"                          : 1,
+    "page-break-after"              : "auto | always | avoid | left | right",
+    "page-break-before"             : "auto | always | avoid | left | right",
+    "page-break-inside"             : "auto | avoid",
+    "page-policy"                   : 1,
+    "pause"                         : 1,
+    "pause-after"                   : 1,
+    "pause-before"                  : 1,
+    "perspective"                   : 1,
+    "perspective-origin"            : 1,
+    "phonemes"                      : 1,
+    "pitch"                         : 1,
+    "pitch-range"                   : 1,
+    "play-during"                   : 1,
+    "pointer-events"                : "auto | none | visiblePainted | visibleFill | visibleStroke | visible | painted | fill | stroke | all",
+    "position"                      : "static | relative | absolute | fixed",
+    "presentation-level"            : 1,
+    "punctuation-trim"              : 1,
+
+    //Q
+    "quotes"                        : 1,
+
+    //R
+    "rendering-intent"              : 1,
+    "resize"                        : 1,
+    "rest"                          : 1,
+    "rest-after"                    : 1,
+    "rest-before"                   : 1,
+    "richness"                      : 1,
+    "right"                         : "<margin-width>",
+    "rotation"                      : 1,
+    "rotation-point"                : 1,
+    "ruby-align"                    : 1,
+    "ruby-overhang"                 : 1,
+    "ruby-position"                 : 1,
+    "ruby-span"                     : 1,
+
+    //S
+    "shape-rendering"               : "auto | optimizeSpeed | crispEdges | geometricPrecision",
+    "size"                          : 1,
+    "speak"                         : "normal | none | spell-out",
+    "speak-header"                  : "once | always",
+    "speak-numeral"                 : "digits | continuous",
+    "speak-punctuation"             : "code | none",
+    "speech-rate"                   : 1,
+    "src"                           : 1,
+    "stop-color"                    : 1,
+    "stop-opacity"                  : "<opacity-value>",
+    "stress"                        : 1,
+    "string-set"                    : 1,
+    "stroke"                        : "<paint>",
+    "stroke-dasharray"              : "none | <dasharray>",
+    "stroke-dashoffset"             : "<percentage> | <length>",
+    "stroke-linecap"                : "butt | round | square",
+    "stroke-linejoin"               : "miter | round | bevel",
+    "stroke-miterlimit"             : "<miterlimit>",
+    "stroke-opacity"                : "<opacity-value>",
+    "stroke-width"                  : "<percentage> | <length>",
+
+    "table-layout"                  : "auto | fixed",
+    "tab-size"                      : "<integer> | <length>",
+    "target"                        : 1,
+    "target-name"                   : 1,
+    "target-new"                    : 1,
+    "target-position"               : 1,
+    "text-align"                    : "left | right | center | justify | match-parent | start | end",
+    "text-align-last"               : 1,
+    "text-anchor"                   : "start | middle | end",
+    "text-decoration"               : "<text-decoration-line> || <text-decoration-style> || <text-decoration-color>",
+    "text-decoration-color"         : "<text-decoration-color>",
+    "text-decoration-line"          : "<text-decoration-line>",
+    "text-decoration-style"         : "<text-decoration-style>",
+    "text-emphasis"                 : 1,
+    "text-height"                   : 1,
+    "text-indent"                   : "<length> | <percentage>",
+    "text-justify"                  : "auto | none | inter-word | inter-ideograph | inter-cluster | distribute | kashida",
+    "text-outline"                  : 1,
+    "text-overflow"                 : 1,
+    "text-rendering"                : "auto | optimizeSpeed | optimizeLegibility | geometricPrecision",
+    "text-shadow"                   : 1,
+    "text-transform"                : "capitalize | uppercase | lowercase | none",
+    "text-wrap"                     : "normal | none | avoid",
+    "top"                           : "<margin-width>",
+    "-ms-touch-action"              : "auto | none | pan-x | pan-y | pan-left | pan-right | pan-up | pan-down | manipulation",
+    "touch-action"                  : "auto | none | pan-x | pan-y | pan-left | pan-right | pan-up | pan-down | manipulation",
+    "transform"                     : 1,
+    "transform-origin"              : 1,
+    "transform-style"               : 1,
+    "transition"                    : 1,
+    "transition-delay"              : 1,
+    "transition-duration"           : 1,
+    "transition-property"           : 1,
+    "transition-timing-function"    : 1,
+
+    //U
+    "unicode-bidi"                  : "normal | embed | isolate | bidi-override | isolate-override | plaintext",
+    "user-modify"                   : "read-only | read-write | write-only",
+    "user-select"                   : "none | text | toggle | element | elements | all",
+
+    //V
+    "vertical-align"                : "auto | use-script | baseline | sub | super | top | text-top | central | middle | bottom | text-bottom | <percentage> | <length>",
+    "visibility"                    : "visible | hidden | collapse",
+    "voice-balance"                 : 1,
+    "voice-duration"                : 1,
+    "voice-family"                  : 1,
+    "voice-pitch"                   : 1,
+    "voice-pitch-range"             : 1,
+    "voice-rate"                    : 1,
+    "voice-stress"                  : 1,
+    "voice-volume"                  : 1,
+    "volume"                        : 1,
+
+    //W
+    "white-space"                   : "normal | pre | nowrap | pre-wrap | pre-line | -pre-wrap | -o-pre-wrap | -moz-pre-wrap | -hp-pre-wrap",   // https://perishablepress.com/wrapping-content/
+    "white-space-collapse"          : 1,
+    "widows"                        : "<integer>",
+    "width"                         : "<length> | <percentage> | <content-sizing> | auto",
+    "will-change"                   : "<will-change>",
+    "word-break"                    : "normal | keep-all | break-all",
+    "word-spacing"                  : "<length> | normal",
+    "word-wrap"                     : "normal | break-word",
+    "writing-mode"                  : "horizontal-tb | vertical-rl | vertical-lr | lr-tb | rl-tb | tb-rl | bt-rl | tb-lr | bt-lr | lr-bt | rl-bt | lr | rl | tb",
+
+    //Z
+    "z-index"                       : "<integer> | auto",
+    "zoom"                          : "<number> | <percentage> | normal"
+};
+
+},{}],8:[function(require,module,exports){
+"use strict";
+
+module.exports = PropertyName;
+
+var SyntaxUnit = require("../util/SyntaxUnit");
+
+var Parser = require("./Parser");
+
+/**
+ * Represents a selector combinator (whitespace, +, >).
+ * @namespace parserlib.css
+ * @class PropertyName
+ * @extends parserlib.util.SyntaxUnit
+ * @constructor
+ * @param {String} text The text representation of the unit.
+ * @param {String} hack The type of IE hack applied ("*", "_", or null).
+ * @param {int} line The line of text on which the unit resides.
+ * @param {int} col The column of text on which the unit resides.
+ */
+function PropertyName(text, hack, line, col) {
+
+    SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_NAME_TYPE);
+
+    /**
+     * The type of IE hack applied ("*", "_", or null).
+     * @type String
+     * @property hack
+     */
+    this.hack = hack;
+
+}
+
+PropertyName.prototype = new SyntaxUnit();
+PropertyName.prototype.constructor = PropertyName;
+PropertyName.prototype.toString = function() {
+    return (this.hack ? this.hack : "") + this.text;
+};
+
+},{"../util/SyntaxUnit":26,"./Parser":6}],9:[function(require,module,exports){
+"use strict";
+
+module.exports = PropertyValue;
+
+var SyntaxUnit = require("../util/SyntaxUnit");
+
+var Parser = require("./Parser");
+
+/**
+ * Represents a single part of a CSS property value, meaning that it represents
+ * just everything single part between ":" and ";". If there are multiple values
+ * separated by commas, this type represents just one of the values.
+ * @param {String[]} parts An array of value parts making up this value.
+ * @param {int} line The line of text on which the unit resides.
+ * @param {int} col The column of text on which the unit resides.
+ * @namespace parserlib.css
+ * @class PropertyValue
+ * @extends parserlib.util.SyntaxUnit
+ * @constructor
+ */
+function PropertyValue(parts, line, col) {
+
+    SyntaxUnit.call(this, parts.join(" "), line, col, Parser.PROPERTY_VALUE_TYPE);
+
+    /**
+     * The parts that make up the selector.
+     * @type Array
+     * @property parts
+     */
+    this.parts = parts;
+
+}
+
+PropertyValue.prototype = new SyntaxUnit();
+PropertyValue.prototype.constructor = PropertyValue;
+
+
+},{"../util/SyntaxUnit":26,"./Parser":6}],10:[function(require,module,exports){
+"use strict";
+
+module.exports = PropertyValueIterator;
+
+/**
+ * A utility class that allows for easy iteration over the various parts of a
+ * property value.
+ * @param {parserlib.css.PropertyValue} value The property value to iterate over.
+ * @namespace parserlib.css
+ * @class PropertyValueIterator
+ * @constructor
+ */
+function PropertyValueIterator(value) {
+
+    /**
+     * Iterator value
+     * @type int
+     * @property _i
+     * @private
+     */
+    this._i = 0;
+
+    /**
+     * The parts that make up the value.
+     * @type Array
+     * @property _parts
+     * @private
+     */
+    this._parts = value.parts;
+
+    /**
+     * Keeps track of bookmarks along the way.
+     * @type Array
+     * @property _marks
+     * @private
+     */
+    this._marks = [];
+
+    /**
+     * Holds the original property value.
+     * @type parserlib.css.PropertyValue
+     * @property value
+     */
+    this.value = value;
+
+}
+
+/**
+ * Returns the total number of parts in the value.
+ * @return {int} The total number of parts in the value.
+ * @method count
+ */
+PropertyValueIterator.prototype.count = function() {
+    return this._parts.length;
+};
+
+/**
+ * Indicates if the iterator is positioned at the first item.
+ * @return {Boolean} True if positioned at first item, false if not.
+ * @method isFirst
+ */
+PropertyValueIterator.prototype.isFirst = function() {
+    return this._i === 0;
+};
+
+/**
+ * Indicates if there are more parts of the property value.
+ * @return {Boolean} True if there are more parts, false if not.
+ * @method hasNext
+ */
+PropertyValueIterator.prototype.hasNext = function() {
+    return this._i < this._parts.length;
+};
+
+/**
+ * Marks the current spot in the iteration so it can be restored to
+ * later on.
+ * @return {void}
+ * @method mark
+ */
+PropertyValueIterator.prototype.mark = function() {
+    this._marks.push(this._i);
+};
+
+/**
+ * Returns the next part of the property value or null if there is no next
+ * part. Does not move the internal counter forward.
+ * @return {parserlib.css.PropertyValuePart} The next part of the property value or null if there is no next
+ * part.
+ * @method peek
+ */
+PropertyValueIterator.prototype.peek = function(count) {
+    return this.hasNext() ? this._parts[this._i + (count || 0)] : null;
+};
+
+/**
+ * Returns the next part of the property value or null if there is no next
+ * part.
+ * @return {parserlib.css.PropertyValuePart} The next part of the property value or null if there is no next
+ * part.
+ * @method next
+ */
+PropertyValueIterator.prototype.next = function() {
+    return this.hasNext() ? this._parts[this._i++] : null;
+};
+
+/**
+ * Returns the previous part of the property value or null if there is no
+ * previous part.
+ * @return {parserlib.css.PropertyValuePart} The previous part of the
+ * property value or null if there is no previous part.
+ * @method previous
+ */
+PropertyValueIterator.prototype.previous = function() {
+    return this._i > 0 ? this._parts[--this._i] : null;
+};
+
+/**
+ * Restores the last saved bookmark.
+ * @return {void}
+ * @method restore
+ */
+PropertyValueIterator.prototype.restore = function() {
+    if (this._marks.length) {
+        this._i = this._marks.pop();
+    }
+};
+
+/**
+ * Drops the last saved bookmark.
+ * @return {void}
+ * @method drop
+ */
+PropertyValueIterator.prototype.drop = function() {
+    this._marks.pop();
+};
+
+},{}],11:[function(require,module,exports){
+"use strict";
+
+module.exports = PropertyValuePart;
+
+var SyntaxUnit = require("../util/SyntaxUnit");
+
+var Colors = require("./Colors");
+var Parser = require("./Parser");
+var Tokens = require("./Tokens");
+
+/**
+ * Represents a single part of a CSS property value, meaning that it represents
+ * just one part of the data between ":" and ";".
+ * @param {String} text The text representation of the unit.
+ * @param {int} line The line of text on which the unit resides.
+ * @param {int} col The column of text on which the unit resides.
+ * @namespace parserlib.css
+ * @class PropertyValuePart
+ * @extends parserlib.util.SyntaxUnit
+ * @constructor
+ */
+function PropertyValuePart(text, line, col, optionalHint) {
+    var hint = optionalHint || {};
+
+    SyntaxUnit.call(this, text, line, col, Parser.PROPERTY_VALUE_PART_TYPE);
+
+    /**
+     * Indicates the type of value unit.
+     * @type String
+     * @property type
+     */
+    this.type = "unknown";
+
+    //figure out what type of data it is
+
+    var temp;
+
+    //it is a measurement?
+    if (/^([+\-]?[\d\.]+)([a-z]+)$/i.test(text)) {  //dimension
+        this.type = "dimension";
+        this.value = +RegExp.$1;
+        this.units = RegExp.$2;
+
+        //try to narrow down
+        switch (this.units.toLowerCase()) {
+
+            case "em":
+            case "rem":
+            case "ex":
+            case "px":
+            case "cm":
+            case "mm":
+            case "in":
+            case "pt":
+            case "pc":
+            case "ch":
+            case "vh":
+            case "vw":
+            case "vmax":
+            case "vmin":
+                this.type = "length";
+                break;
+
+            case "fr":
+                this.type = "grid";
+                break;
+
+            case "deg":
+            case "rad":
+            case "grad":
+            case "turn":
+                this.type = "angle";
+                break;
+
+            case "ms":
+            case "s":
+                this.type = "time";
+                break;
+
+            case "hz":
+            case "khz":
+                this.type = "frequency";
+                break;
+
+            case "dpi":
+            case "dpcm":
+                this.type = "resolution";
+                break;
+
+            //default
+
+        }
+
+    } else if (/^([+\-]?[\d\.]+)%$/i.test(text)) {  //percentage
+        this.type = "percentage";
+        this.value = +RegExp.$1;
+    } else if (/^([+\-]?\d+)$/i.test(text)) {  //integer
+        this.type = "integer";
+        this.value = +RegExp.$1;
+    } else if (/^([+\-]?[\d\.]+)$/i.test(text)) {  //number
+        this.type = "number";
+        this.value = +RegExp.$1;
+
+    } else if (/^#([a-f0-9]{3,6})/i.test(text)) {  //hexcolor
+        this.type = "color";
+        temp = RegExp.$1;
+        if (temp.length === 3) {
+            this.red    = parseInt(temp.charAt(0)+temp.charAt(0), 16);
+            this.green  = parseInt(temp.charAt(1)+temp.charAt(1), 16);
+            this.blue   = parseInt(temp.charAt(2)+temp.charAt(2), 16);
+        } else {
+            this.red    = parseInt(temp.substring(0, 2), 16);
+            this.green  = parseInt(temp.substring(2, 4), 16);
+            this.blue   = parseInt(temp.substring(4, 6), 16);
+        }
+    } else if (/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/i.test(text)) { //rgb() color with absolute numbers
+        this.type   = "color";
+        this.red    = +RegExp.$1;
+        this.green  = +RegExp.$2;
+        this.blue   = +RegExp.$3;
+    } else if (/^rgb\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)) { //rgb() color with percentages
+        this.type   = "color";
+        this.red    = +RegExp.$1 * 255 / 100;
+        this.green  = +RegExp.$2 * 255 / 100;
+        this.blue   = +RegExp.$3 * 255 / 100;
+    } else if (/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/i.test(text)) { //rgba() color with absolute numbers
+        this.type   = "color";
+        this.red    = +RegExp.$1;
+        this.green  = +RegExp.$2;
+        this.blue   = +RegExp.$3;
+        this.alpha  = +RegExp.$4;
+    } else if (/^rgba\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)) { //rgba() color with percentages
+        this.type   = "color";
+        this.red    = +RegExp.$1 * 255 / 100;
+        this.green  = +RegExp.$2 * 255 / 100;
+        this.blue   = +RegExp.$3 * 255 / 100;
+        this.alpha  = +RegExp.$4;
+    } else if (/^hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(text)) { //hsl()
+        this.type   = "color";
+        this.hue    = +RegExp.$1;
+        this.saturation = +RegExp.$2 / 100;
+        this.lightness  = +RegExp.$3 / 100;
+    } else if (/^hsla\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(text)) { //hsla() color with percentages
+        this.type   = "color";
+        this.hue    = +RegExp.$1;
+        this.saturation = +RegExp.$2 / 100;
+        this.lightness  = +RegExp.$3 / 100;
+        this.alpha  = +RegExp.$4;
+    } else if (/^url\(("([^\\"]|\\.)*")\)/i.test(text)) { //URI
+        // generated by TokenStream.readURI, so always double-quoted.
+        this.type   = "uri";
+        this.uri    = PropertyValuePart.parseString(RegExp.$1);
+    } else if (/^([^\(]+)\(/i.test(text)) {
+        this.type   = "function";
+        this.name   = RegExp.$1;
+        this.value  = text;
+    } else if (/^"([^\n\r\f\\"]|\\\r\n|\\[^\r0-9a-f]|\\[0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?)*"/i.test(text)) {    //double-quoted string
+        this.type   = "string";
+        this.value  = PropertyValuePart.parseString(text);
+    } else if (/^'([^\n\r\f\\']|\\\r\n|\\[^\r0-9a-f]|\\[0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?)*'/i.test(text)) {    //single-quoted string
+        this.type   = "string";
+        this.value  = PropertyValuePart.parseString(text);
+    } else if (Colors[text.toLowerCase()]) {  //named color
+        this.type   = "color";
+        temp        = Colors[text.toLowerCase()].substring(1);
+        this.red    = parseInt(temp.substring(0, 2), 16);
+        this.green  = parseInt(temp.substring(2, 4), 16);
+        this.blue   = parseInt(temp.substring(4, 6), 16);
+    } else if (/^[,\/]$/.test(text)) {
+        this.type   = "operator";
+        this.value  = text;
+    } else if (/^-?[a-z_\u00A0-\uFFFF][a-z0-9\-_\u00A0-\uFFFF]*$/i.test(text)) {
+        this.type   = "identifier";
+        this.value  = text;
+    }
+
+    // There can be ambiguity with escape sequences in identifiers, as
+    // well as with "color" parts which are also "identifiers", so record
+    // an explicit hint when the token generating this PropertyValuePart
+    // was an identifier.
+    this.wasIdent = Boolean(hint.ident);
+
+}
+
+PropertyValuePart.prototype = new SyntaxUnit();
+PropertyValuePart.prototype.constructor = PropertyValuePart;
+
+/**
+ * Helper method to parse a CSS string.
+ */
+PropertyValuePart.parseString = function(str) {
+    str = str.slice(1, -1); // Strip surrounding single/double quotes
+    var replacer = function(match, esc) {
+        if (/^(\n|\r\n|\r|\f)$/.test(esc)) {
+            return "";
+        }
+        var m = /^[0-9a-f]{1,6}/i.exec(esc);
+        if (m) {
+            var codePoint = parseInt(m[0], 16);
+            if (String.fromCodePoint) {
+                return String.fromCodePoint(codePoint);
+            } else {
+                // XXX No support for surrogates on old JavaScript engines.
+                return String.fromCharCode(codePoint);
+            }
+        }
+        return esc;
+    };
+    return str.replace(/\\(\r\n|[^\r0-9a-f]|[0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?)/ig,
+                       replacer);
+};
+
+/**
+ * Helper method to serialize a CSS string.
+ */
+PropertyValuePart.serializeString = function(value) {
+    var replacer = function(match, c) {
+        if (c === "\"") {
+            return "\\" + c;
+        }
+        var cp = String.codePointAt ? String.codePointAt(0) :
+            // We only escape non-surrogate chars, so using charCodeAt
+            // is harmless here.
+            String.charCodeAt(0);
+        return "\\" + cp.toString(16) + " ";
+    };
+    return "\"" + value.replace(/["\r\n\f]/g, replacer) + "\"";
+};
+
+/**
+ * Create a new syntax unit based solely on the given token.
+ * Convenience method for creating a new syntax unit when
+ * it represents a single token instead of multiple.
+ * @param {Object} token The token object to represent.
+ * @return {parserlib.css.PropertyValuePart} The object representing the token.
+ * @static
+ * @method fromToken
+ */
+PropertyValuePart.fromToken = function(token) {
+    var part = new PropertyValuePart(token.value, token.startLine, token.startCol, {
+        // Tokens can have escaped characters that would fool the type
+        // identification in the PropertyValuePart constructor, so pass
+        // in a hint if this was an identifier.
+        ident: token.type === Tokens.IDENT
+    });
+    return part;
+};
+
+},{"../util/SyntaxUnit":26,"./Colors":1,"./Parser":6,"./Tokens":18}],12:[function(require,module,exports){
+"use strict";
+
+var Pseudos = module.exports = {
+    __proto__:       null,
+    ":first-letter": 1,
+    ":first-line":   1,
+    ":before":       1,
+    ":after":        1
+};
+
+Pseudos.ELEMENT = 1;
+Pseudos.CLASS = 2;
+
+Pseudos.isElement = function(pseudo) {
+    return pseudo.indexOf("::") === 0 || Pseudos[pseudo.toLowerCase()] === Pseudos.ELEMENT;
+};
+
+},{}],13:[function(require,module,exports){
+"use strict";
+
+module.exports = Selector;
+
+var SyntaxUnit = require("../util/SyntaxUnit");
+
+var Parser = require("./Parser");
+var Specificity = require("./Specificity");
+
+/**
+ * Represents an entire single selector, including all parts but not
+ * including multiple selectors (those separated by commas).
+ * @namespace parserlib.css
+ * @class Selector
+ * @extends parserlib.util.SyntaxUnit
+ * @constructor
+ * @param {Array} parts Array of selectors parts making up this selector.
+ * @param {int} line The line of text on which the unit resides.
+ * @param {int} col The column of text on which the unit resides.
+ */
+function Selector(parts, line, col) {
+
+    SyntaxUnit.call(this, parts.join(" "), line, col, Parser.SELECTOR_TYPE);
+
+    /**
+     * The parts that make up the selector.
+     * @type Array
+     * @property parts
+     */
+    this.parts = parts;
+
+    /**
+     * The specificity of the selector.
+     * @type parserlib.css.Specificity
+     * @property specificity
+     */
+    this.specificity = Specificity.calculate(this);
+
+}
+
+Selector.prototype = new SyntaxUnit();
+Selector.prototype.constructor = Selector;
+
+
+},{"../util/SyntaxUnit":26,"./Parser":6,"./Specificity":16}],14:[function(require,module,exports){
+"use strict";
+
+module.exports = SelectorPart;
+
+var SyntaxUnit = require("../util/SyntaxUnit");
+
+var Parser = require("./Parser");
+
+/**
+ * Represents a single part of a selector string, meaning a single set of
+ * element name and modifiers. This does not include combinators such as
+ * spaces, +, >, etc.
+ * @namespace parserlib.css
+ * @class SelectorPart
+ * @extends parserlib.util.SyntaxUnit
+ * @constructor
+ * @param {String} elementName The element name in the selector or null
+ *      if there is no element name.
+ * @param {Array} modifiers Array of individual modifiers for the element.
+ *      May be empty if there are none.
+ * @param {String} text The text representation of the unit.
+ * @param {int} line The line of text on which the unit resides.
+ * @param {int} col The column of text on which the unit resides.
+ */
+function SelectorPart(elementName, modifiers, text, line, col) {
+
+    SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_PART_TYPE);
+
+    /**
+     * The tag name of the element to which this part
+     * of the selector affects.
+     * @type String
+     * @property elementName
+     */
+    this.elementName = elementName;
+
+    /**
+     * The parts that come after the element name, such as class names, IDs,
+     * pseudo classes/elements, etc.
+     * @type Array
+     * @property modifiers
+     */
+    this.modifiers = modifiers;
+
+}
+
+SelectorPart.prototype = new SyntaxUnit();
+SelectorPart.prototype.constructor = SelectorPart;
+
+
+},{"../util/SyntaxUnit":26,"./Parser":6}],15:[function(require,module,exports){
+"use strict";
+
+module.exports = SelectorSubPart;
+
+var SyntaxUnit = require("../util/SyntaxUnit");
+
+var Parser = require("./Parser");
+
+/**
+ * Represents a selector modifier string, meaning a class name, element name,
+ * element ID, pseudo rule, etc.
+ * @namespace parserlib.css
+ * @class SelectorSubPart
+ * @extends parserlib.util.SyntaxUnit
+ * @constructor
+ * @param {String} text The text representation of the unit.
+ * @param {String} type The type of selector modifier.
+ * @param {int} line The line of text on which the unit resides.
+ * @param {int} col The column of text on which the unit resides.
+ */
+function SelectorSubPart(text, type, line, col) {
+
+    SyntaxUnit.call(this, text, line, col, Parser.SELECTOR_SUB_PART_TYPE);
+
+    /**
+     * The type of modifier.
+     * @type String
+     * @property type
+     */
+    this.type = type;
+
+    /**
+     * Some subparts have arguments, this represents them.
+     * @type Array
+     * @property args
+     */
+    this.args = [];
+
+}
+
+SelectorSubPart.prototype = new SyntaxUnit();
+SelectorSubPart.prototype.constructor = SelectorSubPart;
+
+
+},{"../util/SyntaxUnit":26,"./Parser":6}],16:[function(require,module,exports){
+"use strict";
+
+module.exports = Specificity;
+
+var Pseudos = require("./Pseudos");
+var SelectorPart = require("./SelectorPart");
+
+/**
+ * Represents a selector's specificity.
+ * @namespace parserlib.css
+ * @class Specificity
+ * @constructor
+ * @param {int} a Should be 1 for inline styles, zero for stylesheet styles
+ * @param {int} b Number of ID selectors
+ * @param {int} c Number of classes and pseudo classes
+ * @param {int} d Number of element names and pseudo elements
+ */
+function Specificity(a, b, c, d) {
+    this.a = a;
+    this.b = b;
+    this.c = c;
+    this.d = d;
+}
+
+Specificity.prototype = {
+    constructor: Specificity,
+
+    /**
+     * Compare this specificity to another.
+     * @param {Specificity} other The other specificity to compare to.
+     * @return {int} -1 if the other specificity is larger, 1 if smaller, 0 if equal.
+     * @method compare
+     */
+    compare: function(other) {
+        var comps = ["a", "b", "c", "d"],
+            i, len;
+
+        for (i=0, len=comps.length; i < len; i++) {
+            if (this[comps[i]] < other[comps[i]]) {
+                return -1;
+            } else if (this[comps[i]] > other[comps[i]]) {
+                return 1;
+            }
+        }
+
+        return 0;
+    },
+
+    /**
+     * Creates a numeric value for the specificity.
+     * @return {int} The numeric value for the specificity.
+     * @method valueOf
+     */
+    valueOf: function() {
+        return (this.a * 1000) + (this.b * 100) + (this.c * 10) + this.d;
+    },
+
+    /**
+     * Returns a string representation for specificity.
+     * @return {String} The string representation of specificity.
+     * @method toString
+     */
+    toString: function() {
+        return this.a + "," + this.b + "," + this.c + "," + this.d;
+    }
+
+};
+
+/**
+ * Calculates the specificity of the given selector.
+ * @param {parserlib.css.Selector} The selector to calculate specificity for.
+ * @return {parserlib.css.Specificity} The specificity of the selector.
+ * @static
+ * @method calculate
+ */
+Specificity.calculate = function(selector) {
+
+    var i, len,
+        part,
+        b=0, c=0, d=0;
+
+    function updateValues(part) {
+
+        var i, j, len, num,
+            elementName = part.elementName ? part.elementName.text : "",
+            modifier;
+
+        if (elementName && elementName.charAt(elementName.length-1) !== "*") {
+            d++;
+        }
+
+        for (i=0, len=part.modifiers.length; i < len; i++) {
+            modifier = part.modifiers[i];
+            switch (modifier.type) {
+                case "class":
+                case "attribute":
+                    c++;
+                    break;
+
+                case "id":
+                    b++;
+                    break;
+
+                case "pseudo":
+                    if (Pseudos.isElement(modifier.text)) {
+                        d++;
+                    } else {
+                        c++;
+                    }
+                    break;
+
+                case "not":
+                    for (j=0, num=modifier.args.length; j < num; j++) {
+                        updateValues(modifier.args[j]);
+                    }
+            }
+        }
+    }
+
+    for (i=0, len=selector.parts.length; i < len; i++) {
+        part = selector.parts[i];
+
+        if (part instanceof SelectorPart) {
+            updateValues(part);
+        }
+    }
+
+    return new Specificity(0, b, c, d);
+};
+
+},{"./Pseudos":12,"./SelectorPart":14}],17:[function(require,module,exports){
+"use strict";
+
+module.exports = TokenStream;
+
+var TokenStreamBase = require("../util/TokenStreamBase");
+
+var PropertyValuePart = require("./PropertyValuePart");
+var Tokens = require("./Tokens");
+
+var h = /^[0-9a-fA-F]$/,
+    nonascii = /^[\u00A0-\uFFFF]$/,
+    nl = /\n|\r\n|\r|\f/,
+    whitespace = /\u0009|\u000a|\u000c|\u000d|\u0020/;
+
+//-----------------------------------------------------------------------------
+// Helper functions
+//-----------------------------------------------------------------------------
+
+
+function isHexDigit(c) {
+    return c !== null && h.test(c);
+}
+
+function isDigit(c) {
+    return c !== null && /\d/.test(c);
+}
+
+function isWhitespace(c) {
+    return c !== null && whitespace.test(c);
+}
+
+function isNewLine(c) {
+    return c !== null && nl.test(c);
+}
+
+function isNameStart(c) {
+    return c !== null && /[a-z_\u00A0-\uFFFF\\]/i.test(c);
+}
+
+function isNameChar(c) {
+    return c !== null && (isNameStart(c) || /[0-9\-\\]/.test(c));
+}
+
+function isIdentStart(c) {
+    return c !== null && (isNameStart(c) || /\-\\/.test(c));
+}
+
+function mix(receiver, supplier) {
+    for (var prop in supplier) {
+        if (Object.prototype.hasOwnProperty.call(supplier, prop)) {
+            receiver[prop] = supplier[prop];
+        }
+    }
+    return receiver;
+}
+
+//-----------------------------------------------------------------------------
+// CSS Token Stream
+//-----------------------------------------------------------------------------
+
+
+/**
+ * A token stream that produces CSS tokens.
+ * @param {String|Reader} input The source of text to tokenize.
+ * @constructor
+ * @class TokenStream
+ * @namespace parserlib.css
+ */
+function TokenStream(input) {
+    TokenStreamBase.call(this, input, Tokens);
+}
+
+TokenStream.prototype = mix(new TokenStreamBase(), {
+
+    /**
+     * Overrides the TokenStreamBase method of the same name
+     * to produce CSS tokens.
+     * @return {Object} A token object representing the next token.
+     * @method _getToken
+     * @private
+     */
+    _getToken: function() {
+
+        var c,
+            reader = this._reader,
+            token   = null,
+            startLine   = reader.getLine(),
+            startCol    = reader.getCol();
+
+        c = reader.read();
+
+
+        while (c) {
+            switch (c) {
+
+                /*
+                 * Potential tokens:
+                 * - COMMENT
+                 * - SLASH
+                 * - CHAR
+                 */
+                case "/":
+
+                    if (reader.peek() === "*") {
+                        token = this.commentToken(c, startLine, startCol);
+                    } else {
+                        token = this.charToken(c, startLine, startCol);
+                    }
+                    break;
+
+                /*
+                 * Potential tokens:
+                 * - DASHMATCH
+                 * - INCLUDES
+                 * - PREFIXMATCH
+                 * - SUFFIXMATCH
+                 * - SUBSTRINGMATCH
+                 * - CHAR
+                 */
+                case "|":
+                case "~":
+                case "^":
+                case "$":
+                case "*":
+                    if (reader.peek() === "=") {
+                        token = this.comparisonToken(c, startLine, startCol);
+                    } else {
+                        token = this.charToken(c, startLine, startCol);
+                    }
+                    break;
+
+                /*
+                 * Potential tokens:
+                 * - STRING
+                 * - INVALID
+                 */
+                case "\"":
+                case "'":
+                    token = this.stringToken(c, startLine, startCol);
+                    break;
+
+                /*
+                 * Potential tokens:
+                 * - HASH
+                 * - CHAR
+                 */
+                case "#":
+                    if (isNameChar(reader.peek())) {
+                        token = this.hashToken(c, startLine, startCol);
+                    } else {
+                        token = this.charToken(c, startLine, startCol);
+                    }
+                    break;
+
+                /*
+                 * Potential tokens:
+                 * - DOT
+                 * - NUMBER
+                 * - DIMENSION
+                 * - PERCENTAGE
+                 */
+                case ".":
+                    if (isDigit(reader.peek())) {
+                        token = this.numberToken(c, startLine, startCol);
+                    } else {
+                        token = this.charToken(c, startLine, startCol);
+                    }
+                    break;
+
+                /*
+                 * Potential tokens:
+                 * - CDC
+                 * - MINUS
+                 * - NUMBER
+                 * - DIMENSION
+                 * - PERCENTAGE
+                 */
+                case "-":
+                    if (reader.peek() === "-") {  //could be closing HTML-style comment
+                        token = this.htmlCommentEndToken(c, startLine, startCol);
+                    } else if (isNameStart(reader.peek())) {
+                        token = this.identOrFunctionToken(c, startLine, startCol);
+                    } else {
+                        token = this.charToken(c, startLine, startCol);
+                    }
+                    break;
+
+                /*
+                 * Potential tokens:
+                 * - IMPORTANT_SYM
+                 * - CHAR
+                 */
+                case "!":
+                    token = this.importantToken(c, startLine, startCol);
+                    break;
+
+                /*
+                 * Any at-keyword or CHAR
+                 */
+                case "@":
+                    token = this.atRuleToken(c, startLine, startCol);
+                    break;
+
+                /*
+                 * Potential tokens:
+                 * - NOT
+                 * - CHAR
+                 */
+                case ":":
+                    token = this.notToken(c, startLine, startCol);
+                    break;
+
+                /*
+                 * Potential tokens:
+                 * - CDO
+                 * - CHAR
+                 */
+                case "<":
+                    token = this.htmlCommentStartToken(c, startLine, startCol);
+                    break;
+
+                /*
+                 * Potential tokens:
+                 * - IDENT
+                 * - CHAR
+                 */
+                case "\\":
+                    if (/[^\r\n\f]/.test(reader.peek())) {
+                        token = this.identOrFunctionToken(this.readEscape(c, true), startLine, startCol);
+                    } else {
+                        token = this.charToken(c, startLine, startCol);
+                    }
+                    break;
+
+                /*
+                 * Potential tokens:
+                 * - UNICODE_RANGE
+                 * - URL
+                 * - CHAR
+                 */
+                case "U":
+                case "u":
+                    if (reader.peek() === "+") {
+                        token = this.unicodeRangeToken(c, startLine, startCol);
+                        break;
+                    }
+                    /* falls through */
+                default:
+
+                    /*
+                     * Potential tokens:
+                     * - NUMBER
+                     * - DIMENSION
+                     * - LENGTH
+                     * - FREQ
+                     * - TIME
+                     * - EMS
+                     * - EXS
+                     * - ANGLE
+                     */
+                    if (isDigit(c)) {
+                        token = this.numberToken(c, startLine, startCol);
+                    } else
+
+                    /*
+                     * Potential tokens:
+                     * - S
+                     */
+                    if (isWhitespace(c)) {
+                        token = this.whitespaceToken(c, startLine, startCol);
+                    } else
+
+                    /*
+                     * Potential tokens:
+                     * - IDENT
+                     */
+                    if (isIdentStart(c)) {
+                        token = this.identOrFunctionToken(c, startLine, startCol);
+                    } else {
+                       /*
+                        * Potential tokens:
+                        * - CHAR
+                        * - PLUS
+                        */
+                        token = this.charToken(c, startLine, startCol);
+                    }
+
+            }
+
+            //make sure this token is wanted
+            //TODO: check channel
+            break;
+        }
+
+        if (!token && c === null) {
+            token = this.createToken(Tokens.EOF, null, startLine, startCol);
+        }
+
+        return token;
+    },
+
+    //-------------------------------------------------------------------------
+    // Methods to create tokens
+    //-------------------------------------------------------------------------
+
+    /**
+     * Produces a token based on available data and the current
+     * reader position information. This method is called by other
+     * private methods to create tokens and is never called directly.
+     * @param {int} tt The token type.
+     * @param {String} value The text value of the token.
+     * @param {int} startLine The beginning line for the character.
+     * @param {int} startCol The beginning column for the character.
+     * @param {Object} options (Optional) Specifies a channel property
+     *      to indicate that a different channel should be scanned
+     *      and/or a hide property indicating that the token should
+     *      be hidden.
+     * @return {Object} A token object.
+     * @method createToken
+     */
+    createToken: function(tt, value, startLine, startCol, options) {
+        var reader = this._reader;
+        options = options || {};
+
+        return {
+            value:      value,
+            type:       tt,
+            channel:    options.channel,
+            endChar:    options.endChar,
+            hide:       options.hide || false,
+            startLine:  startLine,
+            startCol:   startCol,
+            endLine:    reader.getLine(),
+            endCol:     reader.getCol()
+        };
+    },
+
+    //-------------------------------------------------------------------------
+    // Methods to create specific tokens
+    //-------------------------------------------------------------------------
+
+    /**
+     * Produces a token for any at-rule. If the at-rule is unknown, then
+     * the token is for a single "@" character.
+     * @param {String} first The first character for the token.
+     * @param {int} startLine The beginning line for the character.
+     * @param {int} startCol The beginning column for the character.
+     * @return {Object} A token object.
+     * @method atRuleToken
+     */
+    atRuleToken: function(first, startLine, startCol) {
+        var rule    = first,
+            reader  = this._reader,
+            tt      = Tokens.CHAR,
+            ident;
+
+        /*
+         * First, mark where we are. There are only four @ rules,
+         * so anything else is really just an invalid token.
+         * Basically, if this doesn't match one of the known @
+         * rules, just return '@' as an unknown token and allow
+         * parsing to continue after that point.
+         */
+        reader.mark();
+
+        //try to find the at-keyword
+        ident = this.readName();
+        rule = first + ident;
+        tt = Tokens.type(rule.toLowerCase());
+
+        //if it's not valid, use the first character only and reset the reader
+        if (tt === Tokens.CHAR || tt === Tokens.UNKNOWN) {
+            if (rule.length > 1) {
+                tt = Tokens.UNKNOWN_SYM;
+            } else {
+                tt = Tokens.CHAR;
+                rule = first;
+                reader.reset();
+            }
+        }
+
+        return this.createToken(tt, rule, startLine, startCol);
+    },
+
+    /**
+     * Produces a character token based on the given character
+     * and location in the stream. If there's a special (non-standard)
+     * token name, this is used; otherwise CHAR is used.
+     * @param {String} c The character for the token.
+     * @param {int} startLine The beginning line for the character.
+     * @param {int} startCol The beginning column for the character.
+     * @return {Object} A token object.
+     * @method charToken
+     */
+    charToken: function(c, startLine, startCol) {
+        var tt = Tokens.type(c);
+        var opts = {};
+
+        if (tt === -1) {
+            tt = Tokens.CHAR;
+        } else {
+            opts.endChar = Tokens[tt].endChar;
+        }
+
+        return this.createToken(tt, c, startLine, startCol, opts);
+    },
+
+    /**
+     * Produces a character token based on the given character
+     * and location in the stream. If there's a special (non-standard)
+     * token name, this is used; otherwise CHAR is used.
+     * @param {String} first The first character for the token.
+     * @param {int} startLine The beginning line for the character.
+     * @param {int} startCol The beginning column for the character.
+     * @return {Object} A token object.
+     * @method commentToken
+     */
+    commentToken: function(first, startLine, startCol) {
+        var comment = this.readComment(first);
+
+        return this.createToken(Tokens.COMMENT, comment, startLine, startCol);
+    },
+
+    /**
+     * Produces a comparison token based on the given character
+     * and location in the stream. The next character must be
+     * read and is already known to be an equals sign.
+     * @param {String} c The character for the token.
+     * @param {int} startLine The beginning line for the character.
+     * @param {int} startCol The beginning column for the character.
+     * @return {Object} A token object.
+     * @method comparisonToken
+     */
+    comparisonToken: function(c, startLine, startCol) {
+        var reader  = this._reader,
+            comparison  = c + reader.read(),
+            tt      = Tokens.type(comparison) || Tokens.CHAR;
+
+        return this.createToken(tt, comparison, startLine, startCol);
+    },
+
+    /**
+     * Produces a hash token based on the specified information. The
+     * first character provided is the pound sign (#) and then this
+     * method reads a name afterward.
+     * @param {String} first The first character (#) in the hash name.
+     * @param {int} startLine The beginning line for the character.
+     * @param {int} startCol The beginning column for the character.
+     * @return {Object} A token object.
+     * @method hashToken
+     */
+    hashToken: function(first, startLine, startCol) {
+        var name    = this.readName(first);
+
+        return this.createToken(Tokens.HASH, name, startLine, startCol);
+    },
+
+    /**
+     * Produces a CDO or CHAR token based on the specified information. The
+     * first character is provided and the rest is read by the function to determine
+     * the correct token to create.
+     * @param {String} first The first character in the token.
+     * @param {int} startLine The beginning line for the character.
+     * @param {int} startCol The beginning column for the character.
+     * @return {Object} A token object.
+     * @method htmlCommentStartToken
+     */
+    htmlCommentStartToken: function(first, startLine, startCol) {
+        var reader      = this._reader,
+            text        = first;
+
+        reader.mark();
+        text += reader.readCount(3);
+
+        if (text === "<!--") {
+            return this.createToken(Tokens.CDO, text, startLine, startCol);
+        } else {
+            reader.reset();
+            return this.charToken(first, startLine, startCol);
+        }
+    },
+
+    /**
+     * Produces a CDC or CHAR token based on the specified information. The
+     * first character is provided and the rest is read by the function to determine
+     * the correct token to create.
+     * @param {String} first The first character in the token.
+     * @param {int} startLine The beginning line for the character.
+     * @param {int} startCol The beginning column for the character.
+     * @return {Object} A token object.
+     * @method htmlCommentEndToken
+     */
+    htmlCommentEndToken: function(first, startLine, startCol) {
+        var reader      = this._reader,
+            text        = first;
+
+        reader.mark();
+        text += reader.readCount(2);
+
+        if (text === "-->") {
+            return this.createToken(Tokens.CDC, text, startLine, startCol);
+        } else {
+            reader.reset();
+            return this.charToken(first, startLine, startCol);
+        }
+    },
+
+    /**
+     * Produces an IDENT or FUNCTION token based on the specified information. The
+     * first character is provided and the rest is read by the function to determine
+     * the correct token to create.
+     * @param {String} first The first character in the identifier.
+     * @param {int} startLine The beginning line for the character.
+     * @param {int} startCol The beginning column for the character.
+     * @return {Object} A token object.
+     * @method identOrFunctionToken
+     */
+    identOrFunctionToken: function(first, startLine, startCol) {
+        var reader  = this._reader,
+            ident   = this.readName(first),
+            tt      = Tokens.IDENT,
+            uriFns  = ["url(", "url-prefix(", "domain("],
+            uri;
+
+        //if there's a left paren immediately after, it's a URI or function
+        if (reader.peek() === "(") {
+            ident += reader.read();
+            if (uriFns.indexOf(ident.toLowerCase()) > -1) {
+                reader.mark();
+                uri = this.readURI(ident);
+                if (uri === null) {
+                    //didn't find a valid URL or there's no closing paren
+                    reader.reset();
+                    tt = Tokens.FUNCTION;
+                } else {
+                    tt = Tokens.URI;
+                    ident = uri;
+                }
+            } else {
+                tt = Tokens.FUNCTION;
+            }
+        } else if (reader.peek() === ":") {  //might be an IE function
+
+            //IE-specific functions always being with progid:
+            if (ident.toLowerCase() === "progid") {
+                ident += reader.readTo("(");
+                tt = Tokens.IE_FUNCTION;
+            }
+        }
+
+        return this.createToken(tt, ident, startLine, startCol);
+    },
+
+    /**
+     * Produces an IMPORTANT_SYM or CHAR token based on the specified information. The
+     * first character is provided and the rest is read by the function to determine
+     * the correct token to create.
+     * @param {String} first The first character in the token.
+     * @param {int} startLine The beginning line for the character.
+     * @param {int} startCol The beginning column for the character.
+     * @return {Object} A token object.
+     * @method importantToken
+     */
+    importantToken: function(first, startLine, startCol) {
+        var reader      = this._reader,
+            important   = first,
+            tt          = Tokens.CHAR,
+            temp,
+            c;
+
+        reader.mark();
+        c = reader.read();
+
+        while (c) {
+
+            //there can be a comment in here
+            if (c === "/") {
+
+                //if the next character isn't a star, then this isn't a valid !important token
+                if (reader.peek() !== "*") {
+                    break;
+                } else {
+                    temp = this.readComment(c);
+                    if (temp === "") {    //broken!
+                        break;
+                    }
+                }
+            } else if (isWhitespace(c)) {
+                important += c + this.readWhitespace();
+            } else if (/i/i.test(c)) {
+                temp = reader.readCount(8);
+                if (/mportant/i.test(temp)) {
+                    important += c + temp;
+                    tt = Tokens.IMPORTANT_SYM;
+
+                }
+                break;  //we're done
+            } else {
+                break;
+            }
+
+            c = reader.read();
+        }
+
+        if (tt === Tokens.CHAR) {
+            reader.reset();
+            return this.charToken(first, startLine, startCol);
+        } else {
+            return this.createToken(tt, important, startLine, startCol);
+        }
+
+
+    },
+
+    /**
+     * Produces a NOT or CHAR token based on the specified information. The
+     * first character is provided and the rest is read by the function to determine
+     * the correct token to create.
+     * @param {String} first The first character in the token.
+     * @param {int} startLine The beginning line for the character.
+     * @param {int} startCol The beginning column for the character.
+     * @return {Object} A token object.
+     * @method notToken
+     */
+    notToken: function(first, startLine, startCol) {
+        var reader      = this._reader,
+            text        = first;
+
+        reader.mark();
+        text += reader.readCount(4);
+
+        if (text.toLowerCase() === ":not(") {
+            return this.createToken(Tokens.NOT, text, startLine, startCol);
+        } else {
+            reader.reset();
+            return this.charToken(first, startLine, startCol);
+        }
+    },
+
+    /**
+     * Produces a number token based on the given character
+     * and location in the stream. This may return a token of
+     * NUMBER, EMS, EXS, LENGTH, ANGLE, TIME, FREQ, DIMENSION,
+     * or PERCENTAGE.
+     * @param {String} first The first character for the token.
+     * @param {int} startLine The beginning line for the character.
+     * @param {int} startCol The beginning column for the character.
+     * @return {Object} A token object.
+     * @method numberToken
+     */
+    numberToken: function(first, startLine, startCol) {
+        var reader  = this._reader,
+            value   = this.readNumber(first),
+            ident,
+            tt      = Tokens.NUMBER,
+            c       = reader.peek();
+
+        if (isIdentStart(c)) {
+            ident = this.readName(reader.read());
+            value += ident;
+
+            if (/^em$|^ex$|^px$|^gd$|^rem$|^vw$|^vh$|^vmax$|^vmin$|^ch$|^cm$|^mm$|^in$|^pt$|^pc$/i.test(ident)) {
+                tt = Tokens.LENGTH;
+            } else if (/^deg|^rad$|^grad$|^turn$/i.test(ident)) {
+                tt = Tokens.ANGLE;
+            } else if (/^ms$|^s$/i.test(ident)) {
+                tt = Tokens.TIME;
+            } else if (/^hz$|^khz$/i.test(ident)) {
+                tt = Tokens.FREQ;
+            } else if (/^dpi$|^dpcm$/i.test(ident)) {
+                tt = Tokens.RESOLUTION;
+            } else {
+                tt = Tokens.DIMENSION;
+            }
+
+        } else if (c === "%") {
+            value += reader.read();
+            tt = Tokens.PERCENTAGE;
+        }
+
+        return this.createToken(tt, value, startLine, startCol);
+    },
+
+    /**
+     * Produces a string token based on the given character
+     * and location in the stream. Since strings may be indicated
+     * by single or double quotes, a failure to match starting
+     * and ending quotes results in an INVALID token being generated.
+     * The first character in the string is passed in and then
+     * the rest are read up to and including the final quotation mark.
+     * @param {String} first The first character in the string.
+     * @param {int} startLine The beginning line for the character.
+     * @param {int} startCol The beginning column for the character.
+     * @return {Object} A token object.
+     * @method stringToken
+     */
+    stringToken: function(first, startLine, startCol) {
+        var delim   = first,
+            string  = first,
+            reader  = this._reader,
+            tt      = Tokens.STRING,
+            c       = reader.read(),
+            i;
+
+        while (c) {
+            string += c;
+
+            if (c === "\\") {
+                c = reader.read();
+                if (c === null) {
+                    break; // premature EOF after backslash
+                } else if (/[^\r\n\f0-9a-f]/i.test(c)) {
+                    // single-character escape
+                    string += c;
+                } else {
+                    // read up to six hex digits
+                    for (i=0; isHexDigit(c) && i<6; i++) {
+                        string += c;
+                        c = reader.read();
+                    }
+                    // swallow trailing newline or space
+                    if (c === "\r" && reader.peek() === "\n") {
+                        string += c;
+                        c = reader.read();
+                    }
+                    if (isWhitespace(c)) {
+                        string += c;
+                    } else {
+                        // This character is null or not part of the escape;
+                        // jump back to the top to process it.
+                        continue;
+                    }
+                }
+            } else if (c === delim) {
+                break; // delimiter found.
+            } else if (isNewLine(reader.peek())) {
+                // newline without an escapement: it's an invalid string
+                tt = Tokens.INVALID;
+                break;
+            }
+            c = reader.read();
+        }
+
+        //if c is null, that means we're out of input and the string was never closed
+        if (c === null) {
+            tt = Tokens.INVALID;
+        }
+
+        return this.createToken(tt, string, startLine, startCol);
+    },
+
+    unicodeRangeToken: function(first, startLine, startCol) {
+        var reader  = this._reader,
+            value   = first,
+            temp,
+            tt      = Tokens.CHAR;
+
+        //then it should be a unicode range
+        if (reader.peek() === "+") {
+            reader.mark();
+            value += reader.read();
+            value += this.readUnicodeRangePart(true);
+
+            //ensure there's an actual unicode range here
+            if (value.length === 2) {
+                reader.reset();
+            } else {
+
+                tt = Tokens.UNICODE_RANGE;
+
+                //if there's a ? in the first part, there can't be a second part
+                if (value.indexOf("?") === -1) {
+
+                    if (reader.peek() === "-") {
+                        reader.mark();
+                        temp = reader.read();
+                        temp += this.readUnicodeRangePart(false);
+
+                        //if there's not another value, back up and just take the first
+                        if (temp.length === 1) {
+                            reader.reset();
+                        } else {
+                            value += temp;
+                        }
+                    }
+
+                }
+            }
+        }
+
+        return this.createToken(tt, value, startLine, startCol);
+    },
+
+    /**
+     * Produces a S token based on the specified information. Since whitespace
+     * may have multiple characters, this consumes all whitespace characters
+     * into a single token.
+     * @param {String} first The first character in the token.
+     * @param {int} startLine The beginning line for the character.
+     * @param {int} startCol The beginning column for the character.
+     * @return {Object} A token object.
+     * @method whitespaceToken
+     */
+    whitespaceToken: function(first, startLine, startCol) {
+        var value   = first + this.readWhitespace();
+        return this.createToken(Tokens.S, value, startLine, startCol);
+    },
+
+
+    //-------------------------------------------------------------------------
+    // Methods to read values from the string stream
+    //-------------------------------------------------------------------------
+
+    readUnicodeRangePart: function(allowQuestionMark) {
+        var reader  = this._reader,
+            part = "",
+            c       = reader.peek();
+
+        //first read hex digits
+        while (isHexDigit(c) && part.length < 6) {
+            reader.read();
+            part += c;
+            c = reader.peek();
+        }
+
+        //then read question marks if allowed
+        if (allowQuestionMark) {
+            while (c === "?" && part.length < 6) {
+                reader.read();
+                part += c;
+                c = reader.peek();
+            }
+        }
+
+        //there can't be any other characters after this point
+
+        return part;
+    },
+
+    readWhitespace: function() {
+        var reader  = this._reader,
+            whitespace = "",
+            c       = reader.peek();
+
+        while (isWhitespace(c)) {
+            reader.read();
+            whitespace += c;
+            c = reader.peek();
+        }
+
+        return whitespace;
+    },
+    readNumber: function(first) {
+        var reader  = this._reader,
+            number  = first,
+            hasDot  = (first === "."),
+            c       = reader.peek();
+
+
+        while (c) {
+            if (isDigit(c)) {
+                number += reader.read();
+            } else if (c === ".") {
+                if (hasDot) {
+                    break;
+                } else {
+                    hasDot = true;
+                    number += reader.read();
+                }
+            } else {
+                break;
+            }
+
+            c = reader.peek();
+        }
+
+        return number;
+    },
+
+    // returns null w/o resetting reader if string is invalid.
+    readString: function() {
+        var token = this.stringToken(this._reader.read(), 0, 0);
+        return token.type === Tokens.INVALID ? null : token.value;
+    },
+
+    // returns null w/o resetting reader if URI is invalid.
+    readURI: function(first) {
+        var reader  = this._reader,
+            uri     = first,
+            inner   = "",
+            c       = reader.peek();
+
+        //skip whitespace before
+        while (c && isWhitespace(c)) {
+            reader.read();
+            c = reader.peek();
+        }
+
+        //it's a string
+        if (c === "'" || c === "\"") {
+            inner = this.readString();
+            if (inner !== null) {
+                inner = PropertyValuePart.parseString(inner);
+            }
+        } else {
+            inner = this.readUnquotedURL();
+        }
+
+        c = reader.peek();
+
+        //skip whitespace after
+        while (c && isWhitespace(c)) {
+            reader.read();
+            c = reader.peek();
+        }
+
+        //if there was no inner value or the next character isn't closing paren, it's not a URI
+        if (inner === null || c !== ")") {
+            uri = null;
+        } else {
+            // Ensure argument to URL is always double-quoted
+            // (This simplifies later processing in PropertyValuePart.)
+            uri += PropertyValuePart.serializeString(inner) + reader.read();
+        }
+
+        return uri;
+    },
+    // This method never fails, although it may return an empty string.
+    readUnquotedURL: function(first) {
+        var reader  = this._reader,
+            url     = first || "",
+            c;
+
+        for (c = reader.peek(); c; c = reader.peek()) {
+            // Note that the grammar at
+            // https://www.w3.org/TR/CSS2/grammar.html#scanner
+            // incorrectly includes the backslash character in the
+            // `url` production, although it is correctly omitted in
+            // the `baduri1` production.
+            if (nonascii.test(c) || /^[\-!#$%&*-\[\]-~]$/.test(c)) {
+                url += c;
+                reader.read();
+            } else if (c === "\\") {
+                if (/^[^\r\n\f]$/.test(reader.peek(2))) {
+                    url += this.readEscape(reader.read(), true);
+                } else {
+                    break; // bad escape sequence.
+                }
+            } else {
+                break; // bad character
+            }
+        }
+
+        return url;
+    },
+
+    readName: function(first) {
+        var reader  = this._reader,
+            ident   = first || "",
+            c;
+
+        for (c = reader.peek(); c; c = reader.peek()) {
+            if (c === "\\") {
+                if (/^[^\r\n\f]$/.test(reader.peek(2))) {
+                    ident += this.readEscape(reader.read(), true);
+                } else {
+                    // Bad escape sequence.
+                    break;
+                }
+            } else if (isNameChar(c)) {
+                ident += reader.read();
+            } else {
+                break;
+            }
+        }
+
+        return ident;
+    },
+
+    readEscape: function(first, unescape) {
+        var reader  = this._reader,
+            cssEscape = first || "",
+            i       = 0,
+            c       = reader.peek();
+
+        if (isHexDigit(c)) {
+            do {
+                cssEscape += reader.read();
+                c = reader.peek();
+            } while (c && isHexDigit(c) && ++i < 6);
+        }
+
+        if (cssEscape.length === 1) {
+            if (/^[^\r\n\f0-9a-f]$/.test(c)) {
+                reader.read();
+                if (unescape) {
+                    return c;
+                }
+            } else {
+                // We should never get here (readName won't call readEscape
+                // if the escape sequence is bad).
+                throw new Error("Bad escape sequence.");
+            }
+        } else if (c === "\r") {
+            reader.read();
+            if (reader.peek() === "\n") {
+                c += reader.read();
+            }
+        } else if (/^[ \t\n\f]$/.test(c)) {
+            reader.read();
+        } else {
+            c = "";
+        }
+
+        if (unescape) {
+            var cp = parseInt(cssEscape.slice(first.length), 16);
+            return String.fromCodePoint ? String.fromCodePoint(cp) :
+                String.fromCharCode(cp);
+        }
+        return cssEscape + c;
+    },
+
+    readComment: function(first) {
+        var reader  = this._reader,
+            comment = first || "",
+            c       = reader.read();
+
+        if (c === "*") {
+            while (c) {
+                comment += c;
+
+                //look for end of comment
+                if (comment.length > 2 && c === "*" && reader.peek() === "/") {
+                    comment += reader.read();
+                    break;
+                }
+
+                c = reader.read();
+            }
+
+            return comment;
+        } else {
+            return "";
+        }
+
+    }
+});
+
+},{"../util/TokenStreamBase":27,"./PropertyValuePart":11,"./Tokens":18}],18:[function(require,module,exports){
+"use strict";
+
+var Tokens = module.exports = [
+
+    /*
+     * The following token names are defined in CSS3 Grammar: https://www.w3.org/TR/css3-syntax/#lexical
+     */
+
+    // HTML-style comments
+    { name: "CDO" },
+    { name: "CDC" },
+
+    // ignorables
+    { name: "S", whitespace: true/*, channel: "ws"*/ },
+    { name: "COMMENT", comment: true, hide: true, channel: "comment" },
+
+    // attribute equality
+    { name: "INCLUDES", text: "~=" },
+    { name: "DASHMATCH", text: "|=" },
+    { name: "PREFIXMATCH", text: "^=" },
+    { name: "SUFFIXMATCH", text: "$=" },
+    { name: "SUBSTRINGMATCH", text: "*=" },
+
+    // identifier types
+    { name: "STRING" },
+    { name: "IDENT" },
+    { name: "HASH" },
+
+    // at-keywords
+    { name: "IMPORT_SYM", text: "@import" },
+    { name: "PAGE_SYM", text: "@page" },
+    { name: "MEDIA_SYM", text: "@media" },
+    { name: "FONT_FACE_SYM", text: "@font-face" },
+    { name: "CHARSET_SYM", text: "@charset" },
+    { name: "NAMESPACE_SYM", text: "@namespace" },
+    { name: "SUPPORTS_SYM", text: "@supports" },
+    { name: "VIEWPORT_SYM", text: ["@viewport", "@-ms-viewport", "@-o-viewport"] },
+    { name: "DOCUMENT_SYM", text: ["@document", "@-moz-document"] },
+    { name: "UNKNOWN_SYM" },
+    //{ name: "ATKEYWORD"},
+
+    // CSS3 animations
+    { name: "KEYFRAMES_SYM", text: [ "@keyframes", "@-webkit-keyframes", "@-moz-keyframes", "@-o-keyframes" ] },
+
+    // important symbol
+    { name: "IMPORTANT_SYM" },
+
+    // measurements
+    { name: "LENGTH" },
+    { name: "ANGLE" },
+    { name: "TIME" },
+    { name: "FREQ" },
+    { name: "DIMENSION" },
+    { name: "PERCENTAGE" },
+    { name: "NUMBER" },
+
+    // functions
+    { name: "URI" },
+    { name: "FUNCTION" },
+
+    // Unicode ranges
+    { name: "UNICODE_RANGE" },
+
+    /*
+     * The following token names are defined in CSS3 Selectors: https://www.w3.org/TR/css3-selectors/#selector-syntax
+     */
+
+    // invalid string
+    { name: "INVALID" },
+
+    // combinators
+    { name: "PLUS", text: "+" },
+    { name: "GREATER", text: ">" },
+    { name: "COMMA", text: "," },
+    { name: "TILDE", text: "~" },
+
+    // modifier
+    { name: "NOT" },
+
+    /*
+     * Defined in CSS3 Paged Media
+     */
+    { name: "TOPLEFTCORNER_SYM", text: "@top-left-corner" },
+    { name: "TOPLEFT_SYM", text: "@top-left" },
+    { name: "TOPCENTER_SYM", text: "@top-center" },
+    { name: "TOPRIGHT_SYM", text: "@top-right" },
+    { name: "TOPRIGHTCORNER_SYM", text: "@top-right-corner" },
+    { name: "BOTTOMLEFTCORNER_SYM", text: "@bottom-left-corner" },
+    { name: "BOTTOMLEFT_SYM", text: "@bottom-left" },
+    { name: "BOTTOMCENTER_SYM", text: "@bottom-center" },
+    { name: "BOTTOMRIGHT_SYM", text: "@bottom-right" },
+    { name: "BOTTOMRIGHTCORNER_SYM", text: "@bottom-right-corner" },
+    { name: "LEFTTOP_SYM", text: "@left-top" },
+    { name: "LEFTMIDDLE_SYM", text: "@left-middle" },
+    { name: "LEFTBOTTOM_SYM", text: "@left-bottom" },
+    { name: "RIGHTTOP_SYM", text: "@right-top" },
+    { name: "RIGHTMIDDLE_SYM", text: "@right-middle" },
+    { name: "RIGHTBOTTOM_SYM", text: "@right-bottom" },
+
+    /*
+     * The following token names are defined in CSS3 Media Queries: https://www.w3.org/TR/css3-mediaqueries/#syntax
+     */
+    /*{ name: "MEDIA_ONLY", state: "media"},
+    { name: "MEDIA_NOT", state: "media"},
+    { name: "MEDIA_AND", state: "media"},*/
+    { name: "RESOLUTION", state: "media" },
+
+    /*
+     * The following token names are not defined in any CSS specification but are used by the lexer.
+     */
+
+    // not a real token, but useful for stupid IE filters
+    { name: "IE_FUNCTION" },
+
+    // part of CSS3 grammar but not the Flex code
+    { name: "CHAR" },
+
+    // TODO: Needed?
+    // Not defined as tokens, but might as well be
+    {
+        name: "PIPE",
+        text: "|"
+    },
+    {
+        name: "SLASH",
+        text: "/"
+    },
+    {
+        name: "MINUS",
+        text: "-"
+    },
+    {
+        name: "STAR",
+        text: "*"
+    },
+
+    {
+        name: "LBRACE",
+        endChar: "}",
+        text: "{"
+    },
+    {
+        name: "RBRACE",
+        text: "}"
+    },
+    {
+        name: "LBRACKET",
+        endChar: "]",
+        text: "["
+    },
+    {
+        name: "RBRACKET",
+        text: "]"
+    },
+    {
+        name: "EQUALS",
+        text: "="
+    },
+    {
+        name: "COLON",
+        text: ":"
+    },
+    {
+        name: "SEMICOLON",
+        text: ";"
+    },
+    {
+        name: "LPAREN",
+        endChar: ")",
+        text: "("
+    },
+    {
+        name: "RPAREN",
+        text: ")"
+    },
+    {
+        name: "DOT",
+        text: "."
+    }
+];
+
+(function() {
+    var nameMap = [],
+        typeMap = Object.create(null);
+
+    Tokens.UNKNOWN = -1;
+    Tokens.unshift({ name:"EOF" });
+    for (var i=0, len = Tokens.length; i < len; i++) {
+        nameMap.push(Tokens[i].name);
+        Tokens[Tokens[i].name] = i;
+        if (Tokens[i].text) {
+            if (Tokens[i].text instanceof Array) {
+                for (var j=0; j < Tokens[i].text.length; j++) {
+                    typeMap[Tokens[i].text[j]] = i;
+                }
+            } else {
+                typeMap[Tokens[i].text] = i;
+            }
+        }
+    }
+
+    Tokens.name = function(tt) {
+        return nameMap[tt];
+    };
+
+    Tokens.type = function(c) {
+        return typeMap[c] || -1;
+    };
+})();
+
+},{}],19:[function(require,module,exports){
+"use strict";
+
+/* exported Validation */
+
+var Matcher = require("./Matcher");
+var Properties = require("./Properties");
+var ValidationTypes = require("./ValidationTypes");
+var ValidationError = require("./ValidationError");
+var PropertyValueIterator = require("./PropertyValueIterator");
+
+var Validation = module.exports = {
+
+    validate: function(property, value) {
+
+        //normalize name
+        var name        = property.toString().toLowerCase(),
+            expression  = new PropertyValueIterator(value),
+            spec        = Properties[name],
+            part;
+
+        if (!spec) {
+            if (name.indexOf("-") !== 0) {    //vendor prefixed are ok
+                throw new ValidationError("Unknown property '" + property + "'.", property.line, property.col);
+            }
+        } else if (typeof spec !== "number") {
+
+            // All properties accept some CSS-wide values.
+            // https://drafts.csswg.org/css-values-3/#common-keywords
+            if (ValidationTypes.isAny(expression, "inherit | initial | unset")) {
+                if (expression.hasNext()) {
+                    part = expression.next();
+                    throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+                }
+                return;
+            }
+
+            // Property-specific validation.
+            this.singleProperty(spec, expression);
+
+        }
+
+    },
+
+    singleProperty: function(types, expression) {
+
+        var result      = false,
+            value       = expression.value,
+            part;
+
+        result = Matcher.parse(types).match(expression);
+
+        if (!result) {
+            if (expression.hasNext() && !expression.isFirst()) {
+                part = expression.peek();
+                throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+            } else {
+                throw new ValidationError("Expected (" + ValidationTypes.describe(types) + ") but found '" + value + "'.", value.line, value.col);
+            }
+        } else if (expression.hasNext()) {
+            part = expression.next();
+            throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
+        }
+
+    }
+
+};
+
+},{"./Matcher":3,"./Properties":7,"./PropertyValueIterator":10,"./ValidationError":20,"./ValidationTypes":21}],20:[function(require,module,exports){
+"use strict";
+
+module.exports = ValidationError;
+
+/**
+ * Type to use when a validation error occurs.
+ * @class ValidationError
+ * @namespace parserlib.util
+ * @constructor
+ * @param {String} message The error message.
+ * @param {int} line The line at which the error occurred.
+ * @param {int} col The column at which the error occurred.
+ */
+function ValidationError(message, line, col) {
+
+    /**
+     * The column at which the error occurred.
+     * @type int
+     * @property col
+     */
+    this.col = col;
+
+    /**
+     * The line at which the error occurred.
+     * @type int
+     * @property line
+     */
+    this.line = line;
+
+    /**
+     * The text representation of the unit.
+     * @type String
+     * @property text
+     */
+    this.message = message;
+
+}
+
+//inherit from Error
+ValidationError.prototype = new Error();
+
+},{}],21:[function(require,module,exports){
+"use strict";
+
+var ValidationTypes = module.exports;
+
+var Matcher = require("./Matcher");
+
+function copy(to, from) {
+    Object.keys(from).forEach(function(prop) {
+        to[prop] = from[prop];
+    });
+}
+copy(ValidationTypes, {
+
+    isLiteral: function (part, literals) {
+        var text = part.text.toString().toLowerCase(),
+            args = literals.split(" | "),
+            i, len, found = false;
+
+        for (i=0, len=args.length; i < len && !found; i++) {
+            if (args[i].charAt(0) === "<") {
+                found = this.simple[args[i]](part);
+            } else if (args[i].slice(-2) === "()") {
+                found = (part.type === "function" &&
+                         part.name === args[i].slice(0, -2));
+            } else if (text === args[i].toLowerCase()) {
+                found = true;
+            }
+        }
+
+        return found;
+    },
+
+    isSimple: function(type) {
+        return Boolean(this.simple[type]);
+    },
+
+    isComplex: function(type) {
+        return Boolean(this.complex[type]);
+    },
+
+    describe: function(type) {
+        if (this.complex[type] instanceof Matcher) {
+            return this.complex[type].toString(0);
+        }
+        return type;
+    },
+
+    /**
+     * Determines if the next part(s) of the given expression
+     * are any of the given types.
+     */
+    isAny: function (expression, types) {
+        var args = types.split(" | "),
+            i, len, found = false;
+
+        for (i=0, len=args.length; i < len && !found && expression.hasNext(); i++) {
+            found = this.isType(expression, args[i]);
+        }
+
+        return found;
+    },
+
+    /**
+     * Determines if the next part(s) of the given expression
+     * are one of a group.
+     */
+    isAnyOfGroup: function(expression, types) {
+        var args = types.split(" || "),
+            i, len, found = false;
+
+        for (i=0, len=args.length; i < len && !found; i++) {
+            found = this.isType(expression, args[i]);
+        }
+
+        return found ? args[i-1] : false;
+    },
+
+    /**
+     * Determines if the next part(s) of the given expression
+     * are of a given type.
+     */
+    isType: function (expression, type) {
+        var part = expression.peek(),
+            result = false;
+
+        if (type.charAt(0) !== "<") {
+            result = this.isLiteral(part, type);
+            if (result) {
+                expression.next();
+            }
+        } else if (this.simple[type]) {
+            result = this.simple[type](part);
+            if (result) {
+                expression.next();
+            }
+        } else if (this.complex[type] instanceof Matcher) {
+            result = this.complex[type].match(expression);
+        } else {
+            result = this.complex[type](expression);
+        }
+
+        return result;
+    },
+
+
+    simple: {
+        __proto__: null,
+
+        "<absolute-size>":
+            "xx-small | x-small | small | medium | large | x-large | xx-large",
+
+        "<animateable-feature>":
+            "scroll-position | contents | <animateable-feature-name>",
+
+        "<animateable-feature-name>": function(part) {
+            return this["<ident>"](part) &&
+                !/^(unset|initial|inherit|will-change|auto|scroll-position|contents)$/i.test(part);
+        },
+
+        "<angle>": function(part) {
+            return part.type === "angle";
+        },
+
+        "<attachment>": "scroll | fixed | local",
+
+        "<attr>": "attr()",
+
+        // inset() = inset( <shape-arg>{1,4} [round <border-radius>]? )
+        // circle() = circle( [<shape-radius>]? [at <position>]? )
+        // ellipse() = ellipse( [<shape-radius>{2}]? [at <position>]? )
+        // polygon() = polygon( [<fill-rule>,]? [<shape-arg> <shape-arg>]# )
+        "<basic-shape>": "inset() | circle() | ellipse() | polygon()",
+
+        "<bg-image>": "<image> | <gradient> | none",
+
+        "<border-style>":
+            "none | hidden | dotted | dashed | solid | double | groove | " +
+            "ridge | inset | outset",
+
+        "<border-width>": "<length> | thin | medium | thick",
+
+        "<box>": "padding-box | border-box | content-box",
+
+        "<clip-source>": "<uri>",
+
+        "<color>": function(part) {
+            return part.type === "color" || String(part) === "transparent" || String(part) === "currentColor";
+        },
+
+        // The SVG <color> spec doesn't include "currentColor" or "transparent" as a color.
+        "<color-svg>": function(part) {
+            return part.type === "color";
+        },
+
+        "<content>": "content()",
+
+        // https://www.w3.org/TR/css3-sizing/#width-height-keywords
+        "<content-sizing>":
+            "fill-available | -moz-available | -webkit-fill-available | " +
+            "max-content | -moz-max-content | -webkit-max-content | " +
+            "min-content | -moz-min-content | -webkit-min-content | " +
+            "fit-content | -moz-fit-content | -webkit-fit-content",
+
+        "<feature-tag-value>": function(part) {
+            return part.type === "function" && /^[A-Z0-9]{4}$/i.test(part);
+        },
+
+        // custom() isn't actually in the spec
+        "<filter-function>":
+            "blur() | brightness() | contrast() | custom() | " +
+            "drop-shadow() | grayscale() | hue-rotate() | invert() | " +
+            "opacity() | saturate() | sepia()",
+
+        "<flex-basis>": "<width>",
+
+        "<flex-direction>": "row | row-reverse | column | column-reverse",
+
+        "<flex-grow>": "<number>",
+
+        "<flex-shrink>": "<number>",
+
+        "<flex-wrap>": "nowrap | wrap | wrap-reverse",
+
+        "<font-size>":
+            "<absolute-size> | <relative-size> | <length> | <percentage>",
+
+        "<font-stretch>":
+            "normal | ultra-condensed | extra-condensed | condensed | " +
+            "semi-condensed | semi-expanded | expanded | extra-expanded | " +
+            "ultra-expanded",
+
+        "<font-style>": "normal | italic | oblique",
+
+        "<font-variant-caps>":
+            "small-caps | all-small-caps | petite-caps | all-petite-caps | " +
+            "unicase | titling-caps",
+
+        "<font-variant-css21>": "normal | small-caps",
+
+        "<font-weight>":
+            "normal | bold | bolder | lighter | " +
+            "100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900",
+
+        "<generic-family>":
+            "serif | sans-serif | cursive | fantasy | monospace",
+
+        "<geometry-box>": "<shape-box> | fill-box | stroke-box | view-box",
+
+        "<glyph-angle>": function(part) {
+            return part.type === "angle" && part.units === "deg";
+        },
+
+        "<gradient>": function(part) {
+            return part.type === "function" && /^(?:\-(?:ms|moz|o|webkit)\-)?(?:repeating\-)?(?:radial\-|linear\-)?gradient/i.test(part);
+        },
+
+        "<icccolor>":
+            "cielab() | cielch() | cielchab() | " +
+            "icc-color() | icc-named-color()",
+
+        //any identifier
+        "<ident>": function(part) {
+            return part.type === "identifier" || part.wasIdent;
+        },
+
+        "<ident-not-generic-family>": function(part) {
+            return this["<ident>"](part) && !this["<generic-family>"](part);
+        },
+
+        "<image>": "<uri>",
+
+        "<integer>": function(part) {
+            return part.type === "integer";
+        },
+
+        "<length>": function(part) {
+            if (part.type === "function" && /^(?:\-(?:ms|moz|o|webkit)\-)?calc/i.test(part)) {
+                return true;
+            } else {
+                return part.type === "length" || part.type === "number" || part.type === "integer" || String(part) === "0";
+            }
+        },
+
+        "<line>": function(part) {
+            return part.type === "integer";
+        },
+
+        "<line-height>": "<number> | <length> | <percentage> | normal",
+
+        "<margin-width>": "<length> | <percentage> | auto",
+
+        "<miterlimit>": function(part) {
+            return this["<number>"](part) && part.value >= 1;
+        },
+
+        "<nonnegative-length-or-percentage>": function(part) {
+            return (this["<length>"](part) || this["<percentage>"](part)) &&
+                (String(part) === "0" || part.type === "function" || (part.value) >= 0);
+        },
+
+        "<nonnegative-number-or-percentage>": function(part) {
+            return (this["<number>"](part) || this["<percentage>"](part)) &&
+                (String(part) === "0" || part.type === "function" || (part.value) >= 0);
+        },
+
+        "<number>": function(part) {
+            return part.type === "number" || this["<integer>"](part);
+        },
+
+        "<opacity-value>": function(part) {
+            return this["<number>"](part) && part.value >= 0 && part.value <= 1;
+        },
+
+        "<padding-width>": "<nonnegative-length-or-percentage>",
+
+        "<percentage>": function(part) {
+            return part.type === "percentage" || String(part) === "0";
+        },
+
+        "<relative-size>": "smaller | larger",
+
+        "<shape>": "rect() | inset-rect()",
+
+        "<shape-box>": "<box> | margin-box",
+
+        "<single-animation-direction>":
+            "normal | reverse | alternate | alternate-reverse",
+
+        "<single-animation-name>": function(part) {
+            return this["<ident>"](part) &&
+                /^-?[a-z_][-a-z0-9_]+$/i.test(part) &&
+                !/^(none|unset|initial|inherit)$/i.test(part);
+        },
+
+        "<string>": function(part) {
+            return part.type === "string";
+        },
+
+        "<time>": function(part) {
+            return part.type === "time";
+        },
+
+        "<uri>": function(part) {
+            return part.type === "uri";
+        },
+
+        "<width>": "<margin-width>"
+    },
+
+    complex: {
+        __proto__: null,
+
+        "<azimuth>":
+            "<angle>" +
+            " | " +
+            "[ [ left-side | far-left | left | center-left | center | " +
+            "center-right | right | far-right | right-side ] || behind ]" +
+            " | "+
+            "leftwards | rightwards",
+
+        "<bg-position>": "<position>#",
+
+        "<bg-size>":
+            "[ <length> | <percentage> | auto ]{1,2} | cover | contain",
+
+        "<border-image-slice>":
+        // [<number> | <percentage>]{1,4} && fill?
+        // *but* fill can appear between any of the numbers
+        Matcher.many([true /* first element is required */],
+                     Matcher.cast("<nonnegative-number-or-percentage>"),
+                     Matcher.cast("<nonnegative-number-or-percentage>"),
+                     Matcher.cast("<nonnegative-number-or-percentage>"),
+                     Matcher.cast("<nonnegative-number-or-percentage>"),
+                     "fill"),
+
+        "<border-radius>":
+            "<nonnegative-length-or-percentage>{1,4} " +
+            "[ / <nonnegative-length-or-percentage>{1,4} ]?",
+
+        "<box-shadow>": "none | <shadow>#",
+
+        "<clip-path>": "<basic-shape> || <geometry-box>",
+
+        "<dasharray>":
+        // "list of comma and/or white space separated <length>s and
+        // <percentage>s".  There is a non-negative constraint.
+        Matcher.cast("<nonnegative-length-or-percentage>")
+            .braces(1, Infinity, "#", Matcher.cast(",").question()),
+
+        "<family-name>":
+            // <string> | <IDENT>+
+            "<string> | <ident-not-generic-family> <ident>*",
+
+        "<filter-function-list>": "[ <filter-function> | <uri> ]+",
+
+        // https://www.w3.org/TR/2014/WD-css-flexbox-1-20140325/#flex-property
+        "<flex>":
+            "none | [ <flex-grow> <flex-shrink>? || <flex-basis> ]",
+
+        "<font-family>": "[ <generic-family> | <family-name> ]#",
+
+        "<font-shorthand>":
+            "[ <font-style> || <font-variant-css21> || " +
+            "<font-weight> || <font-stretch> ]? <font-size> " +
+            "[ / <line-height> ]? <font-family>",
+
+        "<font-variant-alternates>":
+            // stylistic(<feature-value-name>)
+            "stylistic() || " +
+            "historical-forms || " +
+            // styleset(<feature-value-name> #)
+            "styleset() || " +
+            // character-variant(<feature-value-name> #)
+            "character-variant() || " +
+            // swash(<feature-value-name>)
+            "swash() || " +
+            // ornaments(<feature-value-name>)
+            "ornaments() || " +
+            // annotation(<feature-value-name>)
+            "annotation()",
+
+        "<font-variant-ligatures>":
+            // <common-lig-values>
+            "[ common-ligatures | no-common-ligatures ] || " +
+            // <discretionary-lig-values>
+            "[ discretionary-ligatures | no-discretionary-ligatures ] || " +
+            // <historical-lig-values>
+            "[ historical-ligatures | no-historical-ligatures ] || " +
+            // <contextual-alt-values>
+            "[ contextual | no-contextual ]",
+
+        "<font-variant-numeric>":
+            // <numeric-figure-values>
+            "[ lining-nums | oldstyle-nums ] || " +
+            // <numeric-spacing-values>
+            "[ proportional-nums | tabular-nums ] || " +
+            // <numeric-fraction-values>
+            "[ diagonal-fractions | stacked-fractions ] || " +
+            "ordinal || slashed-zero",
+
+        "<font-variant-east-asian>":
+            // <east-asian-variant-values>
+            "[ jis78 | jis83 | jis90 | jis04 | simplified | traditional ] || " +
+            // <east-asian-width-values>
+            "[ full-width | proportional-width ] || " +
+            "ruby",
+
+        // Note that <color> here is "as defined in the SVG spec", which
+        // is more restrictive that the <color> defined in the CSS spec.
+        // none | currentColor | <color> [<icccolor>]? |
+        // <funciri> [ none | currentColor | <color> [<icccolor>]? ]?
+        "<paint>": "<paint-basic> | <uri> <paint-basic>?",
+
+        // Helper definition for <paint> above.
+        "<paint-basic>": "none | currentColor | <color-svg> <icccolor>?",
+
+        "<position>":
+            // Because our `alt` combinator is ordered, we need to test these
+            // in order from longest possible match to shortest.
+            "[ center | [ left | right ] [ <percentage> | <length> ]? ] && " +
+            "[ center | [ top | bottom ] [ <percentage> | <length> ]? ]" +
+            " | " +
+            "[ left | center | right | <percentage> | <length> ] " +
+            "[ top | center | bottom | <percentage> | <length> ]" +
+            " | " +
+            "[ left | center | right | top | bottom | <percentage> | <length> ]",
+
+        "<repeat-style>":
+            "repeat-x | repeat-y | [ repeat | space | round | no-repeat ]{1,2}",
+
+        "<shadow>":
+        //inset? && [ <length>{2,4} && <color>? ]
+        Matcher.many([true /* length is required */],
+                     Matcher.cast("<length>").braces(2, 4), "inset", "<color>"),
+
+        "<text-decoration-color>":
+           "<color>",
+
+        "<text-decoration-line>":
+            "none | [ underline || overline || line-through || blink ]",
+
+        "<text-decoration-style>":
+            "solid | double | dotted | dashed | wavy",
+
+        "<will-change>":
+            "auto | <animateable-feature>#",
+
+        "<x-one-radius>":
+            //[ <length> | <percentage> ] [ <length> | <percentage> ]?
+            "[ <length> | <percentage> ]{1,2}"
+    }
+});
+
+Object.keys(ValidationTypes.simple).forEach(function(nt) {
+    var rule = ValidationTypes.simple[nt];
+    if (typeof rule === "string") {
+        ValidationTypes.simple[nt] = function(part) {
+            return ValidationTypes.isLiteral(part, rule);
+        };
+    }
+});
+
+Object.keys(ValidationTypes.complex).forEach(function(nt) {
+    var rule = ValidationTypes.complex[nt];
+    if (typeof rule === "string") {
+        ValidationTypes.complex[nt] = Matcher.parse(rule);
+    }
+});
+
+// Because this is defined relative to other complex validation types,
+// we need to define it *after* the rest of the types are initialized.
+ValidationTypes.complex["<font-variant>"] =
+    Matcher.oror({ expand: "<font-variant-ligatures>" },
+                 { expand: "<font-variant-alternates>" },
+                 "<font-variant-caps>",
+                 { expand: "<font-variant-numeric>" },
+                 { expand: "<font-variant-east-asian>" });
+
+},{"./Matcher":3}],22:[function(require,module,exports){
+"use strict";
+
+module.exports = {
+    Colors            : require("./Colors"),
+    Combinator        : require("./Combinator"),
+    Parser            : require("./Parser"),
+    PropertyName      : require("./PropertyName"),
+    PropertyValue     : require("./PropertyValue"),
+    PropertyValuePart : require("./PropertyValuePart"),
+    Matcher           : require("./Matcher"),
+    MediaFeature      : require("./MediaFeature"),
+    MediaQuery        : require("./MediaQuery"),
+    Selector          : require("./Selector"),
+    SelectorPart      : require("./SelectorPart"),
+    SelectorSubPart   : require("./SelectorSubPart"),
+    Specificity       : require("./Specificity"),
+    TokenStream       : require("./TokenStream"),
+    Tokens            : require("./Tokens"),
+    ValidationError   : require("./ValidationError")
+};
+
+},{"./Colors":1,"./Combinator":2,"./Matcher":3,"./MediaFeature":4,"./MediaQuery":5,"./Parser":6,"./PropertyName":8,"./PropertyValue":9,"./PropertyValuePart":11,"./Selector":13,"./SelectorPart":14,"./SelectorSubPart":15,"./Specificity":16,"./TokenStream":17,"./Tokens":18,"./ValidationError":20}],23:[function(require,module,exports){
+"use strict";
+
+module.exports = EventTarget;
+
+/**
+ * A generic base to inherit from for any object
+ * that needs event handling.
+ * @class EventTarget
+ * @constructor
+ */
+function EventTarget() {
+
+    /**
+     * The array of listeners for various events.
+     * @type Object
+     * @property _listeners
+     * @private
+     */
+    this._listeners = Object.create(null);
+}
+
+EventTarget.prototype = {
+
+    //restore constructor
+    constructor: EventTarget,
+
+    /**
+     * Adds a listener for a given event type.
+     * @param {String} type The type of event to add a listener for.
+     * @param {Function} listener The function to call when the event occurs.
+     * @return {void}
+     * @method addListener
+     */
+    addListener: function(type, listener) {
+        if (!this._listeners[type]) {
+            this._listeners[type] = [];
+        }
+
+        this._listeners[type].push(listener);
+    },
+
+    /**
+     * Fires an event based on the passed-in object.
+     * @param {Object|String} event An object with at least a 'type' attribute
+     *      or a string indicating the event name.
+     * @return {void}
+     * @method fire
+     */
+    fire: function(event) {
+        if (typeof event === "string") {
+            event = { type: event };
+        }
+        if (typeof event.target !== "undefined") {
+            event.target = this;
+        }
+
+        if (typeof event.type === "undefined") {
+            throw new Error("Event object missing 'type' property.");
+        }
+
+        if (this._listeners[event.type]) {
+
+            //create a copy of the array and use that so listeners can't chane
+            var listeners = this._listeners[event.type].concat();
+            for (var i=0, len=listeners.length; i < len; i++) {
+                listeners[i].call(this, event);
+            }
+        }
+    },
+
+    /**
+     * Removes a listener for a given event type.
+     * @param {String} type The type of event to remove a listener from.
+     * @param {Function} listener The function to remove from the event.
+     * @return {void}
+     * @method removeListener
+     */
+    removeListener: function(type, listener) {
+        if (this._listeners[type]) {
+            var listeners = this._listeners[type];
+            for (var i=0, len=listeners.length; i < len; i++) {
+                if (listeners[i] === listener) {
+                    listeners.splice(i, 1);
+                    break;
+                }
+            }
+
+
+        }
+    }
+};
+
+},{}],24:[function(require,module,exports){
+"use strict";
+
+module.exports = StringReader;
+
+/**
+ * Convenient way to read through strings.
+ * @namespace parserlib.util
+ * @class StringReader
+ * @constructor
+ * @param {String} text The text to read.
+ */
+function StringReader(text) {
+
+    /**
+     * The input text with line endings normalized.
+     * @property _input
+     * @type String
+     * @private
+     */
+    this._input = text.replace(/(\r\n?|\n)/g, "\n");
+
+
+    /**
+     * The row for the character to be read next.
+     * @property _line
+     * @type int
+     * @private
+     */
+    this._line = 1;
+
+
+    /**
+     * The column for the character to be read next.
+     * @property _col
+     * @type int
+     * @private
+     */
+    this._col = 1;
+
+    /**
+     * The index of the character in the input to be read next.
+     * @property _cursor
+     * @type int
+     * @private
+     */
+    this._cursor = 0;
+}
+
+StringReader.prototype = {
+
+    // restore constructor
+    constructor: StringReader,
+
+    //-------------------------------------------------------------------------
+    // Position info
+    //-------------------------------------------------------------------------
+
+    /**
+     * Returns the column of the character to be read next.
+     * @return {int} The column of the character to be read next.
+     * @method getCol
+     */
+    getCol: function() {
+        return this._col;
+    },
+
+    /**
+     * Returns the row of the character to be read next.
+     * @return {int} The row of the character to be read next.
+     * @method getLine
+     */
+    getLine: function() {
+        return this._line;
+    },
+
+    /**
+     * Determines if you're at the end of the input.
+     * @return {Boolean} True if there's no more input, false otherwise.
+     * @method eof
+     */
+    eof: function() {
+        return this._cursor === this._input.length;
+    },
+
+    //-------------------------------------------------------------------------
+    // Basic reading
+    //-------------------------------------------------------------------------
+
+    /**
+     * Reads the next character without advancing the cursor.
+     * @param {int} count How many characters to look ahead (default is 1).
+     * @return {String} The next character or null if there is no next character.
+     * @method peek
+     */
+    peek: function(count) {
+        var c = null;
+        count = typeof count === "undefined" ? 1 : count;
+
+        // if we're not at the end of the input...
+        if (this._cursor < this._input.length) {
+
+            // get character and increment cursor and column
+            c = this._input.charAt(this._cursor + count - 1);
+        }
+
+        return c;
+    },
+
+    /**
+     * Reads the next character from the input and adjusts the row and column
+     * accordingly.
+     * @return {String} The next character or null if there is no next character.
+     * @method read
+     */
+    read: function() {
+        var c = null;
+
+        // if we're not at the end of the input...
+        if (this._cursor < this._input.length) {
+
+            // if the last character was a newline, increment row count
+            // and reset column count
+            if (this._input.charAt(this._cursor) === "\n") {
+                this._line++;
+                this._col=1;
+            } else {
+                this._col++;
+            }
+
+            // get character and increment cursor and column
+            c = this._input.charAt(this._cursor++);
+        }
+
+        return c;
+    },
+
+    //-------------------------------------------------------------------------
+    // Misc
+    //-------------------------------------------------------------------------
+
+    /**
+     * Saves the current location so it can be returned to later.
+     * @method mark
+     * @return {void}
+     */
+    mark: function() {
+        this._bookmark = {
+            cursor: this._cursor,
+            line:   this._line,
+            col:    this._col
+        };
+    },
+
+    reset: function() {
+        if (this._bookmark) {
+            this._cursor = this._bookmark.cursor;
+            this._line = this._bookmark.line;
+            this._col = this._bookmark.col;
+            delete this._bookmark;
+        }
+    },
+
+    //-------------------------------------------------------------------------
+    // Advanced reading
+    //-------------------------------------------------------------------------
+
+    /**
+     * Reads up to and including the given string. Throws an error if that
+     * string is not found.
+     * @param {String} pattern The string to read.
+     * @return {String} The string when it is found.
+     * @throws Error when the string pattern is not found.
+     * @method readTo
+     */
+    readTo: function(pattern) {
+
+        var buffer = "",
+            c;
+
+        /*
+         * First, buffer must be the same length as the pattern.
+         * Then, buffer must end with the pattern or else reach the
+         * end of the input.
+         */
+        while (buffer.length < pattern.length || buffer.lastIndexOf(pattern) !== buffer.length - pattern.length) {
+            c = this.read();
+            if (c) {
+                buffer += c;
+            } else {
+                throw new Error("Expected \"" + pattern + "\" at line " + this._line  + ", col " + this._col + ".");
+            }
+        }
+
+        return buffer;
+
+    },
+
+    /**
+     * Reads characters while each character causes the given
+     * filter function to return true. The function is passed
+     * in each character and either returns true to continue
+     * reading or false to stop.
+     * @param {Function} filter The function to read on each character.
+     * @return {String} The string made up of all characters that passed the
+     *      filter check.
+     * @method readWhile
+     */
+    readWhile: function(filter) {
+
+        var buffer = "",
+            c = this.peek();
+
+        while (c !== null && filter(c)) {
+            buffer += this.read();
+            c = this.peek();
+        }
+
+        return buffer;
+
+    },
+
+    /**
+     * Reads characters that match either text or a regular expression and
+     * returns those characters. If a match is found, the row and column
+     * are adjusted; if no match is found, the reader's state is unchanged.
+     * reading or false to stop.
+     * @param {String|RegExp} matcher If a string, then the literal string
+     *      value is searched for. If a regular expression, then any string
+     *      matching the pattern is search for.
+     * @return {String} The string made up of all characters that matched or
+     *      null if there was no match.
+     * @method readMatch
+     */
+    readMatch: function(matcher) {
+
+        var source = this._input.substring(this._cursor),
+            value = null;
+
+        // if it's a string, just do a straight match
+        if (typeof matcher === "string") {
+            if (source.slice(0, matcher.length) === matcher) {
+                value = this.readCount(matcher.length);
+            }
+        } else if (matcher instanceof RegExp) {
+            if (matcher.test(source)) {
+                value = this.readCount(RegExp.lastMatch.length);
+            }
+        }
+
+        return value;
+    },
+
+
+    /**
+     * Reads a given number of characters. If the end of the input is reached,
+     * it reads only the remaining characters and does not throw an error.
+     * @param {int} count The number of characters to read.
+     * @return {String} The string made up the read characters.
+     * @method readCount
+     */
+    readCount: function(count) {
+        var buffer = "";
+
+        while (count--) {
+            buffer += this.read();
+        }
+
+        return buffer;
+    }
+
+};
+
+},{}],25:[function(require,module,exports){
+"use strict";
+
+module.exports = SyntaxError;
+
+/**
+ * Type to use when a syntax error occurs.
+ * @class SyntaxError
+ * @namespace parserlib.util
+ * @constructor
+ * @param {String} message The error message.
+ * @param {int} line The line at which the error occurred.
+ * @param {int} col The column at which the error occurred.
+ */
+function SyntaxError(message, line, col) {
+    Error.call(this);
+    this.name = this.constructor.name;
+
+    /**
+     * The column at which the error occurred.
+     * @type int
+     * @property col
+     */
+    this.col = col;
+
+    /**
+     * The line at which the error occurred.
+     * @type int
+     * @property line
+     */
+    this.line = line;
+
+    /**
+     * The text representation of the unit.
+     * @type String
+     * @property text
+     */
+    this.message = message;
+
+}
+
+//inherit from Error
+SyntaxError.prototype = Object.create(Error.prototype); // jshint ignore:line
+SyntaxError.prototype.constructor = SyntaxError; // jshint ignore:line
+
+},{}],26:[function(require,module,exports){
+"use strict";
+
+module.exports = SyntaxUnit;
+
+/**
+ * Base type to represent a single syntactic unit.
+ * @class SyntaxUnit
+ * @namespace parserlib.util
+ * @constructor
+ * @param {String} text The text of the unit.
+ * @param {int} line The line of text on which the unit resides.
+ * @param {int} col The column of text on which the unit resides.
+ */
+function SyntaxUnit(text, line, col, type) {
+
+
+    /**
+     * The column of text on which the unit resides.
+     * @type int
+     * @property col
+     */
+    this.col = col;
+
+    /**
+     * The line of text on which the unit resides.
+     * @type int
+     * @property line
+     */
+    this.line = line;
+
+    /**
+     * The text representation of the unit.
+     * @type String
+     * @property text
+     */
+    this.text = text;
+
+    /**
+     * The type of syntax unit.
+     * @type int
+     * @property type
+     */
+    this.type = type;
+}
+
+/**
+ * Create a new syntax unit based solely on the given token.
+ * Convenience method for creating a new syntax unit when
+ * it represents a single token instead of multiple.
+ * @param {Object} token The token object to represent.
+ * @return {parserlib.util.SyntaxUnit} The object representing the token.
+ * @static
+ * @method fromToken
+ */
+SyntaxUnit.fromToken = function(token) {
+    return new SyntaxUnit(token.value, token.startLine, token.startCol);
+};
+
+SyntaxUnit.prototype = {
+
+    //restore constructor
+    constructor: SyntaxUnit,
+
+    /**
+     * Returns the text representation of the unit.
+     * @return {String} The text representation of the unit.
+     * @method valueOf
+     */
+    valueOf: function() {
+        return this.toString();
+    },
+
+    /**
+     * Returns the text representation of the unit.
+     * @return {String} The text representation of the unit.
+     * @method toString
+     */
+    toString: function() {
+        return this.text;
+    }
+
+};
+
+},{}],27:[function(require,module,exports){
+"use strict";
+
+module.exports = TokenStreamBase;
+
+var StringReader = require("./StringReader");
+var SyntaxError = require("./SyntaxError");
+
+/**
+ * Generic TokenStream providing base functionality.
+ * @class TokenStreamBase
+ * @namespace parserlib.util
+ * @constructor
+ * @param {String|StringReader} input The text to tokenize or a reader from
+ *      which to read the input.
+ */
+function TokenStreamBase(input, tokenData) {
+
+    /**
+     * The string reader for easy access to the text.
+     * @type StringReader
+     * @property _reader
+     * @private
+     */
+    this._reader = new StringReader(input ? input.toString() : "");
+
+    /**
+     * Token object for the last consumed token.
+     * @type Token
+     * @property _token
+     * @private
+     */
+    this._token = null;
+
+    /**
+     * The array of token information.
+     * @type Array
+     * @property _tokenData
+     * @private
+     */
+    this._tokenData = tokenData;
+
+    /**
+     * Lookahead token buffer.
+     * @type Array
+     * @property _lt
+     * @private
+     */
+    this._lt = [];
+
+    /**
+     * Lookahead token buffer index.
+     * @type int
+     * @property _ltIndex
+     * @private
+     */
+    this._ltIndex = 0;
+
+    this._ltIndexCache = [];
+}
+
+/**
+ * Accepts an array of token information and outputs
+ * an array of token data containing key-value mappings
+ * and matching functions that the TokenStream needs.
+ * @param {Array} tokens An array of token descriptors.
+ * @return {Array} An array of processed token data.
+ * @method createTokenData
+ * @static
+ */
+TokenStreamBase.createTokenData = function(tokens) {
+
+    var nameMap     = [],
+        typeMap     = Object.create(null),
+        tokenData     = tokens.concat([]),
+        i            = 0,
+        len            = tokenData.length+1;
+
+    tokenData.UNKNOWN = -1;
+    tokenData.unshift({ name:"EOF" });
+
+    for (; i < len; i++) {
+        nameMap.push(tokenData[i].name);
+        tokenData[tokenData[i].name] = i;
+        if (tokenData[i].text) {
+            typeMap[tokenData[i].text] = i;
+        }
+    }
+
+    tokenData.name = function(tt) {
+        return nameMap[tt];
+    };
+
+    tokenData.type = function(c) {
+        return typeMap[c];
+    };
+
+    return tokenData;
+};
+
+TokenStreamBase.prototype = {
+
+    //restore constructor
+    constructor: TokenStreamBase,
+
+    //-------------------------------------------------------------------------
+    // Matching methods
+    //-------------------------------------------------------------------------
+
+    /**
+     * Determines if the next token matches the given token type.
+     * If so, that token is consumed; if not, the token is placed
+     * back onto the token stream. You can pass in any number of
+     * token types and this will return true if any of the token
+     * types is found.
+     * @param {int|int[]} tokenTypes Either a single token type or an array of
+     *      token types that the next token might be. If an array is passed,
+     *      it's assumed that the token can be any of these.
+     * @param {variant} channel (Optional) The channel to read from. If not
+     *      provided, reads from the default (unnamed) channel.
+     * @return {Boolean} True if the token type matches, false if not.
+     * @method match
+     */
+    match: function(tokenTypes, channel) {
+
+        //always convert to an array, makes things easier
+        if (!(tokenTypes instanceof Array)) {
+            tokenTypes = [tokenTypes];
+        }
+
+        var tt  = this.get(channel),
+            i   = 0,
+            len = tokenTypes.length;
+
+        while (i < len) {
+            if (tt === tokenTypes[i++]) {
+                return true;
+            }
+        }
+
+        //no match found, put the token back
+        this.unget();
+        return false;
+    },
+
+    /**
+     * Determines if the next token matches the given token type.
+     * If so, that token is consumed; if not, an error is thrown.
+     * @param {int|int[]} tokenTypes Either a single token type or an array of
+     *      token types that the next token should be. If an array is passed,
+     *      it's assumed that the token must be one of these.
+     * @return {void}
+     * @method mustMatch
+     */
+    mustMatch: function(tokenTypes) {
+
+        var token;
+
+        //always convert to an array, makes things easier
+        if (!(tokenTypes instanceof Array)) {
+            tokenTypes = [tokenTypes];
+        }
+
+        if (!this.match.apply(this, arguments)) {
+            token = this.LT(1);
+            throw new SyntaxError("Expected " + this._tokenData[tokenTypes[0]].name +
+                " at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol);
+        }
+    },
+
+    //-------------------------------------------------------------------------
+    // Consuming methods
+    //-------------------------------------------------------------------------
+
+    /**
+     * Keeps reading from the token stream until either one of the specified
+     * token types is found or until the end of the input is reached.
+     * @param {int|int[]} tokenTypes Either a single token type or an array of
+     *      token types that the next token should be. If an array is passed,
+     *      it's assumed that the token must be one of these.
+     * @param {variant} channel (Optional) The channel to read from. If not
+     *      provided, reads from the default (unnamed) channel.
+     * @return {void}
+     * @method advance
+     */
+    advance: function(tokenTypes, channel) {
+
+        while (this.LA(0) !== 0 && !this.match(tokenTypes, channel)) {
+            this.get();
+        }
+
+        return this.LA(0);
+    },
+
+    /**
+     * Consumes the next token from the token stream.
+     * @return {int} The token type of the token that was just consumed.
+     * @method get
+     */
+    get: function(channel) {
+
+        var tokenInfo   = this._tokenData,
+            i           =0,
+            token,
+            info;
+
+        //check the lookahead buffer first
+        if (this._lt.length && this._ltIndex >= 0 && this._ltIndex < this._lt.length) {
+
+            i++;
+            this._token = this._lt[this._ltIndex++];
+            info = tokenInfo[this._token.type];
+
+            //obey channels logic
+            while ((info.channel !== undefined && channel !== info.channel) &&
+                    this._ltIndex < this._lt.length) {
+                this._token = this._lt[this._ltIndex++];
+                info = tokenInfo[this._token.type];
+                i++;
+            }
+
+            //here be dragons
+            if ((info.channel === undefined || channel === info.channel) &&
+                    this._ltIndex <= this._lt.length) {
+                this._ltIndexCache.push(i);
+                return this._token.type;
+            }
+        }
+
+        //call token retriever method
+        token = this._getToken();
+
+        //if it should be hidden, don't save a token
+        if (token.type > -1 && !tokenInfo[token.type].hide) {
+
+            //apply token channel
+            token.channel = tokenInfo[token.type].channel;
+
+            //save for later
+            this._token = token;
+            this._lt.push(token);
+
+            //save space that will be moved (must be done before array is truncated)
+            this._ltIndexCache.push(this._lt.length - this._ltIndex + i);
+
+            //keep the buffer under 5 items
+            if (this._lt.length > 5) {
+                this._lt.shift();
+            }
+
+            //also keep the shift buffer under 5 items
+            if (this._ltIndexCache.length > 5) {
+                this._ltIndexCache.shift();
+            }
+
+            //update lookahead index
+            this._ltIndex = this._lt.length;
+        }
+
+        /*
+         * Skip to the next token if:
+         * 1. The token type is marked as hidden.
+         * 2. The token type has a channel specified and it isn't the current channel.
+         */
+        info = tokenInfo[token.type];
+        if (info &&
+                (info.hide ||
+                (info.channel !== undefined && channel !== info.channel))) {
+            return this.get(channel);
+        } else {
+            //return just the type
+            return token.type;
+        }
+    },
+
+    /**
+     * Looks ahead a certain number of tokens and returns the token type at
+     * that position. This will throw an error if you lookahead past the
+     * end of input, past the size of the lookahead buffer, or back past
+     * the first token in the lookahead buffer.
+     * @param {int} The index of the token type to retrieve. 0 for the
+     *      current token, 1 for the next, -1 for the previous, etc.
+     * @return {int} The token type of the token in the given position.
+     * @method LA
+     */
+    LA: function(index) {
+        var total = index,
+            tt;
+        if (index > 0) {
+            //TODO: Store 5 somewhere
+            if (index > 5) {
+                throw new Error("Too much lookahead.");
+            }
+
+            //get all those tokens
+            while (total) {
+                tt = this.get();
+                total--;
+            }
+
+            //unget all those tokens
+            while (total < index) {
+                this.unget();
+                total++;
+            }
+        } else if (index < 0) {
+
+            if (this._lt[this._ltIndex+index]) {
+                tt = this._lt[this._ltIndex+index].type;
+            } else {
+                throw new Error("Too much lookbehind.");
+            }
+
+        } else {
+            tt = this._token.type;
+        }
+
+        return tt;
+
+    },
+
+    /**
+     * Looks ahead a certain number of tokens and returns the token at
+     * that position. This will throw an error if you lookahead past the
+     * end of input, past the size of the lookahead buffer, or back past
+     * the first token in the lookahead buffer.
+     * @param {int} The index of the token type to retrieve. 0 for the
+     *      current token, 1 for the next, -1 for the previous, etc.
+     * @return {Object} The token of the token in the given position.
+     * @method LA
+     */
+    LT: function(index) {
+
+        //lookahead first to prime the token buffer
+        this.LA(index);
+
+        //now find the token, subtract one because _ltIndex is already at the next index
+        return this._lt[this._ltIndex+index-1];
+    },
+
+    /**
+     * Returns the token type for the next token in the stream without
+     * consuming it.
+     * @return {int} The token type of the next token in the stream.
+     * @method peek
+     */
+    peek: function() {
+        return this.LA(1);
+    },
+
+    /**
+     * Returns the actual token object for the last consumed token.
+     * @return {Token} The token object for the last consumed token.
+     * @method token
+     */
+    token: function() {
+        return this._token;
+    },
+
+    /**
+     * Returns the name of the token for the given token type.
+     * @param {int} tokenType The type of token to get the name of.
+     * @return {String} The name of the token or "UNKNOWN_TOKEN" for any
+     *      invalid token type.
+     * @method tokenName
+     */
+    tokenName: function(tokenType) {
+        if (tokenType < 0 || tokenType > this._tokenData.length) {
+            return "UNKNOWN_TOKEN";
+        } else {
+            return this._tokenData[tokenType].name;
+        }
+    },
+
+    /**
+     * Returns the token type value for the given token name.
+     * @param {String} tokenName The name of the token whose value should be returned.
+     * @return {int} The token type value for the given token name or -1
+     *      for an unknown token.
+     * @method tokenName
+     */
+    tokenType: function(tokenName) {
+        return this._tokenData[tokenName] || -1;
+    },
+
+    /**
+     * Returns the last consumed token to the token stream.
+     * @method unget
+     */
+    unget: function() {
+        //if (this._ltIndex > -1) {
+        if (this._ltIndexCache.length) {
+            this._ltIndex -= this._ltIndexCache.pop();//--;
+            this._token = this._lt[this._ltIndex - 1];
+        } else {
+            throw new Error("Too much lookahead.");
+        }
+    }
+
+};
+
+
+},{"./StringReader":24,"./SyntaxError":25}],28:[function(require,module,exports){
+"use strict";
+
+module.exports = {
+    StringReader    : require("./StringReader"),
+    SyntaxError     : require("./SyntaxError"),
+    SyntaxUnit      : require("./SyntaxUnit"),
+    EventTarget     : require("./EventTarget"),
+    TokenStreamBase : require("./TokenStreamBase")
+};
+
+},{"./EventTarget":23,"./StringReader":24,"./SyntaxError":25,"./SyntaxUnit":26,"./TokenStreamBase":27}],"parserlib":[function(require,module,exports){
+"use strict";
+
+module.exports = {
+    css  : require("./css"),
+    util : require("./util")
+};
+
+},{"./css":22,"./util":28}]},{},[]);
+
+return require('parserlib');
+})();
+var clone = (function() {
+'use strict';
+
+var nativeMap;
+try {
+  nativeMap = Map;
+} catch(_) {
+  // maybe a reference error because no `Map`. Give it a dummy value that no
+  // value will ever be an instanceof.
+  nativeMap = function() {};
+}
+
+var nativeSet;
+try {
+  nativeSet = Set;
+} catch(_) {
+  nativeSet = function() {};
+}
+
+var nativePromise;
+try {
+  nativePromise = Promise;
+} catch(_) {
+  nativePromise = function() {};
+}
+
+/**
+ * Clones (copies) an Object using deep copying.
+ *
+ * This function supports circular references by default, but if you are certain
+ * there are no circular references in your object, you can save some CPU time
+ * by calling clone(obj, false).
+ *
+ * Caution: if `circular` is false and `parent` contains circular references,
+ * your program may enter an infinite loop and crash.
+ *
+ * @param `parent` - the object to be cloned
+ * @param `circular` - set to true if the object to be cloned may contain
+ *    circular references. (optional - true by default)
+ * @param `depth` - set to a number if the object is only to be cloned to
+ *    a particular depth. (optional - defaults to Infinity)
+ * @param `prototype` - sets the prototype to be used when cloning an object.
+ *    (optional - defaults to parent prototype).
+ * @param `includeNonEnumerable` - set to true if the non-enumerable properties
+ *    should be cloned as well. Non-enumerable properties on the prototype
+ *    chain will be ignored. (optional - false by default)
+*/
+function clone(parent, circular, depth, prototype, includeNonEnumerable) {
+  if (typeof circular === 'object') {
+    depth = circular.depth;
+    prototype = circular.prototype;
+    includeNonEnumerable = circular.includeNonEnumerable;
+    circular = circular.circular;
+  }
+  // maintain two arrays for circular references, where corresponding parents
+  // and children have the same index
+  var allParents = [];
+  var allChildren = [];
+
+  var useBuffer = typeof Buffer != 'undefined';
+
+  if (typeof circular == 'undefined')
+    circular = true;
+
+  if (typeof depth == 'undefined')
+    depth = Infinity;
+
+  // recurse this function so we don't reset allParents and allChildren
+  function _clone(parent, depth) {
+    // cloning null always returns null
+    if (parent === null)
+      return null;
+
+    if (depth === 0)
+      return parent;
+
+    var child;
+    var proto;
+    if (typeof parent != 'object') {
+      return parent;
+    }
+
+    if (parent instanceof nativeMap) {
+      child = new nativeMap();
+    } else if (parent instanceof nativeSet) {
+      child = new nativeSet();
+    } else if (parent instanceof nativePromise) {
+      child = new nativePromise(function (resolve, reject) {
+        parent.then(function(value) {
+          resolve(_clone(value, depth - 1));
+        }, function(err) {
+          reject(_clone(err, depth - 1));
+        });
+      });
+    } else if (clone.__isArray(parent)) {
+      child = [];
+    } else if (clone.__isRegExp(parent)) {
+      child = new RegExp(parent.source, __getRegExpFlags(parent));
+      if (parent.lastIndex) child.lastIndex = parent.lastIndex;
+    } else if (clone.__isDate(parent)) {
+      child = new Date(parent.getTime());
+    } else if (useBuffer && Buffer.isBuffer(parent)) {
+      child = new Buffer(parent.length);
+      parent.copy(child);
+      return child;
+    } else if (parent instanceof Error) {
+      child = Object.create(parent);
+    } else {
+      if (typeof prototype == 'undefined') {
+        proto = Object.getPrototypeOf(parent);
+        child = Object.create(proto);
+      }
+      else {
+        child = Object.create(prototype);
+        proto = prototype;
+      }
+    }
+
+    if (circular) {
+      var index = allParents.indexOf(parent);
+
+      if (index != -1) {
+        return allChildren[index];
+      }
+      allParents.push(parent);
+      allChildren.push(child);
+    }
+
+    if (parent instanceof nativeMap) {
+      var keyIterator = parent.keys();
+      while(true) {
+        var next = keyIterator.next();
+        if (next.done) {
+          break;
+        }
+        var keyChild = _clone(next.value, depth - 1);
+        var valueChild = _clone(parent.get(next.value), depth - 1);
+        child.set(keyChild, valueChild);
+      }
+    }
+    if (parent instanceof nativeSet) {
+      var iterator = parent.keys();
+      while(true) {
+        var next = iterator.next();
+        if (next.done) {
+          break;
+        }
+        var entryChild = _clone(next.value, depth - 1);
+        child.add(entryChild);
+      }
+    }
+
+    for (var i in parent) {
+      var attrs;
+      if (proto) {
+        attrs = Object.getOwnPropertyDescriptor(proto, i);
+      }
+
+      if (attrs && attrs.set == null) {
+        continue;
+      }
+      child[i] = _clone(parent[i], depth - 1);
+    }
+
+    if (Object.getOwnPropertySymbols) {
+      var symbols = Object.getOwnPropertySymbols(parent);
+      for (var i = 0; i < symbols.length; i++) {
+        // Don't need to worry about cloning a symbol because it is a primitive,
+        // like a number or string.
+        var symbol = symbols[i];
+        var descriptor = Object.getOwnPropertyDescriptor(parent, symbol);
+        if (descriptor && !descriptor.enumerable && !includeNonEnumerable) {
+          continue;
+        }
+        child[symbol] = _clone(parent[symbol], depth - 1);
+        if (!descriptor.enumerable) {
+          Object.defineProperty(child, symbol, {
+            enumerable: false
+          });
+        }
+      }
+    }
+
+    if (includeNonEnumerable) {
+      var allPropertyNames = Object.getOwnPropertyNames(parent);
+      for (var i = 0; i < allPropertyNames.length; i++) {
+        var propertyName = allPropertyNames[i];
+        var descriptor = Object.getOwnPropertyDescriptor(parent, propertyName);
+        if (descriptor && descriptor.enumerable) {
+          continue;
+        }
+        child[propertyName] = _clone(parent[propertyName], depth - 1);
+        Object.defineProperty(child, propertyName, {
+          enumerable: false
+        });
+      }
+    }
+
+    return child;
+  }
+
+  return _clone(parent, depth);
+}
+
+/**
+ * Simple flat clone using prototype, accepts only objects, usefull for property
+ * override on FLAT configuration object (no nested props).
+ *
+ * USE WITH CAUTION! This may not behave as you wish if you do not know how this
+ * works.
+ */
+clone.clonePrototype = function clonePrototype(parent) {
+  if (parent === null)
+    return null;
+
+  var c = function () {};
+  c.prototype = parent;
+  return new c();
+};
+
+// private utility functions
+
+function __objToStr(o) {
+  return Object.prototype.toString.call(o);
+}
+clone.__objToStr = __objToStr;
+
+function __isDate(o) {
+  return typeof o === 'object' && __objToStr(o) === '[object Date]';
+}
+clone.__isDate = __isDate;
+
+function __isArray(o) {
+  return typeof o === 'object' && __objToStr(o) === '[object Array]';
+}
+clone.__isArray = __isArray;
+
+function __isRegExp(o) {
+  return typeof o === 'object' && __objToStr(o) === '[object RegExp]';
+}
+clone.__isRegExp = __isRegExp;
+
+function __getRegExpFlags(re) {
+  var flags = '';
+  if (re.global) flags += 'g';
+  if (re.ignoreCase) flags += 'i';
+  if (re.multiline) flags += 'm';
+  return flags;
+}
+clone.__getRegExpFlags = __getRegExpFlags;
+
+return clone;
+})();
+
+if (typeof module === 'object' && module.exports) {
+  module.exports = clone;
+}
+
+/**
+ * Main CSSLint object.
+ * @class CSSLint
+ * @static
+ * @extends parserlib.util.EventTarget
+ */
+
+/* global parserlib, clone, Reporter */
+/* exported CSSLint */
+
+var CSSLint = (function() {
+    "use strict";
+
+    var rules           = [],
+        formatters      = [],
+        embeddedRuleset = /\/\*\s*csslint([^\*]*)\*\//,
+        api             = new parserlib.util.EventTarget();
+
+    api.version = "1.0.4";
+
+    //-------------------------------------------------------------------------
+    // Rule Management
+    //-------------------------------------------------------------------------
+
+    /**
+     * Adds a new rule to the engine.
+     * @param {Object} rule The rule to add.
+     * @method addRule
+     */
+    api.addRule = function(rule) {
+        rules.push(rule);
+        rules[rule.id] = rule;
+    };
+
+    /**
+     * Clears all rule from the engine.
+     * @method clearRules
+     */
+    api.clearRules = function() {
+        rules = [];
+    };
+
+    /**
+     * Returns the rule objects.
+     * @return An array of rule objects.
+     * @method getRules
+     */
+    api.getRules = function() {
+        return [].concat(rules).sort(function(a, b) {
+            return a.id > b.id ? 1 : 0;
+        });
+    };
+
+    /**
+     * Returns a ruleset configuration object with all current rules.
+     * @return A ruleset object.
+     * @method getRuleset
+     */
+    api.getRuleset = function() {
+        var ruleset = {},
+            i = 0,
+            len = rules.length;
+
+        while (i < len) {
+            ruleset[rules[i++].id] = 1;    // by default, everything is a warning
+        }
+
+        return ruleset;
+    };
+
+    /**
+     * Returns a ruleset object based on embedded rules.
+     * @param {String} text A string of css containing embedded rules.
+     * @param {Object} ruleset A ruleset object to modify.
+     * @return {Object} A ruleset object.
+     * @method getEmbeddedRuleset
+     */
+    function applyEmbeddedRuleset(text, ruleset) {
+        var valueMap,
+            embedded = text && text.match(embeddedRuleset),
+            rules = embedded && embedded[1];
+
+        if (rules) {
+            valueMap = {
+                "true": 2,  // true is error
+                "": 1,      // blank is warning
+                "false": 0, // false is ignore
+
+                "2": 2,     // explicit error
+                "1": 1,     // explicit warning
+                "0": 0      // explicit ignore
+            };
+
+            rules.toLowerCase().split(",").forEach(function(rule) {
+                var pair = rule.split(":"),
+                    property = pair[0] || "",
+                    value = pair[1] || "";
+
+                ruleset[property.trim()] = valueMap[value.trim()];
+            });
+        }
+
+        return ruleset;
+    }
+
+    //-------------------------------------------------------------------------
+    // Formatters
+    //-------------------------------------------------------------------------
+
+    /**
+     * Adds a new formatter to the engine.
+     * @param {Object} formatter The formatter to add.
+     * @method addFormatter
+     */
+    api.addFormatter = function(formatter) {
+        // formatters.push(formatter);
+        formatters[formatter.id] = formatter;
+    };
+
+    /**
+     * Retrieves a formatter for use.
+     * @param {String} formatId The name of the format to retrieve.
+     * @return {Object} The formatter or undefined.
+     * @method getFormatter
+     */
+    api.getFormatter = function(formatId) {
+        return formatters[formatId];
+    };
+
+    /**
+     * Formats the results in a particular format for a single file.
+     * @param {Object} result The results returned from CSSLint.verify().
+     * @param {String} filename The filename for which the results apply.
+     * @param {String} formatId The name of the formatter to use.
+     * @param {Object} options (Optional) for special output handling.
+     * @return {String} A formatted string for the results.
+     * @method format
+     */
+    api.format = function(results, filename, formatId, options) {
+        var formatter = this.getFormatter(formatId),
+            result = null;
+
+        if (formatter) {
+            result = formatter.startFormat();
+            result += formatter.formatResults(results, filename, options || {});
+            result += formatter.endFormat();
+        }
+
+        return result;
+    };
+
+    /**
+     * Indicates if the given format is supported.
+     * @param {String} formatId The ID of the format to check.
+     * @return {Boolean} True if the format exists, false if not.
+     * @method hasFormat
+     */
+    api.hasFormat = function(formatId) {
+        return formatters.hasOwnProperty(formatId);
+    };
+
+    //-------------------------------------------------------------------------
+    // Verification
+    //-------------------------------------------------------------------------
+
+    /**
+     * Starts the verification process for the given CSS text.
+     * @param {String} text The CSS text to verify.
+     * @param {Object} ruleset (Optional) List of rules to apply. If null, then
+     *      all rules are used. If a rule has a value of 1 then it's a warning,
+     *      a value of 2 means it's an error.
+     * @return {Object} Results of the verification.
+     * @method verify
+     */
+    api.verify = function(text, ruleset) {
+
+        var i = 0,
+            reporter,
+            lines,
+            allow = {},
+            ignore = [],
+            report,
+            parser = new parserlib.css.Parser({
+                starHack: true,
+                ieFilters: true,
+                underscoreHack: true,
+                strict: false
+            });
+
+        // normalize line endings
+        lines = text.replace(/\n\r?/g, "$split$").split("$split$");
+
+        // find 'allow' comments
+        CSSLint.Util.forEach(lines, function (line, lineno) {
+            var allowLine = line && line.match(/\/\*[ \t]*csslint[ \t]+allow:[ \t]*([^\*]*)\*\//i),
+                allowRules = allowLine && allowLine[1],
+                allowRuleset = {};
+
+            if (allowRules) {
+                allowRules.toLowerCase().split(",").forEach(function(allowRule) {
+                    allowRuleset[allowRule.trim()] = true;
+                });
+                if (Object.keys(allowRuleset).length > 0) {
+                    allow[lineno + 1] = allowRuleset;
+                }
+            }
+        });
+
+        var ignoreStart = null,
+            ignoreEnd = null;
+        CSSLint.Util.forEach(lines, function (line, lineno) {
+            // Keep oldest, "unclosest" ignore:start
+            if (ignoreStart === null && line.match(/\/\*[ \t]*csslint[ \t]+ignore:start[ \t]*\*\//i)) {
+                ignoreStart = lineno;
+            }
+
+            if (line.match(/\/\*[ \t]*csslint[ \t]+ignore:end[ \t]*\*\//i)) {
+                ignoreEnd = lineno;
+            }
+
+            if (ignoreStart !== null && ignoreEnd !== null) {
+                ignore.push([ignoreStart, ignoreEnd]);
+                ignoreStart = ignoreEnd = null;
+            }
+        });
+
+        // Close remaining ignore block, if any
+        if (ignoreStart !== null) {
+            ignore.push([ignoreStart, lines.length]);
+        }
+
+        if (!ruleset) {
+            ruleset = this.getRuleset();
+        }
+
+        if (embeddedRuleset.test(text)) {
+            // defensively copy so that caller's version does not get modified
+            ruleset = clone(ruleset);
+            ruleset = applyEmbeddedRuleset(text, ruleset);
+        }
+
+        reporter = new Reporter(lines, ruleset, allow, ignore);
+
+        ruleset.errors = 2;       // always report parsing errors as errors
+        for (i in ruleset) {
+            if (ruleset.hasOwnProperty(i) && ruleset[i]) {
+                if (rules[i]) {
+                    rules[i].init(parser, reporter);
+                }
+            }
+        }
+
+
+        // capture most horrible error type
+        try {
+            parser.parse(text);
+        } catch (ex) {
+            reporter.error("Fatal error, cannot continue: " + ex.message, ex.line, ex.col, {});
+        }
+
+        report = {
+            messages    : reporter.messages,
+            stats       : reporter.stats,
+            ruleset     : reporter.ruleset,
+            allow       : reporter.allow,
+            ignore      : reporter.ignore
+        };
+
+        // sort by line numbers, rollups at the bottom
+        report.messages.sort(function (a, b) {
+            if (a.rollup && !b.rollup) {
+                return 1;
+            } else if (!a.rollup && b.rollup) {
+                return -1;
+            } else {
+                return a.line - b.line;
+            }
+        });
+
+        return report;
+    };
+
+    //-------------------------------------------------------------------------
+    // Publish the API
+    //-------------------------------------------------------------------------
+
+    return api;
+
+})();
+
+/**
+ * An instance of Report is used to report results of the
+ * verification back to the main API.
+ * @class Reporter
+ * @constructor
+ * @param {String[]} lines The text lines of the source.
+ * @param {Object} ruleset The set of rules to work with, including if
+ *      they are errors or warnings.
+ * @param {Object} explicitly allowed lines
+ * @param {[][]} ingore list of line ranges to be ignored
+ */
+function Reporter(lines, ruleset, allow, ignore) {
+    "use strict";
+
+    /**
+     * List of messages being reported.
+     * @property messages
+     * @type String[]
+     */
+    this.messages = [];
+
+    /**
+     * List of statistics being reported.
+     * @property stats
+     * @type String[]
+     */
+    this.stats = [];
+
+    /**
+     * Lines of code being reported on. Used to provide contextual information
+     * for messages.
+     * @property lines
+     * @type String[]
+     */
+    this.lines = lines;
+
+    /**
+     * Information about the rules. Used to determine whether an issue is an
+     * error or warning.
+     * @property ruleset
+     * @type Object
+     */
+    this.ruleset = ruleset;
+
+    /**
+     * Lines with specific rule messages to leave out of the report.
+     * @property allow
+     * @type Object
+     */
+    this.allow = allow;
+    if (!this.allow) {
+        this.allow = {};
+    }
+
+    /**
+     * Linesets not to include in the report.
+     * @property ignore
+     * @type [][]
+     */
+    this.ignore = ignore;
+    if (!this.ignore) {
+        this.ignore = [];
+    }
+}
+
+Reporter.prototype = {
+
+    // restore constructor
+    constructor: Reporter,
+
+    /**
+     * Report an error.
+     * @param {String} message The message to store.
+     * @param {int} line The line number.
+     * @param {int} col The column number.
+     * @param {Object} rule The rule this message relates to.
+     * @method error
+     */
+    error: function(message, line, col, rule) {
+        "use strict";
+        this.messages.push({
+            type    : "error",
+            line    : line,
+            col     : col,
+            message : message,
+            evidence: this.lines[line-1],
+            rule    : rule || {}
+        });
+    },
+
+    /**
+     * Report an warning.
+     * @param {String} message The message to store.
+     * @param {int} line The line number.
+     * @param {int} col The column number.
+     * @param {Object} rule The rule this message relates to.
+     * @method warn
+     * @deprecated Use report instead.
+     */
+    warn: function(message, line, col, rule) {
+        "use strict";
+        this.report(message, line, col, rule);
+    },
+
+    /**
+     * Report an issue.
+     * @param {String} message The message to store.
+     * @param {int} line The line number.
+     * @param {int} col The column number.
+     * @param {Object} rule The rule this message relates to.
+     * @method report
+     */
+    report: function(message, line, col, rule) {
+        "use strict";
+
+        // Check if rule violation should be allowed
+        if (this.allow.hasOwnProperty(line) && this.allow[line].hasOwnProperty(rule.id)) {
+            return;
+        }
+
+        var ignore = false;
+        CSSLint.Util.forEach(this.ignore, function (range) {
+            if (range[0] <= line && line <= range[1]) {
+                ignore = true;
+            }
+        });
+        if (ignore) {
+            return;
+        }
+
+        this.messages.push({
+            type    : this.ruleset[rule.id] === 2 ? "error" : "warning",
+            line    : line,
+            col     : col,
+            message : message,
+            evidence: this.lines[line-1],
+            rule    : rule
+        });
+    },
+
+    /**
+     * Report some informational text.
+     * @param {String} message The message to store.
+     * @param {int} line The line number.
+     * @param {int} col The column number.
+     * @param {Object} rule The rule this message relates to.
+     * @method info
+     */
+    info: function(message, line, col, rule) {
+        "use strict";
+        this.messages.push({
+            type    : "info",
+            line    : line,
+            col     : col,
+            message : message,
+            evidence: this.lines[line-1],
+            rule    : rule
+        });
+    },
+
+    /**
+     * Report some rollup error information.
+     * @param {String} message The message to store.
+     * @param {Object} rule The rule this message relates to.
+     * @method rollupError
+     */
+    rollupError: function(message, rule) {
+        "use strict";
+        this.messages.push({
+            type    : "error",
+            rollup  : true,
+            message : message,
+            rule    : rule
+        });
+    },
+
+    /**
+     * Report some rollup warning information.
+     * @param {String} message The message to store.
+     * @param {Object} rule The rule this message relates to.
+     * @method rollupWarn
+     */
+    rollupWarn: function(message, rule) {
+        "use strict";
+        this.messages.push({
+            type    : "warning",
+            rollup  : true,
+            message : message,
+            rule    : rule
+        });
+    },
+
+    /**
+     * Report a statistic.
+     * @param {String} name The name of the stat to store.
+     * @param {Variant} value The value of the stat.
+     * @method stat
+     */
+    stat: function(name, value) {
+        "use strict";
+        this.stats[name] = value;
+    }
+};
+
+// expose for testing purposes
+CSSLint._Reporter = Reporter;
+
+/*
+ * Utility functions that make life easier.
+ */
+CSSLint.Util = {
+    /*
+     * Adds all properties from supplier onto receiver,
+     * overwriting if the same name already exists on
+     * receiver.
+     * @param {Object} The object to receive the properties.
+     * @param {Object} The object to provide the properties.
+     * @return {Object} The receiver
+     */
+    mix: function(receiver, supplier) {
+        "use strict";
+        var prop;
+
+        for (prop in supplier) {
+            if (supplier.hasOwnProperty(prop)) {
+                receiver[prop] = supplier[prop];
+            }
+        }
+
+        return prop;
+    },
+
+    /*
+     * Polyfill for array indexOf() method.
+     * @param {Array} values The array to search.
+     * @param {Variant} value The value to search for.
+     * @return {int} The index of the value if found, -1 if not.
+     */
+    indexOf: function(values, value) {
+        "use strict";
+        if (values.indexOf) {
+            return values.indexOf(value);
+        } else {
+            for (var i=0, len=values.length; i < len; i++) {
+                if (values[i] === value) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+    },
+
+    /*
+     * Polyfill for array forEach() method.
+     * @param {Array} values The array to operate on.
+     * @param {Function} func The function to call on each item.
+     * @return {void}
+     */
+    forEach: function(values, func) {
+        "use strict";
+        if (values.forEach) {
+            return values.forEach(func);
+        } else {
+            for (var i=0, len=values.length; i < len; i++) {
+                func(values[i], i, values);
+            }
+        }
+    }
+};
+
+/*
+ * Rule: Don't use adjoining classes (.foo.bar).
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "adjoining-classes",
+    name: "Disallow adjoining classes",
+    desc: "Don't use adjoining classes.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-adjoining-classes",
+    browsers: "IE6",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+        parser.addListener("startrule", function(event) {
+            var selectors = event.selectors,
+                selector,
+                part,
+                modifier,
+                classCount,
+                i, j, k;
+
+            for (i=0; i < selectors.length; i++) {
+                selector = selectors[i];
+                for (j=0; j < selector.parts.length; j++) {
+                    part = selector.parts[j];
+                    if (part.type === parser.SELECTOR_PART_TYPE) {
+                        classCount = 0;
+                        for (k=0; k < part.modifiers.length; k++) {
+                            modifier = part.modifiers[k];
+                            if (modifier.type === "class") {
+                                classCount++;
+                            }
+                            if (classCount > 1){
+                                reporter.report("Adjoining classes: "+selectors[i].text, part.line, part.col, rule);
+                            }
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Don't use width or height when using padding or border.
+ */
+CSSLint.addRule({
+
+    // rule information
+    id: "box-model",
+    name: "Beware of broken box size",
+    desc: "Don't use width or height when using padding or border.",
+    url: "https://github.com/CSSLint/csslint/wiki/Beware-of-box-model-size",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            widthProperties = {
+                border: 1,
+                "border-left": 1,
+                "border-right": 1,
+                padding: 1,
+                "padding-left": 1,
+                "padding-right": 1
+            },
+            heightProperties = {
+                border: 1,
+                "border-bottom": 1,
+                "border-top": 1,
+                padding: 1,
+                "padding-bottom": 1,
+                "padding-top": 1
+            },
+            properties,
+            boxSizing = false;
+
+        function startRule() {
+            properties = {};
+            boxSizing = false;
+        }
+
+        function endRule() {
+            var prop, value;
+
+            if (!boxSizing) {
+                if (properties.height) {
+                    for (prop in heightProperties) {
+                        if (heightProperties.hasOwnProperty(prop) && properties[prop]) {
+                            value = properties[prop].value;
+                            // special case for padding
+                            if (!(prop === "padding" && value.parts.length === 2 && value.parts[0].value === 0)) {
+                                reporter.report("Using height with " + prop + " can sometimes make elements larger than you expect.", properties[prop].line, properties[prop].col, rule);
+                            }
+                        }
+                    }
+                }
+
+                if (properties.width) {
+                    for (prop in widthProperties) {
+                        if (widthProperties.hasOwnProperty(prop) && properties[prop]) {
+                            value = properties[prop].value;
+
+                            if (!(prop === "padding" && value.parts.length === 2 && value.parts[1].value === 0)) {
+                                reporter.report("Using width with " + prop + " can sometimes make elements larger than you expect.", properties[prop].line, properties[prop].col, rule);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);
+        parser.addListener("startviewport", startRule);
+
+        parser.addListener("property", function(event) {
+            var name = event.property.text.toLowerCase();
+
+            if (heightProperties[name] || widthProperties[name]) {
+                if (!/^0\S*$/.test(event.value) && !(name === "border" && event.value.toString() === "none")) {
+                    properties[name] = {
+                        line: event.property.line,
+                        col: event.property.col,
+                        value: event.value
+                    };
+                }
+            } else {
+                if (/^(width|height)/i.test(name) && /^(length|percentage)/.test(event.value.parts[0].type)) {
+                    properties[name] = 1;
+                } else if (name === "box-sizing") {
+                    boxSizing = true;
+                }
+            }
+
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+        parser.addListener("endpage", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endkeyframerule", endRule);
+        parser.addListener("endviewport", endRule);
+    }
+
+});
+
+/*
+ * Rule: box-sizing doesn't work in IE6 and IE7.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "box-sizing",
+    name: "Disallow use of box-sizing",
+    desc: "The box-sizing properties isn't supported in IE6 and IE7.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-box-sizing",
+    browsers: "IE6, IE7",
+    tags: ["Compatibility"],
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        parser.addListener("property", function(event) {
+            var name = event.property.text.toLowerCase();
+
+            if (name === "box-sizing") {
+                reporter.report("The box-sizing property isn't supported in IE6 and IE7.", event.line, event.col, rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Use the bulletproof @font-face syntax to avoid 404's in old IE
+ * (http://www.fontspring.com/blog/the-new-bulletproof-font-face-syntax)
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "bulletproof-font-face",
+    name: "Use the bulletproof @font-face syntax",
+    desc: "Use the bulletproof @font-face syntax to avoid 404's in old IE (http://www.fontspring.com/blog/the-new-bulletproof-font-face-syntax).",
+    url: "https://github.com/CSSLint/csslint/wiki/Bulletproof-font-face",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            fontFaceRule = false,
+            firstSrc = true,
+            ruleFailed = false,
+            line, col;
+
+        // Mark the start of a @font-face declaration so we only test properties inside it
+        parser.addListener("startfontface", function() {
+            fontFaceRule = true;
+        });
+
+        parser.addListener("property", function(event) {
+            // If we aren't inside an @font-face declaration then just return
+            if (!fontFaceRule) {
+                return;
+            }
+
+            var propertyName = event.property.toString().toLowerCase(),
+                value = event.value.toString();
+
+            // Set the line and col numbers for use in the endfontface listener
+            line = event.line;
+            col = event.col;
+
+            // This is the property that we care about, we can ignore the rest
+            if (propertyName === "src") {
+                var regex = /^\s?url\(['"].+\.eot\?.*['"]\)\s*format\(['"]embedded-opentype['"]\).*$/i;
+
+                // We need to handle the advanced syntax with two src properties
+                if (!value.match(regex) && firstSrc) {
+                    ruleFailed = true;
+                    firstSrc = false;
+                } else if (value.match(regex) && !firstSrc) {
+                    ruleFailed = false;
+                }
+            }
+
+
+        });
+
+        // Back to normal rules that we don't need to test
+        parser.addListener("endfontface", function() {
+            fontFaceRule = false;
+
+            if (ruleFailed) {
+                reporter.report("@font-face declaration doesn't follow the fontspring bulletproof syntax.", line, col, rule);
+            }
+        });
+    }
+});
+
+/*
+ * Rule: Include all compatible vendor prefixes to reach a wider
+ * range of users.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "compatible-vendor-prefixes",
+    name: "Require compatible vendor prefixes",
+    desc: "Include all compatible vendor prefixes to reach a wider range of users.",
+    url: "https://github.com/CSSLint/csslint/wiki/Require-compatible-vendor-prefixes",
+    browsers: "All",
+
+    // initialization
+    init: function (parser, reporter) {
+        "use strict";
+        var rule = this,
+            compatiblePrefixes,
+            properties,
+            prop,
+            variations,
+            prefixed,
+            i,
+            len,
+            inKeyFrame = false,
+            arrayPush = Array.prototype.push,
+            applyTo = [];
+
+        // See http://peter.sh/experiments/vendor-prefixed-css-property-overview/ for details
+        compatiblePrefixes = {
+            "animation"                  : "webkit",
+            "animation-delay"            : "webkit",
+            "animation-direction"        : "webkit",
+            "animation-duration"         : "webkit",
+            "animation-fill-mode"        : "webkit",
+            "animation-iteration-count"  : "webkit",
+            "animation-name"             : "webkit",
+            "animation-play-state"       : "webkit",
+            "animation-timing-function"  : "webkit",
+            "appearance"                 : "webkit moz",
+            "border-end"                 : "webkit moz",
+            "border-end-color"           : "webkit moz",
+            "border-end-style"           : "webkit moz",
+            "border-end-width"           : "webkit moz",
+            "border-image"               : "webkit moz o",
+            "border-radius"              : "webkit",
+            "border-start"               : "webkit moz",
+            "border-start-color"         : "webkit moz",
+            "border-start-style"         : "webkit moz",
+            "border-start-width"         : "webkit moz",
+            "box-align"                  : "webkit moz ms",
+            "box-direction"              : "webkit moz ms",
+            "box-flex"                   : "webkit moz ms",
+            "box-lines"                  : "webkit ms",
+            "box-ordinal-group"          : "webkit moz ms",
+            "box-orient"                 : "webkit moz ms",
+            "box-pack"                   : "webkit moz ms",
+            "box-sizing"                 : "",
+            "box-shadow"                 : "",
+            "column-count"               : "webkit moz ms",
+            "column-gap"                 : "webkit moz ms",
+            "column-rule"                : "webkit moz ms",
+            "column-rule-color"          : "webkit moz ms",
+            "column-rule-style"          : "webkit moz ms",
+            "column-rule-width"          : "webkit moz ms",
+            "column-width"               : "webkit moz ms",
+            "hyphens"                    : "epub moz",
+            "line-break"                 : "webkit ms",
+            "margin-end"                 : "webkit moz",
+            "margin-start"               : "webkit moz",
+            "marquee-speed"              : "webkit wap",
+            "marquee-style"              : "webkit wap",
+            "padding-end"                : "webkit moz",
+            "padding-start"              : "webkit moz",
+            "tab-size"                   : "moz o",
+            "text-size-adjust"           : "webkit ms",
+            "transform"                  : "webkit ms",
+            "transform-origin"           : "webkit ms",
+            "transition"                 : "",
+            "transition-delay"           : "",
+            "transition-duration"        : "",
+            "transition-property"        : "",
+            "transition-timing-function" : "",
+            "user-modify"                : "webkit moz",
+            "user-select"                : "webkit moz ms",
+            "word-break"                 : "epub ms",
+            "writing-mode"               : "epub ms"
+        };
+
+
+        for (prop in compatiblePrefixes) {
+            if (compatiblePrefixes.hasOwnProperty(prop)) {
+                variations = [];
+                prefixed = compatiblePrefixes[prop].split(" ");
+                for (i = 0, len = prefixed.length; i < len; i++) {
+                    variations.push("-" + prefixed[i] + "-" + prop);
+                }
+                compatiblePrefixes[prop] = variations;
+                arrayPush.apply(applyTo, variations);
+            }
+        }
+
+        parser.addListener("startrule", function () {
+            properties = [];
+        });
+
+        parser.addListener("startkeyframes", function (event) {
+            inKeyFrame = event.prefix || true;
+        });
+
+        parser.addListener("endkeyframes", function () {
+            inKeyFrame = false;
+        });
+
+        parser.addListener("property", function (event) {
+            var name = event.property;
+            if (CSSLint.Util.indexOf(applyTo, name.text) > -1) {
+
+                // e.g., -moz-transform is okay to be alone in @-moz-keyframes
+                if (!inKeyFrame || typeof inKeyFrame !== "string" ||
+                        name.text.indexOf("-" + inKeyFrame + "-") !== 0) {
+                    properties.push(name);
+                }
+            }
+        });
+
+        parser.addListener("endrule", function () {
+            if (!properties.length) {
+                return;
+            }
+
+            var propertyGroups = {},
+                i,
+                len,
+                name,
+                prop,
+                variations,
+                value,
+                full,
+                actual,
+                item,
+                propertiesSpecified;
+
+            for (i = 0, len = properties.length; i < len; i++) {
+                name = properties[i];
+
+                for (prop in compatiblePrefixes) {
+                    if (compatiblePrefixes.hasOwnProperty(prop)) {
+                        variations = compatiblePrefixes[prop];
+                        if (CSSLint.Util.indexOf(variations, name.text) > -1) {
+                            if (!propertyGroups[prop]) {
+                                propertyGroups[prop] = {
+                                    full: variations.slice(0),
+                                    actual: [],
+                                    actualNodes: []
+                                };
+                            }
+                            if (CSSLint.Util.indexOf(propertyGroups[prop].actual, name.text) === -1) {
+                                propertyGroups[prop].actual.push(name.text);
+                                propertyGroups[prop].actualNodes.push(name);
+                            }
+                        }
+                    }
+                }
+            }
+
+            for (prop in propertyGroups) {
+                if (propertyGroups.hasOwnProperty(prop)) {
+                    value = propertyGroups[prop];
+                    full = value.full;
+                    actual = value.actual;
+
+                    if (full.length > actual.length) {
+                        for (i = 0, len = full.length; i < len; i++) {
+                            item = full[i];
+                            if (CSSLint.Util.indexOf(actual, item) === -1) {
+                                propertiesSpecified = (actual.length === 1) ? actual[0] : (actual.length === 2) ? actual.join(" and ") : actual.join(", ");
+                                reporter.report("The property " + item + " is compatible with " + propertiesSpecified + " and should be included as well.", value.actualNodes[0].line, value.actualNodes[0].col, rule);
+                            }
+                        }
+
+                    }
+                }
+            }
+        });
+    }
+});
+
+/*
+ * Rule: Certain properties don't play well with certain display values.
+ * - float should not be used with inline-block
+ * - height, width, margin-top, margin-bottom, float should not be used with inline
+ * - vertical-align should not be used with block
+ * - margin, float should not be used with table-*
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "display-property-grouping",
+    name: "Require properties appropriate for display",
+    desc: "Certain properties shouldn't be used with certain display property values.",
+    url: "https://github.com/CSSLint/csslint/wiki/Require-properties-appropriate-for-display",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        var propertiesToCheck = {
+                display: 1,
+                "float": "none",
+                height: 1,
+                width: 1,
+                margin: 1,
+                "margin-left": 1,
+                "margin-right": 1,
+                "margin-bottom": 1,
+                "margin-top": 1,
+                padding: 1,
+                "padding-left": 1,
+                "padding-right": 1,
+                "padding-bottom": 1,
+                "padding-top": 1,
+                "vertical-align": 1
+            },
+            properties;
+
+        function reportProperty(name, display, msg) {
+            if (properties[name]) {
+                if (typeof propertiesToCheck[name] !== "string" || properties[name].value.toLowerCase() !== propertiesToCheck[name]) {
+                    reporter.report(msg || name + " can't be used with display: " + display + ".", properties[name].line, properties[name].col, rule);
+                }
+            }
+        }
+
+        function startRule() {
+            properties = {};
+        }
+
+        function endRule() {
+
+            var display = properties.display ? properties.display.value : null;
+            if (display) {
+                switch (display) {
+
+                    case "inline":
+                        // height, width, margin-top, margin-bottom, float should not be used with inline
+                        reportProperty("height", display);
+                        reportProperty("width", display);
+                        reportProperty("margin", display);
+                        reportProperty("margin-top", display);
+                        reportProperty("margin-bottom", display);
+                        reportProperty("float", display, "display:inline has no effect on floated elements (but may be used to fix the IE6 double-margin bug).");
+                        break;
+
+                    case "block":
+                        // vertical-align should not be used with block
+                        reportProperty("vertical-align", display);
+                        break;
+
+                    case "inline-block":
+                        // float should not be used with inline-block
+                        reportProperty("float", display);
+                        break;
+
+                    default:
+                        // margin, float should not be used with table
+                        if (display.indexOf("table-") === 0) {
+                            reportProperty("margin", display);
+                            reportProperty("margin-left", display);
+                            reportProperty("margin-right", display);
+                            reportProperty("margin-top", display);
+                            reportProperty("margin-bottom", display);
+                            reportProperty("float", display);
+                        }
+
+                        // otherwise do nothing
+                }
+            }
+
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startkeyframerule", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startviewport", startRule);
+
+        parser.addListener("property", function(event) {
+            var name = event.property.text.toLowerCase();
+
+            if (propertiesToCheck[name]) {
+                properties[name] = {
+                    value: event.value.text,
+                    line: event.property.line,
+                    col: event.property.col
+                };
+            }
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+        parser.addListener("endkeyframerule", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endpage", endRule);
+        parser.addListener("endviewport", endRule);
+
+    }
+
+});
+
+/*
+ * Rule: Disallow duplicate background-images (using url).
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "duplicate-background-images",
+    name: "Disallow duplicate background images",
+    desc: "Every background-image should be unique. Use a common class for e.g. sprites.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-duplicate-background-images",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            stack = {};
+
+        parser.addListener("property", function(event) {
+            var name = event.property.text,
+                value = event.value,
+                i, len;
+
+            if (name.match(/background/i)) {
+                for (i=0, len=value.parts.length; i < len; i++) {
+                    if (value.parts[i].type === "uri") {
+                        if (typeof stack[value.parts[i].uri] === "undefined") {
+                            stack[value.parts[i].uri] = event;
+                        } else {
+                            reporter.report("Background image '" + value.parts[i].uri + "' was used multiple times, first declared at line " + stack[value.parts[i].uri].line + ", col " + stack[value.parts[i].uri].col + ".", event.line, event.col, rule);
+                        }
+                    }
+                }
+            }
+        });
+    }
+});
+
+/*
+ * Rule: Duplicate properties must appear one after the other. If an already-defined
+ * property appears somewhere else in the rule, then it's likely an error.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "duplicate-properties",
+    name: "Disallow duplicate properties",
+    desc: "Duplicate properties must appear one after the other.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-duplicate-properties",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            properties,
+            lastProperty;
+
+        function startRule() {
+            properties = {};
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);
+        parser.addListener("startviewport", startRule);
+
+        parser.addListener("property", function(event) {
+            var property = event.property,
+                name = property.text.toLowerCase();
+
+            if (properties[name] && (lastProperty !== name || properties[name] === event.value.text)) {
+                reporter.report("Duplicate property '" + event.property + "' found.", event.line, event.col, rule);
+            }
+
+            properties[name] = event.value.text;
+            lastProperty = name;
+
+        });
+
+
+    }
+
+});
+
+/*
+ * Rule: Style rules without any properties defined should be removed.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "empty-rules",
+    name: "Disallow empty rules",
+    desc: "Rules without any properties specified should be removed.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-empty-rules",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            count = 0;
+
+        parser.addListener("startrule", function() {
+            count=0;
+        });
+
+        parser.addListener("property", function() {
+            count++;
+        });
+
+        parser.addListener("endrule", function(event) {
+            var selectors = event.selectors;
+            if (count === 0) {
+                reporter.report("Rule is empty.", selectors[0].line, selectors[0].col, rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: There should be no syntax errors. (Duh.)
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "errors",
+    name: "Parsing Errors",
+    desc: "This rule looks for recoverable syntax errors.",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        parser.addListener("error", function(event) {
+            reporter.error(event.message, event.line, event.col, rule);
+        });
+
+    }
+
+});
+
+CSSLint.addRule({
+
+    // rule information
+    id: "fallback-colors",
+    name: "Require fallback colors",
+    desc: "For older browsers that don't support RGBA, HSL, or HSLA, provide a fallback color.",
+    url: "https://github.com/CSSLint/csslint/wiki/Require-fallback-colors",
+    browsers: "IE6,IE7,IE8",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            lastProperty,
+            propertiesToCheck = {
+                color: 1,
+                background: 1,
+                "border-color": 1,
+                "border-top-color": 1,
+                "border-right-color": 1,
+                "border-bottom-color": 1,
+                "border-left-color": 1,
+                border: 1,
+                "border-top": 1,
+                "border-right": 1,
+                "border-bottom": 1,
+                "border-left": 1,
+                "background-color": 1
+            };
+
+        function startRule() {
+            lastProperty = null;
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);
+        parser.addListener("startviewport", startRule);
+
+        parser.addListener("property", function(event) {
+            var property = event.property,
+                name = property.text.toLowerCase(),
+                parts = event.value.parts,
+                i = 0,
+                colorType = "",
+                len = parts.length;
+
+            if (propertiesToCheck[name]) {
+                while (i < len) {
+                    if (parts[i].type === "color") {
+                        if ("alpha" in parts[i] || "hue" in parts[i]) {
+
+                            if (/([^\)]+)\(/.test(parts[i])) {
+                                colorType = RegExp.$1.toUpperCase();
+                            }
+
+                            if (!lastProperty || (lastProperty.property.text.toLowerCase() !== name || lastProperty.colorType !== "compat")) {
+                                reporter.report("Fallback " + name + " (hex or RGB) should precede " + colorType + " " + name + ".", event.line, event.col, rule);
+                            }
+                        } else {
+                            event.colorType = "compat";
+                        }
+                    }
+
+                    i++;
+                }
+            }
+
+            lastProperty = event;
+        });
+
+    }
+
+});
+
+/*
+ * Rule: You shouldn't use more than 10 floats. If you do, there's probably
+ * room for some abstraction.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "floats",
+    name: "Disallow too many floats",
+    desc: "This rule tests if the float property is used too many times",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-too-many-floats",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+        var count = 0;
+
+        // count how many times "float" is used
+        parser.addListener("property", function(event) {
+            if (event.property.text.toLowerCase() === "float" &&
+                    event.value.text.toLowerCase() !== "none") {
+                count++;
+            }
+        });
+
+        // report the results
+        parser.addListener("endstylesheet", function() {
+            reporter.stat("floats", count);
+            if (count >= 10) {
+                reporter.rollupWarn("Too many floats (" + count + "), you're probably using them for layout. Consider using a grid system instead.", rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Avoid too many @font-face declarations in the same stylesheet.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "font-faces",
+    name: "Don't use too many web fonts",
+    desc: "Too many different web fonts in the same stylesheet.",
+    url: "https://github.com/CSSLint/csslint/wiki/Don%27t-use-too-many-web-fonts",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            count = 0;
+
+
+        parser.addListener("startfontface", function() {
+            count++;
+        });
+
+        parser.addListener("endstylesheet", function() {
+            if (count > 5) {
+                reporter.rollupWarn("Too many @font-face declarations (" + count + ").", rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: You shouldn't need more than 9 font-size declarations.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "font-sizes",
+    name: "Disallow too many font sizes",
+    desc: "Checks the number of font-size declarations.",
+    url: "https://github.com/CSSLint/csslint/wiki/Don%27t-use-too-many-font-size-declarations",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            count = 0;
+
+        // check for use of "font-size"
+        parser.addListener("property", function(event) {
+            if (event.property.toString() === "font-size") {
+                count++;
+            }
+        });
+
+        // report the results
+        parser.addListener("endstylesheet", function() {
+            reporter.stat("font-sizes", count);
+            if (count >= 10) {
+                reporter.rollupWarn("Too many font-size declarations (" + count + "), abstraction needed.", rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: When using a vendor-prefixed gradient, make sure to use them all.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "gradients",
+    name: "Require all gradient definitions",
+    desc: "When using a vendor-prefixed gradient, make sure to use them all.",
+    url: "https://github.com/CSSLint/csslint/wiki/Require-all-gradient-definitions",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            gradients;
+
+        parser.addListener("startrule", function() {
+            gradients = {
+                moz: 0,
+                webkit: 0,
+                oldWebkit: 0,
+                o: 0
+            };
+        });
+
+        parser.addListener("property", function(event) {
+
+            if (/\-(moz|o|webkit)(?:\-(?:linear|radial))\-gradient/i.test(event.value)) {
+                gradients[RegExp.$1] = 1;
+            } else if (/\-webkit\-gradient/i.test(event.value)) {
+                gradients.oldWebkit = 1;
+            }
+
+        });
+
+        parser.addListener("endrule", function(event) {
+            var missing = [];
+
+            if (!gradients.moz) {
+                missing.push("Firefox 3.6+");
+            }
+
+            if (!gradients.webkit) {
+                missing.push("Webkit (Safari 5+, Chrome)");
+            }
+
+            if (!gradients.oldWebkit) {
+                missing.push("Old Webkit (Safari 4+, Chrome)");
+            }
+
+            if (!gradients.o) {
+                missing.push("Opera 11.1+");
+            }
+
+            if (missing.length && missing.length < 4) {
+                reporter.report("Missing vendor-prefixed CSS gradients for " + missing.join(", ") + ".", event.selectors[0].line, event.selectors[0].col, rule);
+            }
+
+        });
+
+    }
+
+});
+
+/*
+ * Rule: Don't use IDs for selectors.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "ids",
+    name: "Disallow IDs in selectors",
+    desc: "Selectors should not contain IDs.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-IDs-in-selectors",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+        parser.addListener("startrule", function(event) {
+            var selectors = event.selectors,
+                selector,
+                part,
+                modifier,
+                idCount,
+                i, j, k;
+
+            for (i=0; i < selectors.length; i++) {
+                selector = selectors[i];
+                idCount = 0;
+
+                for (j=0; j < selector.parts.length; j++) {
+                    part = selector.parts[j];
+                    if (part.type === parser.SELECTOR_PART_TYPE) {
+                        for (k=0; k < part.modifiers.length; k++) {
+                            modifier = part.modifiers[k];
+                            if (modifier.type === "id") {
+                                idCount++;
+                            }
+                        }
+                    }
+                }
+
+                if (idCount === 1) {
+                    reporter.report("Don't use IDs in selectors.", selector.line, selector.col, rule);
+                } else if (idCount > 1) {
+                    reporter.report(idCount + " IDs in the selector, really?", selector.line, selector.col, rule);
+                }
+            }
+
+        });
+    }
+
+});
+
+/*
+ * Rule: IE6-9 supports up to 31 stylesheet import.
+ * Reference:
+ * http://blogs.msdn.com/b/ieinternals/archive/2011/05/14/internet-explorer-stylesheet-rule-selector-import-sheet-limit-maximum.aspx
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "import-ie-limit",
+    name: "@import limit on IE6-IE9",
+    desc: "IE6-9 supports up to 31 @import per stylesheet",
+    browsers: "IE6, IE7, IE8, IE9",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            MAX_IMPORT_COUNT = 31,
+            count = 0;
+
+        function startPage() {
+            count = 0;
+        }
+
+        parser.addListener("startpage", startPage);
+
+        parser.addListener("import", function() {
+            count++;
+        });
+
+        parser.addListener("endstylesheet", function() {
+            if (count > MAX_IMPORT_COUNT) {
+                reporter.rollupError(
+                    "Too many @import rules (" + count + "). IE6-9 supports up to 31 import per stylesheet.",
+                    rule
+                );
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Don't use @import, use <link> instead.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "import",
+    name: "Disallow @import",
+    desc: "Don't use @import, use <link> instead.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-%40import",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        parser.addListener("import", function(event) {
+            reporter.report("@import prevents parallel downloads, use <link> instead.", event.line, event.col, rule);
+        });
+
+    }
+
+});
+
+/*
+ * Rule: Make sure !important is not overused, this could lead to specificity
+ * war. Display a warning on !important declarations, an error if it's
+ * used more at least 10 times.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "important",
+    name: "Disallow !important",
+    desc: "Be careful when using !important declaration",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-%21important",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            count = 0;
+
+        // warn that important is used and increment the declaration counter
+        parser.addListener("property", function(event) {
+            if (event.important === true) {
+                count++;
+                reporter.report("Use of !important", event.line, event.col, rule);
+            }
+        });
+
+        // if there are more than 10, show an error
+        parser.addListener("endstylesheet", function() {
+            reporter.stat("important", count);
+            if (count >= 10) {
+                reporter.rollupWarn("Too many !important declarations (" + count + "), try to use less than 10 to avoid specificity issues.", rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Properties should be known (listed in CSS3 specification) or
+ * be a vendor-prefixed property.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "known-properties",
+    name: "Require use of known properties",
+    desc: "Properties should be known (listed in CSS3 specification) or be a vendor-prefixed property.",
+    url: "https://github.com/CSSLint/csslint/wiki/Require-use-of-known-properties",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        parser.addListener("property", function(event) {
+
+            // the check is handled entirely by the parser-lib (https://github.com/nzakas/parser-lib)
+            if (event.invalid) {
+                reporter.report(event.invalid.message, event.line, event.col, rule);
+            }
+
+        });
+    }
+
+});
+
+/*
+ * Rule: All properties should be in alphabetical order.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "order-alphabetical",
+    name: "Alphabetical order",
+    desc: "Assure properties are in alphabetical order",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            properties;
+
+        var startRule = function () {
+            properties = [];
+        };
+
+        var endRule = function(event) {
+            var currentProperties = properties.join(","),
+                expectedProperties = properties.sort().join(",");
+
+            if (currentProperties !== expectedProperties) {
+                reporter.report("Rule doesn't have all its properties in alphabetical order.", event.line, event.col, rule);
+            }
+        };
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);
+        parser.addListener("startviewport", startRule);
+
+        parser.addListener("property", function(event) {
+            var name = event.property.text,
+                lowerCasePrefixLessName = name.toLowerCase().replace(/^-.*?-/, "");
+
+            properties.push(lowerCasePrefixLessName);
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+        parser.addListener("endpage", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endkeyframerule", endRule);
+        parser.addListener("endviewport", endRule);
+    }
+
+});
+
+/*
+ * Rule: outline: none or outline: 0 should only be used in a :focus rule
+ *       and only if there are other properties in the same rule.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "outline-none",
+    name: "Disallow outline: none",
+    desc: "Use of outline: none or outline: 0 should be limited to :focus rules.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-outline%3Anone",
+    browsers: "All",
+    tags: ["Accessibility"],
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            lastRule;
+
+        function startRule(event) {
+            if (event.selectors) {
+                lastRule = {
+                    line: event.line,
+                    col: event.col,
+                    selectors: event.selectors,
+                    propCount: 0,
+                    outline: false
+                };
+            } else {
+                lastRule = null;
+            }
+        }
+
+        function endRule() {
+            if (lastRule) {
+                if (lastRule.outline) {
+                    if (lastRule.selectors.toString().toLowerCase().indexOf(":focus") === -1) {
+                        reporter.report("Outlines should only be modified using :focus.", lastRule.line, lastRule.col, rule);
+                    } else if (lastRule.propCount === 1) {
+                        reporter.report("Outlines shouldn't be hidden unless other visual changes are made.", lastRule.line, lastRule.col, rule);
+                    }
+                }
+            }
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);
+        parser.addListener("startviewport", startRule);
+
+        parser.addListener("property", function(event) {
+            var name = event.property.text.toLowerCase(),
+                value = event.value;
+
+            if (lastRule) {
+                lastRule.propCount++;
+                if (name === "outline" && (value.toString() === "none" || value.toString() === "0")) {
+                    lastRule.outline = true;
+                }
+            }
+
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+        parser.addListener("endpage", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endkeyframerule", endRule);
+        parser.addListener("endviewport", endRule);
+
+    }
+
+});
+
+/*
+ * Rule: Don't use classes or IDs with elements (a.foo or a#foo).
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "overqualified-elements",
+    name: "Disallow overqualified elements",
+    desc: "Don't use classes or IDs with elements (a.foo or a#foo).",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-overqualified-elements",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            classes = {};
+
+        parser.addListener("startrule", function(event) {
+            var selectors = event.selectors,
+                selector,
+                part,
+                modifier,
+                i, j, k;
+
+            for (i=0; i < selectors.length; i++) {
+                selector = selectors[i];
+
+                for (j=0; j < selector.parts.length; j++) {
+                    part = selector.parts[j];
+                    if (part.type === parser.SELECTOR_PART_TYPE) {
+                        for (k=0; k < part.modifiers.length; k++) {
+                            modifier = part.modifiers[k];
+                            if (part.elementName && modifier.type === "id") {
+                                reporter.report("Element (" + part + ") is overqualified, just use " + modifier + " without element name.", part.line, part.col, rule);
+                            } else if (modifier.type === "class") {
+
+                                if (!classes[modifier]) {
+                                    classes[modifier] = [];
+                                }
+                                classes[modifier].push({
+                                    modifier: modifier,
+                                    part: part
+                                });
+                            }
+                        }
+                    }
+                }
+            }
+        });
+
+        parser.addListener("endstylesheet", function() {
+
+            var prop;
+            for (prop in classes) {
+                if (classes.hasOwnProperty(prop)) {
+
+                    // one use means that this is overqualified
+                    if (classes[prop].length === 1 && classes[prop][0].part.elementName) {
+                        reporter.report("Element (" + classes[prop][0].part + ") is overqualified, just use " + classes[prop][0].modifier + " without element name.", classes[prop][0].part.line, classes[prop][0].part.col, rule);
+                    }
+                }
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Headings (h1-h6) should not be qualified (namespaced).
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "qualified-headings",
+    name: "Disallow qualified headings",
+    desc: "Headings should not be qualified (namespaced).",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-qualified-headings",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        parser.addListener("startrule", function(event) {
+            var selectors = event.selectors,
+                selector,
+                part,
+                i, j;
+
+            for (i=0; i < selectors.length; i++) {
+                selector = selectors[i];
+
+                for (j=0; j < selector.parts.length; j++) {
+                    part = selector.parts[j];
+                    if (part.type === parser.SELECTOR_PART_TYPE) {
+                        if (part.elementName && /h[1-6]/.test(part.elementName.toString()) && j > 0) {
+                            reporter.report("Heading (" + part.elementName + ") should not be qualified.", part.line, part.col, rule);
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Selectors that look like regular expressions are slow and should be avoided.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "regex-selectors",
+    name: "Disallow selectors that look like regexs",
+    desc: "Selectors that look like regular expressions are slow and should be avoided.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-selectors-that-look-like-regular-expressions",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        parser.addListener("startrule", function(event) {
+            var selectors = event.selectors,
+                selector,
+                part,
+                modifier,
+                i, j, k;
+
+            for (i=0; i < selectors.length; i++) {
+                selector = selectors[i];
+                for (j=0; j < selector.parts.length; j++) {
+                    part = selector.parts[j];
+                    if (part.type === parser.SELECTOR_PART_TYPE) {
+                        for (k=0; k < part.modifiers.length; k++) {
+                            modifier = part.modifiers[k];
+                            if (modifier.type === "attribute") {
+                                if (/([~\|\^\$\*]=)/.test(modifier)) {
+                                    reporter.report("Attribute selectors with " + RegExp.$1 + " are slow!", modifier.line, modifier.col, rule);
+                                }
+                            }
+
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Total number of rules should not exceed x.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "rules-count",
+    name: "Rules Count",
+    desc: "Track how many rules there are.",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var count = 0;
+
+        // count each rule
+        parser.addListener("startrule", function() {
+            count++;
+        });
+
+        parser.addListener("endstylesheet", function() {
+            reporter.stat("rule-count", count);
+        });
+    }
+
+});
+
+/*
+ * Rule: Warn people with approaching the IE 4095 limit
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "selector-max-approaching",
+    name: "Warn when approaching the 4095 selector limit for IE",
+    desc: "Will warn when selector count is >= 3800 selectors.",
+    browsers: "IE",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this, count = 0;
+
+        parser.addListener("startrule", function(event) {
+            count += event.selectors.length;
+        });
+
+        parser.addListener("endstylesheet", function() {
+            if (count >= 3800) {
+                reporter.report("You have " + count + " selectors. Internet Explorer supports a maximum of 4095 selectors per stylesheet. Consider refactoring.", 0, 0, rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Warn people past the IE 4095 limit
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "selector-max",
+    name: "Error when past the 4095 selector limit for IE",
+    desc: "Will error when selector count is > 4095.",
+    browsers: "IE",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this, count = 0;
+
+        parser.addListener("startrule", function(event) {
+            count += event.selectors.length;
+        });
+
+        parser.addListener("endstylesheet", function() {
+            if (count > 4095) {
+                reporter.report("You have " + count + " selectors. Internet Explorer supports a maximum of 4095 selectors per stylesheet. Consider refactoring.", 0, 0, rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Avoid new-line characters in selectors.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "selector-newline",
+    name: "Disallow new-line characters in selectors",
+    desc: "New-line characters in selectors are usually a forgotten comma and not a descendant combinator.",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        function startRule(event) {
+            var i, len, selector, p, n, pLen, part, part2, type, currentLine, nextLine,
+                selectors = event.selectors;
+
+            for (i = 0, len = selectors.length; i < len; i++) {
+                selector = selectors[i];
+                for (p = 0, pLen = selector.parts.length; p < pLen; p++) {
+                    for (n = p + 1; n < pLen; n++) {
+                        part = selector.parts[p];
+                        part2 = selector.parts[n];
+                        type = part.type;
+                        currentLine = part.line;
+                        nextLine = part2.line;
+
+                        if (type === "descendant" && nextLine > currentLine) {
+                            reporter.report("newline character found in selector (forgot a comma?)", currentLine, selectors[i].parts[0].col, rule);
+                        }
+                    }
+                }
+
+            }
+        }
+
+        parser.addListener("startrule", startRule);
+
+    }
+});
+
+/*
+ * Rule: Use shorthand properties where possible.
+ *
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "shorthand",
+    name: "Require shorthand properties",
+    desc: "Use shorthand properties where possible.",
+    url: "https://github.com/CSSLint/csslint/wiki/Require-shorthand-properties",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            prop, i, len,
+            propertiesToCheck = {},
+            properties,
+            mapping = {
+                "margin": [
+                    "margin-top",
+                    "margin-bottom",
+                    "margin-left",
+                    "margin-right"
+                ],
+                "padding": [
+                    "padding-top",
+                    "padding-bottom",
+                    "padding-left",
+                    "padding-right"
+                ]
+            };
+
+        // initialize propertiesToCheck
+        for (prop in mapping) {
+            if (mapping.hasOwnProperty(prop)) {
+                for (i=0, len=mapping[prop].length; i < len; i++) {
+                    propertiesToCheck[mapping[prop][i]] = prop;
+                }
+            }
+        }
+
+        function startRule() {
+            properties = {};
+        }
+
+        // event handler for end of rules
+        function endRule(event) {
+
+            var prop, i, len, total;
+
+            // check which properties this rule has
+            for (prop in mapping) {
+                if (mapping.hasOwnProperty(prop)) {
+                    total=0;
+
+                    for (i=0, len=mapping[prop].length; i < len; i++) {
+                        total += properties[mapping[prop][i]] ? 1 : 0;
+                    }
+
+                    if (total === mapping[prop].length) {
+                        reporter.report("The properties " + mapping[prop].join(", ") + " can be replaced by " + prop + ".", event.line, event.col, rule);
+                    }
+                }
+            }
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+
+        // check for use of "font-size"
+        parser.addListener("property", function(event) {
+            var name = event.property.toString().toLowerCase();
+
+            if (propertiesToCheck[name]) {
+                properties[name] = 1;
+            }
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+
+    }
+
+});
+
+/*
+ * Rule: Don't use properties with a star prefix.
+ *
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "star-property-hack",
+    name: "Disallow properties with a star prefix",
+    desc: "Checks for the star property hack (targets IE6/7)",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-star-hack",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        // check if property name starts with "*"
+        parser.addListener("property", function(event) {
+            var property = event.property;
+
+            if (property.hack === "*") {
+                reporter.report("Property with star prefix found.", event.property.line, event.property.col, rule);
+            }
+        });
+    }
+});
+
+/*
+ * Rule: Don't use text-indent for image replacement if you need to support rtl.
+ *
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "text-indent",
+    name: "Disallow negative text-indent",
+    desc: "Checks for text indent less than -99px",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-negative-text-indent",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            textIndent,
+            direction;
+
+
+        function startRule() {
+            textIndent = false;
+            direction = "inherit";
+        }
+
+        // event handler for end of rules
+        function endRule() {
+            if (textIndent && direction !== "ltr") {
+                reporter.report("Negative text-indent doesn't work well with RTL. If you use text-indent for image replacement explicitly set direction for that item to ltr.", textIndent.line, textIndent.col, rule);
+            }
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+
+        // check for use of "font-size"
+        parser.addListener("property", function(event) {
+            var name = event.property.toString().toLowerCase(),
+                value = event.value;
+
+            if (name === "text-indent" && value.parts[0].value < -99) {
+                textIndent = event.property;
+            } else if (name === "direction" && value.toString() === "ltr") {
+                direction = "ltr";
+            }
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+
+    }
+
+});
+
+/*
+ * Rule: Don't use properties with a underscore prefix.
+ *
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "underscore-property-hack",
+    name: "Disallow properties with an underscore prefix",
+    desc: "Checks for the underscore property hack (targets IE6)",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-underscore-hack",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        // check if property name starts with "_"
+        parser.addListener("property", function(event) {
+            var property = event.property;
+
+            if (property.hack === "_") {
+                reporter.report("Property with underscore prefix found.", event.property.line, event.property.col, rule);
+            }
+        });
+    }
+});
+
+/*
+ * Rule: Headings (h1-h6) should be defined only once.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "unique-headings",
+    name: "Headings should only be defined once",
+    desc: "Headings should be defined only once.",
+    url: "https://github.com/CSSLint/csslint/wiki/Headings-should-only-be-defined-once",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        var headings = {
+            h1: 0,
+            h2: 0,
+            h3: 0,
+            h4: 0,
+            h5: 0,
+            h6: 0
+        };
+
+        parser.addListener("startrule", function(event) {
+            var selectors = event.selectors,
+                selector,
+                part,
+                pseudo,
+                i, j;
+
+            for (i=0; i < selectors.length; i++) {
+                selector = selectors[i];
+                part = selector.parts[selector.parts.length-1];
+
+                if (part.elementName && /(h[1-6])/i.test(part.elementName.toString())) {
+
+                    for (j=0; j < part.modifiers.length; j++) {
+                        if (part.modifiers[j].type === "pseudo") {
+                            pseudo = true;
+                            break;
+                        }
+                    }
+
+                    if (!pseudo) {
+                        headings[RegExp.$1]++;
+                        if (headings[RegExp.$1] > 1) {
+                            reporter.report("Heading (" + part.elementName + ") has already been defined.", part.line, part.col, rule);
+                        }
+                    }
+                }
+            }
+        });
+
+        parser.addListener("endstylesheet", function() {
+            var prop,
+                messages = [];
+
+            for (prop in headings) {
+                if (headings.hasOwnProperty(prop)) {
+                    if (headings[prop] > 1) {
+                        messages.push(headings[prop] + " " + prop + "s");
+                    }
+                }
+            }
+
+            if (messages.length) {
+                reporter.rollupWarn("You have " + messages.join(", ") + " defined in this stylesheet.", rule);
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Don't use universal selector because it's slow.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "universal-selector",
+    name: "Disallow universal selector",
+    desc: "The universal selector (*) is known to be slow.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-universal-selector",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        parser.addListener("startrule", function(event) {
+            var selectors = event.selectors,
+                selector,
+                part,
+                i;
+
+            for (i=0; i < selectors.length; i++) {
+                selector = selectors[i];
+
+                part = selector.parts[selector.parts.length-1];
+                if (part.elementName === "*") {
+                    reporter.report(rule.desc, part.line, part.col, rule);
+                }
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: Don't use unqualified attribute selectors because they're just like universal selectors.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "unqualified-attributes",
+    name: "Disallow unqualified attribute selectors",
+    desc: "Unqualified attribute selectors are known to be slow.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-unqualified-attribute-selectors",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+
+        var rule = this;
+
+        parser.addListener("startrule", function(event) {
+
+            var selectors = event.selectors,
+                selectorContainsClassOrId = false,
+                selector,
+                part,
+                modifier,
+                i, k;
+
+            for (i=0; i < selectors.length; i++) {
+                selector = selectors[i];
+
+                part = selector.parts[selector.parts.length-1];
+                if (part.type === parser.SELECTOR_PART_TYPE) {
+                    for (k=0; k < part.modifiers.length; k++) {
+                        modifier = part.modifiers[k];
+
+                        if (modifier.type === "class" || modifier.type === "id") {
+                            selectorContainsClassOrId = true;
+                            break;
+                        }
+                    }
+
+                    if (!selectorContainsClassOrId) {
+                        for (k=0; k < part.modifiers.length; k++) {
+                            modifier = part.modifiers[k];
+                            if (modifier.type === "attribute" && (!part.elementName || part.elementName === "*")) {
+                                reporter.report(rule.desc, part.line, part.col, rule);
+                            }
+                        }
+                    }
+                }
+
+            }
+        });
+    }
+
+});
+
+/*
+ * Rule: When using a vendor-prefixed property, make sure to
+ * include the standard one.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "vendor-prefix",
+    name: "Require standard property with vendor prefix",
+    desc: "When using a vendor-prefixed property, make sure to include the standard one.",
+    url: "https://github.com/CSSLint/csslint/wiki/Require-standard-property-with-vendor-prefix",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this,
+            properties,
+            num,
+            propertiesToCheck = {
+                "-webkit-border-radius": "border-radius",
+                "-webkit-border-top-left-radius": "border-top-left-radius",
+                "-webkit-border-top-right-radius": "border-top-right-radius",
+                "-webkit-border-bottom-left-radius": "border-bottom-left-radius",
+                "-webkit-border-bottom-right-radius": "border-bottom-right-radius",
+
+                "-o-border-radius": "border-radius",
+                "-o-border-top-left-radius": "border-top-left-radius",
+                "-o-border-top-right-radius": "border-top-right-radius",
+                "-o-border-bottom-left-radius": "border-bottom-left-radius",
+                "-o-border-bottom-right-radius": "border-bottom-right-radius",
+
+                "-moz-border-radius": "border-radius",
+                "-moz-border-radius-topleft": "border-top-left-radius",
+                "-moz-border-radius-topright": "border-top-right-radius",
+                "-moz-border-radius-bottomleft": "border-bottom-left-radius",
+                "-moz-border-radius-bottomright": "border-bottom-right-radius",
+
+                "-moz-column-count": "column-count",
+                "-webkit-column-count": "column-count",
+
+                "-moz-column-gap": "column-gap",
+                "-webkit-column-gap": "column-gap",
+
+                "-moz-column-rule": "column-rule",
+                "-webkit-column-rule": "column-rule",
+
+                "-moz-column-rule-style": "column-rule-style",
+                "-webkit-column-rule-style": "column-rule-style",
+
+                "-moz-column-rule-color": "column-rule-color",
+                "-webkit-column-rule-color": "column-rule-color",
+
+                "-moz-column-rule-width": "column-rule-width",
+                "-webkit-column-rule-width": "column-rule-width",
+
+                "-moz-column-width": "column-width",
+                "-webkit-column-width": "column-width",
+
+                "-webkit-column-span": "column-span",
+                "-webkit-columns": "columns",
+
+                "-moz-box-shadow": "box-shadow",
+                "-webkit-box-shadow": "box-shadow",
+
+                "-moz-transform": "transform",
+                "-webkit-transform": "transform",
+                "-o-transform": "transform",
+                "-ms-transform": "transform",
+
+                "-moz-transform-origin": "transform-origin",
+                "-webkit-transform-origin": "transform-origin",
+                "-o-transform-origin": "transform-origin",
+                "-ms-transform-origin": "transform-origin",
+
+                "-moz-box-sizing": "box-sizing",
+                "-webkit-box-sizing": "box-sizing"
+            };
+
+        // event handler for beginning of rules
+        function startRule() {
+            properties = {};
+            num = 1;
+        }
+
+        // event handler for end of rules
+        function endRule() {
+            var prop,
+                i,
+                len,
+                needed,
+                actual,
+                needsStandard = [];
+
+            for (prop in properties) {
+                if (propertiesToCheck[prop]) {
+                    needsStandard.push({
+                        actual: prop,
+                        needed: propertiesToCheck[prop]
+                    });
+                }
+            }
+
+            for (i=0, len=needsStandard.length; i < len; i++) {
+                needed = needsStandard[i].needed;
+                actual = needsStandard[i].actual;
+
+                if (!properties[needed]) {
+                    reporter.report("Missing standard property '" + needed + "' to go along with '" + actual + "'.", properties[actual][0].name.line, properties[actual][0].name.col, rule);
+                } else {
+                    // make sure standard property is last
+                    if (properties[needed][0].pos < properties[actual][0].pos) {
+                        reporter.report("Standard property '" + needed + "' should come after vendor-prefixed property '" + actual + "'.", properties[actual][0].name.line, properties[actual][0].name.col, rule);
+                    }
+                }
+            }
+
+        }
+
+        parser.addListener("startrule", startRule);
+        parser.addListener("startfontface", startRule);
+        parser.addListener("startpage", startRule);
+        parser.addListener("startpagemargin", startRule);
+        parser.addListener("startkeyframerule", startRule);
+        parser.addListener("startviewport", startRule);
+
+        parser.addListener("property", function(event) {
+            var name = event.property.text.toLowerCase();
+
+            if (!properties[name]) {
+                properties[name] = [];
+            }
+
+            properties[name].push({
+                name: event.property,
+                value: event.value,
+                pos: num++
+            });
+        });
+
+        parser.addListener("endrule", endRule);
+        parser.addListener("endfontface", endRule);
+        parser.addListener("endpage", endRule);
+        parser.addListener("endpagemargin", endRule);
+        parser.addListener("endkeyframerule", endRule);
+        parser.addListener("endviewport", endRule);
+    }
+
+});
+
+/*
+ * Rule: You don't need to specify units when a value is 0.
+ */
+
+CSSLint.addRule({
+
+    // rule information
+    id: "zero-units",
+    name: "Disallow units for 0 values",
+    desc: "You don't need to specify units when a value is 0.",
+    url: "https://github.com/CSSLint/csslint/wiki/Disallow-units-for-zero-values",
+    browsers: "All",
+
+    // initialization
+    init: function(parser, reporter) {
+        "use strict";
+        var rule = this;
+
+        // count how many times "float" is used
+        parser.addListener("property", function(event) {
+            var parts = event.value.parts,
+                i = 0,
+                len = parts.length;
+
+            while (i < len) {
+                if ((parts[i].units || parts[i].type === "percentage") && parts[i].value === 0 && parts[i].type !== "time") {
+                    reporter.report("Values of 0 shouldn't have units specified.", parts[i].line, parts[i].col, rule);
+                }
+                i++;
+            }
+
+        });
+
+    }
+
+});
+
+(function() {
+    "use strict";
+
+    /**
+     * Replace special characters before write to output.
+     *
+     * Rules:
+     *  - single quotes is the escape sequence for double-quotes
+     *  - &amp; is the escape sequence for &
+     *  - &lt; is the escape sequence for <
+     *  - &gt; is the escape sequence for >
+     *
+     * @param {String} message to escape
+     * @return escaped message as {String}
+     */
+    var xmlEscape = function(str) {
+        if (!str || str.constructor !== String) {
+            return "";
+        }
+
+        return str.replace(/["&><]/g, function(match) {
+            switch (match) {
+                case "\"":
+                    return "&quot;";
+                case "&":
+                    return "&amp;";
+                case "<":
+                    return "&lt;";
+                case ">":
+                    return "&gt;";
+            }
+        });
+    };
+
+    CSSLint.addFormatter({
+        // format information
+        id: "checkstyle-xml",
+        name: "Checkstyle XML format",
+
+        /**
+         * Return opening root XML tag.
+         * @return {String} to prepend before all results
+         */
+        startFormat: function() {
+            return "<?xml version=\"1.0\" encoding=\"utf-8\"?><checkstyle>";
+        },
+
+        /**
+         * Return closing root XML tag.
+         * @return {String} to append after all results
+         */
+        endFormat: function() {
+            return "</checkstyle>";
+        },
+
+        /**
+         * Returns message when there is a file read error.
+         * @param {String} filename The name of the file that caused the error.
+         * @param {String} message The error message
+         * @return {String} The error message.
+         */
+        readError: function(filename, message) {
+            return "<file name=\"" + xmlEscape(filename) + "\"><error line=\"0\" column=\"0\" severty=\"error\" message=\"" + xmlEscape(message) + "\"></error></file>";
+        },
+
+        /**
+         * Given CSS Lint results for a file, return output for this format.
+         * @param results {Object} with error and warning messages
+         * @param filename {String} relative file path
+         * @param options {Object} (UNUSED for now) specifies special handling of output
+         * @return {String} output for results
+         */
+        formatResults: function(results, filename/*, options*/) {
+            var messages = results.messages,
+                output = [];
+
+            /**
+             * Generate a source string for a rule.
+             * Checkstyle source strings usually resemble Java class names e.g
+             * net.csslint.SomeRuleName
+             * @param {Object} rule
+             * @return rule source as {String}
+             */
+            var generateSource = function(rule) {
+                if (!rule || !("name" in rule)) {
+                    return "";
+                }
+                return "net.csslint." + rule.name.replace(/\s/g, "");
+            };
+
+
+            if (messages.length > 0) {
+                output.push("<file name=\""+filename+"\">");
+                CSSLint.Util.forEach(messages, function (message) {
+                    // ignore rollups for now
+                    if (!message.rollup) {
+                        output.push("<error line=\"" + message.line + "\" column=\"" + message.col + "\" severity=\"" + message.type + "\"" +
+                          " message=\"" + xmlEscape(message.message) + "\" source=\"" + generateSource(message.rule) +"\"/>");
+                    }
+                });
+                output.push("</file>");
+            }
+
+            return output.join("");
+        }
+    });
+
+}());
+
+CSSLint.addFormatter({
+    // format information
+    id: "compact",
+    name: "Compact, 'porcelain' format",
+
+    /**
+     * Return content to be printed before all file results.
+     * @return {String} to prepend before all results
+     */
+    startFormat: function() {
+        "use strict";
+        return "";
+    },
+
+    /**
+     * Return content to be printed after all file results.
+     * @return {String} to append after all results
+     */
+    endFormat: function() {
+        "use strict";
+        return "";
+    },
+
+    /**
+     * Given CSS Lint results for a file, return output for this format.
+     * @param results {Object} with error and warning messages
+     * @param filename {String} relative file path
+     * @param options {Object} (Optional) specifies special handling of output
+     * @return {String} output for results
+     */
+    formatResults: function(results, filename, options) {
+        "use strict";
+        var messages = results.messages,
+            output = "";
+        options = options || {};
+
+        /**
+         * Capitalize and return given string.
+         * @param str {String} to capitalize
+         * @return {String} capitalized
+         */
+        var capitalize = function(str) {
+            return str.charAt(0).toUpperCase() + str.slice(1);
+        };
+
+        if (messages.length === 0) {
+            return options.quiet ? "" : filename + ": Lint Free!";
+        }
+
+        CSSLint.Util.forEach(messages, function(message) {
+            if (message.rollup) {
+                output += filename + ": " + capitalize(message.type) + " - " + message.message + " (" + message.rule.id + ")\n";
+            } else {
+                output += filename + ": line " + message.line +
+                    ", col " + message.col + ", " + capitalize(message.type) + " - " + message.message + " (" + message.rule.id + ")\n";
+            }
+        });
+
+        return output;
+    }
+});
+
+CSSLint.addFormatter({
+    // format information
+    id: "csslint-xml",
+    name: "CSSLint XML format",
+
+    /**
+     * Return opening root XML tag.
+     * @return {String} to prepend before all results
+     */
+    startFormat: function() {
+        "use strict";
+        return "<?xml version=\"1.0\" encoding=\"utf-8\"?><csslint>";
+    },
+
+    /**
+     * Return closing root XML tag.
+     * @return {String} to append after all results
+     */
+    endFormat: function() {
+        "use strict";
+        return "</csslint>";
+    },
+
+    /**
+     * Given CSS Lint results for a file, return output for this format.
+     * @param results {Object} with error and warning messages
+     * @param filename {String} relative file path
+     * @param options {Object} (UNUSED for now) specifies special handling of output
+     * @return {String} output for results
+     */
+    formatResults: function(results, filename/*, options*/) {
+        "use strict";
+        var messages = results.messages,
+            output = [];
+
+        /**
+         * Replace special characters before write to output.
+         *
+         * Rules:
+         *  - single quotes is the escape sequence for double-quotes
+         *  - &amp; is the escape sequence for &
+         *  - &lt; is the escape sequence for <
+         *  - &gt; is the escape sequence for >
+         *
+         * @param {String} message to escape
+         * @return escaped message as {String}
+         */
+        var escapeSpecialCharacters = function(str) {
+            if (!str || str.constructor !== String) {
+                return "";
+            }
+            return str.replace(/"/g, "'").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
+        };
+
+        if (messages.length > 0) {
+            output.push("<file name=\""+filename+"\">");
+            CSSLint.Util.forEach(messages, function (message) {
+                if (message.rollup) {
+                    output.push("<issue severity=\"" + message.type + "\" reason=\"" + escapeSpecialCharacters(message.message) + "\" evidence=\"" + escapeSpecialCharacters(message.evidence) + "\"/>");
+                } else {
+                    output.push("<issue line=\"" + message.line + "\" char=\"" + message.col + "\" severity=\"" + message.type + "\"" +
+                        " reason=\"" + escapeSpecialCharacters(message.message) + "\" evidence=\"" + escapeSpecialCharacters(message.evidence) + "\"/>");
+                }
+            });
+            output.push("</file>");
+        }
+
+        return output.join("");
+    }
+});
+
+/* globals JSON: true */
+
+CSSLint.addFormatter({
+    // format information
+    id: "json",
+    name: "JSON",
+
+    /**
+     * Return content to be printed before all file results.
+     * @return {String} to prepend before all results
+     */
+    startFormat: function() {
+        "use strict";
+        this.json = [];
+        return "";
+    },
+
+    /**
+     * Return content to be printed after all file results.
+     * @return {String} to append after all results
+     */
+    endFormat: function() {
+        "use strict";
+        var ret = "";
+        if (this.json.length > 0) {
+            if (this.json.length === 1) {
+                ret = JSON.stringify(this.json[0]);
+            } else {
+                ret = JSON.stringify(this.json);
+            }
+        }
+        return ret;
+    },
+
+    /**
+     * Given CSS Lint results for a file, return output for this format.
+     * @param results {Object} with error and warning messages
+     * @param filename {String} relative file path (Unused)
+     * @return {String} output for results
+     */
+    formatResults: function(results, filename, options) {
+        "use strict";
+        if (results.messages.length > 0 || !options.quiet) {
+            this.json.push({
+                filename: filename,
+                messages: results.messages,
+                stats: results.stats
+            });
+        }
+        return "";
+    }
+});
+
+CSSLint.addFormatter({
+    // format information
+    id: "junit-xml",
+    name: "JUNIT XML format",
+
+    /**
+     * Return opening root XML tag.
+     * @return {String} to prepend before all results
+     */
+    startFormat: function() {
+        "use strict";
+        return "<?xml version=\"1.0\" encoding=\"utf-8\"?><testsuites>";
+    },
+
+    /**
+     * Return closing root XML tag.
+     * @return {String} to append after all results
+     */
+    endFormat: function() {
+        "use strict";
+        return "</testsuites>";
+    },
+
+    /**
+     * Given CSS Lint results for a file, return output for this format.
+     * @param results {Object} with error and warning messages
+     * @param filename {String} relative file path
+     * @param options {Object} (UNUSED for now) specifies special handling of output
+     * @return {String} output for results
+     */
+    formatResults: function(results, filename/*, options*/) {
+        "use strict";
+
+        var messages = results.messages,
+            output = [],
+            tests = {
+                "error": 0,
+                "failure": 0
+            };
+
+        /**
+         * Generate a source string for a rule.
+         * JUNIT source strings usually resemble Java class names e.g
+         * net.csslint.SomeRuleName
+         * @param {Object} rule
+         * @return rule source as {String}
+         */
+        var generateSource = function(rule) {
+            if (!rule || !("name" in rule)) {
+                return "";
+            }
+            return "net.csslint." + rule.name.replace(/\s/g, "");
+        };
+
+        /**
+         * Replace special characters before write to output.
+         *
+         * Rules:
+         *  - single quotes is the escape sequence for double-quotes
+         *  - &lt; is the escape sequence for <
+         *  - &gt; is the escape sequence for >
+         *
+         * @param {String} message to escape
+         * @return escaped message as {String}
+         */
+        var escapeSpecialCharacters = function(str) {
+
+            if (!str || str.constructor !== String) {
+                return "";
+            }
+
+            return str.replace(/"/g, "'").replace(/</g, "&lt;").replace(/>/g, "&gt;");
+
+        };
+
+        if (messages.length > 0) {
+
+            messages.forEach(function (message) {
+
+                // since junit has no warning class
+                // all issues as errors
+                var type = message.type === "warning" ? "error" : message.type;
+
+                // ignore rollups for now
+                if (!message.rollup) {
+
+                    // build the test case separately, once joined
+                    // we'll add it to a custom array filtered by type
+                    output.push("<testcase time=\"0\" name=\"" + generateSource(message.rule) + "\">");
+                    output.push("<" + type + " message=\"" + escapeSpecialCharacters(message.message) + "\"><![CDATA[" + message.line + ":" + message.col + ":" + escapeSpecialCharacters(message.evidence) + "]]></" + type + ">");
+                    output.push("</testcase>");
+
+                    tests[type] += 1;
+
+                }
+
+            });
+
+            output.unshift("<testsuite time=\"0\" tests=\"" + messages.length + "\" skipped=\"0\" errors=\"" + tests.error + "\" failures=\"" + tests.failure + "\" package=\"net.csslint\" name=\"" + filename + "\">");
+            output.push("</testsuite>");
+
+        }
+
+        return output.join("");
+
+    }
+});
+
+CSSLint.addFormatter({
+    // format information
+    id: "lint-xml",
+    name: "Lint XML format",
+
+    /**
+     * Return opening root XML tag.
+     * @return {String} to prepend before all results
+     */
+    startFormat: function() {
+        "use strict";
+        return "<?xml version=\"1.0\" encoding=\"utf-8\"?><lint>";
+    },
+
+    /**
+     * Return closing root XML tag.
+     * @return {String} to append after all results
+     */
+    endFormat: function() {
+        "use strict";
+        return "</lint>";
+    },
+
+    /**
+     * Given CSS Lint results for a file, return output for this format.
+     * @param results {Object} with error and warning messages
+     * @param filename {String} relative file path
+     * @param options {Object} (UNUSED for now) specifies special handling of output
+     * @return {String} output for results
+     */
+    formatResults: function(results, filename/*, options*/) {
+        "use strict";
+        var messages = results.messages,
+            output = [];
+
+        /**
+         * Replace special characters before write to output.
+         *
+         * Rules:
+         *  - single quotes is the escape sequence for double-quotes
+         *  - &amp; is the escape sequence for &
+         *  - &lt; is the escape sequence for <
+         *  - &gt; is the escape sequence for >
+         *
+         * @param {String} message to escape
+         * @return escaped message as {String}
+         */
+        var escapeSpecialCharacters = function(str) {
+            if (!str || str.constructor !== String) {
+                return "";
+            }
+            return str.replace(/"/g, "'").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
+        };
+
+        if (messages.length > 0) {
+
+            output.push("<file name=\""+filename+"\">");
+            CSSLint.Util.forEach(messages, function (message) {
+                if (message.rollup) {
+                    output.push("<issue severity=\"" + message.type + "\" reason=\"" + escapeSpecialCharacters(message.message) + "\" evidence=\"" + escapeSpecialCharacters(message.evidence) + "\"/>");
+                } else {
+                    var rule = "";
+                    if (message.rule && message.rule.id) {
+                        rule = "rule=\"" + escapeSpecialCharacters(message.rule.id) + "\" ";
+                    }
+                    output.push("<issue " + rule + "line=\"" + message.line + "\" char=\"" + message.col + "\" severity=\"" + message.type + "\"" +
+                        " reason=\"" + escapeSpecialCharacters(message.message) + "\" evidence=\"" + escapeSpecialCharacters(message.evidence) + "\"/>");
+                }
+            });
+            output.push("</file>");
+        }
+
+        return output.join("");
+    }
+});
+
+CSSLint.addFormatter({
+    // format information
+    id: "text",
+    name: "Plain Text",
+
+    /**
+     * Return content to be printed before all file results.
+     * @return {String} to prepend before all results
+     */
+    startFormat: function() {
+        "use strict";
+        return "";
+    },
+
+    /**
+     * Return content to be printed after all file results.
+     * @return {String} to append after all results
+     */
+    endFormat: function() {
+        "use strict";
+        return "";
+    },
+
+    /**
+     * Given CSS Lint results for a file, return output for this format.
+     * @param results {Object} with error and warning messages
+     * @param filename {String} relative file path
+     * @param options {Object} (Optional) specifies special handling of output
+     * @return {String} output for results
+     */
+    formatResults: function(results, filename, options) {
+        "use strict";
+        var messages = results.messages,
+            output = "";
+        options = options || {};
+
+        if (messages.length === 0) {
+            return options.quiet ? "" : "\n\ncsslint: No errors in " + filename + ".";
+        }
+
+        output = "\n\ncsslint: There ";
+        if (messages.length === 1) {
+            output += "is 1 problem";
+        } else {
+            output += "are " + messages.length + " problems";
+        }
+        output += " in " + filename + ".";
+
+        var pos = filename.lastIndexOf("/"),
+            shortFilename = filename;
+
+        if (pos === -1) {
+            pos = filename.lastIndexOf("\\");
+        }
+        if (pos > -1) {
+            shortFilename = filename.substring(pos+1);
+        }
+
+        CSSLint.Util.forEach(messages, function (message, i) {
+            output = output + "\n\n" + shortFilename;
+            if (message.rollup) {
+                output += "\n" + (i+1) + ": " + message.type;
+                output += "\n" + message.message;
+            } else {
+                output += "\n" + (i+1) + ": " + message.type + " at line " + message.line + ", col " + message.col;
+                output += "\n" + message.message;
+                output += "\n" + message.evidence;
+            }
+        });
+
+        return output;
+    }
+});
+
+return CSSLint;
+})();
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjscodemirrorhtmlhintksesjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/src/wp-includes/js/codemirror/htmlhint-kses.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/codemirror/htmlhint-kses.js                              (rev 0)
+++ trunk/src/wp-includes/js/codemirror/htmlhint-kses.js        2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,30 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/* global HTMLHint */
+/* eslint no-magic-numbers: ["error", { "ignore": [0, 1] }] */
+HTMLHint.addRule({
+       id: 'kses',
+       description: 'Element or attribute cannot be used.',
+       init: function( parser, reporter, options ) {
+               'use strict';
+
+               var self = this;
+               parser.addListener( 'tagstart', function( event ) {
+                       var attr, col, attrName, allowedAttributes, i, len, tagName;
+
+                       tagName = event.tagName.toLowerCase();
+                       if ( ! options[ tagName ] ) {
+                               reporter.error( 'Tag <' + event.tagName + '> is not allowed.', event.line, event.col, self, event.raw );
+                               return;
+                       }
+
+                       allowedAttributes = options[ tagName ];
+                       col = event.col + event.tagName.length + 1;
+                       for ( i = 0, len = event.attrs.length; i < len; i++ ) {
+                               attr = event.attrs[ i ];
+                               attrName = attr.name.toLowerCase();
+                               if ( ! allowedAttributes[ attrName ] ) {
+                                       reporter.error( 'Tag attribute [' + attr.raw + ' ] is not allowed.', event.line, col + attr.index, self, attr.raw );
+                               }
+                       }
+               });
+       }
+});
</ins></span></pre></div>
<a id="trunksrcwpincludesjscodemirrorhtmlhintjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/src/wp-includes/js/codemirror/htmlhint.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/codemirror/htmlhint.js                           (rev 0)
+++ trunk/src/wp-includes/js/codemirror/htmlhint.js     2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,8 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/*!
+ * HTMLHint v0.9.14
+ * https://github.com/yaniswang/HTMLHint
+ *
+ * (c) 2014-2017 Yanis Wang <yanis.wang@gmail.com>.
+ * MIT Licensed
+ */
+var HTMLHint=function(e){function t(e,t){return Array(e+1).join(t||" ")}var a={};return a.version="0.9.14",a.release="20170826",a.rules={},a.defaultRuleset={"tagname-lowercase":!0,"attr-lowercase":!0,"attr-value-double-quotes":!0,"doctype-first":!0,"tag-pair":!0,"spec-char-escape":!0,"id-unique":!0,"src-not-empty":!0,"attr-no-duplication":!0,"title-require":!0},a.addRule=function(e){a.rules[e.id]=e},a.verify=function(t,n){(n===e||0===Object.keys(n).length)&&(n=a.defaultRuleset),t=t.replace(/^\s*<!--\s*htmlhint\s+([^\r\n]+?)\s*-->/i,function(t,a){return n===e&&(n={}),a.replace(/(?:^|,)\s*([^:,]+)\s*(?:\:\s*([^,\s]+))?/g,function(t,a,r){"false"===r?r=!1:"true"===r&&(r=!0),n[a]=r===e?!0:r}),""});var r,i=new HTMLParser,s=new a.Reporter(t,n),o=a.rules;for(var l in n)r=o[l],r!==e&&n[l]!==!1&amp
 ;&r.init(i,s,n[l]);return i.parse(t),s.messages},a.format=function(e,a){a=a||{};var n=[],r={white:"",grey:"",red:"",reset:""};a.colors&&(r.white="",r.grey="",r.red="",r.reset="");var i=a.indent||0;return e.forEach(function(e){var a=40,s=a+20,o=e.evidence,l=e.line,u=e.col,d=o.length,c=u>a+1?u-a:1,f=o.length>u+s?u+s:d;a+1>u&&(f+=a-u+1),o=o.replace(/\t/g," ").substring(c-1,f),c>1&&(o="..."+o,c-=3),d>f&&(o+="..."),n.push(r.white+t(i)+"L"+l+" |"+r.grey+o+r.reset);var g=u-c,h=o.substring(0,g).match(/[^\u0000-\u00ff]/g);null!==h&&(g+=h.length),n.push(r.white+t(i)+t((l+"").length+3+g)+"^ "+r.red+e.message+" ("+e.rule.id+")"+r.reset)}),n},a}();"object"==typeof exports&&exports&&(exports.HTMLHint=HTMLHint),function(e){var 
 t=function(){var e=this;e._init.apply(e,arguments)};t.prototype={_init:function(e,t){var a=this;a.html=e,a.lines=e.split(/\r?\n/);var n=e.match(/\r?\n/);a.brLen=null!==n?n[0].length:0,a.ruleset=t,a.messages=[]},error:function(e,t,a,n,r){this.report("error",e,t,a,n,r)},warn:function(e,t,a,n,r){this.report("warning",e,t,a,n,r)},info:function(e,t,a,n,r){this.report("info",e,t,a,n,r)},report:function(e,t,a,n,r,i){for(var s,o,l=this,u=l.lines,d=l.brLen,c=a-1,f=u.length;f>c&&(s=u[c],o=s.length,n>o&&f>a);c++)a++,n-=o,1!==n&&(n-=d);l.messages.push({type:e,message:t,raw:i,evidence:s,line:a,col:n,rule:{id:r.id,description:r.description,link:"https://github.com/yaniswang/HTMLHint/wiki/"+r.id}})}},e.Reporter=t}(HTMLHint);var HTMLParser=function(e){var t=function(){var e=this;e._init.apply(e,arguments)};return t.prototype={_init:function(){var e=this;e._listeners={},e._mapCdataTags=e.makeMap("script,style"),e._arr
 Blocks=[],e.lastEvent=null},makeMap:function(e){for(var t={},a=e.split(","),n=0;a.length>n;n++)t[a[n]]=!0;return t},parse:function(t){function a(t,a,n,r){var i=n-b+1;r===e&&(r={}),r.raw=a,r.pos=n,r.line=w,r.col=i,L.push(r),c.fire(t,r);for(var s;s=m.exec(a);)w++,b=n+m.lastIndex}var n,r,i,s,o,l,u,d,c=this,f=c._mapCdataTags,g=/<(?:\/([^\s>]+)\s*|!--([\s\S]*?)--|!([^>]*?)|([\w\-:]+)((?:\s+[^\s"'>\/=\x00-\x0F\x7F\x80-\x9F]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s"'>]*))?)*?)\s*(\/?))>/g,h=/\s*([^\s"'>\/=\x00-\x0F\x7F\x80-\x9F]+)(?:\s*=\s*(?:(")([^"]*)"|(')([^']*)'|([^\s"'>]*)))?/g,m=/\r?\n/g,p=0,v=0,b=0,w=1,L=c._arrBlocks;for(c.fire("start",{pos:0,line:1,col:1});n=g.exec(t);)if(r=n.index,r>p&&(d=t.substring(p,r),o?u.push(d):a("text",d,p)),p=g.lastIndex,!(i=n[1])||(o&&i===o&&(d=u.join(""),a("cdata",d,v,{tagName:o,attrs:l}),o=null,l=null
 ,u=null),o))if(o)u.push(n[0]);else if(i=n[4]){s=[];for(var y,T=n[5],H=0;y=h.exec(T);){var x=y[1],M=y[2]?y[2]:y[4]?y[4]:"",N=y[3]?y[3]:y[5]?y[5]:y[6]?y[6]:"";s.push({name:x,value:N,quote:M,index:y.index,raw:y[0]}),H+=y[0].length}H===T.length?(a("tagstart",n[0],r,{tagName:i,attrs:s,close:n[6]}),f[i]&&(o=i,l=s.concat(),u=[],v=p)):a("text",n[0],r)}else(n[2]||n[3])&&a("comment",n[0],r,{content:n[2]||n[3],"long":n[2]?!0:!1});else a("tagend",n[0],r,{tagName:i});t.length>p&&(d=t.substring(p,t.length),a("text",d,p)),c.fire("end",{pos:p,line:w,col:t.length-b+1})},addListener:function(t,a){for(var n,r=this._listeners,i=t.split(/[,\s]/),s=0,o=i.length;o>s;s++)n=i[s],r[n]===e&&(r[n]=[]),r[n].push(a)},fire:function(t,a){a===e&&(a={}),a.type=t;var n=this,r=[],i=n._listeners[t],s=n._listeners.all;i!==e&&(r=r.concat(i)),s!==e&&(r=r.concat(s));var o=n
 .lastEvent;null!==o&&(delete o.lastEvent,a.lastEvent=o),n.lastEvent=a;for(var l=0,u=r.length;u>l;l++)r[l].call(n,a)},removeListener:function(t,a){var n=this._listeners[t];if(n!==e)for(var r=0,i=n.length;i>r;r++)if(n[r]===a){n.splice(r,1);break}},fixPos:function(e,t){var a,n=e.raw.substr(0,t),r=n.split(/\r?\n/),i=r.length-1,s=e.line;return i>0?(s+=i,a=r[i].length+1):a=e.col+t,{line:s,col:a}},getMapAttrs:function(e){for(var t,a={},n=0,r=e.length;r>n;n++)t=e[n],a[t.name]=t.value;return a}},t}();"object"==typeof exports&&exports&&(exports.HTMLParser=HTMLParser),HTMLHint.addRule({id:"alt-require",description:"The alt attribute of an <img> element must be present and alt attribute of area[href] and input[type=image] must have a value.",init:function(e,t){var a=this;e.addListener("tagstart",function(n){var r,i=n.tagName.toLowerCase(),s=e.getMapAttrs(n.attrs),o=n.col+i.length+1;"img"!==i||"alt&q
 uot;in s?("area"===i&&"href"in s||"input"===i&&"image"===s.type)&&("alt"in s&&""!==s.alt||(r="area"===i?"area[href]":"input[type=image]",t.warn("The alt attribute of "+r+" must have a value.",n.line,o,a,n.raw))):t.warn("An alt attribute must be present on <img> elements.",n.line,o,a,n.raw)})}}),HTMLHint.addRule({id:"attr-lowercase",description:"All attribute names must be in lowercase.",init:function(e,t,a){var n=this,r=Array.isArray(a)?a:[];e.addListener("tagstart",function(e){for(var a,i=e.attrs,s=e.col+e.tagName.length+1,o=0,l=i.length;l>o;o++){a=i[o];var u=a.name;-1===r.indexOf(u)&&u!==u.toLowerCase()&&t.error("The attribute name of [ "+u+" ] must be in lowercase.",e.line,s+a.index,n,a.raw)}})}}),HTMLHint.addRule({id:"attr-no-duplication",descrip
 tion:"Elements cannot have duplicate attributes.",init:function(e,t){var a=this;e.addListener("tagstart",function(e){for(var n,r,i=e.attrs,s=e.col+e.tagName.length+1,o={},l=0,u=i.length;u>l;l++)n=i[l],r=n.name,o[r]===!0&&t.error("Duplicate of attribute name [ "+n.name+" ] was found.",e.line,s+n.index,a,n.raw),o[r]=!0})}}),HTMLHint.addRule({id:"attr-unsafe-chars",description:"Attribute values cannot contain unsafe chars.",init:function(e,t){var a=this;e.addListener("tagstart",function(e){for(var n,r,i=e.attrs,s=e.col+e.tagName.length+1,o=/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/,l=0,u=i.length;u>l;l++)if(n=i[l],r=n.value.match(o),null!==r){var d=escape(r[0]).replace(/%u/,"\\u").replace(/%/,"\\x");t.warn("The value of attribute [ "+n.name+" ] cannot contain an 
 unsafe char [ "+d+" ].",e.line,s+n.index,a,n.raw)}})}}),HTMLHint.addRule({id:"attr-value-double-quotes",description:"Attribute values must be in double quotes.",init:function(e,t){var a=this;e.addListener("tagstart",function(e){for(var n,r=e.attrs,i=e.col+e.tagName.length+1,s=0,o=r.length;o>s;s++)n=r[s],(""!==n.value&&'"'!==n.quote||""===n.value&&"'"===n.quote)&&t.error("The value of attribute [ "+n.name+" ] must be in double quotes.",e.line,i+n.index,a,n.raw)})}}),HTMLHint.addRule({id:"attr-value-not-empty",description:"All attributes must have values.",init:function(e,t){var a=this;e.addListener("tagstart",function(e){for(var n,r=e.attrs,i=e.col+e.tagName.length+1,s=0,o=r.length;o>s;s++)n=r[s],""===n.quote&&""===n.value&&t.warn("The attribute [ "+n.name+" ] must have a valu
 e.",e.line,i+n.index,a,n.raw)})}}),HTMLHint.addRule({id:"csslint",description:"Scan css with csslint.",init:function(e,t,a){var n=this;e.addListener("cdata",function(e){if("style"===e.tagName.toLowerCase()){var r;if(r="object"==typeof exports&&require?require("csslint").CSSLint.verify:CSSLint.verify,void 0!==a){var i=e.line-1,s=e.col-1;try{var o=r(e.raw,a).messages;o.forEach(function(e){var a=e.line;t["warning"===e.type?"warn":"error"]("["+e.rule.id+"] "+e.message,i+a,(1===a?s:0)+e.col,n,e.evidence)})}catch(l){}}}})}}),HTMLHint.addRule({id:"doctype-first",description:"Doctype must be declared first.",init:function(e,t){var a=this,n=function(r){"start"===r.type||"text"===r.type&&/^\s*$/.test(r.raw)||(("comment"!==r.type&&r.long===!1||/^DOCTYPE\s+/i.test(r.content)===!1)&&t.error("Docty
 pe must be declared first.",r.line,r.col,a,r.raw),e.removeListener("all",n))};e.addListener("all",n)}}),HTMLHint.addRule({id:"doctype-html5",description:'Invalid doctype. Use: "<!DOCTYPE html>"',init:function(e,t){function a(e){e.long===!1&&"doctype html"!==e.content.toLowerCase()&&t.warn('Invalid doctype. Use: "<!DOCTYPE html>"',e.line,e.col,r,e.raw)}function n(){e.removeListener("comment",a),e.removeListener("tagstart",n)}var r=this;e.addListener("all",a),e.addListener("tagstart",n)}}),HTMLHint.addRule({id:"head-script-disabled",description:"The <script> tag cannot be used in a <head> tag.",init:function(e,t){function a(a){var n=e.getMapAttrs(a.attrs),o=n.type,l=a.tagName.toLowerCase();"head"===l&&(s=!0),s!==!0||"script"!==l||o&&i.test(o)!==!0||t.warn("The <script> tag can
 not be used in a <head> tag.",a.line,a.col,r,a.raw)}function n(t){"head"===t.tagName.toLowerCase()&&(e.removeListener("tagstart",a),e.removeListener("tagend",n))}var r=this,i=/^(text\/javascript|application\/javascript)$/i,s=!1;e.addListener("tagstart",a),e.addListener("tagend",n)}}),HTMLHint.addRule({id:"href-abs-or-rel",description:"An href attribute must be either absolute or relative.",init:function(e,t,a){var n=this,r="abs"===a?"absolute":"relative";e.addListener("tagstart",function(e){for(var a,i=e.attrs,s=e.col+e.tagName.length+1,o=0,l=i.length;l>o;o++)if(a=i[o],"href"===a.name){("absolute"===r&&/^\w+?:/.test(a.value)===!1||"relative"===r&&/^https?:\/\//.test(a.value)===!0)&&t.warn("The value of the href attribute [ "+a.value+" ] must be "+r+".",e.line,s+a.index,n
 ,a.raw);break}})}}),HTMLHint.addRule({id:"id-class-ad-disabled",description:"The id and class attributes cannot use the ad keyword, it will be blocked by adblock software.",init:function(e,t){var a=this;e.addListener("tagstart",function(e){for(var n,r,i=e.attrs,s=e.col+e.tagName.length+1,o=0,l=i.length;l>o;o++)n=i[o],r=n.name,/^(id|class)$/i.test(r)&&/(^|[-\_])ad([-\_]|$)/i.test(n.value)&&t.warn("The value of attribute "+r+" cannot use the ad keyword.",e.line,s+n.index,a,n.raw)})}}),HTMLHint.addRule({id:"id-class-value",description:"The id and class attribute values must meet the specified rules.",init:function(e,t,a){var n,r=this,i={underline:{regId:/^[a-z\d]+(_[a-z\d]+)*$/,message:"The id and class attribute values must be in lowercase and split by an underscore."},dash:{regId:/^[a-z\d]+(-[a-z\d]+)*$/,message:"The id and class attribute values must be in lowercase and split by a
  dash."},hump:{regId:/^[a-z][a-zA-Z\d]*([A-Z][a-zA-Z\d]*)*$/,message:"The id and class attribute values must meet the camelCase style."}};if(n="string"==typeof a?i[a]:a,n&&n.regId){var s=n.regId,o=n.message;e.addListener("tagstart",function(e){for(var a,n=e.attrs,i=e.col+e.tagName.length+1,l=0,u=n.length;u>l;l++)if(a=n[l],"id"===a.name.toLowerCase()&&s.test(a.value)===!1&&t.warn(o,e.line,i+a.index,r,a.raw),"class"===a.name.toLowerCase())for(var d,c=a.value.split(/\s+/g),f=0,g=c.length;g>f;f++)d=c[f],d&&s.test(d)===!1&&t.warn(o,e.line,i+a.index,r,d)})}}}),HTMLHint.addRule({id:"id-unique",description:"The value of id attributes must be unique.",init:function(e,t){var a=this,n={};e.addListener("tagstart",function(e){for(var r,i,s=e.attrs,o=e.col+e.tagName.length+1,l=0,u=s.length;u>l;l++)if(r=s[l],"id"===r.name.toLowerCase()){i=r.value,i&&am
 p;(void 0===n[i]?n[i]=1:n[i]++,n[i]>1&&t.error("The id value [ "+i+" ] must be unique.",e.line,o+r.index,a,r.raw));break}})}}),HTMLHint.addRule({id:"inline-script-disabled",description:"Inline script cannot be used.",init:function(e,t){var a=this;e.addListener("tagstart",function(e){for(var n,r,i=e.attrs,s=e.col+e.tagName.length+1,o=/^on(unload|message|submit|select|scroll|resize|mouseover|mouseout|mousemove|mouseleave|mouseenter|mousedown|load|keyup|keypress|keydown|focus|dblclick|click|change|blur|error)$/i,l=0,u=i.length;u>l;l++)n=i[l],r=n.name.toLowerCase(),o.test(r)===!0?t.warn("Inline script [ "+n.raw+" ] cannot be used.",e.line,s+n.index,a,n.raw):("src"===r||"href"===r)&&/^\s*javascript:/i.test(n.value)&&t.warn("Inline script [ "+n.raw+" ] cannot be used.",e.line,s+n.index,a,n.raw)})}}),HTMLHint.addRule({id:"inline-style-disabled&quo
 t;,description:"Inline style cannot be used.",init:function(e,t){var a=this;e.addListener("tagstart",function(e){for(var n,r=e.attrs,i=e.col+e.tagName.length+1,s=0,o=r.length;o>s;s++)n=r[s],"style"===n.name.toLowerCase()&&t.warn("Inline style [ "+n.raw+" ] cannot be used.",e.line,i+n.index,a,n.raw)})}}),HTMLHint.addRule({id:"jshint",description:"Scan script with jshint.",init:function(e,t,a){var n=this;e.addListener("cdata",function(r){if("script"===r.tagName.toLowerCase()){var i=e.getMapAttrs(r.attrs),s=i.type;if(void 0!==i.src||s&&/^(text\/javascript)$/i.test(s)===!1)return;var o;if(o="object"==typeof exports&&require?require("jshint").JSHINT:JSHINT,void 0!==a){var l=r.line-1,u=r.col-1,d=r.raw.replace(/\t/g," ");try{var c=o(d,a,a.globals);c===!1&&o.errors.forEach(function(e){var a=e.line;t.warn(e.reason,l+a,(1===a?u:0)+e.charact
 er,n,e.evidence)})}catch(f){}}}})}}),HTMLHint.addRule({id:"space-tab-mixed-disabled",description:"Do not mix tabs and spaces for indentation.",init:function(e,t,a){var n=this,r="nomix",i=null;if("string"==typeof a){var s=a.match(/^([a-z]+)(\d+)?/);r=s[1],i=s[2]&&parseInt(s[2],10)}e.addListener("text",function(a){for(var s,o=a.raw,l=/(^|\r?\n)([ \t]+)/g;s=l.exec(o);){var u=e.fixPos(a,s.index+s[1].length);if(1===u.col){var d=s[2];"space"===r?i?(/^ +$/.test(d)===!1||0!==d.length%i)&&t.warn("Please use space for indentation and keep "+i+" length.",u.line,1,n,a.raw):/^ +$/.test(d)===!1&&t.warn("Please use space for indentation.",u.line,1,n,a.raw):"tab"===r&&/^\t+$/.test(d)===!1?t.warn("Please use tab for indentation.",u.line,1,n,a.raw):/ +\t|\t+ /.test(d)===!0&&t.warn("Do not mix tabs and spaces for indentation.",u.line,1,n,a.raw)
 }}})}}),HTMLHint.addRule({id:"spec-char-escape",description:"Special characters must be escaped.",init:function(e,t){var a=this;e.addListener("text",function(n){for(var r,i=n.raw,s=/[<>]/g;r=s.exec(i);){var o=e.fixPos(n,r.index);t.error("Special characters must be escaped : [ "+r[0]+" ].",o.line,o.col,a,n.raw)}})}}),HTMLHint.addRule({id:"src-not-empty",description:"The src attribute of an img(script,link) must have a value.",init:function(e,t){var a=this;e.addListener("tagstart",function(e){for(var n,r=e.tagName,i=e.attrs,s=e.col+r.length+1,o=0,l=i.length;l>o;o++)n=i[o],(/^(img|script|embed|bgsound|iframe)$/.test(r)===!0&&"src"===n.name||"link"===r&&"href"===n.name||"object"===r&&"data"===n.name)&&""===n.value&&t.error("The attribute [ "+n.name+" ] of the tag [ "+r+" ] mus
 t have a value.",e.line,s+n.index,a,n.raw)})}}),HTMLHint.addRule({id:"style-disabled",description:"<style> tags cannot be used.",init:function(e,t){var a=this;e.addListener("tagstart",function(e){"style"===e.tagName.toLowerCase()&&t.warn("The <style> tag cannot be used.",e.line,e.col,a,e.raw)})}}),HTMLHint.addRule({id:"tag-pair",description:"Tag must be paired.",init:function(e,t){var a=this,n=[],r=e.makeMap("area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed,track,command,source,keygen,wbr");e.addListener("tagstart",function(e){var t=e.tagName.toLowerCase();void 0!==r[t]||e.close||n.push({tagName:t,line:e.line,raw:e.raw})}),e.addListener("tagend",function(e){for(var r=e.tagName.toLowerCase(),i=n.length-1;i>=0&&n[i].tagName!==r;i--);if(i>=0){for(var s=[],o=n.length-1;o>i;o--)s.push("</"+n[o].tagName+"&
 gt;");if(s.length>0){var l=n[n.length-1];t.error("Tag must be paired, missing: [ "+s.join("")+" ], start tag match failed [ "+l.raw+" ] on line "+l.line+".",e.line,e.col,a,e.raw)}n.length=i}else t.error("Tag must be paired, no start tag: [ "+e.raw+" ]",e.line,e.col,a,e.raw)}),e.addListener("end",function(e){for(var r=[],i=n.length-1;i>=0;i--)r.push("</"+n[i].tagName+">");if(r.length>0){var s=n[n.length-1];t.error("Tag must be paired, missing: [ "+r.join("")+" ], open tag match failed [ "+s.raw+" ] on line "+s.line+".",e.line,e.col,a,"")}})}}),HTMLHint.addRule({id:"tag-self-close",description:"Empty tags must be self closed.",init:function(e,t){var a=this,n=e.makeMap("area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed,track,command,source,keygen,wbr");e.
 addListener("tagstart",function(e){var r=e.tagName.toLowerCase();void 0!==n[r]&&(e.close||t.warn("The empty tag : [ "+r+" ] must be self closed.",e.line,e.col,a,e.raw))})}}),HTMLHint.addRule({id:"tagname-lowercase",description:"All html element names must be in lowercase.",init:function(e,t){var a=this;e.addListener("tagstart,tagend",function(e){var n=e.tagName;n!==n.toLowerCase()&&t.error("The html element name of [ "+n+" ] must be in lowercase.",e.line,e.col,a,e.raw)})}}),HTMLHint.addRule({id:"title-require",description:"<title> must be present in <head> tag.",init:function(e,t){function a(e){var t=e.tagName.toLowerCase();"head"===t?i=!0:"title"===t&&i&&(s=!0)}function n(i){var o=i.tagName.toLowerCase();if(s&&"title"===o){var l=i.lastEvent;("text"!==l.type||"text"===l.type&&
 /^\s*$/.test(l.raw)===!0)&&t.error("<title></title> must not be empty.",i.line,i.col,r,i.raw)}else"head"===o&&(s===!1&&t.error("<title> must be present in <head> tag.",i.line,i.col,r,i.raw),e.removeListener("tagstart",a),e.removeListener("tagend",n))}var r=this,i=!1,s=!1;e.addListener("tagstart",a),e.addListener("tagend",n)}});
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjscodemirrorjshintjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/src/wp-includes/js/codemirror/jshint.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/codemirror/jshint.js                             (rev 0)
+++ trunk/src/wp-includes/js/codemirror/jshint.js       2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,24546 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/*! 2.9.5 */
+var JSHINT;
+if (typeof window === 'undefined') window = {};
+(function () {
+var require;
+require=(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){
+var identifierStartTable = [];
+
+for (var i = 0; i < 128; i++) {
+  identifierStartTable[i] =
+    i === 36 ||           // $
+    i >= 65 && i <= 90 || // A-Z
+    i === 95 ||           // _
+    i >= 97 && i <= 122;  // a-z
+}
+
+var identifierPartTable = [];
+
+for (var i = 0; i < 128; i++) {
+  identifierPartTable[i] =
+    identifierStartTable[i] || // $, _, A-Z, a-z
+    i >= 48 && i <= 57;        // 0-9
+}
+
+module.exports = {
+  asciiIdentifierStartTable: identifierStartTable,
+  asciiIdentifierPartTable: identifierPartTable
+};
+
+},{}],2:[function(require,module,exports){
+var str = '768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,1155,1156,1157,1158,1159,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1471,1473,1474,1476,1477,1479,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1648,1750,1751,1752,1753,1754,1755,1756,1759,176
 0,1761,1762,1763,1764,1767,1768,1770,1771,1772,1773,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1809,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,2027,2028,2029,2030,2031,2032,2033,2034,2035,2070,2071,2072,2073,2075,2076,2077,2078,2079,2080,2081,2082,2083,2085,2086,2087,2089,2090,2091,2092,2093,2137,2138,2139,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2304,2305,2306,2307,2362,2363,2364,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,2380,2381,2382,2383,2385,2386,2387,2388,2389,2390,2391,2402,2403,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2433,2434,2435,2492,2494,2495,2496,2497,2498,2499,2500,2503,2504,2507,2508,2509,2519,2530,2531,2534,2535,2536,2537,2538,2539,2540,
 2541,2542,2543,2561,2562,2563,2620,2622,2623,2624,2625,2626,2631,2632,2635,2636,2637,2641,2662,2663,2664,2665,2666,2667,2668,2669,2670,2671,2672,2673,2677,2689,2690,2691,2748,2750,2751,2752,2753,2754,2755,2756,2757,2759,2760,2761,2763,2764,2765,2786,2787,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,2817,2818,2819,2876,2878,2879,2880,2881,2882,2883,2884,2887,2888,2891,2892,2893,2902,2903,2914,2915,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2946,3006,3007,3008,3009,3010,3014,3015,3016,3018,3019,3020,3021,3031,3046,3047,3048,3049,3050,3051,3052,3053,3054,3055,3073,3074,3075,3134,3135,3136,3137,3138,3139,3140,3142,3143,3144,3146,3147,3148,3149,3157,3158,3170,3171,3174,3175,3176,3177,3178,3179,3180,3181,3182,3183,3202,3203,3260,3262,3263,3264,3265,3266,3267,3268,3270,3271,3272,3274,3275,3276,3277,3285,3286,3298,3299,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3330,3331,3390,3391,3392,3393,3394,3395,3396,3398,3399,3400,3402,3403,3404,3405,3415,3426,3427,3430,3431,3432,34
 33,3434,3435,3436,3437,3438,3439,3458,3459,3530,3535,3536,3537,3538,3539,3540,3542,3544,3545,3546,3547,3548,3549,3550,3551,3570,3571,3633,3636,3637,3638,3639,3640,3641,3642,3655,3656,3657,3658,3659,3660,3661,3662,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3761,3764,3765,3766,3767,3768,3769,3771,3772,3784,3785,3786,3787,3788,3789,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3864,3865,3872,3873,3874,3875,3876,3877,3878,3879,3880,3881,3893,3895,3897,3902,3903,3953,3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,3971,3972,3974,3975,3981,3982,3983,3984,3985,3986,3987,3988,3989,3990,3991,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4038,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,4150,4151,4152,4153,4154,4155,4156,4157,4158,4160,4161,4162,4163,4164,4165,4166,4167,4168,4169,4182,4183,4184,4185,4190
 ,4191,4192,4194,4195,4196,4199,4200,4201,4202,4203,4204,4205,4209,4210,4211,4212,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4239,4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,4957,4958,4959,5906,5907,5908,5938,5939,5940,5970,5971,6002,6003,6068,6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,6109,6112,6113,6114,6115,6116,6117,6118,6119,6120,6121,6155,6156,6157,6160,6161,6162,6163,6164,6165,6166,6167,6168,6169,6313,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,6459,6470,6471,6472,6473,6474,6475,6476,6477,6478,6479,6576,6577,6578,6579,6580,6581,6582,6583,6584,6585,6586,6587,6588,6589,6590,6591,6592,6600,6601,6608,6609,6610,6611,6612,6613,6614,6615,6616,6617,6679,6680,6681,6682,6683,6741,6742,6743,6744,6745,6746,6747,6748,6749,6750,6752,6753,6754,6755,6756,6757,6758,6759,6
 760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,6775,6776,6777,6778,6779,6780,6783,6784,6785,6786,6787,6788,6789,6790,6791,6792,6793,6800,6801,6802,6803,6804,6805,6806,6807,6808,6809,6912,6913,6914,6915,6916,6964,6965,6966,6967,6968,6969,6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,6992,6993,6994,6995,6996,6997,6998,6999,7000,7001,7019,7020,7021,7022,7023,7024,7025,7026,7027,7040,7041,7042,7073,7074,7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7088,7089,7090,7091,7092,7093,7094,7095,7096,7097,7142,7143,7144,7145,7146,7147,7148,7149,7150,7151,7152,7153,7154,7155,7204,7205,7206,7207,7208,7209,7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7232,7233,7234,7235,7236,7237,7238,7239,7240,7241,7248,7249,7250,7251,7252,7253,7254,7255,7256,7257,7376,7377,7378,7380,7381,7382,7383,7384,7385,7386,7387,7388,7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7405,7410,7411,7412,7616,7617,7618,7619,7620,7621,7622,7623,762
 4,7625,7626,7627,7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,7676,7677,7678,7679,8204,8205,8255,8256,8276,8400,8401,8402,8403,8404,8405,8406,8407,8408,8409,8410,8411,8412,8417,8421,8422,8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,11503,11504,11505,11647,11744,11745,11746,11747,11748,11749,11750,11751,11752,11753,11754,11755,11756,11757,11758,11759,11760,11761,11762,11763,11764,11765,11766,11767,11768,11769,11770,11771,11772,11773,11774,11775,12330,12331,12332,12333,12334,12335,12441,12442,42528,42529,42530,42531,42532,42533,42534,42535,42536,42537,42607,42612,42613,42614,42615,42616,42617,42618,42619,42620,42621,42655,42736,42737,43010,43014,43019,43043,43044,43045,43046,43047,43136,43137,43188,43189,43190,43191,43192,43193,43194,43195,43196,43197,43198,43199,43200,43201,43202,43203,43204,43216,43217,43218,43219,43220,43221,43222,43223,43224,43225,43232,43233,43234,43235,43236,43237,4323
 8,43239,43240,43241,43242,43243,43244,43245,43246,43247,43248,43249,43264,43265,43266,43267,43268,43269,43270,43271,43272,43273,43302,43303,43304,43305,43306,43307,43308,43309,43335,43336,43337,43338,43339,43340,43341,43342,43343,43344,43345,43346,43347,43392,43393,43394,43395,43443,43444,43445,43446,43447,43448,43449,43450,43451,43452,43453,43454,43455,43456,43472,43473,43474,43475,43476,43477,43478,43479,43480,43481,43561,43562,43563,43564,43565,43566,43567,43568,43569,43570,43571,43572,43573,43574,43587,43596,43597,43600,43601,43602,43603,43604,43605,43606,43607,43608,43609,43643,43696,43698,43699,43700,43703,43704,43710,43711,43713,43755,43756,43757,43758,43759,43765,43766,44003,44004,44005,44006,44007,44008,44009,44010,44012,44013,44016,44017,44018,44019,44020,44021,44022,44023,44024,44025,64286,65024,65025,65026,65027,65028,65029,65030,65031,65032,65033,65034,65035,65036,65037,65038,65039,65056,65057,65058,65059,65060,65061,65062,65075,65076,65101,65102,65103,65296,65297,65298
 ,65299,65300,65301,65302,65303,65304,65305,65343';
+var arr = str.split(',').map(function(code) {
+  return parseInt(code, 10);
+});
+module.exports = arr;
+},{}],3:[function(require,module,exports){
+var str = '170,181,186,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,43
 7,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686
 ,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,710,711,712,713,714,715,716,717,718,719,720,721,736,737,738,739,740,748,750,880,881,882,883,884,886,887,890,891,892,893,902,904,905,906,908,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085
 ,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182,1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292,1
 293,1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1369,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1520,1521,1522,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1646,1647,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,166
 8,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1749,1765,1766,1774,1775,1786,1787,1788,1791,1808,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,
 1949,1950,1951,1952,1953,1954,1955,1956,1957,1969,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2036,2037,2042,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2074,2084,2088,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2208,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2365,2384,2392,2393,2394,2395,2396,2397,2398,2399,2400,2401,2417,2418,2419,2420,2421,2422,2423,2425,2426,2427,2428,2429,2430,2431,2437,2438,2439,2440,2441,2442,2443,2444,2447,2448,2451,24
 52,2453,2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2474,2475,2476,2477,2478,2479,2480,2482,2486,2487,2488,2489,2493,2510,2524,2525,2527,2528,2529,2544,2545,2565,2566,2567,2568,2569,2570,2575,2576,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,2589,2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2602,2603,2604,2605,2606,2607,2608,2610,2611,2613,2614,2616,2617,2649,2650,2651,2652,2654,2674,2675,2676,2693,2694,2695,2696,2697,2698,2699,2700,2701,2703,2704,2705,2707,2708,2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,2725,2726,2727,2728,2730,2731,2732,2733,2734,2735,2736,2738,2739,2741,2742,2743,2744,2745,2749,2768,2784,2785,2821,2822,2823,2824,2825,2826,2827,2828,2831,2832,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2858,2859,2860,2861,2862,2863,2864,2866,2867,2869,2870,2871,2872,2873,2877,2908,2909,2911,2912,2913,2929,2947,2949
 ,2950,2951,2952,2953,2954,2958,2959,2960,2962,2963,2964,2965,2969,2970,2972,2974,2975,2979,2980,2984,2985,2986,2990,2991,2992,2993,2994,2995,2996,2997,2998,2999,3000,3001,3024,3077,3078,3079,3080,3081,3082,3083,3084,3086,3087,3088,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3114,3115,3116,3117,3118,3119,3120,3121,3122,3123,3125,3126,3127,3128,3129,3133,3160,3161,3168,3169,3205,3206,3207,3208,3209,3210,3211,3212,3214,3215,3216,3218,3219,3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,3239,3240,3242,3243,3244,3245,3246,3247,3248,3249,3250,3251,3253,3254,3255,3256,3257,3261,3294,3296,3297,3313,3314,3333,3334,3335,3336,3337,3338,3339,3340,3342,3343,3344,3346,3347,3348,3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369,3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3389,3406,3424,3
 425,3450,3451,3452,3453,3454,3455,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,3475,3476,3477,3478,3482,3483,3484,3485,3486,3487,3488,3489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,3505,3507,3508,3509,3510,3511,3512,3513,3514,3515,3517,3520,3521,3522,3523,3524,3525,3526,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3634,3635,3648,3649,3650,3651,3652,3653,3654,3713,3714,3716,3719,3720,3722,3725,3732,3733,3734,3735,3737,3738,3739,3740,3741,3742,3743,3745,3746,3747,3749,3751,3754,3755,3757,3758,3759,3760,3762,3763,3773,3776,3777,3778,3779,3780,3782,3804,3805,3806,3807,3840,3904,3905,3906,3907,3908,3909,3910,3911,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,393
 8,3939,3940,3941,3942,3943,3944,3945,3946,3947,3948,3976,3977,3978,3979,3980,4096,4097,4098,4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,4119,4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,4135,4136,4137,4138,4159,4176,4177,4178,4179,4180,4181,4186,4187,4188,4189,4193,4197,4198,4206,4207,4208,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,4224,4225,4238,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,4289,4290,4291,4292,4293,4295,4301,4304,4305,4306,4307,4308,4309,4310,4311,4312,4313,4314,4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325,4326,4327,4328,4329,4330,4331,4332,4333,4334,4335,4336,4337,4338,4339,4340,4341,4342,4343,4344,4345,4346,4348,4349,4350,4351,4352,4353,4354,4355,4356,4357,4358,4359,4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,4374,
 4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,4389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,4404,4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416,4417,4418,4419,4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434,4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,4479,4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,4494,4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,4509,4510,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,4539,4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,4554,4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,4569,4570,4571,4572,4573,45
 74,4575,4576,4577,4578,4579,4580,4581,4582,4583,4584,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,4599,4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,4614,4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,4629,4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,4644,4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,4659,4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,4674,4675,4676,4677,4678,4679,4680,4682,4683,4684,4685,4688,4689,4690,4691,4692,4693,4694,4696,4698,4699,4700,4701,4704,4705,4706,4707,4708,4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,4719,4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4746,4747,4748,4749,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,4764,4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,4779,4780,4781,4782,4783
 ,4784,4786,4787,4788,4789,4792,4793,4794,4795,4796,4797,4798,4800,4802,4803,4804,4805,4808,4809,4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4824,4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,4839,4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,4854,4855,4856,4857,4858,4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,4869,4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4882,4883,4884,4885,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,4899,4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,4914,4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,4929,4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,4944,4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,5004,5005,5006,5007,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5
 047,5048,5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,5121,5122,5123,5124,5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,5184,5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,5199,5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,5214,5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,5245,5246,5247,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,525
 8,5259,5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424,5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456,5457,
 5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632,5633,5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,5649,5650,5651,5652,5653,5654,5655,5656,56
 57,5658,5659,5660,5661,5662,5663,5664,5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680,5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696,5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712,5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728,5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5743,5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756,5757,5758,5759,5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5792,5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824,5825,5826,5827,5828,5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,5859,5860,5861,5862,5863,5864
 ,5865,5866,5870,5871,5872,5888,5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5902,5903,5904,5905,5920,5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936,5937,5952,5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968,5969,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5998,5999,6000,6016,6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6103,6108,6176,6177,6178,6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,6189,6190,6191,6192,6193,6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,6204,6205,6206,6207,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,6219,6220,6221,6222,6223,6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,6234,6235,6236,6237,6238,6239,6240,6241,6242,6243,6244,6245,6246,6
 247,6248,6249,6250,6251,6252,6253,6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,6272,6273,6274,6275,6276,6277,6278,6279,6280,6281,6282,6283,6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,6294,6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,6309,6310,6311,6312,6314,6320,6321,6322,6323,6324,6325,6326,6327,6328,6329,6330,6331,6332,6333,6334,6335,6336,6337,6338,6339,6340,6341,6342,6343,6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,6354,6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,6369,6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,6384,6385,6386,6387,6388,6389,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,6414,6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,6480,6481,6482,6483,6484,6485,6486,6487,6488,6489,6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,6504,6505,6506,6507,6508,6509,6512,6513,6514,6515,6516,6528,6529,6530,6531,6532,6533,653
 4,6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,6549,6550,6551,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,6564,6565,6566,6567,6568,6569,6570,6571,6593,6594,6595,6596,6597,6598,6599,6656,6657,6658,6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,6669,6670,6671,6672,6673,6674,6675,6676,6677,6678,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,6699,6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,6714,6715,6716,6717,6718,6719,6720,6721,6722,6723,6724,6725,6726,6727,6728,6729,6730,6731,6732,6733,6734,6735,6736,6737,6738,6739,6740,6823,6917,6918,6919,6920,6921,6922,6923,6924,6925,6926,6927,6928,6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,6939,6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,6954,6955,6956,6957,6958,6959,6960,6961,6962,6963,6981,6982,6983,6984,6985,6986,6987,7043,7044,7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,7059,7060,7061,7062,7063,7064,7065,7066,
 7067,7068,7069,7070,7071,7072,7086,7087,7098,7099,7100,7101,7102,7103,7104,7105,7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,7119,7120,7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,7135,7136,7137,7138,7139,7140,7141,7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,7179,7180,7181,7182,7183,7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,7194,7195,7196,7197,7198,7199,7200,7201,7202,7203,7245,7246,7247,7258,7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,7269,7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,7284,7285,7286,7287,7288,7289,7290,7291,7292,7293,7401,7402,7403,7404,7406,7407,7408,7409,7413,7414,7424,7425,7426,7427,7428,7429,7430,7431,7432,7433,7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447,7448,7449,7450,7451,7452,7453,7454,7455,7456,7457,7458,7459,7460,7461,7462,7463,7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,7475,7476,7477,7478,7479,7480,7481,7482,7483,7484,7485,74
 86,7487,7488,7489,7490,7491,7492,7493,7494,7495,7496,7497,7498,7499,7500,7501,7502,7503,7504,7505,7506,7507,7508,7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,7522,7523,7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537,7538,7539,7540,7541,7542,7543,7544,7545,7546,7547,7548,7549,7550,7551,7552,7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,7566,7567,7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,7580,7581,7582,7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,7598,7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,7613,7614,7615,7680,7681,7682,7683,7684,7685,7686,7687,7688,7689,7690,7691,7692,7693,7694,7695,7696,7697,7698,7699,7700,7701,7702,7703,7704,7705,7706,7707,7708,7709,7710,7711,7712,7713,7714,7715,7716,7717,7718,7719,7720,7721,7722,7723,7724,7725,7726,7727,7728,7729,7730,7731,7732,7733,7734,7735,7736,7737,7738,7739,7740,7741,7742,7743,7744,7745,7746,7747,7748,7749
 ,7750,7751,7752,7753,7754,7755,7756,7757,7758,7759,7760,7761,7762,7763,7764,7765,7766,7767,7768,7769,7770,7771,7772,7773,7774,7775,7776,7777,7778,7779,7780,7781,7782,7783,7784,7785,7786,7787,7788,7789,7790,7791,7792,7793,7794,7795,7796,7797,7798,7799,7800,7801,7802,7803,7804,7805,7806,7807,7808,7809,7810,7811,7812,7813,7814,7815,7816,7817,7818,7819,7820,7821,7822,7823,7824,7825,7826,7827,7828,7829,7830,7831,7832,7833,7834,7835,7836,7837,7838,7839,7840,7841,7842,7843,7844,7845,7846,7847,7848,7849,7850,7851,7852,7853,7854,7855,7856,7857,7858,7859,7860,7861,7862,7863,7864,7865,7866,7867,7868,7869,7870,7871,7872,7873,7874,7875,7876,7877,7878,7879,7880,7881,7882,7883,7884,7885,7886,7887,7888,7889,7890,7891,7892,7893,7894,7895,7896,7897,7898,7899,7900,7901,7902,7903,7904,7905,7906,7907,7908,7909,7910,7911,7912,7913,7914,7915,7916,7917,7918,7919,7920,7921,7922,7923,7924,7925,7926,7927,7928,7929,7930,7931,7932,7933,7934,7935,7936,7937,7938,7939,7940,7941,7942,7943,7944,7945,7946,7947,7948,7
 949,7950,7951,7952,7953,7954,7955,7956,7957,7960,7961,7962,7963,7964,7965,7968,7969,7970,7971,7972,7973,7974,7975,7976,7977,7978,7979,7980,7981,7982,7983,7984,7985,7986,7987,7988,7989,7990,7991,7992,7993,7994,7995,7996,7997,7998,7999,8000,8001,8002,8003,8004,8005,8008,8009,8010,8011,8012,8013,8016,8017,8018,8019,8020,8021,8022,8023,8025,8027,8029,8031,8032,8033,8034,8035,8036,8037,8038,8039,8040,8041,8042,8043,8044,8045,8046,8047,8048,8049,8050,8051,8052,8053,8054,8055,8056,8057,8058,8059,8060,8061,8064,8065,8066,8067,8068,8069,8070,8071,8072,8073,8074,8075,8076,8077,8078,8079,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8091,8092,8093,8094,8095,8096,8097,8098,8099,8100,8101,8102,8103,8104,8105,8106,8107,8108,8109,8110,8111,8112,8113,8114,8115,8116,8118,8119,8120,8121,8122,8123,8124,8126,8130,8131,8132,8134,8135,8136,8137,8138,8139,8140,8144,8145,8146,8147,8150,8151,8152,8153,8154,8155,8160,8161,8162,8163,8164,8165,8166,8167,8168,8169,8170,8171,8172,8178,8179,8180,8182,818
 3,8184,8185,8186,8187,8188,8305,8319,8336,8337,8338,8339,8340,8341,8342,8343,8344,8345,8346,8347,8348,8450,8455,8458,8459,8460,8461,8462,8463,8464,8465,8466,8467,8469,8473,8474,8475,8476,8477,8484,8486,8488,8490,8491,8492,8493,8495,8496,8497,8498,8499,8500,8501,8502,8503,8504,8505,8508,8509,8510,8511,8517,8518,8519,8520,8521,8526,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,8558,8559,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,8570,8571,8572,8573,8574,8575,8576,8577,8578,8579,8580,8581,8582,8583,8584,11264,11265,11266,11267,11268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279,11280,11281,11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304,11305,11306,11307,11308,11309,11310,11312,11313,11314,11315,11316,11317,11318,11319,11320,11321,11322,11323,11324,11325,11326,11327,11328,11329,11330,11331,11332,11333,11334,11335,11336,11337,11338,11339,11340,1134
 1,11342,11343,11344,11345,11346,11347,11348,11349,11350,11351,11352,11353,11354,11355,11356,11357,11358,11360,11361,11362,11363,11364,11365,11366,11367,11368,11369,11370,11371,11372,11373,11374,11375,11376,11377,11378,11379,11380,11381,11382,11383,11384,11385,11386,11387,11388,11389,11390,11391,11392,11393,11394,11395,11396,11397,11398,11399,11400,11401,11402,11403,11404,11405,11406,11407,11408,11409,11410,11411,11412,11413,11414,11415,11416,11417,11418,11419,11420,11421,11422,11423,11424,11425,11426,11427,11428,11429,11430,11431,11432,11433,11434,11435,11436,11437,11438,11439,11440,11441,11442,11443,11444,11445,11446,11447,11448,11449,11450,11451,11452,11453,11454,11455,11456,11457,11458,11459,11460,11461,11462,11463,11464,11465,11466,11467,11468,11469,11470,11471,11472,11473,11474,11475,11476,11477,11478,11479,11480,11481,11482,11483,11484,11485,11486,11487,11488,11489,11490,11491,11492,11499,11500,11501,11502,11506,11507,11520,11521,11522,11523,11524,11525,11526,11527,11528,11529
 ,11530,11531,11532,11533,11534,11535,11536,11537,11538,11539,11540,11541,11542,11543,11544,11545,11546,11547,11548,11549,11550,11551,11552,11553,11554,11555,11556,11557,11559,11565,11568,11569,11570,11571,11572,11573,11574,11575,11576,11577,11578,11579,11580,11581,11582,11583,11584,11585,11586,11587,11588,11589,11590,11591,11592,11593,11594,11595,11596,11597,11598,11599,11600,11601,11602,11603,11604,11605,11606,11607,11608,11609,11610,11611,11612,11613,11614,11615,11616,11617,11618,11619,11620,11621,11622,11623,11631,11648,11649,11650,11651,11652,11653,11654,11655,11656,11657,11658,11659,11660,11661,11662,11663,11664,11665,11666,11667,11668,11669,11670,11680,11681,11682,11683,11684,11685,11686,11688,11689,11690,11691,11692,11693,11694,11696,11697,11698,11699,11700,11701,11702,11704,11705,11706,11707,11708,11709,11710,11712,11713,11714,11715,11716,11717,11718,11720,11721,11722,11723,11724,11725,11726,11728,11729,11730,11731,11732,11733,11734,11736,11737,11738,11739,11740,11741,11742,
 11823,12293,12294,12295,12321,12322,12323,12324,12325,12326,12327,12328,12329,12337,12338,12339,12340,12341,12344,12345,12346,12347,12348,12353,12354,12355,12356,12357,12358,12359,12360,12361,12362,12363,12364,12365,12366,12367,12368,12369,12370,12371,12372,12373,12374,12375,12376,12377,12378,12379,12380,12381,12382,12383,12384,12385,12386,12387,12388,12389,12390,12391,12392,12393,12394,12395,12396,12397,12398,12399,12400,12401,12402,12403,12404,12405,12406,12407,12408,12409,12410,12411,12412,12413,12414,12415,12416,12417,12418,12419,12420,12421,12422,12423,12424,12425,12426,12427,12428,12429,12430,12431,12432,12433,12434,12435,12436,12437,12438,12445,12446,12447,12449,12450,12451,12452,12453,12454,12455,12456,12457,12458,12459,12460,12461,12462,12463,12464,12465,12466,12467,12468,12469,12470,12471,12472,12473,12474,12475,12476,12477,12478,12479,12480,12481,12482,12483,12484,12485,12486,12487,12488,12489,12490,12491,12492,12493,12494,12495,12496,12497,12498,12499,12500,12501,12502,1
 2503,12504,12505,12506,12507,12508,12509,12510,12511,12512,12513,12514,12515,12516,12517,12518,12519,12520,12521,12522,12523,12524,12525,12526,12527,12528,12529,12530,12531,12532,12533,12534,12535,12536,12537,12538,12540,12541,12542,12543,12549,12550,12551,12552,12553,12554,12555,12556,12557,12558,12559,12560,12561,12562,12563,12564,12565,12566,12567,12568,12569,12570,12571,12572,12573,12574,12575,12576,12577,12578,12579,12580,12581,12582,12583,12584,12585,12586,12587,12588,12589,12593,12594,12595,12596,12597,12598,12599,12600,12601,12602,12603,12604,12605,12606,12607,12608,12609,12610,12611,12612,12613,12614,12615,12616,12617,12618,12619,12620,12621,12622,12623,12624,12625,12626,12627,12628,12629,12630,12631,12632,12633,12634,12635,12636,12637,12638,12639,12640,12641,12642,12643,12644,12645,12646,12647,12648,12649,12650,12651,12652,12653,12654,12655,12656,12657,12658,12659,12660,12661,12662,12663,12664,12665,12666,12667,12668,12669,12670,12671,12672,12673,12674,12675,12676,12677,12
 678,12679,12680,12681,12682,12683,12684,12685,12686,12704,12705,12706,12707,12708,12709,12710,12711,12712,12713,12714,12715,12716,12717,12718,12719,12720,12721,12722,12723,12724,12725,12726,12727,12728,12729,12730,12784,12785,12786,12787,12788,12789,12790,12791,12792,12793,12794,12795,12796,12797,12798,12799,13312,13313,13314,13315,13316,13317,13318,13319,13320,13321,13322,13323,13324,13325,13326,13327,13328,13329,13330,13331,13332,13333,13334,13335,13336,13337,13338,13339,13340,13341,13342,13343,13344,13345,13346,13347,13348,13349,13350,13351,13352,13353,13354,13355,13356,13357,13358,13359,13360,13361,13362,13363,13364,13365,13366,13367,13368,13369,13370,13371,13372,13373,13374,13375,13376,13377,13378,13379,13380,13381,13382,13383,13384,13385,13386,13387,13388,13389,13390,13391,13392,13393,13394,13395,13396,13397,13398,13399,13400,13401,13402,13403,13404,13405,13406,13407,13408,13409,13410,13411,13412,13413,13414,13415,13416,13417,13418,13419,13420,13421,13422,13423,13424,13425,134
 26,13427,13428,13429,13430,13431,13432,13433,13434,13435,13436,13437,13438,13439,13440,13441,13442,13443,13444,13445,13446,13447,13448,13449,13450,13451,13452,13453,13454,13455,13456,13457,13458,13459,13460,13461,13462,13463,13464,13465,13466,13467,13468,13469,13470,13471,13472,13473,13474,13475,13476,13477,13478,13479,13480,13481,13482,13483,13484,13485,13486,13487,13488,13489,13490,13491,13492,13493,13494,13495,13496,13497,13498,13499,13500,13501,13502,13503,13504,13505,13506,13507,13508,13509,13510,13511,13512,13513,13514,13515,13516,13517,13518,13519,13520,13521,13522,13523,13524,13525,13526,13527,13528,13529,13530,13531,13532,13533,13534,13535,13536,13537,13538,13539,13540,13541,13542,13543,13544,13545,13546,13547,13548,13549,13550,13551,13552,13553,13554,13555,13556,13557,13558,13559,13560,13561,13562,13563,13564,13565,13566,13567,13568,13569,13570,13571,13572,13573,13574,13575,13576,13577,13578,13579,13580,13581,13582,13583,13584,13585,13586,13587,13588,13589,13590,13591,1359
 2,13593,13594,13595,13596,13597,13598,13599,13600,13601,13602,13603,13604,13605,13606,13607,13608,13609,13610,13611,13612,13613,13614,13615,13616,13617,13618,13619,13620,13621,13622,13623,13624,13625,13626,13627,13628,13629,13630,13631,13632,13633,13634,13635,13636,13637,13638,13639,13640,13641,13642,13643,13644,13645,13646,13647,13648,13649,13650,13651,13652,13653,13654,13655,13656,13657,13658,13659,13660,13661,13662,13663,13664,13665,13666,13667,13668,13669,13670,13671,13672,13673,13674,13675,13676,13677,13678,13679,13680,13681,13682,13683,13684,13685,13686,13687,13688,13689,13690,13691,13692,13693,13694,13695,13696,13697,13698,13699,13700,13701,13702,13703,13704,13705,13706,13707,13708,13709,13710,13711,13712,13713,13714,13715,13716,13717,13718,13719,13720,13721,13722,13723,13724,13725,13726,13727,13728,13729,13730,13731,13732,13733,13734,13735,13736,13737,13738,13739,13740,13741,13742,13743,13744,13745,13746,13747,13748,13749,13750,13751,13752,13753,13754,13755,13756,13757,13758
 ,13759,13760,13761,13762,13763,13764,13765,13766,13767,13768,13769,13770,13771,13772,13773,13774,13775,13776,13777,13778,13779,13780,13781,13782,13783,13784,13785,13786,13787,13788,13789,13790,13791,13792,13793,13794,13795,13796,13797,13798,13799,13800,13801,13802,13803,13804,13805,13806,13807,13808,13809,13810,13811,13812,13813,13814,13815,13816,13817,13818,13819,13820,13821,13822,13823,13824,13825,13826,13827,13828,13829,13830,13831,13832,13833,13834,13835,13836,13837,13838,13839,13840,13841,13842,13843,13844,13845,13846,13847,13848,13849,13850,13851,13852,13853,13854,13855,13856,13857,13858,13859,13860,13861,13862,13863,13864,13865,13866,13867,13868,13869,13870,13871,13872,13873,13874,13875,13876,13877,13878,13879,13880,13881,13882,13883,13884,13885,13886,13887,13888,13889,13890,13891,13892,13893,13894,13895,13896,13897,13898,13899,13900,13901,13902,13903,13904,13905,13906,13907,13908,13909,13910,13911,13912,13913,13914,13915,13916,13917,13918,13919,13920,13921,13922,13923,13924,
 13925,13926,13927,13928,13929,13930,13931,13932,13933,13934,13935,13936,13937,13938,13939,13940,13941,13942,13943,13944,13945,13946,13947,13948,13949,13950,13951,13952,13953,13954,13955,13956,13957,13958,13959,13960,13961,13962,13963,13964,13965,13966,13967,13968,13969,13970,13971,13972,13973,13974,13975,13976,13977,13978,13979,13980,13981,13982,13983,13984,13985,13986,13987,13988,13989,13990,13991,13992,13993,13994,13995,13996,13997,13998,13999,14000,14001,14002,14003,14004,14005,14006,14007,14008,14009,14010,14011,14012,14013,14014,14015,14016,14017,14018,14019,14020,14021,14022,14023,14024,14025,14026,14027,14028,14029,14030,14031,14032,14033,14034,14035,14036,14037,14038,14039,14040,14041,14042,14043,14044,14045,14046,14047,14048,14049,14050,14051,14052,14053,14054,14055,14056,14057,14058,14059,14060,14061,14062,14063,14064,14065,14066,14067,14068,14069,14070,14071,14072,14073,14074,14075,14076,14077,14078,14079,14080,14081,14082,14083,14084,14085,14086,14087,14088,14089,14090,1
 4091,14092,14093,14094,14095,14096,14097,14098,14099,14100,14101,14102,14103,14104,14105,14106,14107,14108,14109,14110,14111,14112,14113,14114,14115,14116,14117,14118,14119,14120,14121,14122,14123,14124,14125,14126,14127,14128,14129,14130,14131,14132,14133,14134,14135,14136,14137,14138,14139,14140,14141,14142,14143,14144,14145,14146,14147,14148,14149,14150,14151,14152,14153,14154,14155,14156,14157,14158,14159,14160,14161,14162,14163,14164,14165,14166,14167,14168,14169,14170,14171,14172,14173,14174,14175,14176,14177,14178,14179,14180,14181,14182,14183,14184,14185,14186,14187,14188,14189,14190,14191,14192,14193,14194,14195,14196,14197,14198,14199,14200,14201,14202,14203,14204,14205,14206,14207,14208,14209,14210,14211,14212,14213,14214,14215,14216,14217,14218,14219,14220,14221,14222,14223,14224,14225,14226,14227,14228,14229,14230,14231,14232,14233,14234,14235,14236,14237,14238,14239,14240,14241,14242,14243,14244,14245,14246,14247,14248,14249,14250,14251,14252,14253,14254,14255,14256,14
 257,14258,14259,14260,14261,14262,14263,14264,14265,14266,14267,14268,14269,14270,14271,14272,14273,14274,14275,14276,14277,14278,14279,14280,14281,14282,14283,14284,14285,14286,14287,14288,14289,14290,14291,14292,14293,14294,14295,14296,14297,14298,14299,14300,14301,14302,14303,14304,14305,14306,14307,14308,14309,14310,14311,14312,14313,14314,14315,14316,14317,14318,14319,14320,14321,14322,14323,14324,14325,14326,14327,14328,14329,14330,14331,14332,14333,14334,14335,14336,14337,14338,14339,14340,14341,14342,14343,14344,14345,14346,14347,14348,14349,14350,14351,14352,14353,14354,14355,14356,14357,14358,14359,14360,14361,14362,14363,14364,14365,14366,14367,14368,14369,14370,14371,14372,14373,14374,14375,14376,14377,14378,14379,14380,14381,14382,14383,14384,14385,14386,14387,14388,14389,14390,14391,14392,14393,14394,14395,14396,14397,14398,14399,14400,14401,14402,14403,14404,14405,14406,14407,14408,14409,14410,14411,14412,14413,14414,14415,14416,14417,14418,14419,14420,14421,14422,144
 23,14424,14425,14426,14427,14428,14429,14430,14431,14432,14433,14434,14435,14436,14437,14438,14439,14440,14441,14442,14443,14444,14445,14446,14447,14448,14449,14450,14451,14452,14453,14454,14455,14456,14457,14458,14459,14460,14461,14462,14463,14464,14465,14466,14467,14468,14469,14470,14471,14472,14473,14474,14475,14476,14477,14478,14479,14480,14481,14482,14483,14484,14485,14486,14487,14488,14489,14490,14491,14492,14493,14494,14495,14496,14497,14498,14499,14500,14501,14502,14503,14504,14505,14506,14507,14508,14509,14510,14511,14512,14513,14514,14515,14516,14517,14518,14519,14520,14521,14522,14523,14524,14525,14526,14527,14528,14529,14530,14531,14532,14533,14534,14535,14536,14537,14538,14539,14540,14541,14542,14543,14544,14545,14546,14547,14548,14549,14550,14551,14552,14553,14554,14555,14556,14557,14558,14559,14560,14561,14562,14563,14564,14565,14566,14567,14568,14569,14570,14571,14572,14573,14574,14575,14576,14577,14578,14579,14580,14581,14582,14583,14584,14585,14586,14587,14588,1458
 9,14590,14591,14592,14593,14594,14595,14596,14597,14598,14599,14600,14601,14602,14603,14604,14605,14606,14607,14608,14609,14610,14611,14612,14613,14614,14615,14616,14617,14618,14619,14620,14621,14622,14623,14624,14625,14626,14627,14628,14629,14630,14631,14632,14633,14634,14635,14636,14637,14638,14639,14640,14641,14642,14643,14644,14645,14646,14647,14648,14649,14650,14651,14652,14653,14654,14655,14656,14657,14658,14659,14660,14661,14662,14663,14664,14665,14666,14667,14668,14669,14670,14671,14672,14673,14674,14675,14676,14677,14678,14679,14680,14681,14682,14683,14684,14685,14686,14687,14688,14689,14690,14691,14692,14693,14694,14695,14696,14697,14698,14699,14700,14701,14702,14703,14704,14705,14706,14707,14708,14709,14710,14711,14712,14713,14714,14715,14716,14717,14718,14719,14720,14721,14722,14723,14724,14725,14726,14727,14728,14729,14730,14731,14732,14733,14734,14735,14736,14737,14738,14739,14740,14741,14742,14743,14744,14745,14746,14747,14748,14749,14750,14751,14752,14753,14754,14755
 ,14756,14757,14758,14759,14760,14761,14762,14763,14764,14765,14766,14767,14768,14769,14770,14771,14772,14773,14774,14775,14776,14777,14778,14779,14780,14781,14782,14783,14784,14785,14786,14787,14788,14789,14790,14791,14792,14793,14794,14795,14796,14797,14798,14799,14800,14801,14802,14803,14804,14805,14806,14807,14808,14809,14810,14811,14812,14813,14814,14815,14816,14817,14818,14819,14820,14821,14822,14823,14824,14825,14826,14827,14828,14829,14830,14831,14832,14833,14834,14835,14836,14837,14838,14839,14840,14841,14842,14843,14844,14845,14846,14847,14848,14849,14850,14851,14852,14853,14854,14855,14856,14857,14858,14859,14860,14861,14862,14863,14864,14865,14866,14867,14868,14869,14870,14871,14872,14873,14874,14875,14876,14877,14878,14879,14880,14881,14882,14883,14884,14885,14886,14887,14888,14889,14890,14891,14892,14893,14894,14895,14896,14897,14898,14899,14900,14901,14902,14903,14904,14905,14906,14907,14908,14909,14910,14911,14912,14913,14914,14915,14916,14917,14918,14919,14920,14921,
 14922,14923,14924,14925,14926,14927,14928,14929,14930,14931,14932,14933,14934,14935,14936,14937,14938,14939,14940,14941,14942,14943,14944,14945,14946,14947,14948,14949,14950,14951,14952,14953,14954,14955,14956,14957,14958,14959,14960,14961,14962,14963,14964,14965,14966,14967,14968,14969,14970,14971,14972,14973,14974,14975,14976,14977,14978,14979,14980,14981,14982,14983,14984,14985,14986,14987,14988,14989,14990,14991,14992,14993,14994,14995,14996,14997,14998,14999,15000,15001,15002,15003,15004,15005,15006,15007,15008,15009,15010,15011,15012,15013,15014,15015,15016,15017,15018,15019,15020,15021,15022,15023,15024,15025,15026,15027,15028,15029,15030,15031,15032,15033,15034,15035,15036,15037,15038,15039,15040,15041,15042,15043,15044,15045,15046,15047,15048,15049,15050,15051,15052,15053,15054,15055,15056,15057,15058,15059,15060,15061,15062,15063,15064,15065,15066,15067,15068,15069,15070,15071,15072,15073,15074,15075,15076,15077,15078,15079,15080,15081,15082,15083,15084,15085,15086,15087,1
 5088,15089,15090,15091,15092,15093,15094,15095,15096,15097,15098,15099,15100,15101,15102,15103,15104,15105,15106,15107,15108,15109,15110,15111,15112,15113,15114,15115,15116,15117,15118,15119,15120,15121,15122,15123,15124,15125,15126,15127,15128,15129,15130,15131,15132,15133,15134,15135,15136,15137,15138,15139,15140,15141,15142,15143,15144,15145,15146,15147,15148,15149,15150,15151,15152,15153,15154,15155,15156,15157,15158,15159,15160,15161,15162,15163,15164,15165,15166,15167,15168,15169,15170,15171,15172,15173,15174,15175,15176,15177,15178,15179,15180,15181,15182,15183,15184,15185,15186,15187,15188,15189,15190,15191,15192,15193,15194,15195,15196,15197,15198,15199,15200,15201,15202,15203,15204,15205,15206,15207,15208,15209,15210,15211,15212,15213,15214,15215,15216,15217,15218,15219,15220,15221,15222,15223,15224,15225,15226,15227,15228,15229,15230,15231,15232,15233,15234,15235,15236,15237,15238,15239,15240,15241,15242,15243,15244,15245,15246,15247,15248,15249,15250,15251,15252,15253,15
 254,15255,15256,15257,15258,15259,15260,15261,15262,15263,15264,15265,15266,15267,15268,15269,15270,15271,15272,15273,15274,15275,15276,15277,15278,15279,15280,15281,15282,15283,15284,15285,15286,15287,15288,15289,15290,15291,15292,15293,15294,15295,15296,15297,15298,15299,15300,15301,15302,15303,15304,15305,15306,15307,15308,15309,15310,15311,15312,15313,15314,15315,15316,15317,15318,15319,15320,15321,15322,15323,15324,15325,15326,15327,15328,15329,15330,15331,15332,15333,15334,15335,15336,15337,15338,15339,15340,15341,15342,15343,15344,15345,15346,15347,15348,15349,15350,15351,15352,15353,15354,15355,15356,15357,15358,15359,15360,15361,15362,15363,15364,15365,15366,15367,15368,15369,15370,15371,15372,15373,15374,15375,15376,15377,15378,15379,15380,15381,15382,15383,15384,15385,15386,15387,15388,15389,15390,15391,15392,15393,15394,15395,15396,15397,15398,15399,15400,15401,15402,15403,15404,15405,15406,15407,15408,15409,15410,15411,15412,15413,15414,15415,15416,15417,15418,15419,154
 20,15421,15422,15423,15424,15425,15426,15427,15428,15429,15430,15431,15432,15433,15434,15435,15436,15437,15438,15439,15440,15441,15442,15443,15444,15445,15446,15447,15448,15449,15450,15451,15452,15453,15454,15455,15456,15457,15458,15459,15460,15461,15462,15463,15464,15465,15466,15467,15468,15469,15470,15471,15472,15473,15474,15475,15476,15477,15478,15479,15480,15481,15482,15483,15484,15485,15486,15487,15488,15489,15490,15491,15492,15493,15494,15495,15496,15497,15498,15499,15500,15501,15502,15503,15504,15505,15506,15507,15508,15509,15510,15511,15512,15513,15514,15515,15516,15517,15518,15519,15520,15521,15522,15523,15524,15525,15526,15527,15528,15529,15530,15531,15532,15533,15534,15535,15536,15537,15538,15539,15540,15541,15542,15543,15544,15545,15546,15547,15548,15549,15550,15551,15552,15553,15554,15555,15556,15557,15558,15559,15560,15561,15562,15563,15564,15565,15566,15567,15568,15569,15570,15571,15572,15573,15574,15575,15576,15577,15578,15579,15580,15581,15582,15583,15584,15585,1558
 6,15587,15588,15589,15590,15591,15592,15593,15594,15595,15596,15597,15598,15599,15600,15601,15602,15603,15604,15605,15606,15607,15608,15609,15610,15611,15612,15613,15614,15615,15616,15617,15618,15619,15620,15621,15622,15623,15624,15625,15626,15627,15628,15629,15630,15631,15632,15633,15634,15635,15636,15637,15638,15639,15640,15641,15642,15643,15644,15645,15646,15647,15648,15649,15650,15651,15652,15653,15654,15655,15656,15657,15658,15659,15660,15661,15662,15663,15664,15665,15666,15667,15668,15669,15670,15671,15672,15673,15674,15675,15676,15677,15678,15679,15680,15681,15682,15683,15684,15685,15686,15687,15688,15689,15690,15691,15692,15693,15694,15695,15696,15697,15698,15699,15700,15701,15702,15703,15704,15705,15706,15707,15708,15709,15710,15711,15712,15713,15714,15715,15716,15717,15718,15719,15720,15721,15722,15723,15724,15725,15726,15727,15728,15729,15730,15731,15732,15733,15734,15735,15736,15737,15738,15739,15740,15741,15742,15743,15744,15745,15746,15747,15748,15749,15750,15751,15752
 ,15753,15754,15755,15756,15757,15758,15759,15760,15761,15762,15763,15764,15765,15766,15767,15768,15769,15770,15771,15772,15773,15774,15775,15776,15777,15778,15779,15780,15781,15782,15783,15784,15785,15786,15787,15788,15789,15790,15791,15792,15793,15794,15795,15796,15797,15798,15799,15800,15801,15802,15803,15804,15805,15806,15807,15808,15809,15810,15811,15812,15813,15814,15815,15816,15817,15818,15819,15820,15821,15822,15823,15824,15825,15826,15827,15828,15829,15830,15831,15832,15833,15834,15835,15836,15837,15838,15839,15840,15841,15842,15843,15844,15845,15846,15847,15848,15849,15850,15851,15852,15853,15854,15855,15856,15857,15858,15859,15860,15861,15862,15863,15864,15865,15866,15867,15868,15869,15870,15871,15872,15873,15874,15875,15876,15877,15878,15879,15880,15881,15882,15883,15884,15885,15886,15887,15888,15889,15890,15891,15892,15893,15894,15895,15896,15897,15898,15899,15900,15901,15902,15903,15904,15905,15906,15907,15908,15909,15910,15911,15912,15913,15914,15915,15916,15917,15918,
 15919,15920,15921,15922,15923,15924,15925,15926,15927,15928,15929,15930,15931,15932,15933,15934,15935,15936,15937,15938,15939,15940,15941,15942,15943,15944,15945,15946,15947,15948,15949,15950,15951,15952,15953,15954,15955,15956,15957,15958,15959,15960,15961,15962,15963,15964,15965,15966,15967,15968,15969,15970,15971,15972,15973,15974,15975,15976,15977,15978,15979,15980,15981,15982,15983,15984,15985,15986,15987,15988,15989,15990,15991,15992,15993,15994,15995,15996,15997,15998,15999,16000,16001,16002,16003,16004,16005,16006,16007,16008,16009,16010,16011,16012,16013,16014,16015,16016,16017,16018,16019,16020,16021,16022,16023,16024,16025,16026,16027,16028,16029,16030,16031,16032,16033,16034,16035,16036,16037,16038,16039,16040,16041,16042,16043,16044,16045,16046,16047,16048,16049,16050,16051,16052,16053,16054,16055,16056,16057,16058,16059,16060,16061,16062,16063,16064,16065,16066,16067,16068,16069,16070,16071,16072,16073,16074,16075,16076,16077,16078,16079,16080,16081,16082,16083,16084,1
 6085,16086,16087,16088,16089,16090,16091,16092,16093,16094,16095,16096,16097,16098,16099,16100,16101,16102,16103,16104,16105,16106,16107,16108,16109,16110,16111,16112,16113,16114,16115,16116,16117,16118,16119,16120,16121,16122,16123,16124,16125,16126,16127,16128,16129,16130,16131,16132,16133,16134,16135,16136,16137,16138,16139,16140,16141,16142,16143,16144,16145,16146,16147,16148,16149,16150,16151,16152,16153,16154,16155,16156,16157,16158,16159,16160,16161,16162,16163,16164,16165,16166,16167,16168,16169,16170,16171,16172,16173,16174,16175,16176,16177,16178,16179,16180,16181,16182,16183,16184,16185,16186,16187,16188,16189,16190,16191,16192,16193,16194,16195,16196,16197,16198,16199,16200,16201,16202,16203,16204,16205,16206,16207,16208,16209,16210,16211,16212,16213,16214,16215,16216,16217,16218,16219,16220,16221,16222,16223,16224,16225,16226,16227,16228,16229,16230,16231,16232,16233,16234,16235,16236,16237,16238,16239,16240,16241,16242,16243,16244,16245,16246,16247,16248,16249,16250,16
 251,16252,16253,16254,16255,16256,16257,16258,16259,16260,16261,16262,16263,16264,16265,16266,16267,16268,16269,16270,16271,16272,16273,16274,16275,16276,16277,16278,16279,16280,16281,16282,16283,16284,16285,16286,16287,16288,16289,16290,16291,16292,16293,16294,16295,16296,16297,16298,16299,16300,16301,16302,16303,16304,16305,16306,16307,16308,16309,16310,16311,16312,16313,16314,16315,16316,16317,16318,16319,16320,16321,16322,16323,16324,16325,16326,16327,16328,16329,16330,16331,16332,16333,16334,16335,16336,16337,16338,16339,16340,16341,16342,16343,16344,16345,16346,16347,16348,16349,16350,16351,16352,16353,16354,16355,16356,16357,16358,16359,16360,16361,16362,16363,16364,16365,16366,16367,16368,16369,16370,16371,16372,16373,16374,16375,16376,16377,16378,16379,16380,16381,16382,16383,16384,16385,16386,16387,16388,16389,16390,16391,16392,16393,16394,16395,16396,16397,16398,16399,16400,16401,16402,16403,16404,16405,16406,16407,16408,16409,16410,16411,16412,16413,16414,16415,16416,164
 17,16418,16419,16420,16421,16422,16423,16424,16425,16426,16427,16428,16429,16430,16431,16432,16433,16434,16435,16436,16437,16438,16439,16440,16441,16442,16443,16444,16445,16446,16447,16448,16449,16450,16451,16452,16453,16454,16455,16456,16457,16458,16459,16460,16461,16462,16463,16464,16465,16466,16467,16468,16469,16470,16471,16472,16473,16474,16475,16476,16477,16478,16479,16480,16481,16482,16483,16484,16485,16486,16487,16488,16489,16490,16491,16492,16493,16494,16495,16496,16497,16498,16499,16500,16501,16502,16503,16504,16505,16506,16507,16508,16509,16510,16511,16512,16513,16514,16515,16516,16517,16518,16519,16520,16521,16522,16523,16524,16525,16526,16527,16528,16529,16530,16531,16532,16533,16534,16535,16536,16537,16538,16539,16540,16541,16542,16543,16544,16545,16546,16547,16548,16549,16550,16551,16552,16553,16554,16555,16556,16557,16558,16559,16560,16561,16562,16563,16564,16565,16566,16567,16568,16569,16570,16571,16572,16573,16574,16575,16576,16577,16578,16579,16580,16581,16582,1658
 3,16584,16585,16586,16587,16588,16589,16590,16591,16592,16593,16594,16595,16596,16597,16598,16599,16600,16601,16602,16603,16604,16605,16606,16607,16608,16609,16610,16611,16612,16613,16614,16615,16616,16617,16618,16619,16620,16621,16622,16623,16624,16625,16626,16627,16628,16629,16630,16631,16632,16633,16634,16635,16636,16637,16638,16639,16640,16641,16642,16643,16644,16645,16646,16647,16648,16649,16650,16651,16652,16653,16654,16655,16656,16657,16658,16659,16660,16661,16662,16663,16664,16665,16666,16667,16668,16669,16670,16671,16672,16673,16674,16675,16676,16677,16678,16679,16680,16681,16682,16683,16684,16685,16686,16687,16688,16689,16690,16691,16692,16693,16694,16695,16696,16697,16698,16699,16700,16701,16702,16703,16704,16705,16706,16707,16708,16709,16710,16711,16712,16713,16714,16715,16716,16717,16718,16719,16720,16721,16722,16723,16724,16725,16726,16727,16728,16729,16730,16731,16732,16733,16734,16735,16736,16737,16738,16739,16740,16741,16742,16743,16744,16745,16746,16747,16748,16749
 ,16750,16751,16752,16753,16754,16755,16756,16757,16758,16759,16760,16761,16762,16763,16764,16765,16766,16767,16768,16769,16770,16771,16772,16773,16774,16775,16776,16777,16778,16779,16780,16781,16782,16783,16784,16785,16786,16787,16788,16789,16790,16791,16792,16793,16794,16795,16796,16797,16798,16799,16800,16801,16802,16803,16804,16805,16806,16807,16808,16809,16810,16811,16812,16813,16814,16815,16816,16817,16818,16819,16820,16821,16822,16823,16824,16825,16826,16827,16828,16829,16830,16831,16832,16833,16834,16835,16836,16837,16838,16839,16840,16841,16842,16843,16844,16845,16846,16847,16848,16849,16850,16851,16852,16853,16854,16855,16856,16857,16858,16859,16860,16861,16862,16863,16864,16865,16866,16867,16868,16869,16870,16871,16872,16873,16874,16875,16876,16877,16878,16879,16880,16881,16882,16883,16884,16885,16886,16887,16888,16889,16890,16891,16892,16893,16894,16895,16896,16897,16898,16899,16900,16901,16902,16903,16904,16905,16906,16907,16908,16909,16910,16911,16912,16913,16914,16915,
 16916,16917,16918,16919,16920,16921,16922,16923,16924,16925,16926,16927,16928,16929,16930,16931,16932,16933,16934,16935,16936,16937,16938,16939,16940,16941,16942,16943,16944,16945,16946,16947,16948,16949,16950,16951,16952,16953,16954,16955,16956,16957,16958,16959,16960,16961,16962,16963,16964,16965,16966,16967,16968,16969,16970,16971,16972,16973,16974,16975,16976,16977,16978,16979,16980,16981,16982,16983,16984,16985,16986,16987,16988,16989,16990,16991,16992,16993,16994,16995,16996,16997,16998,16999,17000,17001,17002,17003,17004,17005,17006,17007,17008,17009,17010,17011,17012,17013,17014,17015,17016,17017,17018,17019,17020,17021,17022,17023,17024,17025,17026,17027,17028,17029,17030,17031,17032,17033,17034,17035,17036,17037,17038,17039,17040,17041,17042,17043,17044,17045,17046,17047,17048,17049,17050,17051,17052,17053,17054,17055,17056,17057,17058,17059,17060,17061,17062,17063,17064,17065,17066,17067,17068,17069,17070,17071,17072,17073,17074,17075,17076,17077,17078,17079,17080,17081,1
 7082,17083,17084,17085,17086,17087,17088,17089,17090,17091,17092,17093,17094,17095,17096,17097,17098,17099,17100,17101,17102,17103,17104,17105,17106,17107,17108,17109,17110,17111,17112,17113,17114,17115,17116,17117,17118,17119,17120,17121,17122,17123,17124,17125,17126,17127,17128,17129,17130,17131,17132,17133,17134,17135,17136,17137,17138,17139,17140,17141,17142,17143,17144,17145,17146,17147,17148,17149,17150,17151,17152,17153,17154,17155,17156,17157,17158,17159,17160,17161,17162,17163,17164,17165,17166,17167,17168,17169,17170,17171,17172,17173,17174,17175,17176,17177,17178,17179,17180,17181,17182,17183,17184,17185,17186,17187,17188,17189,17190,17191,17192,17193,17194,17195,17196,17197,17198,17199,17200,17201,17202,17203,17204,17205,17206,17207,17208,17209,17210,17211,17212,17213,17214,17215,17216,17217,17218,17219,17220,17221,17222,17223,17224,17225,17226,17227,17228,17229,17230,17231,17232,17233,17234,17235,17236,17237,17238,17239,17240,17241,17242,17243,17244,17245,17246,17247,17
 248,17249,17250,17251,17252,17253,17254,17255,17256,17257,17258,17259,17260,17261,17262,17263,17264,17265,17266,17267,17268,17269,17270,17271,17272,17273,17274,17275,17276,17277,17278,17279,17280,17281,17282,17283,17284,17285,17286,17287,17288,17289,17290,17291,17292,17293,17294,17295,17296,17297,17298,17299,17300,17301,17302,17303,17304,17305,17306,17307,17308,17309,17310,17311,17312,17313,17314,17315,17316,17317,17318,17319,17320,17321,17322,17323,17324,17325,17326,17327,17328,17329,17330,17331,17332,17333,17334,17335,17336,17337,17338,17339,17340,17341,17342,17343,17344,17345,17346,17347,17348,17349,17350,17351,17352,17353,17354,17355,17356,17357,17358,17359,17360,17361,17362,17363,17364,17365,17366,17367,17368,17369,17370,17371,17372,17373,17374,17375,17376,17377,17378,17379,17380,17381,17382,17383,17384,17385,17386,17387,17388,17389,17390,17391,17392,17393,17394,17395,17396,17397,17398,17399,17400,17401,17402,17403,17404,17405,17406,17407,17408,17409,17410,17411,17412,17413,174
 14,17415,17416,17417,17418,17419,17420,17421,17422,17423,17424,17425,17426,17427,17428,17429,17430,17431,17432,17433,17434,17435,17436,17437,17438,17439,17440,17441,17442,17443,17444,17445,17446,17447,17448,17449,17450,17451,17452,17453,17454,17455,17456,17457,17458,17459,17460,17461,17462,17463,17464,17465,17466,17467,17468,17469,17470,17471,17472,17473,17474,17475,17476,17477,17478,17479,17480,17481,17482,17483,17484,17485,17486,17487,17488,17489,17490,17491,17492,17493,17494,17495,17496,17497,17498,17499,17500,17501,17502,17503,17504,17505,17506,17507,17508,17509,17510,17511,17512,17513,17514,17515,17516,17517,17518,17519,17520,17521,17522,17523,17524,17525,17526,17527,17528,17529,17530,17531,17532,17533,17534,17535,17536,17537,17538,17539,17540,17541,17542,17543,17544,17545,17546,17547,17548,17549,17550,17551,17552,17553,17554,17555,17556,17557,17558,17559,17560,17561,17562,17563,17564,17565,17566,17567,17568,17569,17570,17571,17572,17573,17574,17575,17576,17577,17578,17579,1758
 0,17581,17582,17583,17584,17585,17586,17587,17588,17589,17590,17591,17592,17593,17594,17595,17596,17597,17598,17599,17600,17601,17602,17603,17604,17605,17606,17607,17608,17609,17610,17611,17612,17613,17614,17615,17616,17617,17618,17619,17620,17621,17622,17623,17624,17625,17626,17627,17628,17629,17630,17631,17632,17633,17634,17635,17636,17637,17638,17639,17640,17641,17642,17643,17644,17645,17646,17647,17648,17649,17650,17651,17652,17653,17654,17655,17656,17657,17658,17659,17660,17661,17662,17663,17664,17665,17666,17667,17668,17669,17670,17671,17672,17673,17674,17675,17676,17677,17678,17679,17680,17681,17682,17683,17684,17685,17686,17687,17688,17689,17690,17691,17692,17693,17694,17695,17696,17697,17698,17699,17700,17701,17702,17703,17704,17705,17706,17707,17708,17709,17710,17711,17712,17713,17714,17715,17716,17717,17718,17719,17720,17721,17722,17723,17724,17725,17726,17727,17728,17729,17730,17731,17732,17733,17734,17735,17736,17737,17738,17739,17740,17741,17742,17743,17744,17745,17746
 ,17747,17748,17749,17750,17751,17752,17753,17754,17755,17756,17757,17758,17759,17760,17761,17762,17763,17764,17765,17766,17767,17768,17769,17770,17771,17772,17773,17774,17775,17776,17777,17778,17779,17780,17781,17782,17783,17784,17785,17786,17787,17788,17789,17790,17791,17792,17793,17794,17795,17796,17797,17798,17799,17800,17801,17802,17803,17804,17805,17806,17807,17808,17809,17810,17811,17812,17813,17814,17815,17816,17817,17818,17819,17820,17821,17822,17823,17824,17825,17826,17827,17828,17829,17830,17831,17832,17833,17834,17835,17836,17837,17838,17839,17840,17841,17842,17843,17844,17845,17846,17847,17848,17849,17850,17851,17852,17853,17854,17855,17856,17857,17858,17859,17860,17861,17862,17863,17864,17865,17866,17867,17868,17869,17870,17871,17872,17873,17874,17875,17876,17877,17878,17879,17880,17881,17882,17883,17884,17885,17886,17887,17888,17889,17890,17891,17892,17893,17894,17895,17896,17897,17898,17899,17900,17901,17902,17903,17904,17905,17906,17907,17908,17909,17910,17911,17912,
 17913,17914,17915,17916,17917,17918,17919,17920,17921,17922,17923,17924,17925,17926,17927,17928,17929,17930,17931,17932,17933,17934,17935,17936,17937,17938,17939,17940,17941,17942,17943,17944,17945,17946,17947,17948,17949,17950,17951,17952,17953,17954,17955,17956,17957,17958,17959,17960,17961,17962,17963,17964,17965,17966,17967,17968,17969,17970,17971,17972,17973,17974,17975,17976,17977,17978,17979,17980,17981,17982,17983,17984,17985,17986,17987,17988,17989,17990,17991,17992,17993,17994,17995,17996,17997,17998,17999,18000,18001,18002,18003,18004,18005,18006,18007,18008,18009,18010,18011,18012,18013,18014,18015,18016,18017,18018,18019,18020,18021,18022,18023,18024,18025,18026,18027,18028,18029,18030,18031,18032,18033,18034,18035,18036,18037,18038,18039,18040,18041,18042,18043,18044,18045,18046,18047,18048,18049,18050,18051,18052,18053,18054,18055,18056,18057,18058,18059,18060,18061,18062,18063,18064,18065,18066,18067,18068,18069,18070,18071,18072,18073,18074,18075,18076,18077,18078,1
 8079,18080,18081,18082,18083,18084,18085,18086,18087,18088,18089,18090,18091,18092,18093,18094,18095,18096,18097,18098,18099,18100,18101,18102,18103,18104,18105,18106,18107,18108,18109,18110,18111,18112,18113,18114,18115,18116,18117,18118,18119,18120,18121,18122,18123,18124,18125,18126,18127,18128,18129,18130,18131,18132,18133,18134,18135,18136,18137,18138,18139,18140,18141,18142,18143,18144,18145,18146,18147,18148,18149,18150,18151,18152,18153,18154,18155,18156,18157,18158,18159,18160,18161,18162,18163,18164,18165,18166,18167,18168,18169,18170,18171,18172,18173,18174,18175,18176,18177,18178,18179,18180,18181,18182,18183,18184,18185,18186,18187,18188,18189,18190,18191,18192,18193,18194,18195,18196,18197,18198,18199,18200,18201,18202,18203,18204,18205,18206,18207,18208,18209,18210,18211,18212,18213,18214,18215,18216,18217,18218,18219,18220,18221,18222,18223,18224,18225,18226,18227,18228,18229,18230,18231,18232,18233,18234,18235,18236,18237,18238,18239,18240,18241,18242,18243,18244,18
 245,18246,18247,18248,18249,18250,18251,18252,18253,18254,18255,18256,18257,18258,18259,18260,18261,18262,18263,18264,18265,18266,18267,18268,18269,18270,18271,18272,18273,18274,18275,18276,18277,18278,18279,18280,18281,18282,18283,18284,18285,18286,18287,18288,18289,18290,18291,18292,18293,18294,18295,18296,18297,18298,18299,18300,18301,18302,18303,18304,18305,18306,18307,18308,18309,18310,18311,18312,18313,18314,18315,18316,18317,18318,18319,18320,18321,18322,18323,18324,18325,18326,18327,18328,18329,18330,18331,18332,18333,18334,18335,18336,18337,18338,18339,18340,18341,18342,18343,18344,18345,18346,18347,18348,18349,18350,18351,18352,18353,18354,18355,18356,18357,18358,18359,18360,18361,18362,18363,18364,18365,18366,18367,18368,18369,18370,18371,18372,18373,18374,18375,18376,18377,18378,18379,18380,18381,18382,18383,18384,18385,18386,18387,18388,18389,18390,18391,18392,18393,18394,18395,18396,18397,18398,18399,18400,18401,18402,18403,18404,18405,18406,18407,18408,18409,18410,184
 11,18412,18413,18414,18415,18416,18417,18418,18419,18420,18421,18422,18423,18424,18425,18426,18427,18428,18429,18430,18431,18432,18433,18434,18435,18436,18437,18438,18439,18440,18441,18442,18443,18444,18445,18446,18447,18448,18449,18450,18451,18452,18453,18454,18455,18456,18457,18458,18459,18460,18461,18462,18463,18464,18465,18466,18467,18468,18469,18470,18471,18472,18473,18474,18475,18476,18477,18478,18479,18480,18481,18482,18483,18484,18485,18486,18487,18488,18489,18490,18491,18492,18493,18494,18495,18496,18497,18498,18499,18500,18501,18502,18503,18504,18505,18506,18507,18508,18509,18510,18511,18512,18513,18514,18515,18516,18517,18518,18519,18520,18521,18522,18523,18524,18525,18526,18527,18528,18529,18530,18531,18532,18533,18534,18535,18536,18537,18538,18539,18540,18541,18542,18543,18544,18545,18546,18547,18548,18549,18550,18551,18552,18553,18554,18555,18556,18557,18558,18559,18560,18561,18562,18563,18564,18565,18566,18567,18568,18569,18570,18571,18572,18573,18574,18575,18576,1857
 7,18578,18579,18580,18581,18582,18583,18584,18585,18586,18587,18588,18589,18590,18591,18592,18593,18594,18595,18596,18597,18598,18599,18600,18601,18602,18603,18604,18605,18606,18607,18608,18609,18610,18611,18612,18613,18614,18615,18616,18617,18618,18619,18620,18621,18622,18623,18624,18625,18626,18627,18628,18629,18630,18631,18632,18633,18634,18635,18636,18637,18638,18639,18640,18641,18642,18643,18644,18645,18646,18647,18648,18649,18650,18651,18652,18653,18654,18655,18656,18657,18658,18659,18660,18661,18662,18663,18664,18665,18666,18667,18668,18669,18670,18671,18672,18673,18674,18675,18676,18677,18678,18679,18680,18681,18682,18683,18684,18685,18686,18687,18688,18689,18690,18691,18692,18693,18694,18695,18696,18697,18698,18699,18700,18701,18702,18703,18704,18705,18706,18707,18708,18709,18710,18711,18712,18713,18714,18715,18716,18717,18718,18719,18720,18721,18722,18723,18724,18725,18726,18727,18728,18729,18730,18731,18732,18733,18734,18735,18736,18737,18738,18739,18740,18741,18742,18743
 ,18744,18745,18746,18747,18748,18749,18750,18751,18752,18753,18754,18755,18756,18757,18758,18759,18760,18761,18762,18763,18764,18765,18766,18767,18768,18769,18770,18771,18772,18773,18774,18775,18776,18777,18778,18779,18780,18781,18782,18783,18784,18785,18786,18787,18788,18789,18790,18791,18792,18793,18794,18795,18796,18797,18798,18799,18800,18801,18802,18803,18804,18805,18806,18807,18808,18809,18810,18811,18812,18813,18814,18815,18816,18817,18818,18819,18820,18821,18822,18823,18824,18825,18826,18827,18828,18829,18830,18831,18832,18833,18834,18835,18836,18837,18838,18839,18840,18841,18842,18843,18844,18845,18846,18847,18848,18849,18850,18851,18852,18853,18854,18855,18856,18857,18858,18859,18860,18861,18862,18863,18864,18865,18866,18867,18868,18869,18870,18871,18872,18873,18874,18875,18876,18877,18878,18879,18880,18881,18882,18883,18884,18885,18886,18887,18888,18889,18890,18891,18892,18893,18894,18895,18896,18897,18898,18899,18900,18901,18902,18903,18904,18905,18906,18907,18908,18909,
 18910,18911,18912,18913,18914,18915,18916,18917,18918,18919,18920,18921,18922,18923,18924,18925,18926,18927,18928,18929,18930,18931,18932,18933,18934,18935,18936,18937,18938,18939,18940,18941,18942,18943,18944,18945,18946,18947,18948,18949,18950,18951,18952,18953,18954,18955,18956,18957,18958,18959,18960,18961,18962,18963,18964,18965,18966,18967,18968,18969,18970,18971,18972,18973,18974,18975,18976,18977,18978,18979,18980,18981,18982,18983,18984,18985,18986,18987,18988,18989,18990,18991,18992,18993,18994,18995,18996,18997,18998,18999,19000,19001,19002,19003,19004,19005,19006,19007,19008,19009,19010,19011,19012,19013,19014,19015,19016,19017,19018,19019,19020,19021,19022,19023,19024,19025,19026,19027,19028,19029,19030,19031,19032,19033,19034,19035,19036,19037,19038,19039,19040,19041,19042,19043,19044,19045,19046,19047,19048,19049,19050,19051,19052,19053,19054,19055,19056,19057,19058,19059,19060,19061,19062,19063,19064,19065,19066,19067,19068,19069,19070,19071,19072,19073,19074,19075,1
 9076,19077,19078,19079,19080,19081,19082,19083,19084,19085,19086,19087,19088,19089,19090,19091,19092,19093,19094,19095,19096,19097,19098,19099,19100,19101,19102,19103,19104,19105,19106,19107,19108,19109,19110,19111,19112,19113,19114,19115,19116,19117,19118,19119,19120,19121,19122,19123,19124,19125,19126,19127,19128,19129,19130,19131,19132,19133,19134,19135,19136,19137,19138,19139,19140,19141,19142,19143,19144,19145,19146,19147,19148,19149,19150,19151,19152,19153,19154,19155,19156,19157,19158,19159,19160,19161,19162,19163,19164,19165,19166,19167,19168,19169,19170,19171,19172,19173,19174,19175,19176,19177,19178,19179,19180,19181,19182,19183,19184,19185,19186,19187,19188,19189,19190,19191,19192,19193,19194,19195,19196,19197,19198,19199,19200,19201,19202,19203,19204,19205,19206,19207,19208,19209,19210,19211,19212,19213,19214,19215,19216,19217,19218,19219,19220,19221,19222,19223,19224,19225,19226,19227,19228,19229,19230,19231,19232,19233,19234,19235,19236,19237,19238,19239,19240,19241,19
 242,19243,19244,19245,19246,19247,19248,19249,19250,19251,19252,19253,19254,19255,19256,19257,19258,19259,19260,19261,19262,19263,19264,19265,19266,19267,19268,19269,19270,19271,19272,19273,19274,19275,19276,19277,19278,19279,19280,19281,19282,19283,19284,19285,19286,19287,19288,19289,19290,19291,19292,19293,19294,19295,19296,19297,19298,19299,19300,19301,19302,19303,19304,19305,19306,19307,19308,19309,19310,19311,19312,19313,19314,19315,19316,19317,19318,19319,19320,19321,19322,19323,19324,19325,19326,19327,19328,19329,19330,19331,19332,19333,19334,19335,19336,19337,19338,19339,19340,19341,19342,19343,19344,19345,19346,19347,19348,19349,19350,19351,19352,19353,19354,19355,19356,19357,19358,19359,19360,19361,19362,19363,19364,19365,19366,19367,19368,19369,19370,19371,19372,19373,19374,19375,19376,19377,19378,19379,19380,19381,19382,19383,19384,19385,19386,19387,19388,19389,19390,19391,19392,19393,19394,19395,19396,19397,19398,19399,19400,19401,19402,19403,19404,19405,19406,19407,194
 08,19409,19410,19411,19412,19413,19414,19415,19416,19417,19418,19419,19420,19421,19422,19423,19424,19425,19426,19427,19428,19429,19430,19431,19432,19433,19434,19435,19436,19437,19438,19439,19440,19441,19442,19443,19444,19445,19446,19447,19448,19449,19450,19451,19452,19453,19454,19455,19456,19457,19458,19459,19460,19461,19462,19463,19464,19465,19466,19467,19468,19469,19470,19471,19472,19473,19474,19475,19476,19477,19478,19479,19480,19481,19482,19483,19484,19485,19486,19487,19488,19489,19490,19491,19492,19493,19494,19495,19496,19497,19498,19499,19500,19501,19502,19503,19504,19505,19506,19507,19508,19509,19510,19511,19512,19513,19514,19515,19516,19517,19518,19519,19520,19521,19522,19523,19524,19525,19526,19527,19528,19529,19530,19531,19532,19533,19534,19535,19536,19537,19538,19539,19540,19541,19542,19543,19544,19545,19546,19547,19548,19549,19550,19551,19552,19553,19554,19555,19556,19557,19558,19559,19560,19561,19562,19563,19564,19565,19566,19567,19568,19569,19570,19571,19572,19573,1957
 4,19575,19576,19577,19578,19579,19580,19581,19582,19583,19584,19585,19586,19587,19588,19589,19590,19591,19592,19593,19594,19595,19596,19597,19598,19599,19600,19601,19602,19603,19604,19605,19606,19607,19608,19609,19610,19611,19612,19613,19614,19615,19616,19617,19618,19619,19620,19621,19622,19623,19624,19625,19626,19627,19628,19629,19630,19631,19632,19633,19634,19635,19636,19637,19638,19639,19640,19641,19642,19643,19644,19645,19646,19647,19648,19649,19650,19651,19652,19653,19654,19655,19656,19657,19658,19659,19660,19661,19662,19663,19664,19665,19666,19667,19668,19669,19670,19671,19672,19673,19674,19675,19676,19677,19678,19679,19680,19681,19682,19683,19684,19685,19686,19687,19688,19689,19690,19691,19692,19693,19694,19695,19696,19697,19698,19699,19700,19701,19702,19703,19704,19705,19706,19707,19708,19709,19710,19711,19712,19713,19714,19715,19716,19717,19718,19719,19720,19721,19722,19723,19724,19725,19726,19727,19728,19729,19730,19731,19732,19733,19734,19735,19736,19737,19738,19739,19740
 ,19741,19742,19743,19744,19745,19746,19747,19748,19749,19750,19751,19752,19753,19754,19755,19756,19757,19758,19759,19760,19761,19762,19763,19764,19765,19766,19767,19768,19769,19770,19771,19772,19773,19774,19775,19776,19777,19778,19779,19780,19781,19782,19783,19784,19785,19786,19787,19788,19789,19790,19791,19792,19793,19794,19795,19796,19797,19798,19799,19800,19801,19802,19803,19804,19805,19806,19807,19808,19809,19810,19811,19812,19813,19814,19815,19816,19817,19818,19819,19820,19821,19822,19823,19824,19825,19826,19827,19828,19829,19830,19831,19832,19833,19834,19835,19836,19837,19838,19839,19840,19841,19842,19843,19844,19845,19846,19847,19848,19849,19850,19851,19852,19853,19854,19855,19856,19857,19858,19859,19860,19861,19862,19863,19864,19865,19866,19867,19868,19869,19870,19871,19872,19873,19874,19875,19876,19877,19878,19879,19880,19881,19882,19883,19884,19885,19886,19887,19888,19889,19890,19891,19892,19893,19968,19969,19970,19971,19972,19973,19974,19975,19976,19977,19978,19979,19980,
 19981,19982,19983,19984,19985,19986,19987,19988,19989,19990,19991,19992,19993,19994,19995,19996,19997,19998,19999,20000,20001,20002,20003,20004,20005,20006,20007,20008,20009,20010,20011,20012,20013,20014,20015,20016,20017,20018,20019,20020,20021,20022,20023,20024,20025,20026,20027,20028,20029,20030,20031,20032,20033,20034,20035,20036,20037,20038,20039,20040,20041,20042,20043,20044,20045,20046,20047,20048,20049,20050,20051,20052,20053,20054,20055,20056,20057,20058,20059,20060,20061,20062,20063,20064,20065,20066,20067,20068,20069,20070,20071,20072,20073,20074,20075,20076,20077,20078,20079,20080,20081,20082,20083,20084,20085,20086,20087,20088,20089,20090,20091,20092,20093,20094,20095,20096,20097,20098,20099,20100,20101,20102,20103,20104,20105,20106,20107,20108,20109,20110,20111,20112,20113,20114,20115,20116,20117,20118,20119,20120,20121,20122,20123,20124,20125,20126,20127,20128,20129,20130,20131,20132,20133,20134,20135,20136,20137,20138,20139,20140,20141,20142,20143,20144,20145,20146,2
 0147,20148,20149,20150,20151,20152,20153,20154,20155,20156,20157,20158,20159,20160,20161,20162,20163,20164,20165,20166,20167,20168,20169,20170,20171,20172,20173,20174,20175,20176,20177,20178,20179,20180,20181,20182,20183,20184,20185,20186,20187,20188,20189,20190,20191,20192,20193,20194,20195,20196,20197,20198,20199,20200,20201,20202,20203,20204,20205,20206,20207,20208,20209,20210,20211,20212,20213,20214,20215,20216,20217,20218,20219,20220,20221,20222,20223,20224,20225,20226,20227,20228,20229,20230,20231,20232,20233,20234,20235,20236,20237,20238,20239,20240,20241,20242,20243,20244,20245,20246,20247,20248,20249,20250,20251,20252,20253,20254,20255,20256,20257,20258,20259,20260,20261,20262,20263,20264,20265,20266,20267,20268,20269,20270,20271,20272,20273,20274,20275,20276,20277,20278,20279,20280,20281,20282,20283,20284,20285,20286,20287,20288,20289,20290,20291,20292,20293,20294,20295,20296,20297,20298,20299,20300,20301,20302,20303,20304,20305,20306,20307,20308,20309,20310,20311,20312,20
 313,20314,20315,20316,20317,20318,20319,20320,20321,20322,20323,20324,20325,20326,20327,20328,20329,20330,20331,20332,20333,20334,20335,20336,20337,20338,20339,20340,20341,20342,20343,20344,20345,20346,20347,20348,20349,20350,20351,20352,20353,20354,20355,20356,20357,20358,20359,20360,20361,20362,20363,20364,20365,20366,20367,20368,20369,20370,20371,20372,20373,20374,20375,20376,20377,20378,20379,20380,20381,20382,20383,20384,20385,20386,20387,20388,20389,20390,20391,20392,20393,20394,20395,20396,20397,20398,20399,20400,20401,20402,20403,20404,20405,20406,20407,20408,20409,20410,20411,20412,20413,20414,20415,20416,20417,20418,20419,20420,20421,20422,20423,20424,20425,20426,20427,20428,20429,20430,20431,20432,20433,20434,20435,20436,20437,20438,20439,20440,20441,20442,20443,20444,20445,20446,20447,20448,20449,20450,20451,20452,20453,20454,20455,20456,20457,20458,20459,20460,20461,20462,20463,20464,20465,20466,20467,20468,20469,20470,20471,20472,20473,20474,20475,20476,20477,20478,204
 79,20480,20481,20482,20483,20484,20485,20486,20487,20488,20489,20490,20491,20492,20493,20494,20495,20496,20497,20498,20499,20500,20501,20502,20503,20504,20505,20506,20507,20508,20509,20510,20511,20512,20513,20514,20515,20516,20517,20518,20519,20520,20521,20522,20523,20524,20525,20526,20527,20528,20529,20530,20531,20532,20533,20534,20535,20536,20537,20538,20539,20540,20541,20542,20543,20544,20545,20546,20547,20548,20549,20550,20551,20552,20553,20554,20555,20556,20557,20558,20559,20560,20561,20562,20563,20564,20565,20566,20567,20568,20569,20570,20571,20572,20573,20574,20575,20576,20577,20578,20579,20580,20581,20582,20583,20584,20585,20586,20587,20588,20589,20590,20591,20592,20593,20594,20595,20596,20597,20598,20599,20600,20601,20602,20603,20604,20605,20606,20607,20608,20609,20610,20611,20612,20613,20614,20615,20616,20617,20618,20619,20620,20621,20622,20623,20624,20625,20626,20627,20628,20629,20630,20631,20632,20633,20634,20635,20636,20637,20638,20639,20640,20641,20642,20643,20644,2064
 5,20646,20647,20648,20649,20650,20651,20652,20653,20654,20655,20656,20657,20658,20659,20660,20661,20662,20663,20664,20665,20666,20667,20668,20669,20670,20671,20672,20673,20674,20675,20676,20677,20678,20679,20680,20681,20682,20683,20684,20685,20686,20687,20688,20689,20690,20691,20692,20693,20694,20695,20696,20697,20698,20699,20700,20701,20702,20703,20704,20705,20706,20707,20708,20709,20710,20711,20712,20713,20714,20715,20716,20717,20718,20719,20720,20721,20722,20723,20724,20725,20726,20727,20728,20729,20730,20731,20732,20733,20734,20735,20736,20737,20738,20739,20740,20741,20742,20743,20744,20745,20746,20747,20748,20749,20750,20751,20752,20753,20754,20755,20756,20757,20758,20759,20760,20761,20762,20763,20764,20765,20766,20767,20768,20769,20770,20771,20772,20773,20774,20775,20776,20777,20778,20779,20780,20781,20782,20783,20784,20785,20786,20787,20788,20789,20790,20791,20792,20793,20794,20795,20796,20797,20798,20799,20800,20801,20802,20803,20804,20805,20806,20807,20808,20809,20810,20811
 ,20812,20813,20814,20815,20816,20817,20818,20819,20820,20821,20822,20823,20824,20825,20826,20827,20828,20829,20830,20831,20832,20833,20834,20835,20836,20837,20838,20839,20840,20841,20842,20843,20844,20845,20846,20847,20848,20849,20850,20851,20852,20853,20854,20855,20856,20857,20858,20859,20860,20861,20862,20863,20864,20865,20866,20867,20868,20869,20870,20871,20872,20873,20874,20875,20876,20877,20878,20879,20880,20881,20882,20883,20884,20885,20886,20887,20888,20889,20890,20891,20892,20893,20894,20895,20896,20897,20898,20899,20900,20901,20902,20903,20904,20905,20906,20907,20908,20909,20910,20911,20912,20913,20914,20915,20916,20917,20918,20919,20920,20921,20922,20923,20924,20925,20926,20927,20928,20929,20930,20931,20932,20933,20934,20935,20936,20937,20938,20939,20940,20941,20942,20943,20944,20945,20946,20947,20948,20949,20950,20951,20952,20953,20954,20955,20956,20957,20958,20959,20960,20961,20962,20963,20964,20965,20966,20967,20968,20969,20970,20971,20972,20973,20974,20975,20976,20977,
 20978,20979,20980,20981,20982,20983,20984,20985,20986,20987,20988,20989,20990,20991,20992,20993,20994,20995,20996,20997,20998,20999,21000,21001,21002,21003,21004,21005,21006,21007,21008,21009,21010,21011,21012,21013,21014,21015,21016,21017,21018,21019,21020,21021,21022,21023,21024,21025,21026,21027,21028,21029,21030,21031,21032,21033,21034,21035,21036,21037,21038,21039,21040,21041,21042,21043,21044,21045,21046,21047,21048,21049,21050,21051,21052,21053,21054,21055,21056,21057,21058,21059,21060,21061,21062,21063,21064,21065,21066,21067,21068,21069,21070,21071,21072,21073,21074,21075,21076,21077,21078,21079,21080,21081,21082,21083,21084,21085,21086,21087,21088,21089,21090,21091,21092,21093,21094,21095,21096,21097,21098,21099,21100,21101,21102,21103,21104,21105,21106,21107,21108,21109,21110,21111,21112,21113,21114,21115,21116,21117,21118,21119,21120,21121,21122,21123,21124,21125,21126,21127,21128,21129,21130,21131,21132,21133,21134,21135,21136,21137,21138,21139,21140,21141,21142,21143,2
 1144,21145,21146,21147,21148,21149,21150,21151,21152,21153,21154,21155,21156,21157,21158,21159,21160,21161,21162,21163,21164,21165,21166,21167,21168,21169,21170,21171,21172,21173,21174,21175,21176,21177,21178,21179,21180,21181,21182,21183,21184,21185,21186,21187,21188,21189,21190,21191,21192,21193,21194,21195,21196,21197,21198,21199,21200,21201,21202,21203,21204,21205,21206,21207,21208,21209,21210,21211,21212,21213,21214,21215,21216,21217,21218,21219,21220,21221,21222,21223,21224,21225,21226,21227,21228,21229,21230,21231,21232,21233,21234,21235,21236,21237,21238,21239,21240,21241,21242,21243,21244,21245,21246,21247,21248,21249,21250,21251,21252,21253,21254,21255,21256,21257,21258,21259,21260,21261,21262,21263,21264,21265,21266,21267,21268,21269,21270,21271,21272,21273,21274,21275,21276,21277,21278,21279,21280,21281,21282,21283,21284,21285,21286,21287,21288,21289,21290,21291,21292,21293,21294,21295,21296,21297,21298,21299,21300,21301,21302,21303,21304,21305,21306,21307,21308,21309,21
 310,21311,21312,21313,21314,21315,21316,21317,21318,21319,21320,21321,21322,21323,21324,21325,21326,21327,21328,21329,21330,21331,21332,21333,21334,21335,21336,21337,21338,21339,21340,21341,21342,21343,21344,21345,21346,21347,21348,21349,21350,21351,21352,21353,21354,21355,21356,21357,21358,21359,21360,21361,21362,21363,21364,21365,21366,21367,21368,21369,21370,21371,21372,21373,21374,21375,21376,21377,21378,21379,21380,21381,21382,21383,21384,21385,21386,21387,21388,21389,21390,21391,21392,21393,21394,21395,21396,21397,21398,21399,21400,21401,21402,21403,21404,21405,21406,21407,21408,21409,21410,21411,21412,21413,21414,21415,21416,21417,21418,21419,21420,21421,21422,21423,21424,21425,21426,21427,21428,21429,21430,21431,21432,21433,21434,21435,21436,21437,21438,21439,21440,21441,21442,21443,21444,21445,21446,21447,21448,21449,21450,21451,21452,21453,21454,21455,21456,21457,21458,21459,21460,21461,21462,21463,21464,21465,21466,21467,21468,21469,21470,21471,21472,21473,21474,21475,214
 76,21477,21478,21479,21480,21481,21482,21483,21484,21485,21486,21487,21488,21489,21490,21491,21492,21493,21494,21495,21496,21497,21498,21499,21500,21501,21502,21503,21504,21505,21506,21507,21508,21509,21510,21511,21512,21513,21514,21515,21516,21517,21518,21519,21520,21521,21522,21523,21524,21525,21526,21527,21528,21529,21530,21531,21532,21533,21534,21535,21536,21537,21538,21539,21540,21541,21542,21543,21544,21545,21546,21547,21548,21549,21550,21551,21552,21553,21554,21555,21556,21557,21558,21559,21560,21561,21562,21563,21564,21565,21566,21567,21568,21569,21570,21571,21572,21573,21574,21575,21576,21577,21578,21579,21580,21581,21582,21583,21584,21585,21586,21587,21588,21589,21590,21591,21592,21593,21594,21595,21596,21597,21598,21599,21600,21601,21602,21603,21604,21605,21606,21607,21608,21609,21610,21611,21612,21613,21614,21615,21616,21617,21618,21619,21620,21621,21622,21623,21624,21625,21626,21627,21628,21629,21630,21631,21632,21633,21634,21635,21636,21637,21638,21639,21640,21641,2164
 2,21643,21644,21645,21646,21647,21648,21649,21650,21651,21652,21653,21654,21655,21656,21657,21658,21659,21660,21661,21662,21663,21664,21665,21666,21667,21668,21669,21670,21671,21672,21673,21674,21675,21676,21677,21678,21679,21680,21681,21682,21683,21684,21685,21686,21687,21688,21689,21690,21691,21692,21693,21694,21695,21696,21697,21698,21699,21700,21701,21702,21703,21704,21705,21706,21707,21708,21709,21710,21711,21712,21713,21714,21715,21716,21717,21718,21719,21720,21721,21722,21723,21724,21725,21726,21727,21728,21729,21730,21731,21732,21733,21734,21735,21736,21737,21738,21739,21740,21741,21742,21743,21744,21745,21746,21747,21748,21749,21750,21751,21752,21753,21754,21755,21756,21757,21758,21759,21760,21761,21762,21763,21764,21765,21766,21767,21768,21769,21770,21771,21772,21773,21774,21775,21776,21777,21778,21779,21780,21781,21782,21783,21784,21785,21786,21787,21788,21789,21790,21791,21792,21793,21794,21795,21796,21797,21798,21799,21800,21801,21802,21803,21804,21805,21806,21807,21808
 ,21809,21810,21811,21812,21813,21814,21815,21816,21817,21818,21819,21820,21821,21822,21823,21824,21825,21826,21827,21828,21829,21830,21831,21832,21833,21834,21835,21836,21837,21838,21839,21840,21841,21842,21843,21844,21845,21846,21847,21848,21849,21850,21851,21852,21853,21854,21855,21856,21857,21858,21859,21860,21861,21862,21863,21864,21865,21866,21867,21868,21869,21870,21871,21872,21873,21874,21875,21876,21877,21878,21879,21880,21881,21882,21883,21884,21885,21886,21887,21888,21889,21890,21891,21892,21893,21894,21895,21896,21897,21898,21899,21900,21901,21902,21903,21904,21905,21906,21907,21908,21909,21910,21911,21912,21913,21914,21915,21916,21917,21918,21919,21920,21921,21922,21923,21924,21925,21926,21927,21928,21929,21930,21931,21932,21933,21934,21935,21936,21937,21938,21939,21940,21941,21942,21943,21944,21945,21946,21947,21948,21949,21950,21951,21952,21953,21954,21955,21956,21957,21958,21959,21960,21961,21962,21963,21964,21965,21966,21967,21968,21969,21970,21971,21972,21973,21974,
 21975,21976,21977,21978,21979,21980,21981,21982,21983,21984,21985,21986,21987,21988,21989,21990,21991,21992,21993,21994,21995,21996,21997,21998,21999,22000,22001,22002,22003,22004,22005,22006,22007,22008,22009,22010,22011,22012,22013,22014,22015,22016,22017,22018,22019,22020,22021,22022,22023,22024,22025,22026,22027,22028,22029,22030,22031,22032,22033,22034,22035,22036,22037,22038,22039,22040,22041,22042,22043,22044,22045,22046,22047,22048,22049,22050,22051,22052,22053,22054,22055,22056,22057,22058,22059,22060,22061,22062,22063,22064,22065,22066,22067,22068,22069,22070,22071,22072,22073,22074,22075,22076,22077,22078,22079,22080,22081,22082,22083,22084,22085,22086,22087,22088,22089,22090,22091,22092,22093,22094,22095,22096,22097,22098,22099,22100,22101,22102,22103,22104,22105,22106,22107,22108,22109,22110,22111,22112,22113,22114,22115,22116,22117,22118,22119,22120,22121,22122,22123,22124,22125,22126,22127,22128,22129,22130,22131,22132,22133,22134,22135,22136,22137,22138,22139,22140,2
 2141,22142,22143,22144,22145,22146,22147,22148,22149,22150,22151,22152,22153,22154,22155,22156,22157,22158,22159,22160,22161,22162,22163,22164,22165,22166,22167,22168,22169,22170,22171,22172,22173,22174,22175,22176,22177,22178,22179,22180,22181,22182,22183,22184,22185,22186,22187,22188,22189,22190,22191,22192,22193,22194,22195,22196,22197,22198,22199,22200,22201,22202,22203,22204,22205,22206,22207,22208,22209,22210,22211,22212,22213,22214,22215,22216,22217,22218,22219,22220,22221,22222,22223,22224,22225,22226,22227,22228,22229,22230,22231,22232,22233,22234,22235,22236,22237,22238,22239,22240,22241,22242,22243,22244,22245,22246,22247,22248,22249,22250,22251,22252,22253,22254,22255,22256,22257,22258,22259,22260,22261,22262,22263,22264,22265,22266,22267,22268,22269,22270,22271,22272,22273,22274,22275,22276,22277,22278,22279,22280,22281,22282,22283,22284,22285,22286,22287,22288,22289,22290,22291,22292,22293,22294,22295,22296,22297,22298,22299,22300,22301,22302,22303,22304,22305,22306,22
 307,22308,22309,22310,22311,22312,22313,22314,22315,22316,22317,22318,22319,22320,22321,22322,22323,22324,22325,22326,22327,22328,22329,22330,22331,22332,22333,22334,22335,22336,22337,22338,22339,22340,22341,22342,22343,22344,22345,22346,22347,22348,22349,22350,22351,22352,22353,22354,22355,22356,22357,22358,22359,22360,22361,22362,22363,22364,22365,22366,22367,22368,22369,22370,22371,22372,22373,22374,22375,22376,22377,22378,22379,22380,22381,22382,22383,22384,22385,22386,22387,22388,22389,22390,22391,22392,22393,22394,22395,22396,22397,22398,22399,22400,22401,22402,22403,22404,22405,22406,22407,22408,22409,22410,22411,22412,22413,22414,22415,22416,22417,22418,22419,22420,22421,22422,22423,22424,22425,22426,22427,22428,22429,22430,22431,22432,22433,22434,22435,22436,22437,22438,22439,22440,22441,22442,22443,22444,22445,22446,22447,22448,22449,22450,22451,22452,22453,22454,22455,22456,22457,22458,22459,22460,22461,22462,22463,22464,22465,22466,22467,22468,22469,22470,22471,22472,224
 73,22474,22475,22476,22477,22478,22479,22480,22481,22482,22483,22484,22485,22486,22487,22488,22489,22490,22491,22492,22493,22494,22495,22496,22497,22498,22499,22500,22501,22502,22503,22504,22505,22506,22507,22508,22509,22510,22511,22512,22513,22514,22515,22516,22517,22518,22519,22520,22521,22522,22523,22524,22525,22526,22527,22528,22529,22530,22531,22532,22533,22534,22535,22536,22537,22538,22539,22540,22541,22542,22543,22544,22545,22546,22547,22548,22549,22550,22551,22552,22553,22554,22555,22556,22557,22558,22559,22560,22561,22562,22563,22564,22565,22566,22567,22568,22569,22570,22571,22572,22573,22574,22575,22576,22577,22578,22579,22580,22581,22582,22583,22584,22585,22586,22587,22588,22589,22590,22591,22592,22593,22594,22595,22596,22597,22598,22599,22600,22601,22602,22603,22604,22605,22606,22607,22608,22609,22610,22611,22612,22613,22614,22615,22616,22617,22618,22619,22620,22621,22622,22623,22624,22625,22626,22627,22628,22629,22630,22631,22632,22633,22634,22635,22636,22637,22638,2263
 9,22640,22641,22642,22643,22644,22645,22646,22647,22648,22649,22650,22651,22652,22653,22654,22655,22656,22657,22658,22659,22660,22661,22662,22663,22664,22665,22666,22667,22668,22669,22670,22671,22672,22673,22674,22675,22676,22677,22678,22679,22680,22681,22682,22683,22684,22685,22686,22687,22688,22689,22690,22691,22692,22693,22694,22695,22696,22697,22698,22699,22700,22701,22702,22703,22704,22705,22706,22707,22708,22709,22710,22711,22712,22713,22714,22715,22716,22717,22718,22719,22720,22721,22722,22723,22724,22725,22726,22727,22728,22729,22730,22731,22732,22733,22734,22735,22736,22737,22738,22739,22740,22741,22742,22743,22744,22745,22746,22747,22748,22749,22750,22751,22752,22753,22754,22755,22756,22757,22758,22759,22760,22761,22762,22763,22764,22765,22766,22767,22768,22769,22770,22771,22772,22773,22774,22775,22776,22777,22778,22779,22780,22781,22782,22783,22784,22785,22786,22787,22788,22789,22790,22791,22792,22793,22794,22795,22796,22797,22798,22799,22800,22801,22802,22803,22804,22805
 ,22806,22807,22808,22809,22810,22811,22812,22813,22814,22815,22816,22817,22818,22819,22820,22821,22822,22823,22824,22825,22826,22827,22828,22829,22830,22831,22832,22833,22834,22835,22836,22837,22838,22839,22840,22841,22842,22843,22844,22845,22846,22847,22848,22849,22850,22851,22852,22853,22854,22855,22856,22857,22858,22859,22860,22861,22862,22863,22864,22865,22866,22867,22868,22869,22870,22871,22872,22873,22874,22875,22876,22877,22878,22879,22880,22881,22882,22883,22884,22885,22886,22887,22888,22889,22890,22891,22892,22893,22894,22895,22896,22897,22898,22899,22900,22901,22902,22903,22904,22905,22906,22907,22908,22909,22910,22911,22912,22913,22914,22915,22916,22917,22918,22919,22920,22921,22922,22923,22924,22925,22926,22927,22928,22929,22930,22931,22932,22933,22934,22935,22936,22937,22938,22939,22940,22941,22942,22943,22944,22945,22946,22947,22948,22949,22950,22951,22952,22953,22954,22955,22956,22957,22958,22959,22960,22961,22962,22963,22964,22965,22966,22967,22968,22969,22970,22971,
 22972,22973,22974,22975,22976,22977,22978,22979,22980,22981,22982,22983,22984,22985,22986,22987,22988,22989,22990,22991,22992,22993,22994,22995,22996,22997,22998,22999,23000,23001,23002,23003,23004,23005,23006,23007,23008,23009,23010,23011,23012,23013,23014,23015,23016,23017,23018,23019,23020,23021,23022,23023,23024,23025,23026,23027,23028,23029,23030,23031,23032,23033,23034,23035,23036,23037,23038,23039,23040,23041,23042,23043,23044,23045,23046,23047,23048,23049,23050,23051,23052,23053,23054,23055,23056,23057,23058,23059,23060,23061,23062,23063,23064,23065,23066,23067,23068,23069,23070,23071,23072,23073,23074,23075,23076,23077,23078,23079,23080,23081,23082,23083,23084,23085,23086,23087,23088,23089,23090,23091,23092,23093,23094,23095,23096,23097,23098,23099,23100,23101,23102,23103,23104,23105,23106,23107,23108,23109,23110,23111,23112,23113,23114,23115,23116,23117,23118,23119,23120,23121,23122,23123,23124,23125,23126,23127,23128,23129,23130,23131,23132,23133,23134,23135,23136,23137,2
 3138,23139,23140,23141,23142,23143,23144,23145,23146,23147,23148,23149,23150,23151,23152,23153,23154,23155,23156,23157,23158,23159,23160,23161,23162,23163,23164,23165,23166,23167,23168,23169,23170,23171,23172,23173,23174,23175,23176,23177,23178,23179,23180,23181,23182,23183,23184,23185,23186,23187,23188,23189,23190,23191,23192,23193,23194,23195,23196,23197,23198,23199,23200,23201,23202,23203,23204,23205,23206,23207,23208,23209,23210,23211,23212,23213,23214,23215,23216,23217,23218,23219,23220,23221,23222,23223,23224,23225,23226,23227,23228,23229,23230,23231,23232,23233,23234,23235,23236,23237,23238,23239,23240,23241,23242,23243,23244,23245,23246,23247,23248,23249,23250,23251,23252,23253,23254,23255,23256,23257,23258,23259,23260,23261,23262,23263,23264,23265,23266,23267,23268,23269,23270,23271,23272,23273,23274,23275,23276,23277,23278,23279,23280,23281,23282,23283,23284,23285,23286,23287,23288,23289,23290,23291,23292,23293,23294,23295,23296,23297,23298,23299,23300,23301,23302,23303,23
 304,23305,23306,23307,23308,23309,23310,23311,23312,23313,23314,23315,23316,23317,23318,23319,23320,23321,23322,23323,23324,23325,23326,23327,23328,23329,23330,23331,23332,23333,23334,23335,23336,23337,23338,23339,23340,23341,23342,23343,23344,23345,23346,23347,23348,23349,23350,23351,23352,23353,23354,23355,23356,23357,23358,23359,23360,23361,23362,23363,23364,23365,23366,23367,23368,23369,23370,23371,23372,23373,23374,23375,23376,23377,23378,23379,23380,23381,23382,23383,23384,23385,23386,23387,23388,23389,23390,23391,23392,23393,23394,23395,23396,23397,23398,23399,23400,23401,23402,23403,23404,23405,23406,23407,23408,23409,23410,23411,23412,23413,23414,23415,23416,23417,23418,23419,23420,23421,23422,23423,23424,23425,23426,23427,23428,23429,23430,23431,23432,23433,23434,23435,23436,23437,23438,23439,23440,23441,23442,23443,23444,23445,23446,23447,23448,23449,23450,23451,23452,23453,23454,23455,23456,23457,23458,23459,23460,23461,23462,23463,23464,23465,23466,23467,23468,23469,234
 70,23471,23472,23473,23474,23475,23476,23477,23478,23479,23480,23481,23482,23483,23484,23485,23486,23487,23488,23489,23490,23491,23492,23493,23494,23495,23496,23497,23498,23499,23500,23501,23502,23503,23504,23505,23506,23507,23508,23509,23510,23511,23512,23513,23514,23515,23516,23517,23518,23519,23520,23521,23522,23523,23524,23525,23526,23527,23528,23529,23530,23531,23532,23533,23534,23535,23536,23537,23538,23539,23540,23541,23542,23543,23544,23545,23546,23547,23548,23549,23550,23551,23552,23553,23554,23555,23556,23557,23558,23559,23560,23561,23562,23563,23564,23565,23566,23567,23568,23569,23570,23571,23572,23573,23574,23575,23576,23577,23578,23579,23580,23581,23582,23583,23584,23585,23586,23587,23588,23589,23590,23591,23592,23593,23594,23595,23596,23597,23598,23599,23600,23601,23602,23603,23604,23605,23606,23607,23608,23609,23610,23611,23612,23613,23614,23615,23616,23617,23618,23619,23620,23621,23622,23623,23624,23625,23626,23627,23628,23629,23630,23631,23632,23633,23634,23635,2363
 6,23637,23638,23639,23640,23641,23642,23643,23644,23645,23646,23647,23648,23649,23650,23651,23652,23653,23654,23655,23656,23657,23658,23659,23660,23661,23662,23663,23664,23665,23666,23667,23668,23669,23670,23671,23672,23673,23674,23675,23676,23677,23678,23679,23680,23681,23682,23683,23684,23685,23686,23687,23688,23689,23690,23691,23692,23693,23694,23695,23696,23697,23698,23699,23700,23701,23702,23703,23704,23705,23706,23707,23708,23709,23710,23711,23712,23713,23714,23715,23716,23717,23718,23719,23720,23721,23722,23723,23724,23725,23726,23727,23728,23729,23730,23731,23732,23733,23734,23735,23736,23737,23738,23739,23740,23741,23742,23743,23744,23745,23746,23747,23748,23749,23750,23751,23752,23753,23754,23755,23756,23757,23758,23759,23760,23761,23762,23763,23764,23765,23766,23767,23768,23769,23770,23771,23772,23773,23774,23775,23776,23777,23778,23779,23780,23781,23782,23783,23784,23785,23786,23787,23788,23789,23790,23791,23792,23793,23794,23795,23796,23797,23798,23799,23800,23801,23802
 ,23803,23804,23805,23806,23807,23808,23809,23810,23811,23812,23813,23814,23815,23816,23817,23818,23819,23820,23821,23822,23823,23824,23825,23826,23827,23828,23829,23830,23831,23832,23833,23834,23835,23836,23837,23838,23839,23840,23841,23842,23843,23844,23845,23846,23847,23848,23849,23850,23851,23852,23853,23854,23855,23856,23857,23858,23859,23860,23861,23862,23863,23864,23865,23866,23867,23868,23869,23870,23871,23872,23873,23874,23875,23876,23877,23878,23879,23880,23881,23882,23883,23884,23885,23886,23887,23888,23889,23890,23891,23892,23893,23894,23895,23896,23897,23898,23899,23900,23901,23902,23903,23904,23905,23906,23907,23908,23909,23910,23911,23912,23913,23914,23915,23916,23917,23918,23919,23920,23921,23922,23923,23924,23925,23926,23927,23928,23929,23930,23931,23932,23933,23934,23935,23936,23937,23938,23939,23940,23941,23942,23943,23944,23945,23946,23947,23948,23949,23950,23951,23952,23953,23954,23955,23956,23957,23958,23959,23960,23961,23962,23963,23964,23965,23966,23967,23968,
 23969,23970,23971,23972,23973,23974,23975,23976,23977,23978,23979,23980,23981,23982,23983,23984,23985,23986,23987,23988,23989,23990,23991,23992,23993,23994,23995,23996,23997,23998,23999,24000,24001,24002,24003,24004,24005,24006,24007,24008,24009,24010,24011,24012,24013,24014,24015,24016,24017,24018,24019,24020,24021,24022,24023,24024,24025,24026,24027,24028,24029,24030,24031,24032,24033,24034,24035,24036,24037,24038,24039,24040,24041,24042,24043,24044,24045,24046,24047,24048,24049,24050,24051,24052,24053,24054,24055,24056,24057,24058,24059,24060,24061,24062,24063,24064,24065,24066,24067,24068,24069,24070,24071,24072,24073,24074,24075,24076,24077,24078,24079,24080,24081,24082,24083,24084,24085,24086,24087,24088,24089,24090,24091,24092,24093,24094,24095,24096,24097,24098,24099,24100,24101,24102,24103,24104,24105,24106,24107,24108,24109,24110,24111,24112,24113,24114,24115,24116,24117,24118,24119,24120,24121,24122,24123,24124,24125,24126,24127,24128,24129,24130,24131,24132,24133,24134,2
 4135,24136,24137,24138,24139,24140,24141,24142,24143,24144,24145,24146,24147,24148,24149,24150,24151,24152,24153,24154,24155,24156,24157,24158,24159,24160,24161,24162,24163,24164,24165,24166,24167,24168,24169,24170,24171,24172,24173,24174,24175,24176,24177,24178,24179,24180,24181,24182,24183,24184,24185,24186,24187,24188,24189,24190,24191,24192,24193,24194,24195,24196,24197,24198,24199,24200,24201,24202,24203,24204,24205,24206,24207,24208,24209,24210,24211,24212,24213,24214,24215,24216,24217,24218,24219,24220,24221,24222,24223,24224,24225,24226,24227,24228,24229,24230,24231,24232,24233,24234,24235,24236,24237,24238,24239,24240,24241,24242,24243,24244,24245,24246,24247,24248,24249,24250,24251,24252,24253,24254,24255,24256,24257,24258,24259,24260,24261,24262,24263,24264,24265,24266,24267,24268,24269,24270,24271,24272,24273,24274,24275,24276,24277,24278,24279,24280,24281,24282,24283,24284,24285,24286,24287,24288,24289,24290,24291,24292,24293,24294,24295,24296,24297,24298,24299,24300,24
 301,24302,24303,24304,24305,24306,24307,24308,24309,24310,24311,24312,24313,24314,24315,24316,24317,24318,24319,24320,24321,24322,24323,24324,24325,24326,24327,24328,24329,24330,24331,24332,24333,24334,24335,24336,24337,24338,24339,24340,24341,24342,24343,24344,24345,24346,24347,24348,24349,24350,24351,24352,24353,24354,24355,24356,24357,24358,24359,24360,24361,24362,24363,24364,24365,24366,24367,24368,24369,24370,24371,24372,24373,24374,24375,24376,24377,24378,24379,24380,24381,24382,24383,24384,24385,24386,24387,24388,24389,24390,24391,24392,24393,24394,24395,24396,24397,24398,24399,24400,24401,24402,24403,24404,24405,24406,24407,24408,24409,24410,24411,24412,24413,24414,24415,24416,24417,24418,24419,24420,24421,24422,24423,24424,24425,24426,24427,24428,24429,24430,24431,24432,24433,24434,24435,24436,24437,24438,24439,24440,24441,24442,24443,24444,24445,24446,24447,24448,24449,24450,24451,24452,24453,24454,24455,24456,24457,24458,24459,24460,24461,24462,24463,24464,24465,24466,244
 67,24468,24469,24470,24471,24472,24473,24474,24475,24476,24477,24478,24479,24480,24481,24482,24483,24484,24485,24486,24487,24488,24489,24490,24491,24492,24493,24494,24495,24496,24497,24498,24499,24500,24501,24502,24503,24504,24505,24506,24507,24508,24509,24510,24511,24512,24513,24514,24515,24516,24517,24518,24519,24520,24521,24522,24523,24524,24525,24526,24527,24528,24529,24530,24531,24532,24533,24534,24535,24536,24537,24538,24539,24540,24541,24542,24543,24544,24545,24546,24547,24548,24549,24550,24551,24552,24553,24554,24555,24556,24557,24558,24559,24560,24561,24562,24563,24564,24565,24566,24567,24568,24569,24570,24571,24572,24573,24574,24575,24576,24577,24578,24579,24580,24581,24582,24583,24584,24585,24586,24587,24588,24589,24590,24591,24592,24593,24594,24595,24596,24597,24598,24599,24600,24601,24602,24603,24604,24605,24606,24607,24608,24609,24610,24611,24612,24613,24614,24615,24616,24617,24618,24619,24620,24621,24622,24623,24624,24625,24626,24627,24628,24629,24630,24631,24632,2463
 3,24634,24635,24636,24637,24638,24639,24640,24641,24642,24643,24644,24645,24646,24647,24648,24649,24650,24651,24652,24653,24654,24655,24656,24657,24658,24659,24660,24661,24662,24663,24664,24665,24666,24667,24668,24669,24670,24671,24672,24673,24674,24675,24676,24677,24678,24679,24680,24681,24682,24683,24684,24685,24686,24687,24688,24689,24690,24691,24692,24693,24694,24695,24696,24697,24698,24699,24700,24701,24702,24703,24704,24705,24706,24707,24708,24709,24710,24711,24712,24713,24714,24715,24716,24717,24718,24719,24720,24721,24722,24723,24724,24725,24726,24727,24728,24729,24730,24731,24732,24733,24734,24735,24736,24737,24738,24739,24740,24741,24742,24743,24744,24745,24746,24747,24748,24749,24750,24751,24752,24753,24754,24755,24756,24757,24758,24759,24760,24761,24762,24763,24764,24765,24766,24767,24768,24769,24770,24771,24772,24773,24774,24775,24776,24777,24778,24779,24780,24781,24782,24783,24784,24785,24786,24787,24788,24789,24790,24791,24792,24793,24794,24795,24796,24797,24798,24799
 ,24800,24801,24802,24803,24804,24805,24806,24807,24808,24809,24810,24811,24812,24813,24814,24815,24816,24817,24818,24819,24820,24821,24822,24823,24824,24825,24826,24827,24828,24829,24830,24831,24832,24833,24834,24835,24836,24837,24838,24839,24840,24841,24842,24843,24844,24845,24846,24847,24848,24849,24850,24851,24852,24853,24854,24855,24856,24857,24858,24859,24860,24861,24862,24863,24864,24865,24866,24867,24868,24869,24870,24871,24872,24873,24874,24875,24876,24877,24878,24879,24880,24881,24882,24883,24884,24885,24886,24887,24888,24889,24890,24891,24892,24893,24894,24895,24896,24897,24898,24899,24900,24901,24902,24903,24904,24905,24906,24907,24908,24909,24910,24911,24912,24913,24914,24915,24916,24917,24918,24919,24920,24921,24922,24923,24924,24925,24926,24927,24928,24929,24930,24931,24932,24933,24934,24935,24936,24937,24938,24939,24940,24941,24942,24943,24944,24945,24946,24947,24948,24949,24950,24951,24952,24953,24954,24955,24956,24957,24958,24959,24960,24961,24962,24963,24964,24965,
 24966,24967,24968,24969,24970,24971,24972,24973,24974,24975,24976,24977,24978,24979,24980,24981,24982,24983,24984,24985,24986,24987,24988,24989,24990,24991,24992,24993,24994,24995,24996,24997,24998,24999,25000,25001,25002,25003,25004,25005,25006,25007,25008,25009,25010,25011,25012,25013,25014,25015,25016,25017,25018,25019,25020,25021,25022,25023,25024,25025,25026,25027,25028,25029,25030,25031,25032,25033,25034,25035,25036,25037,25038,25039,25040,25041,25042,25043,25044,25045,25046,25047,25048,25049,25050,25051,25052,25053,25054,25055,25056,25057,25058,25059,25060,25061,25062,25063,25064,25065,25066,25067,25068,25069,25070,25071,25072,25073,25074,25075,25076,25077,25078,25079,25080,25081,25082,25083,25084,25085,25086,25087,25088,25089,25090,25091,25092,25093,25094,25095,25096,25097,25098,25099,25100,25101,25102,25103,25104,25105,25106,25107,25108,25109,25110,25111,25112,25113,25114,25115,25116,25117,25118,25119,25120,25121,25122,25123,25124,25125,25126,25127,25128,25129,25130,25131,2
 5132,25133,25134,25135,25136,25137,25138,25139,25140,25141,25142,25143,25144,25145,25146,25147,25148,25149,25150,25151,25152,25153,25154,25155,25156,25157,25158,25159,25160,25161,25162,25163,25164,25165,25166,25167,25168,25169,25170,25171,25172,25173,25174,25175,25176,25177,25178,25179,25180,25181,25182,25183,25184,25185,25186,25187,25188,25189,25190,25191,25192,25193,25194,25195,25196,25197,25198,25199,25200,25201,25202,25203,25204,25205,25206,25207,25208,25209,25210,25211,25212,25213,25214,25215,25216,25217,25218,25219,25220,25221,25222,25223,25224,25225,25226,25227,25228,25229,25230,25231,25232,25233,25234,25235,25236,25237,25238,25239,25240,25241,25242,25243,25244,25245,25246,25247,25248,25249,25250,25251,25252,25253,25254,25255,25256,25257,25258,25259,25260,25261,25262,25263,25264,25265,25266,25267,25268,25269,25270,25271,25272,25273,25274,25275,25276,25277,25278,25279,25280,25281,25282,25283,25284,25285,25286,25287,25288,25289,25290,25291,25292,25293,25294,25295,25296,25297,25
 298,25299,25300,25301,25302,25303,25304,25305,25306,25307,25308,25309,25310,25311,25312,25313,25314,25315,25316,25317,25318,25319,25320,25321,25322,25323,25324,25325,25326,25327,25328,25329,25330,25331,25332,25333,25334,25335,25336,25337,25338,25339,25340,25341,25342,25343,25344,25345,25346,25347,25348,25349,25350,25351,25352,25353,25354,25355,25356,25357,25358,25359,25360,25361,25362,25363,25364,25365,25366,25367,25368,25369,25370,25371,25372,25373,25374,25375,25376,25377,25378,25379,25380,25381,25382,25383,25384,25385,25386,25387,25388,25389,25390,25391,25392,25393,25394,25395,25396,25397,25398,25399,25400,25401,25402,25403,25404,25405,25406,25407,25408,25409,25410,25411,25412,25413,25414,25415,25416,25417,25418,25419,25420,25421,25422,25423,25424,25425,25426,25427,25428,25429,25430,25431,25432,25433,25434,25435,25436,25437,25438,25439,25440,25441,25442,25443,25444,25445,25446,25447,25448,25449,25450,25451,25452,25453,25454,25455,25456,25457,25458,25459,25460,25461,25462,25463,254
 64,25465,25466,25467,25468,25469,25470,25471,25472,25473,25474,25475,25476,25477,25478,25479,25480,25481,25482,25483,25484,25485,25486,25487,25488,25489,25490,25491,25492,25493,25494,25495,25496,25497,25498,25499,25500,25501,25502,25503,25504,25505,25506,25507,25508,25509,25510,25511,25512,25513,25514,25515,25516,25517,25518,25519,25520,25521,25522,25523,25524,25525,25526,25527,25528,25529,25530,25531,25532,25533,25534,25535,25536,25537,25538,25539,25540,25541,25542,25543,25544,25545,25546,25547,25548,25549,25550,25551,25552,25553,25554,25555,25556,25557,25558,25559,25560,25561,25562,25563,25564,25565,25566,25567,25568,25569,25570,25571,25572,25573,25574,25575,25576,25577,25578,25579,25580,25581,25582,25583,25584,25585,25586,25587,25588,25589,25590,25591,25592,25593,25594,25595,25596,25597,25598,25599,25600,25601,25602,25603,25604,25605,25606,25607,25608,25609,25610,25611,25612,25613,25614,25615,25616,25617,25618,25619,25620,25621,25622,25623,25624,25625,25626,25627,25628,25629,2563
 0,25631,25632,25633,25634,25635,25636,25637,25638,25639,25640,25641,25642,25643,25644,25645,25646,25647,25648,25649,25650,25651,25652,25653,25654,25655,25656,25657,25658,25659,25660,25661,25662,25663,25664,25665,25666,25667,25668,25669,25670,25671,25672,25673,25674,25675,25676,25677,25678,25679,25680,25681,25682,25683,25684,25685,25686,25687,25688,25689,25690,25691,25692,25693,25694,25695,25696,25697,25698,25699,25700,25701,25702,25703,25704,25705,25706,25707,25708,25709,25710,25711,25712,25713,25714,25715,25716,25717,25718,25719,25720,25721,25722,25723,25724,25725,25726,25727,25728,25729,25730,25731,25732,25733,25734,25735,25736,25737,25738,25739,25740,25741,25742,25743,25744,25745,25746,25747,25748,25749,25750,25751,25752,25753,25754,25755,25756,25757,25758,25759,25760,25761,25762,25763,25764,25765,25766,25767,25768,25769,25770,25771,25772,25773,25774,25775,25776,25777,25778,25779,25780,25781,25782,25783,25784,25785,25786,25787,25788,25789,25790,25791,25792,25793,25794,25795,25796
 ,25797,25798,25799,25800,25801,25802,25803,25804,25805,25806,25807,25808,25809,25810,25811,25812,25813,25814,25815,25816,25817,25818,25819,25820,25821,25822,25823,25824,25825,25826,25827,25828,25829,25830,25831,25832,25833,25834,25835,25836,25837,25838,25839,25840,25841,25842,25843,25844,25845,25846,25847,25848,25849,25850,25851,25852,25853,25854,25855,25856,25857,25858,25859,25860,25861,25862,25863,25864,25865,25866,25867,25868,25869,25870,25871,25872,25873,25874,25875,25876,25877,25878,25879,25880,25881,25882,25883,25884,25885,25886,25887,25888,25889,25890,25891,25892,25893,25894,25895,25896,25897,25898,25899,25900,25901,25902,25903,25904,25905,25906,25907,25908,25909,25910,25911,25912,25913,25914,25915,25916,25917,25918,25919,25920,25921,25922,25923,25924,25925,25926,25927,25928,25929,25930,25931,25932,25933,25934,25935,25936,25937,25938,25939,25940,25941,25942,25943,25944,25945,25946,25947,25948,25949,25950,25951,25952,25953,25954,25955,25956,25957,25958,25959,25960,25961,25962,
 25963,25964,25965,25966,25967,25968,25969,25970,25971,25972,25973,25974,25975,25976,25977,25978,25979,25980,25981,25982,25983,25984,25985,25986,25987,25988,25989,25990,25991,25992,25993,25994,25995,25996,25997,25998,25999,26000,26001,26002,26003,26004,26005,26006,26007,26008,26009,26010,26011,26012,26013,26014,26015,26016,26017,26018,26019,26020,26021,26022,26023,26024,26025,26026,26027,26028,26029,26030,26031,26032,26033,26034,26035,26036,26037,26038,26039,26040,26041,26042,26043,26044,26045,26046,26047,26048,26049,26050,26051,26052,26053,26054,26055,26056,26057,26058,26059,26060,26061,26062,26063,26064,26065,26066,26067,26068,26069,26070,26071,26072,26073,26074,26075,26076,26077,26078,26079,26080,26081,26082,26083,26084,26085,26086,26087,26088,26089,26090,26091,26092,26093,26094,26095,26096,26097,26098,26099,26100,26101,26102,26103,26104,26105,26106,26107,26108,26109,26110,26111,26112,26113,26114,26115,26116,26117,26118,26119,26120,26121,26122,26123,26124,26125,26126,26127,26128,2
 6129,26130,26131,26132,26133,26134,26135,26136,26137,26138,26139,26140,26141,26142,26143,26144,26145,26146,26147,26148,26149,26150,26151,26152,26153,26154,26155,26156,26157,26158,26159,26160,26161,26162,26163,26164,26165,26166,26167,26168,26169,26170,26171,26172,26173,26174,26175,26176,26177,26178,26179,26180,26181,26182,26183,26184,26185,26186,26187,26188,26189,26190,26191,26192,26193,26194,26195,26196,26197,26198,26199,26200,26201,26202,26203,26204,26205,26206,26207,26208,26209,26210,26211,26212,26213,26214,26215,26216,26217,26218,26219,26220,26221,26222,26223,26224,26225,26226,26227,26228,26229,26230,26231,26232,26233,26234,26235,26236,26237,26238,26239,26240,26241,26242,26243,26244,26245,26246,26247,26248,26249,26250,26251,26252,26253,26254,26255,26256,26257,26258,26259,26260,26261,26262,26263,26264,26265,26266,26267,26268,26269,26270,26271,26272,26273,26274,26275,26276,26277,26278,26279,26280,26281,26282,26283,26284,26285,26286,26287,26288,26289,26290,26291,26292,26293,26294,26
 295,26296,26297,26298,26299,26300,26301,26302,26303,26304,26305,26306,26307,26308,26309,26310,26311,26312,26313,26314,26315,26316,26317,26318,26319,26320,26321,26322,26323,26324,26325,26326,26327,26328,26329,26330,26331,26332,26333,26334,26335,26336,26337,26338,26339,26340,26341,26342,26343,26344,26345,26346,26347,26348,26349,26350,26351,26352,26353,26354,26355,26356,26357,26358,26359,26360,26361,26362,26363,26364,26365,26366,26367,26368,26369,26370,26371,26372,26373,26374,26375,26376,26377,26378,26379,26380,26381,26382,26383,26384,26385,26386,26387,26388,26389,26390,26391,26392,26393,26394,26395,26396,26397,26398,26399,26400,26401,26402,26403,26404,26405,26406,26407,26408,26409,26410,26411,26412,26413,26414,26415,26416,26417,26418,26419,26420,26421,26422,26423,26424,26425,26426,26427,26428,26429,26430,26431,26432,26433,26434,26435,26436,26437,26438,26439,26440,26441,26442,26443,26444,26445,26446,26447,26448,26449,26450,26451,26452,26453,26454,26455,26456,26457,26458,26459,26460,264
 61,26462,26463,26464,26465,26466,26467,26468,26469,26470,26471,26472,26473,26474,26475,26476,26477,26478,26479,26480,26481,26482,26483,26484,26485,26486,26487,26488,26489,26490,26491,26492,26493,26494,26495,26496,26497,26498,26499,26500,26501,26502,26503,26504,26505,26506,26507,26508,26509,26510,26511,26512,26513,26514,26515,26516,26517,26518,26519,26520,26521,26522,26523,26524,26525,26526,26527,26528,26529,26530,26531,26532,26533,26534,26535,26536,26537,26538,26539,26540,26541,26542,26543,26544,26545,26546,26547,26548,26549,26550,26551,26552,26553,26554,26555,26556,26557,26558,26559,26560,26561,26562,26563,26564,26565,26566,26567,26568,26569,26570,26571,26572,26573,26574,26575,26576,26577,26578,26579,26580,26581,26582,26583,26584,26585,26586,26587,26588,26589,26590,26591,26592,26593,26594,26595,26596,26597,26598,26599,26600,26601,26602,26603,26604,26605,26606,26607,26608,26609,26610,26611,26612,26613,26614,26615,26616,26617,26618,26619,26620,26621,26622,26623,26624,26625,26626,2662
 7,26628,26629,26630,26631,26632,26633,26634,26635,26636,26637,26638,26639,26640,26641,26642,26643,26644,26645,26646,26647,26648,26649,26650,26651,26652,26653,26654,26655,26656,26657,26658,26659,26660,26661,26662,26663,26664,26665,26666,26667,26668,26669,26670,26671,26672,26673,26674,26675,26676,26677,26678,26679,26680,26681,26682,26683,26684,26685,26686,26687,26688,26689,26690,26691,26692,26693,26694,26695,26696,26697,26698,26699,26700,26701,26702,26703,26704,26705,26706,26707,26708,26709,26710,26711,26712,26713,26714,26715,26716,26717,26718,26719,26720,26721,26722,26723,26724,26725,26726,26727,26728,26729,26730,26731,26732,26733,26734,26735,26736,26737,26738,26739,26740,26741,26742,26743,26744,26745,26746,26747,26748,26749,26750,26751,26752,26753,26754,26755,26756,26757,26758,26759,26760,26761,26762,26763,26764,26765,26766,26767,26768,26769,26770,26771,26772,26773,26774,26775,26776,26777,26778,26779,26780,26781,26782,26783,26784,26785,26786,26787,26788,26789,26790,26791,26792,26793
 ,26794,26795,26796,26797,26798,26799,26800,26801,26802,26803,26804,26805,26806,26807,26808,26809,26810,26811,26812,26813,26814,26815,26816,26817,26818,26819,26820,26821,26822,26823,26824,26825,26826,26827,26828,26829,26830,26831,26832,26833,26834,26835,26836,26837,26838,26839,26840,26841,26842,26843,26844,26845,26846,26847,26848,26849,26850,26851,26852,26853,26854,26855,26856,26857,26858,26859,26860,26861,26862,26863,26864,26865,26866,26867,26868,26869,26870,26871,26872,26873,26874,26875,26876,26877,26878,26879,26880,26881,26882,26883,26884,26885,26886,26887,26888,26889,26890,26891,26892,26893,26894,26895,26896,26897,26898,26899,26900,26901,26902,26903,26904,26905,26906,26907,26908,26909,26910,26911,26912,26913,26914,26915,26916,26917,26918,26919,26920,26921,26922,26923,26924,26925,26926,26927,26928,26929,26930,26931,26932,26933,26934,26935,26936,26937,26938,26939,26940,26941,26942,26943,26944,26945,26946,26947,26948,26949,26950,26951,26952,26953,26954,26955,26956,26957,26958,26959,
 26960,26961,26962,26963,26964,26965,26966,26967,26968,26969,26970,26971,26972,26973,26974,26975,26976,26977,26978,26979,26980,26981,26982,26983,26984,26985,26986,26987,26988,26989,26990,26991,26992,26993,26994,26995,26996,26997,26998,26999,27000,27001,27002,27003,27004,27005,27006,27007,27008,27009,27010,27011,27012,27013,27014,27015,27016,27017,27018,27019,27020,27021,27022,27023,27024,27025,27026,27027,27028,27029,27030,27031,27032,27033,27034,27035,27036,27037,27038,27039,27040,27041,27042,27043,27044,27045,27046,27047,27048,27049,27050,27051,27052,27053,27054,27055,27056,27057,27058,27059,27060,27061,27062,27063,27064,27065,27066,27067,27068,27069,27070,27071,27072,27073,27074,27075,27076,27077,27078,27079,27080,27081,27082,27083,27084,27085,27086,27087,27088,27089,27090,27091,27092,27093,27094,27095,27096,27097,27098,27099,27100,27101,27102,27103,27104,27105,27106,27107,27108,27109,27110,27111,27112,27113,27114,27115,27116,27117,27118,27119,27120,27121,27122,27123,27124,27125,2
 7126,27127,27128,27129,27130,27131,27132,27133,27134,27135,27136,27137,27138,27139,27140,27141,27142,27143,27144,27145,27146,27147,27148,27149,27150,27151,27152,27153,27154,27155,27156,27157,27158,27159,27160,27161,27162,27163,27164,27165,27166,27167,27168,27169,27170,27171,27172,27173,27174,27175,27176,27177,27178,27179,27180,27181,27182,27183,27184,27185,27186,27187,27188,27189,27190,27191,27192,27193,27194,27195,27196,27197,27198,27199,27200,27201,27202,27203,27204,27205,27206,27207,27208,27209,27210,27211,27212,27213,27214,27215,27216,27217,27218,27219,27220,27221,27222,27223,27224,27225,27226,27227,27228,27229,27230,27231,27232,27233,27234,27235,27236,27237,27238,27239,27240,27241,27242,27243,27244,27245,27246,27247,27248,27249,27250,27251,27252,27253,27254,27255,27256,27257,27258,27259,27260,27261,27262,27263,27264,27265,27266,27267,27268,27269,27270,27271,27272,27273,27274,27275,27276,27277,27278,27279,27280,27281,27282,27283,27284,27285,27286,27287,27288,27289,27290,27291,27
 292,27293,27294,27295,27296,27297,27298,27299,27300,27301,27302,27303,27304,27305,27306,27307,27308,27309,27310,27311,27312,27313,27314,27315,27316,27317,27318,27319,27320,27321,27322,27323,27324,27325,27326,27327,27328,27329,27330,27331,27332,27333,27334,27335,27336,27337,27338,27339,27340,27341,27342,27343,27344,27345,27346,27347,27348,27349,27350,27351,27352,27353,27354,27355,27356,27357,27358,27359,27360,27361,27362,27363,27364,27365,27366,27367,27368,27369,27370,27371,27372,27373,27374,27375,27376,27377,27378,27379,27380,27381,27382,27383,27384,27385,27386,27387,27388,27389,27390,27391,27392,27393,27394,27395,27396,27397,27398,27399,27400,27401,27402,27403,27404,27405,27406,27407,27408,27409,27410,27411,27412,27413,27414,27415,27416,27417,27418,27419,27420,27421,27422,27423,27424,27425,27426,27427,27428,27429,27430,27431,27432,27433,27434,27435,27436,27437,27438,27439,27440,27441,27442,27443,27444,27445,27446,27447,27448,27449,27450,27451,27452,27453,27454,27455,27456,27457,274
 58,27459,27460,27461,27462,27463,27464,27465,27466,27467,27468,27469,27470,27471,27472,27473,27474,27475,27476,27477,27478,27479,27480,27481,27482,27483,27484,27485,27486,27487,27488,27489,27490,27491,27492,27493,27494,27495,27496,27497,27498,27499,27500,27501,27502,27503,27504,27505,27506,27507,27508,27509,27510,27511,27512,27513,27514,27515,27516,27517,27518,27519,27520,27521,27522,27523,27524,27525,27526,27527,27528,27529,27530,27531,27532,27533,27534,27535,27536,27537,27538,27539,27540,27541,27542,27543,27544,27545,27546,27547,27548,27549,27550,27551,27552,27553,27554,27555,27556,27557,27558,27559,27560,27561,27562,27563,27564,27565,27566,27567,27568,27569,27570,27571,27572,27573,27574,27575,27576,27577,27578,27579,27580,27581,27582,27583,27584,27585,27586,27587,27588,27589,27590,27591,27592,27593,27594,27595,27596,27597,27598,27599,27600,27601,27602,27603,27604,27605,27606,27607,27608,27609,27610,27611,27612,27613,27614,27615,27616,27617,27618,27619,27620,27621,27622,27623,2762
 4,27625,27626,27627,27628,27629,27630,27631,27632,27633,27634,27635,27636,27637,27638,27639,27640,27641,27642,27643,27644,27645,27646,27647,27648,27649,27650,27651,27652,27653,27654,27655,27656,27657,27658,27659,27660,27661,27662,27663,27664,27665,27666,27667,27668,27669,27670,27671,27672,27673,27674,27675,27676,27677,27678,27679,27680,27681,27682,27683,27684,27685,27686,27687,27688,27689,27690,27691,27692,27693,27694,27695,27696,27697,27698,27699,27700,27701,27702,27703,27704,27705,27706,27707,27708,27709,27710,27711,27712,27713,27714,27715,27716,27717,27718,27719,27720,27721,27722,27723,27724,27725,27726,27727,27728,27729,27730,27731,27732,27733,27734,27735,27736,27737,27738,27739,27740,27741,27742,27743,27744,27745,27746,27747,27748,27749,27750,27751,27752,27753,27754,27755,27756,27757,27758,27759,27760,27761,27762,27763,27764,27765,27766,27767,27768,27769,27770,27771,27772,27773,27774,27775,27776,27777,27778,27779,27780,27781,27782,27783,27784,27785,27786,27787,27788,27789,27790
 ,27791,27792,27793,27794,27795,27796,27797,27798,27799,27800,27801,27802,27803,27804,27805,27806,27807,27808,27809,27810,27811,27812,27813,27814,27815,27816,27817,27818,27819,27820,27821,27822,27823,27824,27825,27826,27827,27828,27829,27830,27831,27832,27833,27834,27835,27836,27837,27838,27839,27840,27841,27842,27843,27844,27845,27846,27847,27848,27849,27850,27851,27852,27853,27854,27855,27856,27857,27858,27859,27860,27861,27862,27863,27864,27865,27866,27867,27868,27869,27870,27871,27872,27873,27874,27875,27876,27877,27878,27879,27880,27881,27882,27883,27884,27885,27886,27887,27888,27889,27890,27891,27892,27893,27894,27895,27896,27897,27898,27899,27900,27901,27902,27903,27904,27905,27906,27907,27908,27909,27910,27911,27912,27913,27914,27915,27916,27917,27918,27919,27920,27921,27922,27923,27924,27925,27926,27927,27928,27929,27930,27931,27932,27933,27934,27935,27936,27937,27938,27939,27940,27941,27942,27943,27944,27945,27946,27947,27948,27949,27950,27951,27952,27953,27954,27955,27956,
 27957,27958,27959,27960,27961,27962,27963,27964,27965,27966,27967,27968,27969,27970,27971,27972,27973,27974,27975,27976,27977,27978,27979,27980,27981,27982,27983,27984,27985,27986,27987,27988,27989,27990,27991,27992,27993,27994,27995,27996,27997,27998,27999,28000,28001,28002,28003,28004,28005,28006,28007,28008,28009,28010,28011,28012,28013,28014,28015,28016,28017,28018,28019,28020,28021,28022,28023,28024,28025,28026,28027,28028,28029,28030,28031,28032,28033,28034,28035,28036,28037,28038,28039,28040,28041,28042,28043,28044,28045,28046,28047,28048,28049,28050,28051,28052,28053,28054,28055,28056,28057,28058,28059,28060,28061,28062,28063,28064,28065,28066,28067,28068,28069,28070,28071,28072,28073,28074,28075,28076,28077,28078,28079,28080,28081,28082,28083,28084,28085,28086,28087,28088,28089,28090,28091,28092,28093,28094,28095,28096,28097,28098,28099,28100,28101,28102,28103,28104,28105,28106,28107,28108,28109,28110,28111,28112,28113,28114,28115,28116,28117,28118,28119,28120,28121,28122,2
 8123,28124,28125,28126,28127,28128,28129,28130,28131,28132,28133,28134,28135,28136,28137,28138,28139,28140,28141,28142,28143,28144,28145,28146,28147,28148,28149,28150,28151,28152,28153,28154,28155,28156,28157,28158,28159,28160,28161,28162,28163,28164,28165,28166,28167,28168,28169,28170,28171,28172,28173,28174,28175,28176,28177,28178,28179,28180,28181,28182,28183,28184,28185,28186,28187,28188,28189,28190,28191,28192,28193,28194,28195,28196,28197,28198,28199,28200,28201,28202,28203,28204,28205,28206,28207,28208,28209,28210,28211,28212,28213,28214,28215,28216,28217,28218,28219,28220,28221,28222,28223,28224,28225,28226,28227,28228,28229,28230,28231,28232,28233,28234,28235,28236,28237,28238,28239,28240,28241,28242,28243,28244,28245,28246,28247,28248,28249,28250,28251,28252,28253,28254,28255,28256,28257,28258,28259,28260,28261,28262,28263,28264,28265,28266,28267,28268,28269,28270,28271,28272,28273,28274,28275,28276,28277,28278,28279,28280,28281,28282,28283,28284,28285,28286,28287,28288,28
 289,28290,28291,28292,28293,28294,28295,28296,28297,28298,28299,28300,28301,28302,28303,28304,28305,28306,28307,28308,28309,28310,28311,28312,28313,28314,28315,28316,28317,28318,28319,28320,28321,28322,28323,28324,28325,28326,28327,28328,28329,28330,28331,28332,28333,28334,28335,28336,28337,28338,28339,28340,28341,28342,28343,28344,28345,28346,28347,28348,28349,28350,28351,28352,28353,28354,28355,28356,28357,28358,28359,28360,28361,28362,28363,28364,28365,28366,28367,28368,28369,28370,28371,28372,28373,28374,28375,28376,28377,28378,28379,28380,28381,28382,28383,28384,28385,28386,28387,28388,28389,28390,28391,28392,28393,28394,28395,28396,28397,28398,28399,28400,28401,28402,28403,28404,28405,28406,28407,28408,28409,28410,28411,28412,28413,28414,28415,28416,28417,28418,28419,28420,28421,28422,28423,28424,28425,28426,28427,28428,28429,28430,28431,28432,28433,28434,28435,28436,28437,28438,28439,28440,28441,28442,28443,28444,28445,28446,28447,28448,28449,28450,28451,28452,28453,28454,284
 55,28456,28457,28458,28459,28460,28461,28462,28463,28464,28465,28466,28467,28468,28469,28470,28471,28472,28473,28474,28475,28476,28477,28478,28479,28480,28481,28482,28483,28484,28485,28486,28487,28488,28489,28490,28491,28492,28493,28494,28495,28496,28497,28498,28499,28500,28501,28502,28503,28504,28505,28506,28507,28508,28509,28510,28511,28512,28513,28514,28515,28516,28517,28518,28519,28520,28521,28522,28523,28524,28525,28526,28527,28528,28529,28530,28531,28532,28533,28534,28535,28536,28537,28538,28539,28540,28541,28542,28543,28544,28545,28546,28547,28548,28549,28550,28551,28552,28553,28554,28555,28556,28557,28558,28559,28560,28561,28562,28563,28564,28565,28566,28567,28568,28569,28570,28571,28572,28573,28574,28575,28576,28577,28578,28579,28580,28581,28582,28583,28584,28585,28586,28587,28588,28589,28590,28591,28592,28593,28594,28595,28596,28597,28598,28599,28600,28601,28602,28603,28604,28605,28606,28607,28608,28609,28610,28611,28612,28613,28614,28615,28616,28617,28618,28619,28620,2862
 1,28622,28623,28624,28625,28626,28627,28628,28629,28630,28631,28632,28633,28634,28635,28636,28637,28638,28639,28640,28641,28642,28643,28644,28645,28646,28647,28648,28649,28650,28651,28652,28653,28654,28655,28656,28657,28658,28659,28660,28661,28662,28663,28664,28665,28666,28667,28668,28669,28670,28671,28672,28673,28674,28675,28676,28677,28678,28679,28680,28681,28682,28683,28684,28685,28686,28687,28688,28689,28690,28691,28692,28693,28694,28695,28696,28697,28698,28699,28700,28701,28702,28703,28704,28705,28706,28707,28708,28709,28710,28711,28712,28713,28714,28715,28716,28717,28718,28719,28720,28721,28722,28723,28724,28725,28726,28727,28728,28729,28730,28731,28732,28733,28734,28735,28736,28737,28738,28739,28740,28741,28742,28743,28744,28745,28746,28747,28748,28749,28750,28751,28752,28753,28754,28755,28756,28757,28758,28759,28760,28761,28762,28763,28764,28765,28766,28767,28768,28769,28770,28771,28772,28773,28774,28775,28776,28777,28778,28779,28780,28781,28782,28783,28784,28785,28786,28787
 ,28788,28789,28790,28791,28792,28793,28794,28795,28796,28797,28798,28799,28800,28801,28802,28803,28804,28805,28806,28807,28808,28809,28810,28811,28812,28813,28814,28815,28816,28817,28818,28819,28820,28821,28822,28823,28824,28825,28826,28827,28828,28829,28830,28831,28832,28833,28834,28835,28836,28837,28838,28839,28840,28841,28842,28843,28844,28845,28846,28847,28848,28849,28850,28851,28852,28853,28854,28855,28856,28857,28858,28859,28860,28861,28862,28863,28864,28865,28866,28867,28868,28869,28870,28871,28872,28873,28874,28875,28876,28877,28878,28879,28880,28881,28882,28883,28884,28885,28886,28887,28888,28889,28890,28891,28892,28893,28894,28895,28896,28897,28898,28899,28900,28901,28902,28903,28904,28905,28906,28907,28908,28909,28910,28911,28912,28913,28914,28915,28916,28917,28918,28919,28920,28921,28922,28923,28924,28925,28926,28927,28928,28929,28930,28931,28932,28933,28934,28935,28936,28937,28938,28939,28940,28941,28942,28943,28944,28945,28946,28947,28948,28949,28950,28951,28952,28953,
 28954,28955,28956,28957,28958,28959,28960,28961,28962,28963,28964,28965,28966,28967,28968,28969,28970,28971,28972,28973,28974,28975,28976,28977,28978,28979,28980,28981,28982,28983,28984,28985,28986,28987,28988,28989,28990,28991,28992,28993,28994,28995,28996,28997,28998,28999,29000,29001,29002,29003,29004,29005,29006,29007,29008,29009,29010,29011,29012,29013,29014,29015,29016,29017,29018,29019,29020,29021,29022,29023,29024,29025,29026,29027,29028,29029,29030,29031,29032,29033,29034,29035,29036,29037,29038,29039,29040,29041,29042,29043,29044,29045,29046,29047,29048,29049,29050,29051,29052,29053,29054,29055,29056,29057,29058,29059,29060,29061,29062,29063,29064,29065,29066,29067,29068,29069,29070,29071,29072,29073,29074,29075,29076,29077,29078,29079,29080,29081,29082,29083,29084,29085,29086,29087,29088,29089,29090,29091,29092,29093,29094,29095,29096,29097,29098,29099,29100,29101,29102,29103,29104,29105,29106,29107,29108,29109,29110,29111,29112,29113,29114,29115,29116,29117,29118,29119,2
 9120,29121,29122,29123,29124,29125,29126,29127,29128,29129,29130,29131,29132,29133,29134,29135,29136,29137,29138,29139,29140,29141,29142,29143,29144,29145,29146,29147,29148,29149,29150,29151,29152,29153,29154,29155,29156,29157,29158,29159,29160,29161,29162,29163,29164,29165,29166,29167,29168,29169,29170,29171,29172,29173,29174,29175,29176,29177,29178,29179,29180,29181,29182,29183,29184,29185,29186,29187,29188,29189,29190,29191,29192,29193,29194,29195,29196,29197,29198,29199,29200,29201,29202,29203,29204,29205,29206,29207,29208,29209,29210,29211,29212,29213,29214,29215,29216,29217,29218,29219,29220,29221,29222,29223,29224,29225,29226,29227,29228,29229,29230,29231,29232,29233,29234,29235,29236,29237,29238,29239,29240,29241,29242,29243,29244,29245,29246,29247,29248,29249,29250,29251,29252,29253,29254,29255,29256,29257,29258,29259,29260,29261,29262,29263,29264,29265,29266,29267,29268,29269,29270,29271,29272,29273,29274,29275,29276,29277,29278,29279,29280,29281,29282,29283,29284,29285,29
 286,29287,29288,29289,29290,29291,29292,29293,29294,29295,29296,29297,29298,29299,29300,29301,29302,29303,29304,29305,29306,29307,29308,29309,29310,29311,29312,29313,29314,29315,29316,29317,29318,29319,29320,29321,29322,29323,29324,29325,29326,29327,29328,29329,29330,29331,29332,29333,29334,29335,29336,29337,29338,29339,29340,29341,29342,29343,29344,29345,29346,29347,29348,29349,29350,29351,29352,29353,29354,29355,29356,29357,29358,29359,29360,29361,29362,29363,29364,29365,29366,29367,29368,29369,29370,29371,29372,29373,29374,29375,29376,29377,29378,29379,29380,29381,29382,29383,29384,29385,29386,29387,29388,29389,29390,29391,29392,29393,29394,29395,29396,29397,29398,29399,29400,29401,29402,29403,29404,29405,29406,29407,29408,29409,29410,29411,29412,29413,29414,29415,29416,29417,29418,29419,29420,29421,29422,29423,29424,29425,29426,29427,29428,29429,29430,29431,29432,29433,29434,29435,29436,29437,29438,29439,29440,29441,29442,29443,29444,29445,29446,29447,29448,29449,29450,29451,294
 52,29453,29454,29455,29456,29457,29458,29459,29460,29461,29462,29463,29464,29465,29466,29467,29468,29469,29470,29471,29472,29473,29474,29475,29476,29477,29478,29479,29480,29481,29482,29483,29484,29485,29486,29487,29488,29489,29490,29491,29492,29493,29494,29495,29496,29497,29498,29499,29500,29501,29502,29503,29504,29505,29506,29507,29508,29509,29510,29511,29512,29513,29514,29515,29516,29517,29518,29519,29520,29521,29522,29523,29524,29525,29526,29527,29528,29529,29530,29531,29532,29533,29534,29535,29536,29537,29538,29539,29540,29541,29542,29543,29544,29545,29546,29547,29548,29549,29550,29551,29552,29553,29554,29555,29556,29557,29558,29559,29560,29561,29562,29563,29564,29565,29566,29567,29568,29569,29570,29571,29572,29573,29574,29575,29576,29577,29578,29579,29580,29581,29582,29583,29584,29585,29586,29587,29588,29589,29590,29591,29592,29593,29594,29595,29596,29597,29598,29599,29600,29601,29602,29603,29604,29605,29606,29607,29608,29609,29610,29611,29612,29613,29614,29615,29616,29617,2961
 8,29619,29620,29621,29622,29623,29624,29625,29626,29627,29628,29629,29630,29631,29632,29633,29634,29635,29636,29637,29638,29639,29640,29641,29642,29643,29644,29645,29646,29647,29648,29649,29650,29651,29652,29653,29654,29655,29656,29657,29658,29659,29660,29661,29662,29663,29664,29665,29666,29667,29668,29669,29670,29671,29672,29673,29674,29675,29676,29677,29678,29679,29680,29681,29682,29683,29684,29685,29686,29687,29688,29689,29690,29691,29692,29693,29694,29695,29696,29697,29698,29699,29700,29701,29702,29703,29704,29705,29706,29707,29708,29709,29710,29711,29712,29713,29714,29715,29716,29717,29718,29719,29720,29721,29722,29723,29724,29725,29726,29727,29728,29729,29730,29731,29732,29733,29734,29735,29736,29737,29738,29739,29740,29741,29742,29743,29744,29745,29746,29747,29748,29749,29750,29751,29752,29753,29754,29755,29756,29757,29758,29759,29760,29761,29762,29763,29764,29765,29766,29767,29768,29769,29770,29771,29772,29773,29774,29775,29776,29777,29778,29779,29780,29781,29782,29783,29784
 ,29785,29786,29787,29788,29789,29790,29791,29792,29793,29794,29795,29796,29797,29798,29799,29800,29801,29802,29803,29804,29805,29806,29807,29808,29809,29810,29811,29812,29813,29814,29815,29816,29817,29818,29819,29820,29821,29822,29823,29824,29825,29826,29827,29828,29829,29830,29831,29832,29833,29834,29835,29836,29837,29838,29839,29840,29841,29842,29843,29844,29845,29846,29847,29848,29849,29850,29851,29852,29853,29854,29855,29856,29857,29858,29859,29860,29861,29862,29863,29864,29865,29866,29867,29868,29869,29870,29871,29872,29873,29874,29875,29876,29877,29878,29879,29880,29881,29882,29883,29884,29885,29886,29887,29888,29889,29890,29891,29892,29893,29894,29895,29896,29897,29898,29899,29900,29901,29902,29903,29904,29905,29906,29907,29908,29909,29910,29911,29912,29913,29914,29915,29916,29917,29918,29919,29920,29921,29922,29923,29924,29925,29926,29927,29928,29929,29930,29931,29932,29933,29934,29935,29936,29937,29938,29939,29940,29941,29942,29943,29944,29945,29946,29947,29948,29949,29950,
 29951,29952,29953,29954,29955,29956,29957,29958,29959,29960,29961,29962,29963,29964,29965,29966,29967,29968,29969,29970,29971,29972,29973,29974,29975,29976,29977,29978,29979,29980,29981,29982,29983,29984,29985,29986,29987,29988,29989,29990,29991,29992,29993,29994,29995,29996,29997,29998,29999,30000,30001,30002,30003,30004,30005,30006,30007,30008,30009,30010,30011,30012,30013,30014,30015,30016,30017,30018,30019,30020,30021,30022,30023,30024,30025,30026,30027,30028,30029,30030,30031,30032,30033,30034,30035,30036,30037,30038,30039,30040,30041,30042,30043,30044,30045,30046,30047,30048,30049,30050,30051,30052,30053,30054,30055,30056,30057,30058,30059,30060,30061,30062,30063,30064,30065,30066,30067,30068,30069,30070,30071,30072,30073,30074,30075,30076,30077,30078,30079,30080,30081,30082,30083,30084,30085,30086,30087,30088,30089,30090,30091,30092,30093,30094,30095,30096,30097,30098,30099,30100,30101,30102,30103,30104,30105,30106,30107,30108,30109,30110,30111,30112,30113,30114,30115,30116,3
 0117,30118,30119,30120,30121,30122,30123,30124,30125,30126,30127,30128,30129,30130,30131,30132,30133,30134,30135,30136,30137,30138,30139,30140,30141,30142,30143,30144,30145,30146,30147,30148,30149,30150,30151,30152,30153,30154,30155,30156,30157,30158,30159,30160,30161,30162,30163,30164,30165,30166,30167,30168,30169,30170,30171,30172,30173,30174,30175,30176,30177,30178,30179,30180,30181,30182,30183,30184,30185,30186,30187,30188,30189,30190,30191,30192,30193,30194,30195,30196,30197,30198,30199,30200,30201,30202,30203,30204,30205,30206,30207,30208,30209,30210,30211,30212,30213,30214,30215,30216,30217,30218,30219,30220,30221,30222,30223,30224,30225,30226,30227,30228,30229,30230,30231,30232,30233,30234,30235,30236,30237,30238,30239,30240,30241,30242,30243,30244,30245,30246,30247,30248,30249,30250,30251,30252,30253,30254,30255,30256,30257,30258,30259,30260,30261,30262,30263,30264,30265,30266,30267,30268,30269,30270,30271,30272,30273,30274,30275,30276,30277,30278,30279,30280,30281,30282,30
 283,30284,30285,30286,30287,30288,30289,30290,30291,30292,30293,30294,30295,30296,30297,30298,30299,30300,30301,30302,30303,30304,30305,30306,30307,30308,30309,30310,30311,30312,30313,30314,30315,30316,30317,30318,30319,30320,30321,30322,30323,30324,30325,30326,30327,30328,30329,30330,30331,30332,30333,30334,30335,30336,30337,30338,30339,30340,30341,30342,30343,30344,30345,30346,30347,30348,30349,30350,30351,30352,30353,30354,30355,30356,30357,30358,30359,30360,30361,30362,30363,30364,30365,30366,30367,30368,30369,30370,30371,30372,30373,30374,30375,30376,30377,30378,30379,30380,30381,30382,30383,30384,30385,30386,30387,30388,30389,30390,30391,30392,30393,30394,30395,30396,30397,30398,30399,30400,30401,30402,30403,30404,30405,30406,30407,30408,30409,30410,30411,30412,30413,30414,30415,30416,30417,30418,30419,30420,30421,30422,30423,30424,30425,30426,30427,30428,30429,30430,30431,30432,30433,30434,30435,30436,30437,30438,30439,30440,30441,30442,30443,30444,30445,30446,30447,30448,304
 49,30450,30451,30452,30453,30454,30455,30456,30457,30458,30459,30460,30461,30462,30463,30464,30465,30466,30467,30468,30469,30470,30471,30472,30473,30474,30475,30476,30477,30478,30479,30480,30481,30482,30483,30484,30485,30486,30487,30488,30489,30490,30491,30492,30493,30494,30495,30496,30497,30498,30499,30500,30501,30502,30503,30504,30505,30506,30507,30508,30509,30510,30511,30512,30513,30514,30515,30516,30517,30518,30519,30520,30521,30522,30523,30524,30525,30526,30527,30528,30529,30530,30531,30532,30533,30534,30535,30536,30537,30538,30539,30540,30541,30542,30543,30544,30545,30546,30547,30548,30549,30550,30551,30552,30553,30554,30555,30556,30557,30558,30559,30560,30561,30562,30563,30564,30565,30566,30567,30568,30569,30570,30571,30572,30573,30574,30575,30576,30577,30578,30579,30580,30581,30582,30583,30584,30585,30586,30587,30588,30589,30590,30591,30592,30593,30594,30595,30596,30597,30598,30599,30600,30601,30602,30603,30604,30605,30606,30607,30608,30609,30610,30611,30612,30613,30614,3061
 5,30616,30617,30618,30619,30620,30621,30622,30623,30624,30625,30626,30627,30628,30629,30630,30631,30632,30633,30634,30635,30636,30637,30638,30639,30640,30641,30642,30643,30644,30645,30646,30647,30648,30649,30650,30651,30652,30653,30654,30655,30656,30657,30658,30659,30660,30661,30662,30663,30664,30665,30666,30667,30668,30669,30670,30671,30672,30673,30674,30675,30676,30677,30678,30679,30680,30681,30682,30683,30684,30685,30686,30687,30688,30689,30690,30691,30692,30693,30694,30695,30696,30697,30698,30699,30700,30701,30702,30703,30704,30705,30706,30707,30708,30709,30710,30711,30712,30713,30714,30715,30716,30717,30718,30719,30720,30721,30722,30723,30724,30725,30726,30727,30728,30729,30730,30731,30732,30733,30734,30735,30736,30737,30738,30739,30740,30741,30742,30743,30744,30745,30746,30747,30748,30749,30750,30751,30752,30753,30754,30755,30756,30757,30758,30759,30760,30761,30762,30763,30764,30765,30766,30767,30768,30769,30770,30771,30772,30773,30774,30775,30776,30777,30778,30779,30780,30781
 ,30782,30783,30784,30785,30786,30787,30788,30789,30790,30791,30792,30793,30794,30795,30796,30797,30798,30799,30800,30801,30802,30803,30804,30805,30806,30807,30808,30809,30810,30811,30812,30813,30814,30815,30816,30817,30818,30819,30820,30821,30822,30823,30824,30825,30826,30827,30828,30829,30830,30831,30832,30833,30834,30835,30836,30837,30838,30839,30840,30841,30842,30843,30844,30845,30846,30847,30848,30849,30850,30851,30852,30853,30854,30855,30856,30857,30858,30859,30860,30861,30862,30863,30864,30865,30866,30867,30868,30869,30870,30871,30872,30873,30874,30875,30876,30877,30878,30879,30880,30881,30882,30883,30884,30885,30886,30887,30888,30889,30890,30891,30892,30893,30894,30895,30896,30897,30898,30899,30900,30901,30902,30903,30904,30905,30906,30907,30908,30909,30910,30911,30912,30913,30914,30915,30916,30917,30918,30919,30920,30921,30922,30923,30924,30925,30926,30927,30928,30929,30930,30931,30932,30933,30934,30935,30936,30937,30938,30939,30940,30941,30942,30943,30944,30945,30946,30947,
 30948,30949,30950,30951,30952,30953,30954,30955,30956,30957,30958,30959,30960,30961,30962,30963,30964,30965,30966,30967,30968,30969,30970,30971,30972,30973,30974,30975,30976,30977,30978,30979,30980,30981,30982,30983,30984,30985,30986,30987,30988,30989,30990,30991,30992,30993,30994,30995,30996,30997,30998,30999,31000,31001,31002,31003,31004,31005,31006,31007,31008,31009,31010,31011,31012,31013,31014,31015,31016,31017,31018,31019,31020,31021,31022,31023,31024,31025,31026,31027,31028,31029,31030,31031,31032,31033,31034,31035,31036,31037,31038,31039,31040,31041,31042,31043,31044,31045,31046,31047,31048,31049,31050,31051,31052,31053,31054,31055,31056,31057,31058,31059,31060,31061,31062,31063,31064,31065,31066,31067,31068,31069,31070,31071,31072,31073,31074,31075,31076,31077,31078,31079,31080,31081,31082,31083,31084,31085,31086,31087,31088,31089,31090,31091,31092,31093,31094,31095,31096,31097,31098,31099,31100,31101,31102,31103,31104,31105,31106,31107,31108,31109,31110,31111,31112,31113,3
 1114,31115,31116,31117,31118,31119,31120,31121,31122,31123,31124,31125,31126,31127,31128,31129,31130,31131,31132,31133,31134,31135,31136,31137,31138,31139,31140,31141,31142,31143,31144,31145,31146,31147,31148,31149,31150,31151,31152,31153,31154,31155,31156,31157,31158,31159,31160,31161,31162,31163,31164,31165,31166,31167,31168,31169,31170,31171,31172,31173,31174,31175,31176,31177,31178,31179,31180,31181,31182,31183,31184,31185,31186,31187,31188,31189,31190,31191,31192,31193,31194,31195,31196,31197,31198,31199,31200,31201,31202,31203,31204,31205,31206,31207,31208,31209,31210,31211,31212,31213,31214,31215,31216,31217,31218,31219,31220,31221,31222,31223,31224,31225,31226,31227,31228,31229,31230,31231,31232,31233,31234,31235,31236,31237,31238,31239,31240,31241,31242,31243,31244,31245,31246,31247,31248,31249,31250,31251,31252,31253,31254,31255,31256,31257,31258,31259,31260,31261,31262,31263,31264,31265,31266,31267,31268,31269,31270,31271,31272,31273,31274,31275,31276,31277,31278,31279,31
 280,31281,31282,31283,31284,31285,31286,31287,31288,31289,31290,31291,31292,31293,31294,31295,31296,31297,31298,31299,31300,31301,31302,31303,31304,31305,31306,31307,31308,31309,31310,31311,31312,31313,31314,31315,31316,31317,31318,31319,31320,31321,31322,31323,31324,31325,31326,31327,31328,31329,31330,31331,31332,31333,31334,31335,31336,31337,31338,31339,31340,31341,31342,31343,31344,31345,31346,31347,31348,31349,31350,31351,31352,31353,31354,31355,31356,31357,31358,31359,31360,31361,31362,31363,31364,31365,31366,31367,31368,31369,31370,31371,31372,31373,31374,31375,31376,31377,31378,31379,31380,31381,31382,31383,31384,31385,31386,31387,31388,31389,31390,31391,31392,31393,31394,31395,31396,31397,31398,31399,31400,31401,31402,31403,31404,31405,31406,31407,31408,31409,31410,31411,31412,31413,31414,31415,31416,31417,31418,31419,31420,31421,31422,31423,31424,31425,31426,31427,31428,31429,31430,31431,31432,31433,31434,31435,31436,31437,31438,31439,31440,31441,31442,31443,31444,31445,314
 46,31447,31448,31449,31450,31451,31452,31453,31454,31455,31456,31457,31458,31459,31460,31461,31462,31463,31464,31465,31466,31467,31468,31469,31470,31471,31472,31473,31474,31475,31476,31477,31478,31479,31480,31481,31482,31483,31484,31485,31486,31487,31488,31489,31490,31491,31492,31493,31494,31495,31496,31497,31498,31499,31500,31501,31502,31503,31504,31505,31506,31507,31508,31509,31510,31511,31512,31513,31514,31515,31516,31517,31518,31519,31520,31521,31522,31523,31524,31525,31526,31527,31528,31529,31530,31531,31532,31533,31534,31535,31536,31537,31538,31539,31540,31541,31542,31543,31544,31545,31546,31547,31548,31549,31550,31551,31552,31553,31554,31555,31556,31557,31558,31559,31560,31561,31562,31563,31564,31565,31566,31567,31568,31569,31570,31571,31572,31573,31574,31575,31576,31577,31578,31579,31580,31581,31582,31583,31584,31585,31586,31587,31588,31589,31590,31591,31592,31593,31594,31595,31596,31597,31598,31599,31600,31601,31602,31603,31604,31605,31606,31607,31608,31609,31610,31611,3161
 2,31613,31614,31615,31616,31617,31618,31619,31620,31621,31622,31623,31624,31625,31626,31627,31628,31629,31630,31631,31632,31633,31634,31635,31636,31637,31638,31639,31640,31641,31642,31643,31644,31645,31646,31647,31648,31649,31650,31651,31652,31653,31654,31655,31656,31657,31658,31659,31660,31661,31662,31663,31664,31665,31666,31667,31668,31669,31670,31671,31672,31673,31674,31675,31676,31677,31678,31679,31680,31681,31682,31683,31684,31685,31686,31687,31688,31689,31690,31691,31692,31693,31694,31695,31696,31697,31698,31699,31700,31701,31702,31703,31704,31705,31706,31707,31708,31709,31710,31711,31712,31713,31714,31715,31716,31717,31718,31719,31720,31721,31722,31723,31724,31725,31726,31727,31728,31729,31730,31731,31732,31733,31734,31735,31736,31737,31738,31739,31740,31741,31742,31743,31744,31745,31746,31747,31748,31749,31750,31751,31752,31753,31754,31755,31756,31757,31758,31759,31760,31761,31762,31763,31764,31765,31766,31767,31768,31769,31770,31771,31772,31773,31774,31775,31776,31777,31778
 ,31779,31780,31781,31782,31783,31784,31785,31786,31787,31788,31789,31790,31791,31792,31793,31794,31795,31796,31797,31798,31799,31800,31801,31802,31803,31804,31805,31806,31807,31808,31809,31810,31811,31812,31813,31814,31815,31816,31817,31818,31819,31820,31821,31822,31823,31824,31825,31826,31827,31828,31829,31830,31831,31832,31833,31834,31835,31836,31837,31838,31839,31840,31841,31842,31843,31844,31845,31846,31847,31848,31849,31850,31851,31852,31853,31854,31855,31856,31857,31858,31859,31860,31861,31862,31863,31864,31865,31866,31867,31868,31869,31870,31871,31872,31873,31874,31875,31876,31877,31878,31879,31880,31881,31882,31883,31884,31885,31886,31887,31888,31889,31890,31891,31892,31893,31894,31895,31896,31897,31898,31899,31900,31901,31902,31903,31904,31905,31906,31907,31908,31909,31910,31911,31912,31913,31914,31915,31916,31917,31918,31919,31920,31921,31922,31923,31924,31925,31926,31927,31928,31929,31930,31931,31932,31933,31934,31935,31936,31937,31938,31939,31940,31941,31942,31943,31944,
 31945,31946,31947,31948,31949,31950,31951,31952,31953,31954,31955,31956,31957,31958,31959,31960,31961,31962,31963,31964,31965,31966,31967,31968,31969,31970,31971,31972,31973,31974,31975,31976,31977,31978,31979,31980,31981,31982,31983,31984,31985,31986,31987,31988,31989,31990,31991,31992,31993,31994,31995,31996,31997,31998,31999,32000,32001,32002,32003,32004,32005,32006,32007,32008,32009,32010,32011,32012,32013,32014,32015,32016,32017,32018,32019,32020,32021,32022,32023,32024,32025,32026,32027,32028,32029,32030,32031,32032,32033,32034,32035,32036,32037,32038,32039,32040,32041,32042,32043,32044,32045,32046,32047,32048,32049,32050,32051,32052,32053,32054,32055,32056,32057,32058,32059,32060,32061,32062,32063,32064,32065,32066,32067,32068,32069,32070,32071,32072,32073,32074,32075,32076,32077,32078,32079,32080,32081,32082,32083,32084,32085,32086,32087,32088,32089,32090,32091,32092,32093,32094,32095,32096,32097,32098,32099,32100,32101,32102,32103,32104,32105,32106,32107,32108,32109,32110,3
 2111,32112,32113,32114,32115,32116,32117,32118,32119,32120,32121,32122,32123,32124,32125,32126,32127,32128,32129,32130,32131,32132,32133,32134,32135,32136,32137,32138,32139,32140,32141,32142,32143,32144,32145,32146,32147,32148,32149,32150,32151,32152,32153,32154,32155,32156,32157,32158,32159,32160,32161,32162,32163,32164,32165,32166,32167,32168,32169,32170,32171,32172,32173,32174,32175,32176,32177,32178,32179,32180,32181,32182,32183,32184,32185,32186,32187,32188,32189,32190,32191,32192,32193,32194,32195,32196,32197,32198,32199,32200,32201,32202,32203,32204,32205,32206,32207,32208,32209,32210,32211,32212,32213,32214,32215,32216,32217,32218,32219,32220,32221,32222,32223,32224,32225,32226,32227,32228,32229,32230,32231,32232,32233,32234,32235,32236,32237,32238,32239,32240,32241,32242,32243,32244,32245,32246,32247,32248,32249,32250,32251,32252,32253,32254,32255,32256,32257,32258,32259,32260,32261,32262,32263,32264,32265,32266,32267,32268,32269,32270,32271,32272,32273,32274,32275,32276,32
 277,32278,32279,32280,32281,32282,32283,32284,32285,32286,32287,32288,32289,32290,32291,32292,32293,32294,32295,32296,32297,32298,32299,32300,32301,32302,32303,32304,32305,32306,32307,32308,32309,32310,32311,32312,32313,32314,32315,32316,32317,32318,32319,32320,32321,32322,32323,32324,32325,32326,32327,32328,32329,32330,32331,32332,32333,32334,32335,32336,32337,32338,32339,32340,32341,32342,32343,32344,32345,32346,32347,32348,32349,32350,32351,32352,32353,32354,32355,32356,32357,32358,32359,32360,32361,32362,32363,32364,32365,32366,32367,32368,32369,32370,32371,32372,32373,32374,32375,32376,32377,32378,32379,32380,32381,32382,32383,32384,32385,32386,32387,32388,32389,32390,32391,32392,32393,32394,32395,32396,32397,32398,32399,32400,32401,32402,32403,32404,32405,32406,32407,32408,32409,32410,32411,32412,32413,32414,32415,32416,32417,32418,32419,32420,32421,32422,32423,32424,32425,32426,32427,32428,32429,32430,32431,32432,32433,32434,32435,32436,32437,32438,32439,32440,32441,32442,324
 43,32444,32445,32446,32447,32448,32449,32450,32451,32452,32453,32454,32455,32456,32457,32458,32459,32460,32461,32462,32463,32464,32465,32466,32467,32468,32469,32470,32471,32472,32473,32474,32475,32476,32477,32478,32479,32480,32481,32482,32483,32484,32485,32486,32487,32488,32489,32490,32491,32492,32493,32494,32495,32496,32497,32498,32499,32500,32501,32502,32503,32504,32505,32506,32507,32508,32509,32510,32511,32512,32513,32514,32515,32516,32517,32518,32519,32520,32521,32522,32523,32524,32525,32526,32527,32528,32529,32530,32531,32532,32533,32534,32535,32536,32537,32538,32539,32540,32541,32542,32543,32544,32545,32546,32547,32548,32549,32550,32551,32552,32553,32554,32555,32556,32557,32558,32559,32560,32561,32562,32563,32564,32565,32566,32567,32568,32569,32570,32571,32572,32573,32574,32575,32576,32577,32578,32579,32580,32581,32582,32583,32584,32585,32586,32587,32588,32589,32590,32591,32592,32593,32594,32595,32596,32597,32598,32599,32600,32601,32602,32603,32604,32605,32606,32607,32608,3260
 9,32610,32611,32612,32613,32614,32615,32616,32617,32618,32619,32620,32621,32622,32623,32624,32625,32626,32627,32628,32629,32630,32631,32632,32633,32634,32635,32636,32637,32638,32639,32640,32641,32642,32643,32644,32645,32646,32647,32648,32649,32650,32651,32652,32653,32654,32655,32656,32657,32658,32659,32660,32661,32662,32663,32664,32665,32666,32667,32668,32669,32670,32671,32672,32673,32674,32675,32676,32677,32678,32679,32680,32681,32682,32683,32684,32685,32686,32687,32688,32689,32690,32691,32692,32693,32694,32695,32696,32697,32698,32699,32700,32701,32702,32703,32704,32705,32706,32707,32708,32709,32710,32711,32712,32713,32714,32715,32716,32717,32718,32719,32720,32721,32722,32723,32724,32725,32726,32727,32728,32729,32730,32731,32732,32733,32734,32735,32736,32737,32738,32739,32740,32741,32742,32743,32744,32745,32746,32747,32748,32749,32750,32751,32752,32753,32754,32755,32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768,32769,32770,32771,32772,32773,32774,32775
 ,32776,32777,32778,32779,32780,32781,32782,32783,32784,32785,32786,32787,32788,32789,32790,32791,32792,32793,32794,32795,32796,32797,32798,32799,32800,32801,32802,32803,32804,32805,32806,32807,32808,32809,32810,32811,32812,32813,32814,32815,32816,32817,32818,32819,32820,32821,32822,32823,32824,32825,32826,32827,32828,32829,32830,32831,32832,32833,32834,32835,32836,32837,32838,32839,32840,32841,32842,32843,32844,32845,32846,32847,32848,32849,32850,32851,32852,32853,32854,32855,32856,32857,32858,32859,32860,32861,32862,32863,32864,32865,32866,32867,32868,32869,32870,32871,32872,32873,32874,32875,32876,32877,32878,32879,32880,32881,32882,32883,32884,32885,32886,32887,32888,32889,32890,32891,32892,32893,32894,32895,32896,32897,32898,32899,32900,32901,32902,32903,32904,32905,32906,32907,32908,32909,32910,32911,32912,32913,32914,32915,32916,32917,32918,32919,32920,32921,32922,32923,32924,32925,32926,32927,32928,32929,32930,32931,32932,32933,32934,32935,32936,32937,32938,32939,32940,32941,
 32942,32943,32944,32945,32946,32947,32948,32949,32950,32951,32952,32953,32954,32955,32956,32957,32958,32959,32960,32961,32962,32963,32964,32965,32966,32967,32968,32969,32970,32971,32972,32973,32974,32975,32976,32977,32978,32979,32980,32981,32982,32983,32984,32985,32986,32987,32988,32989,32990,32991,32992,32993,32994,32995,32996,32997,32998,32999,33000,33001,33002,33003,33004,33005,33006,33007,33008,33009,33010,33011,33012,33013,33014,33015,33016,33017,33018,33019,33020,33021,33022,33023,33024,33025,33026,33027,33028,33029,33030,33031,33032,33033,33034,33035,33036,33037,33038,33039,33040,33041,33042,33043,33044,33045,33046,33047,33048,33049,33050,33051,33052,33053,33054,33055,33056,33057,33058,33059,33060,33061,33062,33063,33064,33065,33066,33067,33068,33069,33070,33071,33072,33073,33074,33075,33076,33077,33078,33079,33080,33081,33082,33083,33084,33085,33086,33087,33088,33089,33090,33091,33092,33093,33094,33095,33096,33097,33098,33099,33100,33101,33102,33103,33104,33105,33106,33107,3
 3108,33109,33110,33111,33112,33113,33114,33115,33116,33117,33118,33119,33120,33121,33122,33123,33124,33125,33126,33127,33128,33129,33130,33131,33132,33133,33134,33135,33136,33137,33138,33139,33140,33141,33142,33143,33144,33145,33146,33147,33148,33149,33150,33151,33152,33153,33154,33155,33156,33157,33158,33159,33160,33161,33162,33163,33164,33165,33166,33167,33168,33169,33170,33171,33172,33173,33174,33175,33176,33177,33178,33179,33180,33181,33182,33183,33184,33185,33186,33187,33188,33189,33190,33191,33192,33193,33194,33195,33196,33197,33198,33199,33200,33201,33202,33203,33204,33205,33206,33207,33208,33209,33210,33211,33212,33213,33214,33215,33216,33217,33218,33219,33220,33221,33222,33223,33224,33225,33226,33227,33228,33229,33230,33231,33232,33233,33234,33235,33236,33237,33238,33239,33240,33241,33242,33243,33244,33245,33246,33247,33248,33249,33250,33251,33252,33253,33254,33255,33256,33257,33258,33259,33260,33261,33262,33263,33264,33265,33266,33267,33268,33269,33270,33271,33272,33273,33
 274,33275,33276,33277,33278,33279,33280,33281,33282,33283,33284,33285,33286,33287,33288,33289,33290,33291,33292,33293,33294,33295,33296,33297,33298,33299,33300,33301,33302,33303,33304,33305,33306,33307,33308,33309,33310,33311,33312,33313,33314,33315,33316,33317,33318,33319,33320,33321,33322,33323,33324,33325,33326,33327,33328,33329,33330,33331,33332,33333,33334,33335,33336,33337,33338,33339,33340,33341,33342,33343,33344,33345,33346,33347,33348,33349,33350,33351,33352,33353,33354,33355,33356,33357,33358,33359,33360,33361,33362,33363,33364,33365,33366,33367,33368,33369,33370,33371,33372,33373,33374,33375,33376,33377,33378,33379,33380,33381,33382,33383,33384,33385,33386,33387,33388,33389,33390,33391,33392,33393,33394,33395,33396,33397,33398,33399,33400,33401,33402,33403,33404,33405,33406,33407,33408,33409,33410,33411,33412,33413,33414,33415,33416,33417,33418,33419,33420,33421,33422,33423,33424,33425,33426,33427,33428,33429,33430,33431,33432,33433,33434,33435,33436,33437,33438,33439,334
 40,33441,33442,33443,33444,33445,33446,33447,33448,33449,33450,33451,33452,33453,33454,33455,33456,33457,33458,33459,33460,33461,33462,33463,33464,33465,33466,33467,33468,33469,33470,33471,33472,33473,33474,33475,33476,33477,33478,33479,33480,33481,33482,33483,33484,33485,33486,33487,33488,33489,33490,33491,33492,33493,33494,33495,33496,33497,33498,33499,33500,33501,33502,33503,33504,33505,33506,33507,33508,33509,33510,33511,33512,33513,33514,33515,33516,33517,33518,33519,33520,33521,33522,33523,33524,33525,33526,33527,33528,33529,33530,33531,33532,33533,33534,33535,33536,33537,33538,33539,33540,33541,33542,33543,33544,33545,33546,33547,33548,33549,33550,33551,33552,33553,33554,33555,33556,33557,33558,33559,33560,33561,33562,33563,33564,33565,33566,33567,33568,33569,33570,33571,33572,33573,33574,33575,33576,33577,33578,33579,33580,33581,33582,33583,33584,33585,33586,33587,33588,33589,33590,33591,33592,33593,33594,33595,33596,33597,33598,33599,33600,33601,33602,33603,33604,33605,3360
 6,33607,33608,33609,33610,33611,33612,33613,33614,33615,33616,33617,33618,33619,33620,33621,33622,33623,33624,33625,33626,33627,33628,33629,33630,33631,33632,33633,33634,33635,33636,33637,33638,33639,33640,33641,33642,33643,33644,33645,33646,33647,33648,33649,33650,33651,33652,33653,33654,33655,33656,33657,33658,33659,33660,33661,33662,33663,33664,33665,33666,33667,33668,33669,33670,33671,33672,33673,33674,33675,33676,33677,33678,33679,33680,33681,33682,33683,33684,33685,33686,33687,33688,33689,33690,33691,33692,33693,33694,33695,33696,33697,33698,33699,33700,33701,33702,33703,33704,33705,33706,33707,33708,33709,33710,33711,33712,33713,33714,33715,33716,33717,33718,33719,33720,33721,33722,33723,33724,33725,33726,33727,33728,33729,33730,33731,33732,33733,33734,33735,33736,33737,33738,33739,33740,33741,33742,33743,33744,33745,33746,33747,33748,33749,33750,33751,33752,33753,33754,33755,33756,33757,33758,33759,33760,33761,33762,33763,33764,33765,33766,33767,33768,33769,33770,33771,33772
 ,33773,33774,33775,33776,33777,33778,33779,33780,33781,33782,33783,33784,33785,33786,33787,33788,33789,33790,33791,33792,33793,33794,33795,33796,33797,33798,33799,33800,33801,33802,33803,33804,33805,33806,33807,33808,33809,33810,33811,33812,33813,33814,33815,33816,33817,33818,33819,33820,33821,33822,33823,33824,33825,33826,33827,33828,33829,33830,33831,33832,33833,33834,33835,33836,33837,33838,33839,33840,33841,33842,33843,33844,33845,33846,33847,33848,33849,33850,33851,33852,33853,33854,33855,33856,33857,33858,33859,33860,33861,33862,33863,33864,33865,33866,33867,33868,33869,33870,33871,33872,33873,33874,33875,33876,33877,33878,33879,33880,33881,33882,33883,33884,33885,33886,33887,33888,33889,33890,33891,33892,33893,33894,33895,33896,33897,33898,33899,33900,33901,33902,33903,33904,33905,33906,33907,33908,33909,33910,33911,33912,33913,33914,33915,33916,33917,33918,33919,33920,33921,33922,33923,33924,33925,33926,33927,33928,33929,33930,33931,33932,33933,33934,33935,33936,33937,33938,
 33939,33940,33941,33942,33943,33944,33945,33946,33947,33948,33949,33950,33951,33952,33953,33954,33955,33956,33957,33958,33959,33960,33961,33962,33963,33964,33965,33966,33967,33968,33969,33970,33971,33972,33973,33974,33975,33976,33977,33978,33979,33980,33981,33982,33983,33984,33985,33986,33987,33988,33989,33990,33991,33992,33993,33994,33995,33996,33997,33998,33999,34000,34001,34002,34003,34004,34005,34006,34007,34008,34009,34010,34011,34012,34013,34014,34015,34016,34017,34018,34019,34020,34021,34022,34023,34024,34025,34026,34027,34028,34029,34030,34031,34032,34033,34034,34035,34036,34037,34038,34039,34040,34041,34042,34043,34044,34045,34046,34047,34048,34049,34050,34051,34052,34053,34054,34055,34056,34057,34058,34059,34060,34061,34062,34063,34064,34065,34066,34067,34068,34069,34070,34071,34072,34073,34074,34075,34076,34077,34078,34079,34080,34081,34082,34083,34084,34085,34086,34087,34088,34089,34090,34091,34092,34093,34094,34095,34096,34097,34098,34099,34100,34101,34102,34103,34104,3
 4105,34106,34107,34108,34109,34110,34111,34112,34113,34114,34115,34116,34117,34118,34119,34120,34121,34122,34123,34124,34125,34126,34127,34128,34129,34130,34131,34132,34133,34134,34135,34136,34137,34138,34139,34140,34141,34142,34143,34144,34145,34146,34147,34148,34149,34150,34151,34152,34153,34154,34155,34156,34157,34158,34159,34160,34161,34162,34163,34164,34165,34166,34167,34168,34169,34170,34171,34172,34173,34174,34175,34176,34177,34178,34179,34180,34181,34182,34183,34184,34185,34186,34187,34188,34189,34190,34191,34192,34193,34194,34195,34196,34197,34198,34199,34200,34201,34202,34203,34204,34205,34206,34207,34208,34209,34210,34211,34212,34213,34214,34215,34216,34217,34218,34219,34220,34221,34222,34223,34224,34225,34226,34227,34228,34229,34230,34231,34232,34233,34234,34235,34236,34237,34238,34239,34240,34241,34242,34243,34244,34245,34246,34247,34248,34249,34250,34251,34252,34253,34254,34255,34256,34257,34258,34259,34260,34261,34262,34263,34264,34265,34266,34267,34268,34269,34270,34
 271,34272,34273,34274,34275,34276,34277,34278,34279,34280,34281,34282,34283,34284,34285,34286,34287,34288,34289,34290,34291,34292,34293,34294,34295,34296,34297,34298,34299,34300,34301,34302,34303,34304,34305,34306,34307,34308,34309,34310,34311,34312,34313,34314,34315,34316,34317,34318,34319,34320,34321,34322,34323,34324,34325,34326,34327,34328,34329,34330,34331,34332,34333,34334,34335,34336,34337,34338,34339,34340,34341,34342,34343,34344,34345,34346,34347,34348,34349,34350,34351,34352,34353,34354,34355,34356,34357,34358,34359,34360,34361,34362,34363,34364,34365,34366,34367,34368,34369,34370,34371,34372,34373,34374,34375,34376,34377,34378,34379,34380,34381,34382,34383,34384,34385,34386,34387,34388,34389,34390,34391,34392,34393,34394,34395,34396,34397,34398,34399,34400,34401,34402,34403,34404,34405,34406,34407,34408,34409,34410,34411,34412,34413,34414,34415,34416,34417,34418,34419,34420,34421,34422,34423,34424,34425,34426,34427,34428,34429,34430,34431,34432,34433,34434,34435,34436,344
 37,34438,34439,34440,34441,34442,34443,34444,34445,34446,34447,34448,34449,34450,34451,34452,34453,34454,34455,34456,34457,34458,34459,34460,34461,34462,34463,34464,34465,34466,34467,34468,34469,34470,34471,34472,34473,34474,34475,34476,34477,34478,34479,34480,34481,34482,34483,34484,34485,34486,34487,34488,34489,34490,34491,34492,34493,34494,34495,34496,34497,34498,34499,34500,34501,34502,34503,34504,34505,34506,34507,34508,34509,34510,34511,34512,34513,34514,34515,34516,34517,34518,34519,34520,34521,34522,34523,34524,34525,34526,34527,34528,34529,34530,34531,34532,34533,34534,34535,34536,34537,34538,34539,34540,34541,34542,34543,34544,34545,34546,34547,34548,34549,34550,34551,34552,34553,34554,34555,34556,34557,34558,34559,34560,34561,34562,34563,34564,34565,34566,34567,34568,34569,34570,34571,34572,34573,34574,34575,34576,34577,34578,34579,34580,34581,34582,34583,34584,34585,34586,34587,34588,34589,34590,34591,34592,34593,34594,34595,34596,34597,34598,34599,34600,34601,34602,3460
 3,34604,34605,34606,34607,34608,34609,34610,34611,34612,34613,34614,34615,34616,34617,34618,34619,34620,34621,34622,34623,34624,34625,34626,34627,34628,34629,34630,34631,34632,34633,34634,34635,34636,34637,34638,34639,34640,34641,34642,34643,34644,34645,34646,34647,34648,34649,34650,34651,34652,34653,34654,34655,34656,34657,34658,34659,34660,34661,34662,34663,34664,34665,34666,34667,34668,34669,34670,34671,34672,34673,34674,34675,34676,34677,34678,34679,34680,34681,34682,34683,34684,34685,34686,34687,34688,34689,34690,34691,34692,34693,34694,34695,34696,34697,34698,34699,34700,34701,34702,34703,34704,34705,34706,34707,34708,34709,34710,34711,34712,34713,34714,34715,34716,34717,34718,34719,34720,34721,34722,34723,34724,34725,34726,34727,34728,34729,34730,34731,34732,34733,34734,34735,34736,34737,34738,34739,34740,34741,34742,34743,34744,34745,34746,34747,34748,34749,34750,34751,34752,34753,34754,34755,34756,34757,34758,34759,34760,34761,34762,34763,34764,34765,34766,34767,34768,34769
 ,34770,34771,34772,34773,34774,34775,34776,34777,34778,34779,34780,34781,34782,34783,34784,34785,34786,34787,34788,34789,34790,34791,34792,34793,34794,34795,34796,34797,34798,34799,34800,34801,34802,34803,34804,34805,34806,34807,34808,34809,34810,34811,34812,34813,34814,34815,34816,34817,34818,34819,34820,34821,34822,34823,34824,34825,34826,34827,34828,34829,34830,34831,34832,34833,34834,34835,34836,34837,34838,34839,34840,34841,34842,34843,34844,34845,34846,34847,34848,34849,34850,34851,34852,34853,34854,34855,34856,34857,34858,34859,34860,34861,34862,34863,34864,34865,34866,34867,34868,34869,34870,34871,34872,34873,34874,34875,34876,34877,34878,34879,34880,34881,34882,34883,34884,34885,34886,34887,34888,34889,34890,34891,34892,34893,34894,34895,34896,34897,34898,34899,34900,34901,34902,34903,34904,34905,34906,34907,34908,34909,34910,34911,34912,34913,34914,34915,34916,34917,34918,34919,34920,34921,34922,34923,34924,34925,34926,34927,34928,34929,34930,34931,34932,34933,34934,34935,
 34936,34937,34938,34939,34940,34941,34942,34943,34944,34945,34946,34947,34948,34949,34950,34951,34952,34953,34954,34955,34956,34957,34958,34959,34960,34961,34962,34963,34964,34965,34966,34967,34968,34969,34970,34971,34972,34973,34974,34975,34976,34977,34978,34979,34980,34981,34982,34983,34984,34985,34986,34987,34988,34989,34990,34991,34992,34993,34994,34995,34996,34997,34998,34999,35000,35001,35002,35003,35004,35005,35006,35007,35008,35009,35010,35011,35012,35013,35014,35015,35016,35017,35018,35019,35020,35021,35022,35023,35024,35025,35026,35027,35028,35029,35030,35031,35032,35033,35034,35035,35036,35037,35038,35039,35040,35041,35042,35043,35044,35045,35046,35047,35048,35049,35050,35051,35052,35053,35054,35055,35056,35057,35058,35059,35060,35061,35062,35063,35064,35065,35066,35067,35068,35069,35070,35071,35072,35073,35074,35075,35076,35077,35078,35079,35080,35081,35082,35083,35084,35085,35086,35087,35088,35089,35090,35091,35092,35093,35094,35095,35096,35097,35098,35099,35100,35101,3
 5102,35103,35104,35105,35106,35107,35108,35109,35110,35111,35112,35113,35114,35115,35116,35117,35118,35119,35120,35121,35122,35123,35124,35125,35126,35127,35128,35129,35130,35131,35132,35133,35134,35135,35136,35137,35138,35139,35140,35141,35142,35143,35144,35145,35146,35147,35148,35149,35150,35151,35152,35153,35154,35155,35156,35157,35158,35159,35160,35161,35162,35163,35164,35165,35166,35167,35168,35169,35170,35171,35172,35173,35174,35175,35176,35177,35178,35179,35180,35181,35182,35183,35184,35185,35186,35187,35188,35189,35190,35191,35192,35193,35194,35195,35196,35197,35198,35199,35200,35201,35202,35203,35204,35205,35206,35207,35208,35209,35210,35211,35212,35213,35214,35215,35216,35217,35218,35219,35220,35221,35222,35223,35224,35225,35226,35227,35228,35229,35230,35231,35232,35233,35234,35235,35236,35237,35238,35239,35240,35241,35242,35243,35244,35245,35246,35247,35248,35249,35250,35251,35252,35253,35254,35255,35256,35257,35258,35259,35260,35261,35262,35263,35264,35265,35266,35267,35
 268,35269,35270,35271,35272,35273,35274,35275,35276,35277,35278,35279,35280,35281,35282,35283,35284,35285,35286,35287,35288,35289,35290,35291,35292,35293,35294,35295,35296,35297,35298,35299,35300,35301,35302,35303,35304,35305,35306,35307,35308,35309,35310,35311,35312,35313,35314,35315,35316,35317,35318,35319,35320,35321,35322,35323,35324,35325,35326,35327,35328,35329,35330,35331,35332,35333,35334,35335,35336,35337,35338,35339,35340,35341,35342,35343,35344,35345,35346,35347,35348,35349,35350,35351,35352,35353,35354,35355,35356,35357,35358,35359,35360,35361,35362,35363,35364,35365,35366,35367,35368,35369,35370,35371,35372,35373,35374,35375,35376,35377,35378,35379,35380,35381,35382,35383,35384,35385,35386,35387,35388,35389,35390,35391,35392,35393,35394,35395,35396,35397,35398,35399,35400,35401,35402,35403,35404,35405,35406,35407,35408,35409,35410,35411,35412,35413,35414,35415,35416,35417,35418,35419,35420,35421,35422,35423,35424,35425,35426,35427,35428,35429,35430,35431,35432,35433,354
 34,35435,35436,35437,35438,35439,35440,35441,35442,35443,35444,35445,35446,35447,35448,35449,35450,35451,35452,35453,35454,35455,35456,35457,35458,35459,35460,35461,35462,35463,35464,35465,35466,35467,35468,35469,35470,35471,35472,35473,35474,35475,35476,35477,35478,35479,35480,35481,35482,35483,35484,35485,35486,35487,35488,35489,35490,35491,35492,35493,35494,35495,35496,35497,35498,35499,35500,35501,35502,35503,35504,35505,35506,35507,35508,35509,35510,35511,35512,35513,35514,35515,35516,35517,35518,35519,35520,35521,35522,35523,35524,35525,35526,35527,35528,35529,35530,35531,35532,35533,35534,35535,35536,35537,35538,35539,35540,35541,35542,35543,35544,35545,35546,35547,35548,35549,35550,35551,35552,35553,35554,35555,35556,35557,35558,35559,35560,35561,35562,35563,35564,35565,35566,35567,35568,35569,35570,35571,35572,35573,35574,35575,35576,35577,35578,35579,35580,35581,35582,35583,35584,35585,35586,35587,35588,35589,35590,35591,35592,35593,35594,35595,35596,35597,35598,35599,3560
 0,35601,35602,35603,35604,35605,35606,35607,35608,35609,35610,35611,35612,35613,35614,35615,35616,35617,35618,35619,35620,35621,35622,35623,35624,35625,35626,35627,35628,35629,35630,35631,35632,35633,35634,35635,35636,35637,35638,35639,35640,35641,35642,35643,35644,35645,35646,35647,35648,35649,35650,35651,35652,35653,35654,35655,35656,35657,35658,35659,35660,35661,35662,35663,35664,35665,35666,35667,35668,35669,35670,35671,35672,35673,35674,35675,35676,35677,35678,35679,35680,35681,35682,35683,35684,35685,35686,35687,35688,35689,35690,35691,35692,35693,35694,35695,35696,35697,35698,35699,35700,35701,35702,35703,35704,35705,35706,35707,35708,35709,35710,35711,35712,35713,35714,35715,35716,35717,35718,35719,35720,35721,35722,35723,35724,35725,35726,35727,35728,35729,35730,35731,35732,35733,35734,35735,35736,35737,35738,35739,35740,35741,35742,35743,35744,35745,35746,35747,35748,35749,35750,35751,35752,35753,35754,35755,35756,35757,35758,35759,35760,35761,35762,35763,35764,35765,35766
 ,35767,35768,35769,35770,35771,35772,35773,35774,35775,35776,35777,35778,35779,35780,35781,35782,35783,35784,35785,35786,35787,35788,35789,35790,35791,35792,35793,35794,35795,35796,35797,35798,35799,35800,35801,35802,35803,35804,35805,35806,35807,35808,35809,35810,35811,35812,35813,35814,35815,35816,35817,35818,35819,35820,35821,35822,35823,35824,35825,35826,35827,35828,35829,35830,35831,35832,35833,35834,35835,35836,35837,35838,35839,35840,35841,35842,35843,35844,35845,35846,35847,35848,35849,35850,35851,35852,35853,35854,35855,35856,35857,35858,35859,35860,35861,35862,35863,35864,35865,35866,35867,35868,35869,35870,35871,35872,35873,35874,35875,35876,35877,35878,35879,35880,35881,35882,35883,35884,35885,35886,35887,35888,35889,35890,35891,35892,35893,35894,35895,35896,35897,35898,35899,35900,35901,35902,35903,35904,35905,35906,35907,35908,35909,35910,35911,35912,35913,35914,35915,35916,35917,35918,35919,35920,35921,35922,35923,35924,35925,35926,35927,35928,35929,35930,35931,35932,
 35933,35934,35935,35936,35937,35938,35939,35940,35941,35942,35943,35944,35945,35946,35947,35948,35949,35950,35951,35952,35953,35954,35955,35956,35957,35958,35959,35960,35961,35962,35963,35964,35965,35966,35967,35968,35969,35970,35971,35972,35973,35974,35975,35976,35977,35978,35979,35980,35981,35982,35983,35984,35985,35986,35987,35988,35989,35990,35991,35992,35993,35994,35995,35996,35997,35998,35999,36000,36001,36002,36003,36004,36005,36006,36007,36008,36009,36010,36011,36012,36013,36014,36015,36016,36017,36018,36019,36020,36021,36022,36023,36024,36025,36026,36027,36028,36029,36030,36031,36032,36033,36034,36035,36036,36037,36038,36039,36040,36041,36042,36043,36044,36045,36046,36047,36048,36049,36050,36051,36052,36053,36054,36055,36056,36057,36058,36059,36060,36061,36062,36063,36064,36065,36066,36067,36068,36069,36070,36071,36072,36073,36074,36075,36076,36077,36078,36079,36080,36081,36082,36083,36084,36085,36086,36087,36088,36089,36090,36091,36092,36093,36094,36095,36096,36097,36098,3
 6099,36100,36101,36102,36103,36104,36105,36106,36107,36108,36109,36110,36111,36112,36113,36114,36115,36116,36117,36118,36119,36120,36121,36122,36123,36124,36125,36126,36127,36128,36129,36130,36131,36132,36133,36134,36135,36136,36137,36138,36139,36140,36141,36142,36143,36144,36145,36146,36147,36148,36149,36150,36151,36152,36153,36154,36155,36156,36157,36158,36159,36160,36161,36162,36163,36164,36165,36166,36167,36168,36169,36170,36171,36172,36173,36174,36175,36176,36177,36178,36179,36180,36181,36182,36183,36184,36185,36186,36187,36188,36189,36190,36191,36192,36193,36194,36195,36196,36197,36198,36199,36200,36201,36202,36203,36204,36205,36206,36207,36208,36209,36210,36211,36212,36213,36214,36215,36216,36217,36218,36219,36220,36221,36222,36223,36224,36225,36226,36227,36228,36229,36230,36231,36232,36233,36234,36235,36236,36237,36238,36239,36240,36241,36242,36243,36244,36245,36246,36247,36248,36249,36250,36251,36252,36253,36254,36255,36256,36257,36258,36259,36260,36261,36262,36263,36264,36
 265,36266,36267,36268,36269,36270,36271,36272,36273,36274,36275,36276,36277,36278,36279,36280,36281,36282,36283,36284,36285,36286,36287,36288,36289,36290,36291,36292,36293,36294,36295,36296,36297,36298,36299,36300,36301,36302,36303,36304,36305,36306,36307,36308,36309,36310,36311,36312,36313,36314,36315,36316,36317,36318,36319,36320,36321,36322,36323,36324,36325,36326,36327,36328,36329,36330,36331,36332,36333,36334,36335,36336,36337,36338,36339,36340,36341,36342,36343,36344,36345,36346,36347,36348,36349,36350,36351,36352,36353,36354,36355,36356,36357,36358,36359,36360,36361,36362,36363,36364,36365,36366,36367,36368,36369,36370,36371,36372,36373,36374,36375,36376,36377,36378,36379,36380,36381,36382,36383,36384,36385,36386,36387,36388,36389,36390,36391,36392,36393,36394,36395,36396,36397,36398,36399,36400,36401,36402,36403,36404,36405,36406,36407,36408,36409,36410,36411,36412,36413,36414,36415,36416,36417,36418,36419,36420,36421,36422,36423,36424,36425,36426,36427,36428,36429,36430,364
 31,36432,36433,36434,36435,36436,36437,36438,36439,36440,36441,36442,36443,36444,36445,36446,36447,36448,36449,36450,36451,36452,36453,36454,36455,36456,36457,36458,36459,36460,36461,36462,36463,36464,36465,36466,36467,36468,36469,36470,36471,36472,36473,36474,36475,36476,36477,36478,36479,36480,36481,36482,36483,36484,36485,36486,36487,36488,36489,36490,36491,36492,36493,36494,36495,36496,36497,36498,36499,36500,36501,36502,36503,36504,36505,36506,36507,36508,36509,36510,36511,36512,36513,36514,36515,36516,36517,36518,36519,36520,36521,36522,36523,36524,36525,36526,36527,36528,36529,36530,36531,36532,36533,36534,36535,36536,36537,36538,36539,36540,36541,36542,36543,36544,36545,36546,36547,36548,36549,36550,36551,36552,36553,36554,36555,36556,36557,36558,36559,36560,36561,36562,36563,36564,36565,36566,36567,36568,36569,36570,36571,36572,36573,36574,36575,36576,36577,36578,36579,36580,36581,36582,36583,36584,36585,36586,36587,36588,36589,36590,36591,36592,36593,36594,36595,36596,3659
 7,36598,36599,36600,36601,36602,36603,36604,36605,36606,36607,36608,36609,36610,36611,36612,36613,36614,36615,36616,36617,36618,36619,36620,36621,36622,36623,36624,36625,36626,36627,36628,36629,36630,36631,36632,36633,36634,36635,36636,36637,36638,36639,36640,36641,36642,36643,36644,36645,36646,36647,36648,36649,36650,36651,36652,36653,36654,36655,36656,36657,36658,36659,36660,36661,36662,36663,36664,36665,36666,36667,36668,36669,36670,36671,36672,36673,36674,36675,36676,36677,36678,36679,36680,36681,36682,36683,36684,36685,36686,36687,36688,36689,36690,36691,36692,36693,36694,36695,36696,36697,36698,36699,36700,36701,36702,36703,36704,36705,36706,36707,36708,36709,36710,36711,36712,36713,36714,36715,36716,36717,36718,36719,36720,36721,36722,36723,36724,36725,36726,36727,36728,36729,36730,36731,36732,36733,36734,36735,36736,36737,36738,36739,36740,36741,36742,36743,36744,36745,36746,36747,36748,36749,36750,36751,36752,36753,36754,36755,36756,36757,36758,36759,36760,36761,36762,36763
 ,36764,36765,36766,36767,36768,36769,36770,36771,36772,36773,36774,36775,36776,36777,36778,36779,36780,36781,36782,36783,36784,36785,36786,36787,36788,36789,36790,36791,36792,36793,36794,36795,36796,36797,36798,36799,36800,36801,36802,36803,36804,36805,36806,36807,36808,36809,36810,36811,36812,36813,36814,36815,36816,36817,36818,36819,36820,36821,36822,36823,36824,36825,36826,36827,36828,36829,36830,36831,36832,36833,36834,36835,36836,36837,36838,36839,36840,36841,36842,36843,36844,36845,36846,36847,36848,36849,36850,36851,36852,36853,36854,36855,36856,36857,36858,36859,36860,36861,36862,36863,36864,36865,36866,36867,36868,36869,36870,36871,36872,36873,36874,36875,36876,36877,36878,36879,36880,36881,36882,36883,36884,36885,36886,36887,36888,36889,36890,36891,36892,36893,36894,36895,36896,36897,36898,36899,36900,36901,36902,36903,36904,36905,36906,36907,36908,36909,36910,36911,36912,36913,36914,36915,36916,36917,36918,36919,36920,36921,36922,36923,36924,36925,36926,36927,36928,36929,
 36930,36931,36932,36933,36934,36935,36936,36937,36938,36939,36940,36941,36942,36943,36944,36945,36946,36947,36948,36949,36950,36951,36952,36953,36954,36955,36956,36957,36958,36959,36960,36961,36962,36963,36964,36965,36966,36967,36968,36969,36970,36971,36972,36973,36974,36975,36976,36977,36978,36979,36980,36981,36982,36983,36984,36985,36986,36987,36988,36989,36990,36991,36992,36993,36994,36995,36996,36997,36998,36999,37000,37001,37002,37003,37004,37005,37006,37007,37008,37009,37010,37011,37012,37013,37014,37015,37016,37017,37018,37019,37020,37021,37022,37023,37024,37025,37026,37027,37028,37029,37030,37031,37032,37033,37034,37035,37036,37037,37038,37039,37040,37041,37042,37043,37044,37045,37046,37047,37048,37049,37050,37051,37052,37053,37054,37055,37056,37057,37058,37059,37060,37061,37062,37063,37064,37065,37066,37067,37068,37069,37070,37071,37072,37073,37074,37075,37076,37077,37078,37079,37080,37081,37082,37083,37084,37085,37086,37087,37088,37089,37090,37091,37092,37093,37094,37095,3
 7096,37097,37098,37099,37100,37101,37102,37103,37104,37105,37106,37107,37108,37109,37110,37111,37112,37113,37114,37115,37116,37117,37118,37119,37120,37121,37122,37123,37124,37125,37126,37127,37128,37129,37130,37131,37132,37133,37134,37135,37136,37137,37138,37139,37140,37141,37142,37143,37144,37145,37146,37147,37148,37149,37150,37151,37152,37153,37154,37155,37156,37157,37158,37159,37160,37161,37162,37163,37164,37165,37166,37167,37168,37169,37170,37171,37172,37173,37174,37175,37176,37177,37178,37179,37180,37181,37182,37183,37184,37185,37186,37187,37188,37189,37190,37191,37192,37193,37194,37195,37196,37197,37198,37199,37200,37201,37202,37203,37204,37205,37206,37207,37208,37209,37210,37211,37212,37213,37214,37215,37216,37217,37218,37219,37220,37221,37222,37223,37224,37225,37226,37227,37228,37229,37230,37231,37232,37233,37234,37235,37236,37237,37238,37239,37240,37241,37242,37243,37244,37245,37246,37247,37248,37249,37250,37251,37252,37253,37254,37255,37256,37257,37258,37259,37260,37261,37
 262,37263,37264,37265,37266,37267,37268,37269,37270,37271,37272,37273,37274,37275,37276,37277,37278,37279,37280,37281,37282,37283,37284,37285,37286,37287,37288,37289,37290,37291,37292,37293,37294,37295,37296,37297,37298,37299,37300,37301,37302,37303,37304,37305,37306,37307,37308,37309,37310,37311,37312,37313,37314,37315,37316,37317,37318,37319,37320,37321,37322,37323,37324,37325,37326,37327,37328,37329,37330,37331,37332,37333,37334,37335,37336,37337,37338,37339,37340,37341,37342,37343,37344,37345,37346,37347,37348,37349,37350,37351,37352,37353,37354,37355,37356,37357,37358,37359,37360,37361,37362,37363,37364,37365,37366,37367,37368,37369,37370,37371,37372,37373,37374,37375,37376,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37387,37388,37389,37390,37391,37392,37393,37394,37395,37396,37397,37398,37399,37400,37401,37402,37403,37404,37405,37406,37407,37408,37409,37410,37411,37412,37413,37414,37415,37416,37417,37418,37419,37420,37421,37422,37423,37424,37425,37426,37427,374
 28,37429,37430,37431,37432,37433,37434,37435,37436,37437,37438,37439,37440,37441,37442,37443,37444,37445,37446,37447,37448,37449,37450,37451,37452,37453,37454,37455,37456,37457,37458,37459,37460,37461,37462,37463,37464,37465,37466,37467,37468,37469,37470,37471,37472,37473,37474,37475,37476,37477,37478,37479,37480,37481,37482,37483,37484,37485,37486,37487,37488,37489,37490,37491,37492,37493,37494,37495,37496,37497,37498,37499,37500,37501,37502,37503,37504,37505,37506,37507,37508,37509,37510,37511,37512,37513,37514,37515,37516,37517,37518,37519,37520,37521,37522,37523,37524,37525,37526,37527,37528,37529,37530,37531,37532,37533,37534,37535,37536,37537,37538,37539,37540,37541,37542,37543,37544,37545,37546,37547,37548,37549,37550,37551,37552,37553,37554,37555,37556,37557,37558,37559,37560,37561,37562,37563,37564,37565,37566,37567,37568,37569,37570,37571,37572,37573,37574,37575,37576,37577,37578,37579,37580,37581,37582,37583,37584,37585,37586,37587,37588,37589,37590,37591,37592,37593,3759
 4,37595,37596,37597,37598,37599,37600,37601,37602,37603,37604,37605,37606,37607,37608,37609,37610,37611,37612,37613,37614,37615,37616,37617,37618,37619,37620,37621,37622,37623,37624,37625,37626,37627,37628,37629,37630,37631,37632,37633,37634,37635,37636,37637,37638,37639,37640,37641,37642,37643,37644,37645,37646,37647,37648,37649,37650,37651,37652,37653,37654,37655,37656,37657,37658,37659,37660,37661,37662,37663,37664,37665,37666,37667,37668,37669,37670,37671,37672,37673,37674,37675,37676,37677,37678,37679,37680,37681,37682,37683,37684,37685,37686,37687,37688,37689,37690,37691,37692,37693,37694,37695,37696,37697,37698,37699,37700,37701,37702,37703,37704,37705,37706,37707,37708,37709,37710,37711,37712,37713,37714,37715,37716,37717,37718,37719,37720,37721,37722,37723,37724,37725,37726,37727,37728,37729,37730,37731,37732,37733,37734,37735,37736,37737,37738,37739,37740,37741,37742,37743,37744,37745,37746,37747,37748,37749,37750,37751,37752,37753,37754,37755,37756,37757,37758,37759,37760
 ,37761,37762,37763,37764,37765,37766,37767,37768,37769,37770,37771,37772,37773,37774,37775,37776,37777,37778,37779,37780,37781,37782,37783,37784,37785,37786,37787,37788,37789,37790,37791,37792,37793,37794,37795,37796,37797,37798,37799,37800,37801,37802,37803,37804,37805,37806,37807,37808,37809,37810,37811,37812,37813,37814,37815,37816,37817,37818,37819,37820,37821,37822,37823,37824,37825,37826,37827,37828,37829,37830,37831,37832,37833,37834,37835,37836,37837,37838,37839,37840,37841,37842,37843,37844,37845,37846,37847,37848,37849,37850,37851,37852,37853,37854,37855,37856,37857,37858,37859,37860,37861,37862,37863,37864,37865,37866,37867,37868,37869,37870,37871,37872,37873,37874,37875,37876,37877,37878,37879,37880,37881,37882,37883,37884,37885,37886,37887,37888,37889,37890,37891,37892,37893,37894,37895,37896,37897,37898,37899,37900,37901,37902,37903,37904,37905,37906,37907,37908,37909,37910,37911,37912,37913,37914,37915,37916,37917,37918,37919,37920,37921,37922,37923,37924,37925,37926,
 37927,37928,37929,37930,37931,37932,37933,37934,37935,37936,37937,37938,37939,37940,37941,37942,37943,37944,37945,37946,37947,37948,37949,37950,37951,37952,37953,37954,37955,37956,37957,37958,37959,37960,37961,37962,37963,37964,37965,37966,37967,37968,37969,37970,37971,37972,37973,37974,37975,37976,37977,37978,37979,37980,37981,37982,37983,37984,37985,37986,37987,37988,37989,37990,37991,37992,37993,37994,37995,37996,37997,37998,37999,38000,38001,38002,38003,38004,38005,38006,38007,38008,38009,38010,38011,38012,38013,38014,38015,38016,38017,38018,38019,38020,38021,38022,38023,38024,38025,38026,38027,38028,38029,38030,38031,38032,38033,38034,38035,38036,38037,38038,38039,38040,38041,38042,38043,38044,38045,38046,38047,38048,38049,38050,38051,38052,38053,38054,38055,38056,38057,38058,38059,38060,38061,38062,38063,38064,38065,38066,38067,38068,38069,38070,38071,38072,38073,38074,38075,38076,38077,38078,38079,38080,38081,38082,38083,38084,38085,38086,38087,38088,38089,38090,38091,38092,3
 8093,38094,38095,38096,38097,38098,38099,38100,38101,38102,38103,38104,38105,38106,38107,38108,38109,38110,38111,38112,38113,38114,38115,38116,38117,38118,38119,38120,38121,38122,38123,38124,38125,38126,38127,38128,38129,38130,38131,38132,38133,38134,38135,38136,38137,38138,38139,38140,38141,38142,38143,38144,38145,38146,38147,38148,38149,38150,38151,38152,38153,38154,38155,38156,38157,38158,38159,38160,38161,38162,38163,38164,38165,38166,38167,38168,38169,38170,38171,38172,38173,38174,38175,38176,38177,38178,38179,38180,38181,38182,38183,38184,38185,38186,38187,38188,38189,38190,38191,38192,38193,38194,38195,38196,38197,38198,38199,38200,38201,38202,38203,38204,38205,38206,38207,38208,38209,38210,38211,38212,38213,38214,38215,38216,38217,38218,38219,38220,38221,38222,38223,38224,38225,38226,38227,38228,38229,38230,38231,38232,38233,38234,38235,38236,38237,38238,38239,38240,38241,38242,38243,38244,38245,38246,38247,38248,38249,38250,38251,38252,38253,38254,38255,38256,38257,38258,38
 259,38260,38261,38262,38263,38264,38265,38266,38267,38268,38269,38270,38271,38272,38273,38274,38275,38276,38277,38278,38279,38280,38281,38282,38283,38284,38285,38286,38287,38288,38289,38290,38291,38292,38293,38294,38295,38296,38297,38298,38299,38300,38301,38302,38303,38304,38305,38306,38307,38308,38309,38310,38311,38312,38313,38314,38315,38316,38317,38318,38319,38320,38321,38322,38323,38324,38325,38326,38327,38328,38329,38330,38331,38332,38333,38334,38335,38336,38337,38338,38339,38340,38341,38342,38343,38344,38345,38346,38347,38348,38349,38350,38351,38352,38353,38354,38355,38356,38357,38358,38359,38360,38361,38362,38363,38364,38365,38366,38367,38368,38369,38370,38371,38372,38373,38374,38375,38376,38377,38378,38379,38380,38381,38382,38383,38384,38385,38386,38387,38388,38389,38390,38391,38392,38393,38394,38395,38396,38397,38398,38399,38400,38401,38402,38403,38404,38405,38406,38407,38408,38409,38410,38411,38412,38413,38414,38415,38416,38417,38418,38419,38420,38421,38422,38423,38424,384
 25,38426,38427,38428,38429,38430,38431,38432,38433,38434,38435,38436,38437,38438,38439,38440,38441,38442,38443,38444,38445,38446,38447,38448,38449,38450,38451,38452,38453,38454,38455,38456,38457,38458,38459,38460,38461,38462,38463,38464,38465,38466,38467,38468,38469,38470,38471,38472,38473,38474,38475,38476,38477,38478,38479,38480,38481,38482,38483,38484,38485,38486,38487,38488,38489,38490,38491,38492,38493,38494,38495,38496,38497,38498,38499,38500,38501,38502,38503,38504,38505,38506,38507,38508,38509,38510,38511,38512,38513,38514,38515,38516,38517,38518,38519,38520,38521,38522,38523,38524,38525,38526,38527,38528,38529,38530,38531,38532,38533,38534,38535,38536,38537,38538,38539,38540,38541,38542,38543,38544,38545,38546,38547,38548,38549,38550,38551,38552,38553,38554,38555,38556,38557,38558,38559,38560,38561,38562,38563,38564,38565,38566,38567,38568,38569,38570,38571,38572,38573,38574,38575,38576,38577,38578,38579,38580,38581,38582,38583,38584,38585,38586,38587,38588,38589,38590,3859
 1,38592,38593,38594,38595,38596,38597,38598,38599,38600,38601,38602,38603,38604,38605,38606,38607,38608,38609,38610,38611,38612,38613,38614,38615,38616,38617,38618,38619,38620,38621,38622,38623,38624,38625,38626,38627,38628,38629,38630,38631,38632,38633,38634,38635,38636,38637,38638,38639,38640,38641,38642,38643,38644,38645,38646,38647,38648,38649,38650,38651,38652,38653,38654,38655,38656,38657,38658,38659,38660,38661,38662,38663,38664,38665,38666,38667,38668,38669,38670,38671,38672,38673,38674,38675,38676,38677,38678,38679,38680,38681,38682,38683,38684,38685,38686,38687,38688,38689,38690,38691,38692,38693,38694,38695,38696,38697,38698,38699,38700,38701,38702,38703,38704,38705,38706,38707,38708,38709,38710,38711,38712,38713,38714,38715,38716,38717,38718,38719,38720,38721,38722,38723,38724,38725,38726,38727,38728,38729,38730,38731,38732,38733,38734,38735,38736,38737,38738,38739,38740,38741,38742,38743,38744,38745,38746,38747,38748,38749,38750,38751,38752,38753,38754,38755,38756,38757
 ,38758,38759,38760,38761,38762,38763,38764,38765,38766,38767,38768,38769,38770,38771,38772,38773,38774,38775,38776,38777,38778,38779,38780,38781,38782,38783,38784,38785,38786,38787,38788,38789,38790,38791,38792,38793,38794,38795,38796,38797,38798,38799,38800,38801,38802,38803,38804,38805,38806,38807,38808,38809,38810,38811,38812,38813,38814,38815,38816,38817,38818,38819,38820,38821,38822,38823,38824,38825,38826,38827,38828,38829,38830,38831,38832,38833,38834,38835,38836,38837,38838,38839,38840,38841,38842,38843,38844,38845,38846,38847,38848,38849,38850,38851,38852,38853,38854,38855,38856,38857,38858,38859,38860,38861,38862,38863,38864,38865,38866,38867,38868,38869,38870,38871,38872,38873,38874,38875,38876,38877,38878,38879,38880,38881,38882,38883,38884,38885,38886,38887,38888,38889,38890,38891,38892,38893,38894,38895,38896,38897,38898,38899,38900,38901,38902,38903,38904,38905,38906,38907,38908,38909,38910,38911,38912,38913,38914,38915,38916,38917,38918,38919,38920,38921,38922,38923,
 38924,38925,38926,38927,38928,38929,38930,38931,38932,38933,38934,38935,38936,38937,38938,38939,38940,38941,38942,38943,38944,38945,38946,38947,38948,38949,38950,38951,38952,38953,38954,38955,38956,38957,38958,38959,38960,38961,38962,38963,38964,38965,38966,38967,38968,38969,38970,38971,38972,38973,38974,38975,38976,38977,38978,38979,38980,38981,38982,38983,38984,38985,38986,38987,38988,38989,38990,38991,38992,38993,38994,38995,38996,38997,38998,38999,39000,39001,39002,39003,39004,39005,39006,39007,39008,39009,39010,39011,39012,39013,39014,39015,39016,39017,39018,39019,39020,39021,39022,39023,39024,39025,39026,39027,39028,39029,39030,39031,39032,39033,39034,39035,39036,39037,39038,39039,39040,39041,39042,39043,39044,39045,39046,39047,39048,39049,39050,39051,39052,39053,39054,39055,39056,39057,39058,39059,39060,39061,39062,39063,39064,39065,39066,39067,39068,39069,39070,39071,39072,39073,39074,39075,39076,39077,39078,39079,39080,39081,39082,39083,39084,39085,39086,39087,39088,39089,3
 9090,39091,39092,39093,39094,39095,39096,39097,39098,39099,39100,39101,39102,39103,39104,39105,39106,39107,39108,39109,39110,39111,39112,39113,39114,39115,39116,39117,39118,39119,39120,39121,39122,39123,39124,39125,39126,39127,39128,39129,39130,39131,39132,39133,39134,39135,39136,39137,39138,39139,39140,39141,39142,39143,39144,39145,39146,39147,39148,39149,39150,39151,39152,39153,39154,39155,39156,39157,39158,39159,39160,39161,39162,39163,39164,39165,39166,39167,39168,39169,39170,39171,39172,39173,39174,39175,39176,39177,39178,39179,39180,39181,39182,39183,39184,39185,39186,39187,39188,39189,39190,39191,39192,39193,39194,39195,39196,39197,39198,39199,39200,39201,39202,39203,39204,39205,39206,39207,39208,39209,39210,39211,39212,39213,39214,39215,39216,39217,39218,39219,39220,39221,39222,39223,39224,39225,39226,39227,39228,39229,39230,39231,39232,39233,39234,39235,39236,39237,39238,39239,39240,39241,39242,39243,39244,39245,39246,39247,39248,39249,39250,39251,39252,39253,39254,39255,39
 256,39257,39258,39259,39260,39261,39262,39263,39264,39265,39266,39267,39268,39269,39270,39271,39272,39273,39274,39275,39276,39277,39278,39279,39280,39281,39282,39283,39284,39285,39286,39287,39288,39289,39290,39291,39292,39293,39294,39295,39296,39297,39298,39299,39300,39301,39302,39303,39304,39305,39306,39307,39308,39309,39310,39311,39312,39313,39314,39315,39316,39317,39318,39319,39320,39321,39322,39323,39324,39325,39326,39327,39328,39329,39330,39331,39332,39333,39334,39335,39336,39337,39338,39339,39340,39341,39342,39343,39344,39345,39346,39347,39348,39349,39350,39351,39352,39353,39354,39355,39356,39357,39358,39359,39360,39361,39362,39363,39364,39365,39366,39367,39368,39369,39370,39371,39372,39373,39374,39375,39376,39377,39378,39379,39380,39381,39382,39383,39384,39385,39386,39387,39388,39389,39390,39391,39392,39393,39394,39395,39396,39397,39398,39399,39400,39401,39402,39403,39404,39405,39406,39407,39408,39409,39410,39411,39412,39413,39414,39415,39416,39417,39418,39419,39420,39421,394
 22,39423,39424,39425,39426,39427,39428,39429,39430,39431,39432,39433,39434,39435,39436,39437,39438,39439,39440,39441,39442,39443,39444,39445,39446,39447,39448,39449,39450,39451,39452,39453,39454,39455,39456,39457,39458,39459,39460,39461,39462,39463,39464,39465,39466,39467,39468,39469,39470,39471,39472,39473,39474,39475,39476,39477,39478,39479,39480,39481,39482,39483,39484,39485,39486,39487,39488,39489,39490,39491,39492,39493,39494,39495,39496,39497,39498,39499,39500,39501,39502,39503,39504,39505,39506,39507,39508,39509,39510,39511,39512,39513,39514,39515,39516,39517,39518,39519,39520,39521,39522,39523,39524,39525,39526,39527,39528,39529,39530,39531,39532,39533,39534,39535,39536,39537,39538,39539,39540,39541,39542,39543,39544,39545,39546,39547,39548,39549,39550,39551,39552,39553,39554,39555,39556,39557,39558,39559,39560,39561,39562,39563,39564,39565,39566,39567,39568,39569,39570,39571,39572,39573,39574,39575,39576,39577,39578,39579,39580,39581,39582,39583,39584,39585,39586,39587,3958
 8,39589,39590,39591,39592,39593,39594,39595,39596,39597,39598,39599,39600,39601,39602,39603,39604,39605,39606,39607,39608,39609,39610,39611,39612,39613,39614,39615,39616,39617,39618,39619,39620,39621,39622,39623,39624,39625,39626,39627,39628,39629,39630,39631,39632,39633,39634,39635,39636,39637,39638,39639,39640,39641,39642,39643,39644,39645,39646,39647,39648,39649,39650,39651,39652,39653,39654,39655,39656,39657,39658,39659,39660,39661,39662,39663,39664,39665,39666,39667,39668,39669,39670,39671,39672,39673,39674,39675,39676,39677,39678,39679,39680,39681,39682,39683,39684,39685,39686,39687,39688,39689,39690,39691,39692,39693,39694,39695,39696,39697,39698,39699,39700,39701,39702,39703,39704,39705,39706,39707,39708,39709,39710,39711,39712,39713,39714,39715,39716,39717,39718,39719,39720,39721,39722,39723,39724,39725,39726,39727,39728,39729,39730,39731,39732,39733,39734,39735,39736,39737,39738,39739,39740,39741,39742,39743,39744,39745,39746,39747,39748,39749,39750,39751,39752,39753,39754
 ,39755,39756,39757,39758,39759,39760,39761,39762,39763,39764,39765,39766,39767,39768,39769,39770,39771,39772,39773,39774,39775,39776,39777,39778,39779,39780,39781,39782,39783,39784,39785,39786,39787,39788,39789,39790,39791,39792,39793,39794,39795,39796,39797,39798,39799,39800,39801,39802,39803,39804,39805,39806,39807,39808,39809,39810,39811,39812,39813,39814,39815,39816,39817,39818,39819,39820,39821,39822,39823,39824,39825,39826,39827,39828,39829,39830,39831,39832,39833,39834,39835,39836,39837,39838,39839,39840,39841,39842,39843,39844,39845,39846,39847,39848,39849,39850,39851,39852,39853,39854,39855,39856,39857,39858,39859,39860,39861,39862,39863,39864,39865,39866,39867,39868,39869,39870,39871,39872,39873,39874,39875,39876,39877,39878,39879,39880,39881,39882,39883,39884,39885,39886,39887,39888,39889,39890,39891,39892,39893,39894,39895,39896,39897,39898,39899,39900,39901,39902,39903,39904,39905,39906,39907,39908,39909,39910,39911,39912,39913,39914,39915,39916,39917,39918,39919,39920,
 39921,39922,39923,39924,39925,39926,39927,39928,39929,39930,39931,39932,39933,39934,39935,39936,39937,39938,39939,39940,39941,39942,39943,39944,39945,39946,39947,39948,39949,39950,39951,39952,39953,39954,39955,39956,39957,39958,39959,39960,39961,39962,39963,39964,39965,39966,39967,39968,39969,39970,39971,39972,39973,39974,39975,39976,39977,39978,39979,39980,39981,39982,39983,39984,39985,39986,39987,39988,39989,39990,39991,39992,39993,39994,39995,39996,39997,39998,39999,40000,40001,40002,40003,40004,40005,40006,40007,40008,40009,40010,40011,40012,40013,40014,40015,40016,40017,40018,40019,40020,40021,40022,40023,40024,40025,40026,40027,40028,40029,40030,40031,40032,40033,40034,40035,40036,40037,40038,40039,40040,40041,40042,40043,40044,40045,40046,40047,40048,40049,40050,40051,40052,40053,40054,40055,40056,40057,40058,40059,40060,40061,40062,40063,40064,40065,40066,40067,40068,40069,40070,40071,40072,40073,40074,40075,40076,40077,40078,40079,40080,40081,40082,40083,40084,40085,40086,4
 0087,40088,40089,40090,40091,40092,40093,40094,40095,40096,40097,40098,40099,40100,40101,40102,40103,40104,40105,40106,40107,40108,40109,40110,40111,40112,40113,40114,40115,40116,40117,40118,40119,40120,40121,40122,40123,40124,40125,40126,40127,40128,40129,40130,40131,40132,40133,40134,40135,40136,40137,40138,40139,40140,40141,40142,40143,40144,40145,40146,40147,40148,40149,40150,40151,40152,40153,40154,40155,40156,40157,40158,40159,40160,40161,40162,40163,40164,40165,40166,40167,40168,40169,40170,40171,40172,40173,40174,40175,40176,40177,40178,40179,40180,40181,40182,40183,40184,40185,40186,40187,40188,40189,40190,40191,40192,40193,40194,40195,40196,40197,40198,40199,40200,40201,40202,40203,40204,40205,40206,40207,40208,40209,40210,40211,40212,40213,40214,40215,40216,40217,40218,40219,40220,40221,40222,40223,40224,40225,40226,40227,40228,40229,40230,40231,40232,40233,40234,40235,40236,40237,40238,40239,40240,40241,40242,40243,40244,40245,40246,40247,40248,40249,40250,40251,40252,40
 253,40254,40255,40256,40257,40258,40259,40260,40261,40262,40263,40264,40265,40266,40267,40268,40269,40270,40271,40272,40273,40274,40275,40276,40277,40278,40279,40280,40281,40282,40283,40284,40285,40286,40287,40288,40289,40290,40291,40292,40293,40294,40295,40296,40297,40298,40299,40300,40301,40302,40303,40304,40305,40306,40307,40308,40309,40310,40311,40312,40313,40314,40315,40316,40317,40318,40319,40320,40321,40322,40323,40324,40325,40326,40327,40328,40329,40330,40331,40332,40333,40334,40335,40336,40337,40338,40339,40340,40341,40342,40343,40344,40345,40346,40347,40348,40349,40350,40351,40352,40353,40354,40355,40356,40357,40358,40359,40360,40361,40362,40363,40364,40365,40366,40367,40368,40369,40370,40371,40372,40373,40374,40375,40376,40377,40378,40379,40380,40381,40382,40383,40384,40385,40386,40387,40388,40389,40390,40391,40392,40393,40394,40395,40396,40397,40398,40399,40400,40401,40402,40403,40404,40405,40406,40407,40408,40409,40410,40411,40412,40413,40414,40415,40416,40417,40418,404
 19,40420,40421,40422,40423,40424,40425,40426,40427,40428,40429,40430,40431,40432,40433,40434,40435,40436,40437,40438,40439,40440,40441,40442,40443,40444,40445,40446,40447,40448,40449,40450,40451,40452,40453,40454,40455,40456,40457,40458,40459,40460,40461,40462,40463,40464,40465,40466,40467,40468,40469,40470,40471,40472,40473,40474,40475,40476,40477,40478,40479,40480,40481,40482,40483,40484,40485,40486,40487,40488,40489,40490,40491,40492,40493,40494,40495,40496,40497,40498,40499,40500,40501,40502,40503,40504,40505,40506,40507,40508,40509,40510,40511,40512,40513,40514,40515,40516,40517,40518,40519,40520,40521,40522,40523,40524,40525,40526,40527,40528,40529,40530,40531,40532,40533,40534,40535,40536,40537,40538,40539,40540,40541,40542,40543,40544,40545,40546,40547,40548,40549,40550,40551,40552,40553,40554,40555,40556,40557,40558,40559,40560,40561,40562,40563,40564,40565,40566,40567,40568,40569,40570,40571,40572,40573,40574,40575,40576,40577,40578,40579,40580,40581,40582,40583,40584,4058
 5,40586,40587,40588,40589,40590,40591,40592,40593,40594,40595,40596,40597,40598,40599,40600,40601,40602,40603,40604,40605,40606,40607,40608,40609,40610,40611,40612,40613,40614,40615,40616,40617,40618,40619,40620,40621,40622,40623,40624,40625,40626,40627,40628,40629,40630,40631,40632,40633,40634,40635,40636,40637,40638,40639,40640,40641,40642,40643,40644,40645,40646,40647,40648,40649,40650,40651,40652,40653,40654,40655,40656,40657,40658,40659,40660,40661,40662,40663,40664,40665,40666,40667,40668,40669,40670,40671,40672,40673,40674,40675,40676,40677,40678,40679,40680,40681,40682,40683,40684,40685,40686,40687,40688,40689,40690,40691,40692,40693,40694,40695,40696,40697,40698,40699,40700,40701,40702,40703,40704,40705,40706,40707,40708,40709,40710,40711,40712,40713,40714,40715,40716,40717,40718,40719,40720,40721,40722,40723,40724,40725,40726,40727,40728,40729,40730,40731,40732,40733,40734,40735,40736,40737,40738,40739,40740,40741,40742,40743,40744,40745,40746,40747,40748,40749,40750,40751
 ,40752,40753,40754,40755,40756,40757,40758,40759,40760,40761,40762,40763,40764,40765,40766,40767,40768,40769,40770,40771,40772,40773,40774,40775,40776,40777,40778,40779,40780,40781,40782,40783,40784,40785,40786,40787,40788,40789,40790,40791,40792,40793,40794,40795,40796,40797,40798,40799,40800,40801,40802,40803,40804,40805,40806,40807,40808,40809,40810,40811,40812,40813,40814,40815,40816,40817,40818,40819,40820,40821,40822,40823,40824,40825,40826,40827,40828,40829,40830,40831,40832,40833,40834,40835,40836,40837,40838,40839,40840,40841,40842,40843,40844,40845,40846,40847,40848,40849,40850,40851,40852,40853,40854,40855,40856,40857,40858,40859,40860,40861,40862,40863,40864,40865,40866,40867,40868,40869,40870,40871,40872,40873,40874,40875,40876,40877,40878,40879,40880,40881,40882,40883,40884,40885,40886,40887,40888,40889,40890,40891,40892,40893,40894,40895,40896,40897,40898,40899,40900,40901,40902,40903,40904,40905,40906,40907,40908,40960,40961,40962,40963,40964,40965,40966,40967,40968,
 40969,40970,40971,40972,40973,40974,40975,40976,40977,40978,40979,40980,40981,40982,40983,40984,40985,40986,40987,40988,40989,40990,40991,40992,40993,40994,40995,40996,40997,40998,40999,41000,41001,41002,41003,41004,41005,41006,41007,41008,41009,41010,41011,41012,41013,41014,41015,41016,41017,41018,41019,41020,41021,41022,41023,41024,41025,41026,41027,41028,41029,41030,41031,41032,41033,41034,41035,41036,41037,41038,41039,41040,41041,41042,41043,41044,41045,41046,41047,41048,41049,41050,41051,41052,41053,41054,41055,41056,41057,41058,41059,41060,41061,41062,41063,41064,41065,41066,41067,41068,41069,41070,41071,41072,41073,41074,41075,41076,41077,41078,41079,41080,41081,41082,41083,41084,41085,41086,41087,41088,41089,41090,41091,41092,41093,41094,41095,41096,41097,41098,41099,41100,41101,41102,41103,41104,41105,41106,41107,41108,41109,41110,41111,41112,41113,41114,41115,41116,41117,41118,41119,41120,41121,41122,41123,41124,41125,41126,41127,41128,41129,41130,41131,41132,41133,41134,4
 1135,41136,41137,41138,41139,41140,41141,41142,41143,41144,41145,41146,41147,41148,41149,41150,41151,41152,41153,41154,41155,41156,41157,41158,41159,41160,41161,41162,41163,41164,41165,41166,41167,41168,41169,41170,41171,41172,41173,41174,41175,41176,41177,41178,41179,41180,41181,41182,41183,41184,41185,41186,41187,41188,41189,41190,41191,41192,41193,41194,41195,41196,41197,41198,41199,41200,41201,41202,41203,41204,41205,41206,41207,41208,41209,41210,41211,41212,41213,41214,41215,41216,41217,41218,41219,41220,41221,41222,41223,41224,41225,41226,41227,41228,41229,41230,41231,41232,41233,41234,41235,41236,41237,41238,41239,41240,41241,41242,41243,41244,41245,41246,41247,41248,41249,41250,41251,41252,41253,41254,41255,41256,41257,41258,41259,41260,41261,41262,41263,41264,41265,41266,41267,41268,41269,41270,41271,41272,41273,41274,41275,41276,41277,41278,41279,41280,41281,41282,41283,41284,41285,41286,41287,41288,41289,41290,41291,41292,41293,41294,41295,41296,41297,41298,41299,41300,41
 301,41302,41303,41304,41305,41306,41307,41308,41309,41310,41311,41312,41313,41314,41315,41316,41317,41318,41319,41320,41321,41322,41323,41324,41325,41326,41327,41328,41329,41330,41331,41332,41333,41334,41335,41336,41337,41338,41339,41340,41341,41342,41343,41344,41345,41346,41347,41348,41349,41350,41351,41352,41353,41354,41355,41356,41357,41358,41359,41360,41361,41362,41363,41364,41365,41366,41367,41368,41369,41370,41371,41372,41373,41374,41375,41376,41377,41378,41379,41380,41381,41382,41383,41384,41385,41386,41387,41388,41389,41390,41391,41392,41393,41394,41395,41396,41397,41398,41399,41400,41401,41402,41403,41404,41405,41406,41407,41408,41409,41410,41411,41412,41413,41414,41415,41416,41417,41418,41419,41420,41421,41422,41423,41424,41425,41426,41427,41428,41429,41430,41431,41432,41433,41434,41435,41436,41437,41438,41439,41440,41441,41442,41443,41444,41445,41446,41447,41448,41449,41450,41451,41452,41453,41454,41455,41456,41457,41458,41459,41460,41461,41462,41463,41464,41465,41466,414
 67,41468,41469,41470,41471,41472,41473,41474,41475,41476,41477,41478,41479,41480,41481,41482,41483,41484,41485,41486,41487,41488,41489,41490,41491,41492,41493,41494,41495,41496,41497,41498,41499,41500,41501,41502,41503,41504,41505,41506,41507,41508,41509,41510,41511,41512,41513,41514,41515,41516,41517,41518,41519,41520,41521,41522,41523,41524,41525,41526,41527,41528,41529,41530,41531,41532,41533,41534,41535,41536,41537,41538,41539,41540,41541,41542,41543,41544,41545,41546,41547,41548,41549,41550,41551,41552,41553,41554,41555,41556,41557,41558,41559,41560,41561,41562,41563,41564,41565,41566,41567,41568,41569,41570,41571,41572,41573,41574,41575,41576,41577,41578,41579,41580,41581,41582,41583,41584,41585,41586,41587,41588,41589,41590,41591,41592,41593,41594,41595,41596,41597,41598,41599,41600,41601,41602,41603,41604,41605,41606,41607,41608,41609,41610,41611,41612,41613,41614,41615,41616,41617,41618,41619,41620,41621,41622,41623,41624,41625,41626,41627,41628,41629,41630,41631,41632,4163
 3,41634,41635,41636,41637,41638,41639,41640,41641,41642,41643,41644,41645,41646,41647,41648,41649,41650,41651,41652,41653,41654,41655,41656,41657,41658,41659,41660,41661,41662,41663,41664,41665,41666,41667,41668,41669,41670,41671,41672,41673,41674,41675,41676,41677,41678,41679,41680,41681,41682,41683,41684,41685,41686,41687,41688,41689,41690,41691,41692,41693,41694,41695,41696,41697,41698,41699,41700,41701,41702,41703,41704,41705,41706,41707,41708,41709,41710,41711,41712,41713,41714,41715,41716,41717,41718,41719,41720,41721,41722,41723,41724,41725,41726,41727,41728,41729,41730,41731,41732,41733,41734,41735,41736,41737,41738,41739,41740,41741,41742,41743,41744,41745,41746,41747,41748,41749,41750,41751,41752,41753,41754,41755,41756,41757,41758,41759,41760,41761,41762,41763,41764,41765,41766,41767,41768,41769,41770,41771,41772,41773,41774,41775,41776,41777,41778,41779,41780,41781,41782,41783,41784,41785,41786,41787,41788,41789,41790,41791,41792,41793,41794,41795,41796,41797,41798,41799
 ,41800,41801,41802,41803,41804,41805,41806,41807,41808,41809,41810,41811,41812,41813,41814,41815,41816,41817,41818,41819,41820,41821,41822,41823,41824,41825,41826,41827,41828,41829,41830,41831,41832,41833,41834,41835,41836,41837,41838,41839,41840,41841,41842,41843,41844,41845,41846,41847,41848,41849,41850,41851,41852,41853,41854,41855,41856,41857,41858,41859,41860,41861,41862,41863,41864,41865,41866,41867,41868,41869,41870,41871,41872,41873,41874,41875,41876,41877,41878,41879,41880,41881,41882,41883,41884,41885,41886,41887,41888,41889,41890,41891,41892,41893,41894,41895,41896,41897,41898,41899,41900,41901,41902,41903,41904,41905,41906,41907,41908,41909,41910,41911,41912,41913,41914,41915,41916,41917,41918,41919,41920,41921,41922,41923,41924,41925,41926,41927,41928,41929,41930,41931,41932,41933,41934,41935,41936,41937,41938,41939,41940,41941,41942,41943,41944,41945,41946,41947,41948,41949,41950,41951,41952,41953,41954,41955,41956,41957,41958,41959,41960,41961,41962,41963,41964,41965,
 41966,41967,41968,41969,41970,41971,41972,41973,41974,41975,41976,41977,41978,41979,41980,41981,41982,41983,41984,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,41997,41998,41999,42000,42001,42002,42003,42004,42005,42006,42007,42008,42009,42010,42011,42012,42013,42014,42015,42016,42017,42018,42019,42020,42021,42022,42023,42024,42025,42026,42027,42028,42029,42030,42031,42032,42033,42034,42035,42036,42037,42038,42039,42040,42041,42042,42043,42044,42045,42046,42047,42048,42049,42050,42051,42052,42053,42054,42055,42056,42057,42058,42059,42060,42061,42062,42063,42064,42065,42066,42067,42068,42069,42070,42071,42072,42073,42074,42075,42076,42077,42078,42079,42080,42081,42082,42083,42084,42085,42086,42087,42088,42089,42090,42091,42092,42093,42094,42095,42096,42097,42098,42099,42100,42101,42102,42103,42104,42105,42106,42107,42108,42109,42110,42111,42112,42113,42114,42115,42116,42117,42118,42119,42120,42121,42122,42123,42124,42192,42193,42194,42195,42196,42197,42198,4
 2199,42200,42201,42202,42203,42204,42205,42206,42207,42208,42209,42210,42211,42212,42213,42214,42215,42216,42217,42218,42219,42220,42221,42222,42223,42224,42225,42226,42227,42228,42229,42230,42231,42232,42233,42234,42235,42236,42237,42240,42241,42242,42243,42244,42245,42246,42247,42248,42249,42250,42251,42252,42253,42254,42255,42256,42257,42258,42259,42260,42261,42262,42263,42264,42265,42266,42267,42268,42269,42270,42271,42272,42273,42274,42275,42276,42277,42278,42279,42280,42281,42282,42283,42284,42285,42286,42287,42288,42289,42290,42291,42292,42293,42294,42295,42296,42297,42298,42299,42300,42301,42302,42303,42304,42305,42306,42307,42308,42309,42310,42311,42312,42313,42314,42315,42316,42317,42318,42319,42320,42321,42322,42323,42324,42325,42326,42327,42328,42329,42330,42331,42332,42333,42334,42335,42336,42337,42338,42339,42340,42341,42342,42343,42344,42345,42346,42347,42348,42349,42350,42351,42352,42353,42354,42355,42356,42357,42358,42359,42360,42361,42362,42363,42364,42365,42366,42
 367,42368,42369,42370,42371,42372,42373,42374,42375,42376,42377,42378,42379,42380,42381,42382,42383,42384,42385,42386,42387,42388,42389,42390,42391,42392,42393,42394,42395,42396,42397,42398,42399,42400,42401,42402,42403,42404,42405,42406,42407,42408,42409,42410,42411,42412,42413,42414,42415,42416,42417,42418,42419,42420,42421,42422,42423,42424,42425,42426,42427,42428,42429,42430,42431,42432,42433,42434,42435,42436,42437,42438,42439,42440,42441,42442,42443,42444,42445,42446,42447,42448,42449,42450,42451,42452,42453,42454,42455,42456,42457,42458,42459,42460,42461,42462,42463,42464,42465,42466,42467,42468,42469,42470,42471,42472,42473,42474,42475,42476,42477,42478,42479,42480,42481,42482,42483,42484,42485,42486,42487,42488,42489,42490,42491,42492,42493,42494,42495,42496,42497,42498,42499,42500,42501,42502,42503,42504,42505,42506,42507,42508,42512,42513,42514,42515,42516,42517,42518,42519,42520,42521,42522,42523,42524,42525,42526,42527,42538,42539,42560,42561,42562,42563,42564,42565,425
 66,42567,42568,42569,42570,42571,42572,42573,42574,42575,42576,42577,42578,42579,42580,42581,42582,42583,42584,42585,42586,42587,42588,42589,42590,42591,42592,42593,42594,42595,42596,42597,42598,42599,42600,42601,42602,42603,42604,42605,42606,42623,42624,42625,42626,42627,42628,42629,42630,42631,42632,42633,42634,42635,42636,42637,42638,42639,42640,42641,42642,42643,42644,42645,42646,42647,42656,42657,42658,42659,42660,42661,42662,42663,42664,42665,42666,42667,42668,42669,42670,42671,42672,42673,42674,42675,42676,42677,42678,42679,42680,42681,42682,42683,42684,42685,42686,42687,42688,42689,42690,42691,42692,42693,42694,42695,42696,42697,42698,42699,42700,42701,42702,42703,42704,42705,42706,42707,42708,42709,42710,42711,42712,42713,42714,42715,42716,42717,42718,42719,42720,42721,42722,42723,42724,42725,42726,42727,42728,42729,42730,42731,42732,42733,42734,42735,42775,42776,42777,42778,42779,42780,42781,42782,42783,42786,42787,42788,42789,42790,42791,42792,42793,42794,42795,42796,4279
 7,42798,42799,42800,42801,42802,42803,42804,42805,42806,42807,42808,42809,42810,42811,42812,42813,42814,42815,42816,42817,42818,42819,42820,42821,42822,42823,42824,42825,42826,42827,42828,42829,42830,42831,42832,42833,42834,42835,42836,42837,42838,42839,42840,42841,42842,42843,42844,42845,42846,42847,42848,42849,42850,42851,42852,42853,42854,42855,42856,42857,42858,42859,42860,42861,42862,42863,42864,42865,42866,42867,42868,42869,42870,42871,42872,42873,42874,42875,42876,42877,42878,42879,42880,42881,42882,42883,42884,42885,42886,42887,42888,42891,42892,42893,42894,42896,42897,42898,42899,42912,42913,42914,42915,42916,42917,42918,42919,42920,42921,42922,43000,43001,43002,43003,43004,43005,43006,43007,43008,43009,43011,43012,43013,43015,43016,43017,43018,43020,43021,43022,43023,43024,43025,43026,43027,43028,43029,43030,43031,43032,43033,43034,43035,43036,43037,43038,43039,43040,43041,43042,43072,43073,43074,43075,43076,43077,43078,43079,43080,43081,43082,43083,43084,43085,43086,43087
 ,43088,43089,43090,43091,43092,43093,43094,43095,43096,43097,43098,43099,43100,43101,43102,43103,43104,43105,43106,43107,43108,43109,43110,43111,43112,43113,43114,43115,43116,43117,43118,43119,43120,43121,43122,43123,43138,43139,43140,43141,43142,43143,43144,43145,43146,43147,43148,43149,43150,43151,43152,43153,43154,43155,43156,43157,43158,43159,43160,43161,43162,43163,43164,43165,43166,43167,43168,43169,43170,43171,43172,43173,43174,43175,43176,43177,43178,43179,43180,43181,43182,43183,43184,43185,43186,43187,43250,43251,43252,43253,43254,43255,43259,43274,43275,43276,43277,43278,43279,43280,43281,43282,43283,43284,43285,43286,43287,43288,43289,43290,43291,43292,43293,43294,43295,43296,43297,43298,43299,43300,43301,43312,43313,43314,43315,43316,43317,43318,43319,43320,43321,43322,43323,43324,43325,43326,43327,43328,43329,43330,43331,43332,43333,43334,43360,43361,43362,43363,43364,43365,43366,43367,43368,43369,43370,43371,43372,43373,43374,43375,43376,43377,43378,43379,43380,43381,
 43382,43383,43384,43385,43386,43387,43388,43396,43397,43398,43399,43400,43401,43402,43403,43404,43405,43406,43407,43408,43409,43410,43411,43412,43413,43414,43415,43416,43417,43418,43419,43420,43421,43422,43423,43424,43425,43426,43427,43428,43429,43430,43431,43432,43433,43434,43435,43436,43437,43438,43439,43440,43441,43442,43471,43520,43521,43522,43523,43524,43525,43526,43527,43528,43529,43530,43531,43532,43533,43534,43535,43536,43537,43538,43539,43540,43541,43542,43543,43544,43545,43546,43547,43548,43549,43550,43551,43552,43553,43554,43555,43556,43557,43558,43559,43560,43584,43585,43586,43588,43589,43590,43591,43592,43593,43594,43595,43616,43617,43618,43619,43620,43621,43622,43623,43624,43625,43626,43627,43628,43629,43630,43631,43632,43633,43634,43635,43636,43637,43638,43642,43648,43649,43650,43651,43652,43653,43654,43655,43656,43657,43658,43659,43660,43661,43662,43663,43664,43665,43666,43667,43668,43669,43670,43671,43672,43673,43674,43675,43676,43677,43678,43679,43680,43681,43682,4
 3683,43684,43685,43686,43687,43688,43689,43690,43691,43692,43693,43694,43695,43697,43701,43702,43705,43706,43707,43708,43709,43712,43714,43739,43740,43741,43744,43745,43746,43747,43748,43749,43750,43751,43752,43753,43754,43762,43763,43764,43777,43778,43779,43780,43781,43782,43785,43786,43787,43788,43789,43790,43793,43794,43795,43796,43797,43798,43808,43809,43810,43811,43812,43813,43814,43816,43817,43818,43819,43820,43821,43822,43968,43969,43970,43971,43972,43973,43974,43975,43976,43977,43978,43979,43980,43981,43982,43983,43984,43985,43986,43987,43988,43989,43990,43991,43992,43993,43994,43995,43996,43997,43998,43999,44000,44001,44002,44032,44033,44034,44035,44036,44037,44038,44039,44040,44041,44042,44043,44044,44045,44046,44047,44048,44049,44050,44051,44052,44053,44054,44055,44056,44057,44058,44059,44060,44061,44062,44063,44064,44065,44066,44067,44068,44069,44070,44071,44072,44073,44074,44075,44076,44077,44078,44079,44080,44081,44082,44083,44084,44085,44086,44087,44088,44089,44090,44
 091,44092,44093,44094,44095,44096,44097,44098,44099,44100,44101,44102,44103,44104,44105,44106,44107,44108,44109,44110,44111,44112,44113,44114,44115,44116,44117,44118,44119,44120,44121,44122,44123,44124,44125,44126,44127,44128,44129,44130,44131,44132,44133,44134,44135,44136,44137,44138,44139,44140,44141,44142,44143,44144,44145,44146,44147,44148,44149,44150,44151,44152,44153,44154,44155,44156,44157,44158,44159,44160,44161,44162,44163,44164,44165,44166,44167,44168,44169,44170,44171,44172,44173,44174,44175,44176,44177,44178,44179,44180,44181,44182,44183,44184,44185,44186,44187,44188,44189,44190,44191,44192,44193,44194,44195,44196,44197,44198,44199,44200,44201,44202,44203,44204,44205,44206,44207,44208,44209,44210,44211,44212,44213,44214,44215,44216,44217,44218,44219,44220,44221,44222,44223,44224,44225,44226,44227,44228,44229,44230,44231,44232,44233,44234,44235,44236,44237,44238,44239,44240,44241,44242,44243,44244,44245,44246,44247,44248,44249,44250,44251,44252,44253,44254,44255,44256,442
 57,44258,44259,44260,44261,44262,44263,44264,44265,44266,44267,44268,44269,44270,44271,44272,44273,44274,44275,44276,44277,44278,44279,44280,44281,44282,44283,44284,44285,44286,44287,44288,44289,44290,44291,44292,44293,44294,44295,44296,44297,44298,44299,44300,44301,44302,44303,44304,44305,44306,44307,44308,44309,44310,44311,44312,44313,44314,44315,44316,44317,44318,44319,44320,44321,44322,44323,44324,44325,44326,44327,44328,44329,44330,44331,44332,44333,44334,44335,44336,44337,44338,44339,44340,44341,44342,44343,44344,44345,44346,44347,44348,44349,44350,44351,44352,44353,44354,44355,44356,44357,44358,44359,44360,44361,44362,44363,44364,44365,44366,44367,44368,44369,44370,44371,44372,44373,44374,44375,44376,44377,44378,44379,44380,44381,44382,44383,44384,44385,44386,44387,44388,44389,44390,44391,44392,44393,44394,44395,44396,44397,44398,44399,44400,44401,44402,44403,44404,44405,44406,44407,44408,44409,44410,44411,44412,44413,44414,44415,44416,44417,44418,44419,44420,44421,44422,4442
 3,44424,44425,44426,44427,44428,44429,44430,44431,44432,44433,44434,44435,44436,44437,44438,44439,44440,44441,44442,44443,44444,44445,44446,44447,44448,44449,44450,44451,44452,44453,44454,44455,44456,44457,44458,44459,44460,44461,44462,44463,44464,44465,44466,44467,44468,44469,44470,44471,44472,44473,44474,44475,44476,44477,44478,44479,44480,44481,44482,44483,44484,44485,44486,44487,44488,44489,44490,44491,44492,44493,44494,44495,44496,44497,44498,44499,44500,44501,44502,44503,44504,44505,44506,44507,44508,44509,44510,44511,44512,44513,44514,44515,44516,44517,44518,44519,44520,44521,44522,44523,44524,44525,44526,44527,44528,44529,44530,44531,44532,44533,44534,44535,44536,44537,44538,44539,44540,44541,44542,44543,44544,44545,44546,44547,44548,44549,44550,44551,44552,44553,44554,44555,44556,44557,44558,44559,44560,44561,44562,44563,44564,44565,44566,44567,44568,44569,44570,44571,44572,44573,44574,44575,44576,44577,44578,44579,44580,44581,44582,44583,44584,44585,44586,44587,44588,44589
 ,44590,44591,44592,44593,44594,44595,44596,44597,44598,44599,44600,44601,44602,44603,44604,44605,44606,44607,44608,44609,44610,44611,44612,44613,44614,44615,44616,44617,44618,44619,44620,44621,44622,44623,44624,44625,44626,44627,44628,44629,44630,44631,44632,44633,44634,44635,44636,44637,44638,44639,44640,44641,44642,44643,44644,44645,44646,44647,44648,44649,44650,44651,44652,44653,44654,44655,44656,44657,44658,44659,44660,44661,44662,44663,44664,44665,44666,44667,44668,44669,44670,44671,44672,44673,44674,44675,44676,44677,44678,44679,44680,44681,44682,44683,44684,44685,44686,44687,44688,44689,44690,44691,44692,44693,44694,44695,44696,44697,44698,44699,44700,44701,44702,44703,44704,44705,44706,44707,44708,44709,44710,44711,44712,44713,44714,44715,44716,44717,44718,44719,44720,44721,44722,44723,44724,44725,44726,44727,44728,44729,44730,44731,44732,44733,44734,44735,44736,44737,44738,44739,44740,44741,44742,44743,44744,44745,44746,44747,44748,44749,44750,44751,44752,44753,44754,44755,
 44756,44757,44758,44759,44760,44761,44762,44763,44764,44765,44766,44767,44768,44769,44770,44771,44772,44773,44774,44775,44776,44777,44778,44779,44780,44781,44782,44783,44784,44785,44786,44787,44788,44789,44790,44791,44792,44793,44794,44795,44796,44797,44798,44799,44800,44801,44802,44803,44804,44805,44806,44807,44808,44809,44810,44811,44812,44813,44814,44815,44816,44817,44818,44819,44820,44821,44822,44823,44824,44825,44826,44827,44828,44829,44830,44831,44832,44833,44834,44835,44836,44837,44838,44839,44840,44841,44842,44843,44844,44845,44846,44847,44848,44849,44850,44851,44852,44853,44854,44855,44856,44857,44858,44859,44860,44861,44862,44863,44864,44865,44866,44867,44868,44869,44870,44871,44872,44873,44874,44875,44876,44877,44878,44879,44880,44881,44882,44883,44884,44885,44886,44887,44888,44889,44890,44891,44892,44893,44894,44895,44896,44897,44898,44899,44900,44901,44902,44903,44904,44905,44906,44907,44908,44909,44910,44911,44912,44913,44914,44915,44916,44917,44918,44919,44920,44921,4
 4922,44923,44924,44925,44926,44927,44928,44929,44930,44931,44932,44933,44934,44935,44936,44937,44938,44939,44940,44941,44942,44943,44944,44945,44946,44947,44948,44949,44950,44951,44952,44953,44954,44955,44956,44957,44958,44959,44960,44961,44962,44963,44964,44965,44966,44967,44968,44969,44970,44971,44972,44973,44974,44975,44976,44977,44978,44979,44980,44981,44982,44983,44984,44985,44986,44987,44988,44989,44990,44991,44992,44993,44994,44995,44996,44997,44998,44999,45000,45001,45002,45003,45004,45005,45006,45007,45008,45009,45010,45011,45012,45013,45014,45015,45016,45017,45018,45019,45020,45021,45022,45023,45024,45025,45026,45027,45028,45029,45030,45031,45032,45033,45034,45035,45036,45037,45038,45039,45040,45041,45042,45043,45044,45045,45046,45047,45048,45049,45050,45051,45052,45053,45054,45055,45056,45057,45058,45059,45060,45061,45062,45063,45064,45065,45066,45067,45068,45069,45070,45071,45072,45073,45074,45075,45076,45077,45078,45079,45080,45081,45082,45083,45084,45085,45086,45087,45
 088,45089,45090,45091,45092,45093,45094,45095,45096,45097,45098,45099,45100,45101,45102,45103,45104,45105,45106,45107,45108,45109,45110,45111,45112,45113,45114,45115,45116,45117,45118,45119,45120,45121,45122,45123,45124,45125,45126,45127,45128,45129,45130,45131,45132,45133,45134,45135,45136,45137,45138,45139,45140,45141,45142,45143,45144,45145,45146,45147,45148,45149,45150,45151,45152,45153,45154,45155,45156,45157,45158,45159,45160,45161,45162,45163,45164,45165,45166,45167,45168,45169,45170,45171,45172,45173,45174,45175,45176,45177,45178,45179,45180,45181,45182,45183,45184,45185,45186,45187,45188,45189,45190,45191,45192,45193,45194,45195,45196,45197,45198,45199,45200,45201,45202,45203,45204,45205,45206,45207,45208,45209,45210,45211,45212,45213,45214,45215,45216,45217,45218,45219,45220,45221,45222,45223,45224,45225,45226,45227,45228,45229,45230,45231,45232,45233,45234,45235,45236,45237,45238,45239,45240,45241,45242,45243,45244,45245,45246,45247,45248,45249,45250,45251,45252,45253,452
 54,45255,45256,45257,45258,45259,45260,45261,45262,45263,45264,45265,45266,45267,45268,45269,45270,45271,45272,45273,45274,45275,45276,45277,45278,45279,45280,45281,45282,45283,45284,45285,45286,45287,45288,45289,45290,45291,45292,45293,45294,45295,45296,45297,45298,45299,45300,45301,45302,45303,45304,45305,45306,45307,45308,45309,45310,45311,45312,45313,45314,45315,45316,45317,45318,45319,45320,45321,45322,45323,45324,45325,45326,45327,45328,45329,45330,45331,45332,45333,45334,45335,45336,45337,45338,45339,45340,45341,45342,45343,45344,45345,45346,45347,45348,45349,45350,45351,45352,45353,45354,45355,45356,45357,45358,45359,45360,45361,45362,45363,45364,45365,45366,45367,45368,45369,45370,45371,45372,45373,45374,45375,45376,45377,45378,45379,45380,45381,45382,45383,45384,45385,45386,45387,45388,45389,45390,45391,45392,45393,45394,45395,45396,45397,45398,45399,45400,45401,45402,45403,45404,45405,45406,45407,45408,45409,45410,45411,45412,45413,45414,45415,45416,45417,45418,45419,4542
 0,45421,45422,45423,45424,45425,45426,45427,45428,45429,45430,45431,45432,45433,45434,45435,45436,45437,45438,45439,45440,45441,45442,45443,45444,45445,45446,45447,45448,45449,45450,45451,45452,45453,45454,45455,45456,45457,45458,45459,45460,45461,45462,45463,45464,45465,45466,45467,45468,45469,45470,45471,45472,45473,45474,45475,45476,45477,45478,45479,45480,45481,45482,45483,45484,45485,45486,45487,45488,45489,45490,45491,45492,45493,45494,45495,45496,45497,45498,45499,45500,45501,45502,45503,45504,45505,45506,45507,45508,45509,45510,45511,45512,45513,45514,45515,45516,45517,45518,45519,45520,45521,45522,45523,45524,45525,45526,45527,45528,45529,45530,45531,45532,45533,45534,45535,45536,45537,45538,45539,45540,45541,45542,45543,45544,45545,45546,45547,45548,45549,45550,45551,45552,45553,45554,45555,45556,45557,45558,45559,45560,45561,45562,45563,45564,45565,45566,45567,45568,45569,45570,45571,45572,45573,45574,45575,45576,45577,45578,45579,45580,45581,45582,45583,45584,45585,45586
 ,45587,45588,45589,45590,45591,45592,45593,45594,45595,45596,45597,45598,45599,45600,45601,45602,45603,45604,45605,45606,45607,45608,45609,45610,45611,45612,45613,45614,45615,45616,45617,45618,45619,45620,45621,45622,45623,45624,45625,45626,45627,45628,45629,45630,45631,45632,45633,45634,45635,45636,45637,45638,45639,45640,45641,45642,45643,45644,45645,45646,45647,45648,45649,45650,45651,45652,45653,45654,45655,45656,45657,45658,45659,45660,45661,45662,45663,45664,45665,45666,45667,45668,45669,45670,45671,45672,45673,45674,45675,45676,45677,45678,45679,45680,45681,45682,45683,45684,45685,45686,45687,45688,45689,45690,45691,45692,45693,45694,45695,45696,45697,45698,45699,45700,45701,45702,45703,45704,45705,45706,45707,45708,45709,45710,45711,45712,45713,45714,45715,45716,45717,45718,45719,45720,45721,45722,45723,45724,45725,45726,45727,45728,45729,45730,45731,45732,45733,45734,45735,45736,45737,45738,45739,45740,45741,45742,45743,45744,45745,45746,45747,45748,45749,45750,45751,45752,
 45753,45754,45755,45756,45757,45758,45759,45760,45761,45762,45763,45764,45765,45766,45767,45768,45769,45770,45771,45772,45773,45774,45775,45776,45777,45778,45779,45780,45781,45782,45783,45784,45785,45786,45787,45788,45789,45790,45791,45792,45793,45794,45795,45796,45797,45798,45799,45800,45801,45802,45803,45804,45805,45806,45807,45808,45809,45810,45811,45812,45813,45814,45815,45816,45817,45818,45819,45820,45821,45822,45823,45824,45825,45826,45827,45828,45829,45830,45831,45832,45833,45834,45835,45836,45837,45838,45839,45840,45841,45842,45843,45844,45845,45846,45847,45848,45849,45850,45851,45852,45853,45854,45855,45856,45857,45858,45859,45860,45861,45862,45863,45864,45865,45866,45867,45868,45869,45870,45871,45872,45873,45874,45875,45876,45877,45878,45879,45880,45881,45882,45883,45884,45885,45886,45887,45888,45889,45890,45891,45892,45893,45894,45895,45896,45897,45898,45899,45900,45901,45902,45903,45904,45905,45906,45907,45908,45909,45910,45911,45912,45913,45914,45915,45916,45917,45918,4
 5919,45920,45921,45922,45923,45924,45925,45926,45927,45928,45929,45930,45931,45932,45933,45934,45935,45936,45937,45938,45939,45940,45941,45942,45943,45944,45945,45946,45947,45948,45949,45950,45951,45952,45953,45954,45955,45956,45957,45958,45959,45960,45961,45962,45963,45964,45965,45966,45967,45968,45969,45970,45971,45972,45973,45974,45975,45976,45977,45978,45979,45980,45981,45982,45983,45984,45985,45986,45987,45988,45989,45990,45991,45992,45993,45994,45995,45996,45997,45998,45999,46000,46001,46002,46003,46004,46005,46006,46007,46008,46009,46010,46011,46012,46013,46014,46015,46016,46017,46018,46019,46020,46021,46022,46023,46024,46025,46026,46027,46028,46029,46030,46031,46032,46033,46034,46035,46036,46037,46038,46039,46040,46041,46042,46043,46044,46045,46046,46047,46048,46049,46050,46051,46052,46053,46054,46055,46056,46057,46058,46059,46060,46061,46062,46063,46064,46065,46066,46067,46068,46069,46070,46071,46072,46073,46074,46075,46076,46077,46078,46079,46080,46081,46082,46083,46084,46
 085,46086,46087,46088,46089,46090,46091,46092,46093,46094,46095,46096,46097,46098,46099,46100,46101,46102,46103,46104,46105,46106,46107,46108,46109,46110,46111,46112,46113,46114,46115,46116,46117,46118,46119,46120,46121,46122,46123,46124,46125,46126,46127,46128,46129,46130,46131,46132,46133,46134,46135,46136,46137,46138,46139,46140,46141,46142,46143,46144,46145,46146,46147,46148,46149,46150,46151,46152,46153,46154,46155,46156,46157,46158,46159,46160,46161,46162,46163,46164,46165,46166,46167,46168,46169,46170,46171,46172,46173,46174,46175,46176,46177,46178,46179,46180,46181,46182,46183,46184,46185,46186,46187,46188,46189,46190,46191,46192,46193,46194,46195,46196,46197,46198,46199,46200,46201,46202,46203,46204,46205,46206,46207,46208,46209,46210,46211,46212,46213,46214,46215,46216,46217,46218,46219,46220,46221,46222,46223,46224,46225,46226,46227,46228,46229,46230,46231,46232,46233,46234,46235,46236,46237,46238,46239,46240,46241,46242,46243,46244,46245,46246,46247,46248,46249,46250,462
 51,46252,46253,46254,46255,46256,46257,46258,46259,46260,46261,46262,46263,46264,46265,46266,46267,46268,46269,46270,46271,46272,46273,46274,46275,46276,46277,46278,46279,46280,46281,46282,46283,46284,46285,46286,46287,46288,46289,46290,46291,46292,46293,46294,46295,46296,46297,46298,46299,46300,46301,46302,46303,46304,46305,46306,46307,46308,46309,46310,46311,46312,46313,46314,46315,46316,46317,46318,46319,46320,46321,46322,46323,46324,46325,46326,46327,46328,46329,46330,46331,46332,46333,46334,46335,46336,46337,46338,46339,46340,46341,46342,46343,46344,46345,46346,46347,46348,46349,46350,46351,46352,46353,46354,46355,46356,46357,46358,46359,46360,46361,46362,46363,46364,46365,46366,46367,46368,46369,46370,46371,46372,46373,46374,46375,46376,46377,46378,46379,46380,46381,46382,46383,46384,46385,46386,46387,46388,46389,46390,46391,46392,46393,46394,46395,46396,46397,46398,46399,46400,46401,46402,46403,46404,46405,46406,46407,46408,46409,46410,46411,46412,46413,46414,46415,46416,4641
 7,46418,46419,46420,46421,46422,46423,46424,46425,46426,46427,46428,46429,46430,46431,46432,46433,46434,46435,46436,46437,46438,46439,46440,46441,46442,46443,46444,46445,46446,46447,46448,46449,46450,46451,46452,46453,46454,46455,46456,46457,46458,46459,46460,46461,46462,46463,46464,46465,46466,46467,46468,46469,46470,46471,46472,46473,46474,46475,46476,46477,46478,46479,46480,46481,46482,46483,46484,46485,46486,46487,46488,46489,46490,46491,46492,46493,46494,46495,46496,46497,46498,46499,46500,46501,46502,46503,46504,46505,46506,46507,46508,46509,46510,46511,46512,46513,46514,46515,46516,46517,46518,46519,46520,46521,46522,46523,46524,46525,46526,46527,46528,46529,46530,46531,46532,46533,46534,46535,46536,46537,46538,46539,46540,46541,46542,46543,46544,46545,46546,46547,46548,46549,46550,46551,46552,46553,46554,46555,46556,46557,46558,46559,46560,46561,46562,46563,46564,46565,46566,46567,46568,46569,46570,46571,46572,46573,46574,46575,46576,46577,46578,46579,46580,46581,46582,46583
 ,46584,46585,46586,46587,46588,46589,46590,46591,46592,46593,46594,46595,46596,46597,46598,46599,46600,46601,46602,46603,46604,46605,46606,46607,46608,46609,46610,46611,46612,46613,46614,46615,46616,46617,46618,46619,46620,46621,46622,46623,46624,46625,46626,46627,46628,46629,46630,46631,46632,46633,46634,46635,46636,46637,46638,46639,46640,46641,46642,46643,46644,46645,46646,46647,46648,46649,46650,46651,46652,46653,46654,46655,46656,46657,46658,46659,46660,46661,46662,46663,46664,46665,46666,46667,46668,46669,46670,46671,46672,46673,46674,46675,46676,46677,46678,46679,46680,46681,46682,46683,46684,46685,46686,46687,46688,46689,46690,46691,46692,46693,46694,46695,46696,46697,46698,46699,46700,46701,46702,46703,46704,46705,46706,46707,46708,46709,46710,46711,46712,46713,46714,46715,46716,46717,46718,46719,46720,46721,46722,46723,46724,46725,46726,46727,46728,46729,46730,46731,46732,46733,46734,46735,46736,46737,46738,46739,46740,46741,46742,46743,46744,46745,46746,46747,46748,46749,
 46750,46751,46752,46753,46754,46755,46756,46757,46758,46759,46760,46761,46762,46763,46764,46765,46766,46767,46768,46769,46770,46771,46772,46773,46774,46775,46776,46777,46778,46779,46780,46781,46782,46783,46784,46785,46786,46787,46788,46789,46790,46791,46792,46793,46794,46795,46796,46797,46798,46799,46800,46801,46802,46803,46804,46805,46806,46807,46808,46809,46810,46811,46812,46813,46814,46815,46816,46817,46818,46819,46820,46821,46822,46823,46824,46825,46826,46827,46828,46829,46830,46831,46832,46833,46834,46835,46836,46837,46838,46839,46840,46841,46842,46843,46844,46845,46846,46847,46848,46849,46850,46851,46852,46853,46854,46855,46856,46857,46858,46859,46860,46861,46862,46863,46864,46865,46866,46867,46868,46869,46870,46871,46872,46873,46874,46875,46876,46877,46878,46879,46880,46881,46882,46883,46884,46885,46886,46887,46888,46889,46890,46891,46892,46893,46894,46895,46896,46897,46898,46899,46900,46901,46902,46903,46904,46905,46906,46907,46908,46909,46910,46911,46912,46913,46914,46915,4
 6916,46917,46918,46919,46920,46921,46922,46923,46924,46925,46926,46927,46928,46929,46930,46931,46932,46933,46934,46935,46936,46937,46938,46939,46940,46941,46942,46943,46944,46945,46946,46947,46948,46949,46950,46951,46952,46953,46954,46955,46956,46957,46958,46959,46960,46961,46962,46963,46964,46965,46966,46967,46968,46969,46970,46971,46972,46973,46974,46975,46976,46977,46978,46979,46980,46981,46982,46983,46984,46985,46986,46987,46988,46989,46990,46991,46992,46993,46994,46995,46996,46997,46998,46999,47000,47001,47002,47003,47004,47005,47006,47007,47008,47009,47010,47011,47012,47013,47014,47015,47016,47017,47018,47019,47020,47021,47022,47023,47024,47025,47026,47027,47028,47029,47030,47031,47032,47033,47034,47035,47036,47037,47038,47039,47040,47041,47042,47043,47044,47045,47046,47047,47048,47049,47050,47051,47052,47053,47054,47055,47056,47057,47058,47059,47060,47061,47062,47063,47064,47065,47066,47067,47068,47069,47070,47071,47072,47073,47074,47075,47076,47077,47078,47079,47080,47081,47
 082,47083,47084,47085,47086,47087,47088,47089,47090,47091,47092,47093,47094,47095,47096,47097,47098,47099,47100,47101,47102,47103,47104,47105,47106,47107,47108,47109,47110,47111,47112,47113,47114,47115,47116,47117,47118,47119,47120,47121,47122,47123,47124,47125,47126,47127,47128,47129,47130,47131,47132,47133,47134,47135,47136,47137,47138,47139,47140,47141,47142,47143,47144,47145,47146,47147,47148,47149,47150,47151,47152,47153,47154,47155,47156,47157,47158,47159,47160,47161,47162,47163,47164,47165,47166,47167,47168,47169,47170,47171,47172,47173,47174,47175,47176,47177,47178,47179,47180,47181,47182,47183,47184,47185,47186,47187,47188,47189,47190,47191,47192,47193,47194,47195,47196,47197,47198,47199,47200,47201,47202,47203,47204,47205,47206,47207,47208,47209,47210,47211,47212,47213,47214,47215,47216,47217,47218,47219,47220,47221,47222,47223,47224,47225,47226,47227,47228,47229,47230,47231,47232,47233,47234,47235,47236,47237,47238,47239,47240,47241,47242,47243,47244,47245,47246,47247,472
 48,47249,47250,47251,47252,47253,47254,47255,47256,47257,47258,47259,47260,47261,47262,47263,47264,47265,47266,47267,47268,47269,47270,47271,47272,47273,47274,47275,47276,47277,47278,47279,47280,47281,47282,47283,47284,47285,47286,47287,47288,47289,47290,47291,47292,47293,47294,47295,47296,47297,47298,47299,47300,47301,47302,47303,47304,47305,47306,47307,47308,47309,47310,47311,47312,47313,47314,47315,47316,47317,47318,47319,47320,47321,47322,47323,47324,47325,47326,47327,47328,47329,47330,47331,47332,47333,47334,47335,47336,47337,47338,47339,47340,47341,47342,47343,47344,47345,47346,47347,47348,47349,47350,47351,47352,47353,47354,47355,47356,47357,47358,47359,47360,47361,47362,47363,47364,47365,47366,47367,47368,47369,47370,47371,47372,47373,47374,47375,47376,47377,47378,47379,47380,47381,47382,47383,47384,47385,47386,47387,47388,47389,47390,47391,47392,47393,47394,47395,47396,47397,47398,47399,47400,47401,47402,47403,47404,47405,47406,47407,47408,47409,47410,47411,47412,47413,4741
 4,47415,47416,47417,47418,47419,47420,47421,47422,47423,47424,47425,47426,47427,47428,47429,47430,47431,47432,47433,47434,47435,47436,47437,47438,47439,47440,47441,47442,47443,47444,47445,47446,47447,47448,47449,47450,47451,47452,47453,47454,47455,47456,47457,47458,47459,47460,47461,47462,47463,47464,47465,47466,47467,47468,47469,47470,47471,47472,47473,47474,47475,47476,47477,47478,47479,47480,47481,47482,47483,47484,47485,47486,47487,47488,47489,47490,47491,47492,47493,47494,47495,47496,47497,47498,47499,47500,47501,47502,47503,47504,47505,47506,47507,47508,47509,47510,47511,47512,47513,47514,47515,47516,47517,47518,47519,47520,47521,47522,47523,47524,47525,47526,47527,47528,47529,47530,47531,47532,47533,47534,47535,47536,47537,47538,47539,47540,47541,47542,47543,47544,47545,47546,47547,47548,47549,47550,47551,47552,47553,47554,47555,47556,47557,47558,47559,47560,47561,47562,47563,47564,47565,47566,47567,47568,47569,47570,47571,47572,47573,47574,47575,47576,47577,47578,47579,47580
 ,47581,47582,47583,47584,47585,47586,47587,47588,47589,47590,47591,47592,47593,47594,47595,47596,47597,47598,47599,47600,47601,47602,47603,47604,47605,47606,47607,47608,47609,47610,47611,47612,47613,47614,47615,47616,47617,47618,47619,47620,47621,47622,47623,47624,47625,47626,47627,47628,47629,47630,47631,47632,47633,47634,47635,47636,47637,47638,47639,47640,47641,47642,47643,47644,47645,47646,47647,47648,47649,47650,47651,47652,47653,47654,47655,47656,47657,47658,47659,47660,47661,47662,47663,47664,47665,47666,47667,47668,47669,47670,47671,47672,47673,47674,47675,47676,47677,47678,47679,47680,47681,47682,47683,47684,47685,47686,47687,47688,47689,47690,47691,47692,47693,47694,47695,47696,47697,47698,47699,47700,47701,47702,47703,47704,47705,47706,47707,47708,47709,47710,47711,47712,47713,47714,47715,47716,47717,47718,47719,47720,47721,47722,47723,47724,47725,47726,47727,47728,47729,47730,47731,47732,47733,47734,47735,47736,47737,47738,47739,47740,47741,47742,47743,47744,47745,47746,
 47747,47748,47749,47750,47751,47752,47753,47754,47755,47756,47757,47758,47759,47760,47761,47762,47763,47764,47765,47766,47767,47768,47769,47770,47771,47772,47773,47774,47775,47776,47777,47778,47779,47780,47781,47782,47783,47784,47785,47786,47787,47788,47789,47790,47791,47792,47793,47794,47795,47796,47797,47798,47799,47800,47801,47802,47803,47804,47805,47806,47807,47808,47809,47810,47811,47812,47813,47814,47815,47816,47817,47818,47819,47820,47821,47822,47823,47824,47825,47826,47827,47828,47829,47830,47831,47832,47833,47834,47835,47836,47837,47838,47839,47840,47841,47842,47843,47844,47845,47846,47847,47848,47849,47850,47851,47852,47853,47854,47855,47856,47857,47858,47859,47860,47861,47862,47863,47864,47865,47866,47867,47868,47869,47870,47871,47872,47873,47874,47875,47876,47877,47878,47879,47880,47881,47882,47883,47884,47885,47886,47887,47888,47889,47890,47891,47892,47893,47894,47895,47896,47897,47898,47899,47900,47901,47902,47903,47904,47905,47906,47907,47908,47909,47910,47911,47912,4
 7913,47914,47915,47916,47917,47918,47919,47920,47921,47922,47923,47924,47925,47926,47927,47928,47929,47930,47931,47932,47933,47934,47935,47936,47937,47938,47939,47940,47941,47942,47943,47944,47945,47946,47947,47948,47949,47950,47951,47952,47953,47954,47955,47956,47957,47958,47959,47960,47961,47962,47963,47964,47965,47966,47967,47968,47969,47970,47971,47972,47973,47974,47975,47976,47977,47978,47979,47980,47981,47982,47983,47984,47985,47986,47987,47988,47989,47990,47991,47992,47993,47994,47995,47996,47997,47998,47999,48000,48001,48002,48003,48004,48005,48006,48007,48008,48009,48010,48011,48012,48013,48014,48015,48016,48017,48018,48019,48020,48021,48022,48023,48024,48025,48026,48027,48028,48029,48030,48031,48032,48033,48034,48035,48036,48037,48038,48039,48040,48041,48042,48043,48044,48045,48046,48047,48048,48049,48050,48051,48052,48053,48054,48055,48056,48057,48058,48059,48060,48061,48062,48063,48064,48065,48066,48067,48068,48069,48070,48071,48072,48073,48074,48075,48076,48077,48078,48
 079,48080,48081,48082,48083,48084,48085,48086,48087,48088,48089,48090,48091,48092,48093,48094,48095,48096,48097,48098,48099,48100,48101,48102,48103,48104,48105,48106,48107,48108,48109,48110,48111,48112,48113,48114,48115,48116,48117,48118,48119,48120,48121,48122,48123,48124,48125,48126,48127,48128,48129,48130,48131,48132,48133,48134,48135,48136,48137,48138,48139,48140,48141,48142,48143,48144,48145,48146,48147,48148,48149,48150,48151,48152,48153,48154,48155,48156,48157,48158,48159,48160,48161,48162,48163,48164,48165,48166,48167,48168,48169,48170,48171,48172,48173,48174,48175,48176,48177,48178,48179,48180,48181,48182,48183,48184,48185,48186,48187,48188,48189,48190,48191,48192,48193,48194,48195,48196,48197,48198,48199,48200,48201,48202,48203,48204,48205,48206,48207,48208,48209,48210,48211,48212,48213,48214,48215,48216,48217,48218,48219,48220,48221,48222,48223,48224,48225,48226,48227,48228,48229,48230,48231,48232,48233,48234,48235,48236,48237,48238,48239,48240,48241,48242,48243,48244,482
 45,48246,48247,48248,48249,48250,48251,48252,48253,48254,48255,48256,48257,48258,48259,48260,48261,48262,48263,48264,48265,48266,48267,48268,48269,48270,48271,48272,48273,48274,48275,48276,48277,48278,48279,48280,48281,48282,48283,48284,48285,48286,48287,48288,48289,48290,48291,48292,48293,48294,48295,48296,48297,48298,48299,48300,48301,48302,48303,48304,48305,48306,48307,48308,48309,48310,48311,48312,48313,48314,48315,48316,48317,48318,48319,48320,48321,48322,48323,48324,48325,48326,48327,48328,48329,48330,48331,48332,48333,48334,48335,48336,48337,48338,48339,48340,48341,48342,48343,48344,48345,48346,48347,48348,48349,48350,48351,48352,48353,48354,48355,48356,48357,48358,48359,48360,48361,48362,48363,48364,48365,48366,48367,48368,48369,48370,48371,48372,48373,48374,48375,48376,48377,48378,48379,48380,48381,48382,48383,48384,48385,48386,48387,48388,48389,48390,48391,48392,48393,48394,48395,48396,48397,48398,48399,48400,48401,48402,48403,48404,48405,48406,48407,48408,48409,48410,4841
 1,48412,48413,48414,48415,48416,48417,48418,48419,48420,48421,48422,48423,48424,48425,48426,48427,48428,48429,48430,48431,48432,48433,48434,48435,48436,48437,48438,48439,48440,48441,48442,48443,48444,48445,48446,48447,48448,48449,48450,48451,48452,48453,48454,48455,48456,48457,48458,48459,48460,48461,48462,48463,48464,48465,48466,48467,48468,48469,48470,48471,48472,48473,48474,48475,48476,48477,48478,48479,48480,48481,48482,48483,48484,48485,48486,48487,48488,48489,48490,48491,48492,48493,48494,48495,48496,48497,48498,48499,48500,48501,48502,48503,48504,48505,48506,48507,48508,48509,48510,48511,48512,48513,48514,48515,48516,48517,48518,48519,48520,48521,48522,48523,48524,48525,48526,48527,48528,48529,48530,48531,48532,48533,48534,48535,48536,48537,48538,48539,48540,48541,48542,48543,48544,48545,48546,48547,48548,48549,48550,48551,48552,48553,48554,48555,48556,48557,48558,48559,48560,48561,48562,48563,48564,48565,48566,48567,48568,48569,48570,48571,48572,48573,48574,48575,48576,48577
 ,48578,48579,48580,48581,48582,48583,48584,48585,48586,48587,48588,48589,48590,48591,48592,48593,48594,48595,48596,48597,48598,48599,48600,48601,48602,48603,48604,48605,48606,48607,48608,48609,48610,48611,48612,48613,48614,48615,48616,48617,48618,48619,48620,48621,48622,48623,48624,48625,48626,48627,48628,48629,48630,48631,48632,48633,48634,48635,48636,48637,48638,48639,48640,48641,48642,48643,48644,48645,48646,48647,48648,48649,48650,48651,48652,48653,48654,48655,48656,48657,48658,48659,48660,48661,48662,48663,48664,48665,48666,48667,48668,48669,48670,48671,48672,48673,48674,48675,48676,48677,48678,48679,48680,48681,48682,48683,48684,48685,48686,48687,48688,48689,48690,48691,48692,48693,48694,48695,48696,48697,48698,48699,48700,48701,48702,48703,48704,48705,48706,48707,48708,48709,48710,48711,48712,48713,48714,48715,48716,48717,48718,48719,48720,48721,48722,48723,48724,48725,48726,48727,48728,48729,48730,48731,48732,48733,48734,48735,48736,48737,48738,48739,48740,48741,48742,48743,
 48744,48745,48746,48747,48748,48749,48750,48751,48752,48753,48754,48755,48756,48757,48758,48759,48760,48761,48762,48763,48764,48765,48766,48767,48768,48769,48770,48771,48772,48773,48774,48775,48776,48777,48778,48779,48780,48781,48782,48783,48784,48785,48786,48787,48788,48789,48790,48791,48792,48793,48794,48795,48796,48797,48798,48799,48800,48801,48802,48803,48804,48805,48806,48807,48808,48809,48810,48811,48812,48813,48814,48815,48816,48817,48818,48819,48820,48821,48822,48823,48824,48825,48826,48827,48828,48829,48830,48831,48832,48833,48834,48835,48836,48837,48838,48839,48840,48841,48842,48843,48844,48845,48846,48847,48848,48849,48850,48851,48852,48853,48854,48855,48856,48857,48858,48859,48860,48861,48862,48863,48864,48865,48866,48867,48868,48869,48870,48871,48872,48873,48874,48875,48876,48877,48878,48879,48880,48881,48882,48883,48884,48885,48886,48887,48888,48889,48890,48891,48892,48893,48894,48895,48896,48897,48898,48899,48900,48901,48902,48903,48904,48905,48906,48907,48908,48909,4
 8910,48911,48912,48913,48914,48915,48916,48917,48918,48919,48920,48921,48922,48923,48924,48925,48926,48927,48928,48929,48930,48931,48932,48933,48934,48935,48936,48937,48938,48939,48940,48941,48942,48943,48944,48945,48946,48947,48948,48949,48950,48951,48952,48953,48954,48955,48956,48957,48958,48959,48960,48961,48962,48963,48964,48965,48966,48967,48968,48969,48970,48971,48972,48973,48974,48975,48976,48977,48978,48979,48980,48981,48982,48983,48984,48985,48986,48987,48988,48989,48990,48991,48992,48993,48994,48995,48996,48997,48998,48999,49000,49001,49002,49003,49004,49005,49006,49007,49008,49009,49010,49011,49012,49013,49014,49015,49016,49017,49018,49019,49020,49021,49022,49023,49024,49025,49026,49027,49028,49029,49030,49031,49032,49033,49034,49035,49036,49037,49038,49039,49040,49041,49042,49043,49044,49045,49046,49047,49048,49049,49050,49051,49052,49053,49054,49055,49056,49057,49058,49059,49060,49061,49062,49063,49064,49065,49066,49067,49068,49069,49070,49071,49072,49073,49074,49075,49
 076,49077,49078,49079,49080,49081,49082,49083,49084,49085,49086,49087,49088,49089,49090,49091,49092,49093,49094,49095,49096,49097,49098,49099,49100,49101,49102,49103,49104,49105,49106,49107,49108,49109,49110,49111,49112,49113,49114,49115,49116,49117,49118,49119,49120,49121,49122,49123,49124,49125,49126,49127,49128,49129,49130,49131,49132,49133,49134,49135,49136,49137,49138,49139,49140,49141,49142,49143,49144,49145,49146,49147,49148,49149,49150,49151,49152,49153,49154,49155,49156,49157,49158,49159,49160,49161,49162,49163,49164,49165,49166,49167,49168,49169,49170,49171,49172,49173,49174,49175,49176,49177,49178,49179,49180,49181,49182,49183,49184,49185,49186,49187,49188,49189,49190,49191,49192,49193,49194,49195,49196,49197,49198,49199,49200,49201,49202,49203,49204,49205,49206,49207,49208,49209,49210,49211,49212,49213,49214,49215,49216,49217,49218,49219,49220,49221,49222,49223,49224,49225,49226,49227,49228,49229,49230,49231,49232,49233,49234,49235,49236,49237,49238,49239,49240,49241,492
 42,49243,49244,49245,49246,49247,49248,49249,49250,49251,49252,49253,49254,49255,49256,49257,49258,49259,49260,49261,49262,49263,49264,49265,49266,49267,49268,49269,49270,49271,49272,49273,49274,49275,49276,49277,49278,49279,49280,49281,49282,49283,49284,49285,49286,49287,49288,49289,49290,49291,49292,49293,49294,49295,49296,49297,49298,49299,49300,49301,49302,49303,49304,49305,49306,49307,49308,49309,49310,49311,49312,49313,49314,49315,49316,49317,49318,49319,49320,49321,49322,49323,49324,49325,49326,49327,49328,49329,49330,49331,49332,49333,49334,49335,49336,49337,49338,49339,49340,49341,49342,49343,49344,49345,49346,49347,49348,49349,49350,49351,49352,49353,49354,49355,49356,49357,49358,49359,49360,49361,49362,49363,49364,49365,49366,49367,49368,49369,49370,49371,49372,49373,49374,49375,49376,49377,49378,49379,49380,49381,49382,49383,49384,49385,49386,49387,49388,49389,49390,49391,49392,49393,49394,49395,49396,49397,49398,49399,49400,49401,49402,49403,49404,49405,49406,49407,4940
 8,49409,49410,49411,49412,49413,49414,49415,49416,49417,49418,49419,49420,49421,49422,49423,49424,49425,49426,49427,49428,49429,49430,49431,49432,49433,49434,49435,49436,49437,49438,49439,49440,49441,49442,49443,49444,49445,49446,49447,49448,49449,49450,49451,49452,49453,49454,49455,49456,49457,49458,49459,49460,49461,49462,49463,49464,49465,49466,49467,49468,49469,49470,49471,49472,49473,49474,49475,49476,49477,49478,49479,49480,49481,49482,49483,49484,49485,49486,49487,49488,49489,49490,49491,49492,49493,49494,49495,49496,49497,49498,49499,49500,49501,49502,49503,49504,49505,49506,49507,49508,49509,49510,49511,49512,49513,49514,49515,49516,49517,49518,49519,49520,49521,49522,49523,49524,49525,49526,49527,49528,49529,49530,49531,49532,49533,49534,49535,49536,49537,49538,49539,49540,49541,49542,49543,49544,49545,49546,49547,49548,49549,49550,49551,49552,49553,49554,49555,49556,49557,49558,49559,49560,49561,49562,49563,49564,49565,49566,49567,49568,49569,49570,49571,49572,49573,49574
 ,49575,49576,49577,49578,49579,49580,49581,49582,49583,49584,49585,49586,49587,49588,49589,49590,49591,49592,49593,49594,49595,49596,49597,49598,49599,49600,49601,49602,49603,49604,49605,49606,49607,49608,49609,49610,49611,49612,49613,49614,49615,49616,49617,49618,49619,49620,49621,49622,49623,49624,49625,49626,49627,49628,49629,49630,49631,49632,49633,49634,49635,49636,49637,49638,49639,49640,49641,49642,49643,49644,49645,49646,49647,49648,49649,49650,49651,49652,49653,49654,49655,49656,49657,49658,49659,49660,49661,49662,49663,49664,49665,49666,49667,49668,49669,49670,49671,49672,49673,49674,49675,49676,49677,49678,49679,49680,49681,49682,49683,49684,49685,49686,49687,49688,49689,49690,49691,49692,49693,49694,49695,49696,49697,49698,49699,49700,49701,49702,49703,49704,49705,49706,49707,49708,49709,49710,49711,49712,49713,49714,49715,49716,49717,49718,49719,49720,49721,49722,49723,49724,49725,49726,49727,49728,49729,49730,49731,49732,49733,49734,49735,49736,49737,49738,49739,49740,
 49741,49742,49743,49744,49745,49746,49747,49748,49749,49750,49751,49752,49753,49754,49755,49756,49757,49758,49759,49760,49761,49762,49763,49764,49765,49766,49767,49768,49769,49770,49771,49772,49773,49774,49775,49776,49777,49778,49779,49780,49781,49782,49783,49784,49785,49786,49787,49788,49789,49790,49791,49792,49793,49794,49795,49796,49797,49798,49799,49800,49801,49802,49803,49804,49805,49806,49807,49808,49809,49810,49811,49812,49813,49814,49815,49816,49817,49818,49819,49820,49821,49822,49823,49824,49825,49826,49827,49828,49829,49830,49831,49832,49833,49834,49835,49836,49837,49838,49839,49840,49841,49842,49843,49844,49845,49846,49847,49848,49849,49850,49851,49852,49853,49854,49855,49856,49857,49858,49859,49860,49861,49862,49863,49864,49865,49866,49867,49868,49869,49870,49871,49872,49873,49874,49875,49876,49877,49878,49879,49880,49881,49882,49883,49884,49885,49886,49887,49888,49889,49890,49891,49892,49893,49894,49895,49896,49897,49898,49899,49900,49901,49902,49903,49904,49905,49906,4
 9907,49908,49909,49910,49911,49912,49913,49914,49915,49916,49917,49918,49919,49920,49921,49922,49923,49924,49925,49926,49927,49928,49929,49930,49931,49932,49933,49934,49935,49936,49937,49938,49939,49940,49941,49942,49943,49944,49945,49946,49947,49948,49949,49950,49951,49952,49953,49954,49955,49956,49957,49958,49959,49960,49961,49962,49963,49964,49965,49966,49967,49968,49969,49970,49971,49972,49973,49974,49975,49976,49977,49978,49979,49980,49981,49982,49983,49984,49985,49986,49987,49988,49989,49990,49991,49992,49993,49994,49995,49996,49997,49998,49999,50000,50001,50002,50003,50004,50005,50006,50007,50008,50009,50010,50011,50012,50013,50014,50015,50016,50017,50018,50019,50020,50021,50022,50023,50024,50025,50026,50027,50028,50029,50030,50031,50032,50033,50034,50035,50036,50037,50038,50039,50040,50041,50042,50043,50044,50045,50046,50047,50048,50049,50050,50051,50052,50053,50054,50055,50056,50057,50058,50059,50060,50061,50062,50063,50064,50065,50066,50067,50068,50069,50070,50071,50072,50
 073,50074,50075,50076,50077,50078,50079,50080,50081,50082,50083,50084,50085,50086,50087,50088,50089,50090,50091,50092,50093,50094,50095,50096,50097,50098,50099,50100,50101,50102,50103,50104,50105,50106,50107,50108,50109,50110,50111,50112,50113,50114,50115,50116,50117,50118,50119,50120,50121,50122,50123,50124,50125,50126,50127,50128,50129,50130,50131,50132,50133,50134,50135,50136,50137,50138,50139,50140,50141,50142,50143,50144,50145,50146,50147,50148,50149,50150,50151,50152,50153,50154,50155,50156,50157,50158,50159,50160,50161,50162,50163,50164,50165,50166,50167,50168,50169,50170,50171,50172,50173,50174,50175,50176,50177,50178,50179,50180,50181,50182,50183,50184,50185,50186,50187,50188,50189,50190,50191,50192,50193,50194,50195,50196,50197,50198,50199,50200,50201,50202,50203,50204,50205,50206,50207,50208,50209,50210,50211,50212,50213,50214,50215,50216,50217,50218,50219,50220,50221,50222,50223,50224,50225,50226,50227,50228,50229,50230,50231,50232,50233,50234,50235,50236,50237,50238,502
 39,50240,50241,50242,50243,50244,50245,50246,50247,50248,50249,50250,50251,50252,50253,50254,50255,50256,50257,50258,50259,50260,50261,50262,50263,50264,50265,50266,50267,50268,50269,50270,50271,50272,50273,50274,50275,50276,50277,50278,50279,50280,50281,50282,50283,50284,50285,50286,50287,50288,50289,50290,50291,50292,50293,50294,50295,50296,50297,50298,50299,50300,50301,50302,50303,50304,50305,50306,50307,50308,50309,50310,50311,50312,50313,50314,50315,50316,50317,50318,50319,50320,50321,50322,50323,50324,50325,50326,50327,50328,50329,50330,50331,50332,50333,50334,50335,50336,50337,50338,50339,50340,50341,50342,50343,50344,50345,50346,50347,50348,50349,50350,50351,50352,50353,50354,50355,50356,50357,50358,50359,50360,50361,50362,50363,50364,50365,50366,50367,50368,50369,50370,50371,50372,50373,50374,50375,50376,50377,50378,50379,50380,50381,50382,50383,50384,50385,50386,50387,50388,50389,50390,50391,50392,50393,50394,50395,50396,50397,50398,50399,50400,50401,50402,50403,50404,5040
 5,50406,50407,50408,50409,50410,50411,50412,50413,50414,50415,50416,50417,50418,50419,50420,50421,50422,50423,50424,50425,50426,50427,50428,50429,50430,50431,50432,50433,50434,50435,50436,50437,50438,50439,50440,50441,50442,50443,50444,50445,50446,50447,50448,50449,50450,50451,50452,50453,50454,50455,50456,50457,50458,50459,50460,50461,50462,50463,50464,50465,50466,50467,50468,50469,50470,50471,50472,50473,50474,50475,50476,50477,50478,50479,50480,50481,50482,50483,50484,50485,50486,50487,50488,50489,50490,50491,50492,50493,50494,50495,50496,50497,50498,50499,50500,50501,50502,50503,50504,50505,50506,50507,50508,50509,50510,50511,50512,50513,50514,50515,50516,50517,50518,50519,50520,50521,50522,50523,50524,50525,50526,50527,50528,50529,50530,50531,50532,50533,50534,50535,50536,50537,50538,50539,50540,50541,50542,50543,50544,50545,50546,50547,50548,50549,50550,50551,50552,50553,50554,50555,50556,50557,50558,50559,50560,50561,50562,50563,50564,50565,50566,50567,50568,50569,50570,50571
 ,50572,50573,50574,50575,50576,50577,50578,50579,50580,50581,50582,50583,50584,50585,50586,50587,50588,50589,50590,50591,50592,50593,50594,50595,50596,50597,50598,50599,50600,50601,50602,50603,50604,50605,50606,50607,50608,50609,50610,50611,50612,50613,50614,50615,50616,50617,50618,50619,50620,50621,50622,50623,50624,50625,50626,50627,50628,50629,50630,50631,50632,50633,50634,50635,50636,50637,50638,50639,50640,50641,50642,50643,50644,50645,50646,50647,50648,50649,50650,50651,50652,50653,50654,50655,50656,50657,50658,50659,50660,50661,50662,50663,50664,50665,50666,50667,50668,50669,50670,50671,50672,50673,50674,50675,50676,50677,50678,50679,50680,50681,50682,50683,50684,50685,50686,50687,50688,50689,50690,50691,50692,50693,50694,50695,50696,50697,50698,50699,50700,50701,50702,50703,50704,50705,50706,50707,50708,50709,50710,50711,50712,50713,50714,50715,50716,50717,50718,50719,50720,50721,50722,50723,50724,50725,50726,50727,50728,50729,50730,50731,50732,50733,50734,50735,50736,50737,
 50738,50739,50740,50741,50742,50743,50744,50745,50746,50747,50748,50749,50750,50751,50752,50753,50754,50755,50756,50757,50758,50759,50760,50761,50762,50763,50764,50765,50766,50767,50768,50769,50770,50771,50772,50773,50774,50775,50776,50777,50778,50779,50780,50781,50782,50783,50784,50785,50786,50787,50788,50789,50790,50791,50792,50793,50794,50795,50796,50797,50798,50799,50800,50801,50802,50803,50804,50805,50806,50807,50808,50809,50810,50811,50812,50813,50814,50815,50816,50817,50818,50819,50820,50821,50822,50823,50824,50825,50826,50827,50828,50829,50830,50831,50832,50833,50834,50835,50836,50837,50838,50839,50840,50841,50842,50843,50844,50845,50846,50847,50848,50849,50850,50851,50852,50853,50854,50855,50856,50857,50858,50859,50860,50861,50862,50863,50864,50865,50866,50867,50868,50869,50870,50871,50872,50873,50874,50875,50876,50877,50878,50879,50880,50881,50882,50883,50884,50885,50886,50887,50888,50889,50890,50891,50892,50893,50894,50895,50896,50897,50898,50899,50900,50901,50902,50903,5
 0904,50905,50906,50907,50908,50909,50910,50911,50912,50913,50914,50915,50916,50917,50918,50919,50920,50921,50922,50923,50924,50925,50926,50927,50928,50929,50930,50931,50932,50933,50934,50935,50936,50937,50938,50939,50940,50941,50942,50943,50944,50945,50946,50947,50948,50949,50950,50951,50952,50953,50954,50955,50956,50957,50958,50959,50960,50961,50962,50963,50964,50965,50966,50967,50968,50969,50970,50971,50972,50973,50974,50975,50976,50977,50978,50979,50980,50981,50982,50983,50984,50985,50986,50987,50988,50989,50990,50991,50992,50993,50994,50995,50996,50997,50998,50999,51000,51001,51002,51003,51004,51005,51006,51007,51008,51009,51010,51011,51012,51013,51014,51015,51016,51017,51018,51019,51020,51021,51022,51023,51024,51025,51026,51027,51028,51029,51030,51031,51032,51033,51034,51035,51036,51037,51038,51039,51040,51041,51042,51043,51044,51045,51046,51047,51048,51049,51050,51051,51052,51053,51054,51055,51056,51057,51058,51059,51060,51061,51062,51063,51064,51065,51066,51067,51068,51069,51
 070,51071,51072,51073,51074,51075,51076,51077,51078,51079,51080,51081,51082,51083,51084,51085,51086,51087,51088,51089,51090,51091,51092,51093,51094,51095,51096,51097,51098,51099,51100,51101,51102,51103,51104,51105,51106,51107,51108,51109,51110,51111,51112,51113,51114,51115,51116,51117,51118,51119,51120,51121,51122,51123,51124,51125,51126,51127,51128,51129,51130,51131,51132,51133,51134,51135,51136,51137,51138,51139,51140,51141,51142,51143,51144,51145,51146,51147,51148,51149,51150,51151,51152,51153,51154,51155,51156,51157,51158,51159,51160,51161,51162,51163,51164,51165,51166,51167,51168,51169,51170,51171,51172,51173,51174,51175,51176,51177,51178,51179,51180,51181,51182,51183,51184,51185,51186,51187,51188,51189,51190,51191,51192,51193,51194,51195,51196,51197,51198,51199,51200,51201,51202,51203,51204,51205,51206,51207,51208,51209,51210,51211,51212,51213,51214,51215,51216,51217,51218,51219,51220,51221,51222,51223,51224,51225,51226,51227,51228,51229,51230,51231,51232,51233,51234,51235,512
 36,51237,51238,51239,51240,51241,51242,51243,51244,51245,51246,51247,51248,51249,51250,51251,51252,51253,51254,51255,51256,51257,51258,51259,51260,51261,51262,51263,51264,51265,51266,51267,51268,51269,51270,51271,51272,51273,51274,51275,51276,51277,51278,51279,51280,51281,51282,51283,51284,51285,51286,51287,51288,51289,51290,51291,51292,51293,51294,51295,51296,51297,51298,51299,51300,51301,51302,51303,51304,51305,51306,51307,51308,51309,51310,51311,51312,51313,51314,51315,51316,51317,51318,51319,51320,51321,51322,51323,51324,51325,51326,51327,51328,51329,51330,51331,51332,51333,51334,51335,51336,51337,51338,51339,51340,51341,51342,51343,51344,51345,51346,51347,51348,51349,51350,51351,51352,51353,51354,51355,51356,51357,51358,51359,51360,51361,51362,51363,51364,51365,51366,51367,51368,51369,51370,51371,51372,51373,51374,51375,51376,51377,51378,51379,51380,51381,51382,51383,51384,51385,51386,51387,51388,51389,51390,51391,51392,51393,51394,51395,51396,51397,51398,51399,51400,51401,5140
 2,51403,51404,51405,51406,51407,51408,51409,51410,51411,51412,51413,51414,51415,51416,51417,51418,51419,51420,51421,51422,51423,51424,51425,51426,51427,51428,51429,51430,51431,51432,51433,51434,51435,51436,51437,51438,51439,51440,51441,51442,51443,51444,51445,51446,51447,51448,51449,51450,51451,51452,51453,51454,51455,51456,51457,51458,51459,51460,51461,51462,51463,51464,51465,51466,51467,51468,51469,51470,51471,51472,51473,51474,51475,51476,51477,51478,51479,51480,51481,51482,51483,51484,51485,51486,51487,51488,51489,51490,51491,51492,51493,51494,51495,51496,51497,51498,51499,51500,51501,51502,51503,51504,51505,51506,51507,51508,51509,51510,51511,51512,51513,51514,51515,51516,51517,51518,51519,51520,51521,51522,51523,51524,51525,51526,51527,51528,51529,51530,51531,51532,51533,51534,51535,51536,51537,51538,51539,51540,51541,51542,51543,51544,51545,51546,51547,51548,51549,51550,51551,51552,51553,51554,51555,51556,51557,51558,51559,51560,51561,51562,51563,51564,51565,51566,51567,51568
 ,51569,51570,51571,51572,51573,51574,51575,51576,51577,51578,51579,51580,51581,51582,51583,51584,51585,51586,51587,51588,51589,51590,51591,51592,51593,51594,51595,51596,51597,51598,51599,51600,51601,51602,51603,51604,51605,51606,51607,51608,51609,51610,51611,51612,51613,51614,51615,51616,51617,51618,51619,51620,51621,51622,51623,51624,51625,51626,51627,51628,51629,51630,51631,51632,51633,51634,51635,51636,51637,51638,51639,51640,51641,51642,51643,51644,51645,51646,51647,51648,51649,51650,51651,51652,51653,51654,51655,51656,51657,51658,51659,51660,51661,51662,51663,51664,51665,51666,51667,51668,51669,51670,51671,51672,51673,51674,51675,51676,51677,51678,51679,51680,51681,51682,51683,51684,51685,51686,51687,51688,51689,51690,51691,51692,51693,51694,51695,51696,51697,51698,51699,51700,51701,51702,51703,51704,51705,51706,51707,51708,51709,51710,51711,51712,51713,51714,51715,51716,51717,51718,51719,51720,51721,51722,51723,51724,51725,51726,51727,51728,51729,51730,51731,51732,51733,51734,
 51735,51736,51737,51738,51739,51740,51741,51742,51743,51744,51745,51746,51747,51748,51749,51750,51751,51752,51753,51754,51755,51756,51757,51758,51759,51760,51761,51762,51763,51764,51765,51766,51767,51768,51769,51770,51771,51772,51773,51774,51775,51776,51777,51778,51779,51780,51781,51782,51783,51784,51785,51786,51787,51788,51789,51790,51791,51792,51793,51794,51795,51796,51797,51798,51799,51800,51801,51802,51803,51804,51805,51806,51807,51808,51809,51810,51811,51812,51813,51814,51815,51816,51817,51818,51819,51820,51821,51822,51823,51824,51825,51826,51827,51828,51829,51830,51831,51832,51833,51834,51835,51836,51837,51838,51839,51840,51841,51842,51843,51844,51845,51846,51847,51848,51849,51850,51851,51852,51853,51854,51855,51856,51857,51858,51859,51860,51861,51862,51863,51864,51865,51866,51867,51868,51869,51870,51871,51872,51873,51874,51875,51876,51877,51878,51879,51880,51881,51882,51883,51884,51885,51886,51887,51888,51889,51890,51891,51892,51893,51894,51895,51896,51897,51898,51899,51900,5
 1901,51902,51903,51904,51905,51906,51907,51908,51909,51910,51911,51912,51913,51914,51915,51916,51917,51918,51919,51920,51921,51922,51923,51924,51925,51926,51927,51928,51929,51930,51931,51932,51933,51934,51935,51936,51937,51938,51939,51940,51941,51942,51943,51944,51945,51946,51947,51948,51949,51950,51951,51952,51953,51954,51955,51956,51957,51958,51959,51960,51961,51962,51963,51964,51965,51966,51967,51968,51969,51970,51971,51972,51973,51974,51975,51976,51977,51978,51979,51980,51981,51982,51983,51984,51985,51986,51987,51988,51989,51990,51991,51992,51993,51994,51995,51996,51997,51998,51999,52000,52001,52002,52003,52004,52005,52006,52007,52008,52009,52010,52011,52012,52013,52014,52015,52016,52017,52018,52019,52020,52021,52022,52023,52024,52025,52026,52027,52028,52029,52030,52031,52032,52033,52034,52035,52036,52037,52038,52039,52040,52041,52042,52043,52044,52045,52046,52047,52048,52049,52050,52051,52052,52053,52054,52055,52056,52057,52058,52059,52060,52061,52062,52063,52064,52065,52066,52
 067,52068,52069,52070,52071,52072,52073,52074,52075,52076,52077,52078,52079,52080,52081,52082,52083,52084,52085,52086,52087,52088,52089,52090,52091,52092,52093,52094,52095,52096,52097,52098,52099,52100,52101,52102,52103,52104,52105,52106,52107,52108,52109,52110,52111,52112,52113,52114,52115,52116,52117,52118,52119,52120,52121,52122,52123,52124,52125,52126,52127,52128,52129,52130,52131,52132,52133,52134,52135,52136,52137,52138,52139,52140,52141,52142,52143,52144,52145,52146,52147,52148,52149,52150,52151,52152,52153,52154,52155,52156,52157,52158,52159,52160,52161,52162,52163,52164,52165,52166,52167,52168,52169,52170,52171,52172,52173,52174,52175,52176,52177,52178,52179,52180,52181,52182,52183,52184,52185,52186,52187,52188,52189,52190,52191,52192,52193,52194,52195,52196,52197,52198,52199,52200,52201,52202,52203,52204,52205,52206,52207,52208,52209,52210,52211,52212,52213,52214,52215,52216,52217,52218,52219,52220,52221,52222,52223,52224,52225,52226,52227,52228,52229,52230,52231,52232,522
 33,52234,52235,52236,52237,52238,52239,52240,52241,52242,52243,52244,52245,52246,52247,52248,52249,52250,52251,52252,52253,52254,52255,52256,52257,52258,52259,52260,52261,52262,52263,52264,52265,52266,52267,52268,52269,52270,52271,52272,52273,52274,52275,52276,52277,52278,52279,52280,52281,52282,52283,52284,52285,52286,52287,52288,52289,52290,52291,52292,52293,52294,52295,52296,52297,52298,52299,52300,52301,52302,52303,52304,52305,52306,52307,52308,52309,52310,52311,52312,52313,52314,52315,52316,52317,52318,52319,52320,52321,52322,52323,52324,52325,52326,52327,52328,52329,52330,52331,52332,52333,52334,52335,52336,52337,52338,52339,52340,52341,52342,52343,52344,52345,52346,52347,52348,52349,52350,52351,52352,52353,52354,52355,52356,52357,52358,52359,52360,52361,52362,52363,52364,52365,52366,52367,52368,52369,52370,52371,52372,52373,52374,52375,52376,52377,52378,52379,52380,52381,52382,52383,52384,52385,52386,52387,52388,52389,52390,52391,52392,52393,52394,52395,52396,52397,52398,5239
 9,52400,52401,52402,52403,52404,52405,52406,52407,52408,52409,52410,52411,52412,52413,52414,52415,52416,52417,52418,52419,52420,52421,52422,52423,52424,52425,52426,52427,52428,52429,52430,52431,52432,52433,52434,52435,52436,52437,52438,52439,52440,52441,52442,52443,52444,52445,52446,52447,52448,52449,52450,52451,52452,52453,52454,52455,52456,52457,52458,52459,52460,52461,52462,52463,52464,52465,52466,52467,52468,52469,52470,52471,52472,52473,52474,52475,52476,52477,52478,52479,52480,52481,52482,52483,52484,52485,52486,52487,52488,52489,52490,52491,52492,52493,52494,52495,52496,52497,52498,52499,52500,52501,52502,52503,52504,52505,52506,52507,52508,52509,52510,52511,52512,52513,52514,52515,52516,52517,52518,52519,52520,52521,52522,52523,52524,52525,52526,52527,52528,52529,52530,52531,52532,52533,52534,52535,52536,52537,52538,52539,52540,52541,52542,52543,52544,52545,52546,52547,52548,52549,52550,52551,52552,52553,52554,52555,52556,52557,52558,52559,52560,52561,52562,52563,52564,52565
 ,52566,52567,52568,52569,52570,52571,52572,52573,52574,52575,52576,52577,52578,52579,52580,52581,52582,52583,52584,52585,52586,52587,52588,52589,52590,52591,52592,52593,52594,52595,52596,52597,52598,52599,52600,52601,52602,52603,52604,52605,52606,52607,52608,52609,52610,52611,52612,52613,52614,52615,52616,52617,52618,52619,52620,52621,52622,52623,52624,52625,52626,52627,52628,52629,52630,52631,52632,52633,52634,52635,52636,52637,52638,52639,52640,52641,52642,52643,52644,52645,52646,52647,52648,52649,52650,52651,52652,52653,52654,52655,52656,52657,52658,52659,52660,52661,52662,52663,52664,52665,52666,52667,52668,52669,52670,52671,52672,52673,52674,52675,52676,52677,52678,52679,52680,52681,52682,52683,52684,52685,52686,52687,52688,52689,52690,52691,52692,52693,52694,52695,52696,52697,52698,52699,52700,52701,52702,52703,52704,52705,52706,52707,52708,52709,52710,52711,52712,52713,52714,52715,52716,52717,52718,52719,52720,52721,52722,52723,52724,52725,52726,52727,52728,52729,52730,52731,
 52732,52733,52734,52735,52736,52737,52738,52739,52740,52741,52742,52743,52744,52745,52746,52747,52748,52749,52750,52751,52752,52753,52754,52755,52756,52757,52758,52759,52760,52761,52762,52763,52764,52765,52766,52767,52768,52769,52770,52771,52772,52773,52774,52775,52776,52777,52778,52779,52780,52781,52782,52783,52784,52785,52786,52787,52788,52789,52790,52791,52792,52793,52794,52795,52796,52797,52798,52799,52800,52801,52802,52803,52804,52805,52806,52807,52808,52809,52810,52811,52812,52813,52814,52815,52816,52817,52818,52819,52820,52821,52822,52823,52824,52825,52826,52827,52828,52829,52830,52831,52832,52833,52834,52835,52836,52837,52838,52839,52840,52841,52842,52843,52844,52845,52846,52847,52848,52849,52850,52851,52852,52853,52854,52855,52856,52857,52858,52859,52860,52861,52862,52863,52864,52865,52866,52867,52868,52869,52870,52871,52872,52873,52874,52875,52876,52877,52878,52879,52880,52881,52882,52883,52884,52885,52886,52887,52888,52889,52890,52891,52892,52893,52894,52895,52896,52897,5
 2898,52899,52900,52901,52902,52903,52904,52905,52906,52907,52908,52909,52910,52911,52912,52913,52914,52915,52916,52917,52918,52919,52920,52921,52922,52923,52924,52925,52926,52927,52928,52929,52930,52931,52932,52933,52934,52935,52936,52937,52938,52939,52940,52941,52942,52943,52944,52945,52946,52947,52948,52949,52950,52951,52952,52953,52954,52955,52956,52957,52958,52959,52960,52961,52962,52963,52964,52965,52966,52967,52968,52969,52970,52971,52972,52973,52974,52975,52976,52977,52978,52979,52980,52981,52982,52983,52984,52985,52986,52987,52988,52989,52990,52991,52992,52993,52994,52995,52996,52997,52998,52999,53000,53001,53002,53003,53004,53005,53006,53007,53008,53009,53010,53011,53012,53013,53014,53015,53016,53017,53018,53019,53020,53021,53022,53023,53024,53025,53026,53027,53028,53029,53030,53031,53032,53033,53034,53035,53036,53037,53038,53039,53040,53041,53042,53043,53044,53045,53046,53047,53048,53049,53050,53051,53052,53053,53054,53055,53056,53057,53058,53059,53060,53061,53062,53063,53
 064,53065,53066,53067,53068,53069,53070,53071,53072,53073,53074,53075,53076,53077,53078,53079,53080,53081,53082,53083,53084,53085,53086,53087,53088,53089,53090,53091,53092,53093,53094,53095,53096,53097,53098,53099,53100,53101,53102,53103,53104,53105,53106,53107,53108,53109,53110,53111,53112,53113,53114,53115,53116,53117,53118,53119,53120,53121,53122,53123,53124,53125,53126,53127,53128,53129,53130,53131,53132,53133,53134,53135,53136,53137,53138,53139,53140,53141,53142,53143,53144,53145,53146,53147,53148,53149,53150,53151,53152,53153,53154,53155,53156,53157,53158,53159,53160,53161,53162,53163,53164,53165,53166,53167,53168,53169,53170,53171,53172,53173,53174,53175,53176,53177,53178,53179,53180,53181,53182,53183,53184,53185,53186,53187,53188,53189,53190,53191,53192,53193,53194,53195,53196,53197,53198,53199,53200,53201,53202,53203,53204,53205,53206,53207,53208,53209,53210,53211,53212,53213,53214,53215,53216,53217,53218,53219,53220,53221,53222,53223,53224,53225,53226,53227,53228,53229,532
 30,53231,53232,53233,53234,53235,53236,53237,53238,53239,53240,53241,53242,53243,53244,53245,53246,53247,53248,53249,53250,53251,53252,53253,53254,53255,53256,53257,53258,53259,53260,53261,53262,53263,53264,53265,53266,53267,53268,53269,53270,53271,53272,53273,53274,53275,53276,53277,53278,53279,53280,53281,53282,53283,53284,53285,53286,53287,53288,53289,53290,53291,53292,53293,53294,53295,53296,53297,53298,53299,53300,53301,53302,53303,53304,53305,53306,53307,53308,53309,53310,53311,53312,53313,53314,53315,53316,53317,53318,53319,53320,53321,53322,53323,53324,53325,53326,53327,53328,53329,53330,53331,53332,53333,53334,53335,53336,53337,53338,53339,53340,53341,53342,53343,53344,53345,53346,53347,53348,53349,53350,53351,53352,53353,53354,53355,53356,53357,53358,53359,53360,53361,53362,53363,53364,53365,53366,53367,53368,53369,53370,53371,53372,53373,53374,53375,53376,53377,53378,53379,53380,53381,53382,53383,53384,53385,53386,53387,53388,53389,53390,53391,53392,53393,53394,53395,5339
 6,53397,53398,53399,53400,53401,53402,53403,53404,53405,53406,53407,53408,53409,53410,53411,53412,53413,53414,53415,53416,53417,53418,53419,53420,53421,53422,53423,53424,53425,53426,53427,53428,53429,53430,53431,53432,53433,53434,53435,53436,53437,53438,53439,53440,53441,53442,53443,53444,53445,53446,53447,53448,53449,53450,53451,53452,53453,53454,53455,53456,53457,53458,53459,53460,53461,53462,53463,53464,53465,53466,53467,53468,53469,53470,53471,53472,53473,53474,53475,53476,53477,53478,53479,53480,53481,53482,53483,53484,53485,53486,53487,53488,53489,53490,53491,53492,53493,53494,53495,53496,53497,53498,53499,53500,53501,53502,53503,53504,53505,53506,53507,53508,53509,53510,53511,53512,53513,53514,53515,53516,53517,53518,53519,53520,53521,53522,53523,53524,53525,53526,53527,53528,53529,53530,53531,53532,53533,53534,53535,53536,53537,53538,53539,53540,53541,53542,53543,53544,53545,53546,53547,53548,53549,53550,53551,53552,53553,53554,53555,53556,53557,53558,53559,53560,53561,53562
 ,53563,53564,53565,53566,53567,53568,53569,53570,53571,53572,53573,53574,53575,53576,53577,53578,53579,53580,53581,53582,53583,53584,53585,53586,53587,53588,53589,53590,53591,53592,53593,53594,53595,53596,53597,53598,53599,53600,53601,53602,53603,53604,53605,53606,53607,53608,53609,53610,53611,53612,53613,53614,53615,53616,53617,53618,53619,53620,53621,53622,53623,53624,53625,53626,53627,53628,53629,53630,53631,53632,53633,53634,53635,53636,53637,53638,53639,53640,53641,53642,53643,53644,53645,53646,53647,53648,53649,53650,53651,53652,53653,53654,53655,53656,53657,53658,53659,53660,53661,53662,53663,53664,53665,53666,53667,53668,53669,53670,53671,53672,53673,53674,53675,53676,53677,53678,53679,53680,53681,53682,53683,53684,53685,53686,53687,53688,53689,53690,53691,53692,53693,53694,53695,53696,53697,53698,53699,53700,53701,53702,53703,53704,53705,53706,53707,53708,53709,53710,53711,53712,53713,53714,53715,53716,53717,53718,53719,53720,53721,53722,53723,53724,53725,53726,53727,53728,
 53729,53730,53731,53732,53733,53734,53735,53736,53737,53738,53739,53740,53741,53742,53743,53744,53745,53746,53747,53748,53749,53750,53751,53752,53753,53754,53755,53756,53757,53758,53759,53760,53761,53762,53763,53764,53765,53766,53767,53768,53769,53770,53771,53772,53773,53774,53775,53776,53777,53778,53779,53780,53781,53782,53783,53784,53785,53786,53787,53788,53789,53790,53791,53792,53793,53794,53795,53796,53797,53798,53799,53800,53801,53802,53803,53804,53805,53806,53807,53808,53809,53810,53811,53812,53813,53814,53815,53816,53817,53818,53819,53820,53821,53822,53823,53824,53825,53826,53827,53828,53829,53830,53831,53832,53833,53834,53835,53836,53837,53838,53839,53840,53841,53842,53843,53844,53845,53846,53847,53848,53849,53850,53851,53852,53853,53854,53855,53856,53857,53858,53859,53860,53861,53862,53863,53864,53865,53866,53867,53868,53869,53870,53871,53872,53873,53874,53875,53876,53877,53878,53879,53880,53881,53882,53883,53884,53885,53886,53887,53888,53889,53890,53891,53892,53893,53894,5
 3895,53896,53897,53898,53899,53900,53901,53902,53903,53904,53905,53906,53907,53908,53909,53910,53911,53912,53913,53914,53915,53916,53917,53918,53919,53920,53921,53922,53923,53924,53925,53926,53927,53928,53929,53930,53931,53932,53933,53934,53935,53936,53937,53938,53939,53940,53941,53942,53943,53944,53945,53946,53947,53948,53949,53950,53951,53952,53953,53954,53955,53956,53957,53958,53959,53960,53961,53962,53963,53964,53965,53966,53967,53968,53969,53970,53971,53972,53973,53974,53975,53976,53977,53978,53979,53980,53981,53982,53983,53984,53985,53986,53987,53988,53989,53990,53991,53992,53993,53994,53995,53996,53997,53998,53999,54000,54001,54002,54003,54004,54005,54006,54007,54008,54009,54010,54011,54012,54013,54014,54015,54016,54017,54018,54019,54020,54021,54022,54023,54024,54025,54026,54027,54028,54029,54030,54031,54032,54033,54034,54035,54036,54037,54038,54039,54040,54041,54042,54043,54044,54045,54046,54047,54048,54049,54050,54051,54052,54053,54054,54055,54056,54057,54058,54059,54060,54
 061,54062,54063,54064,54065,54066,54067,54068,54069,54070,54071,54072,54073,54074,54075,54076,54077,54078,54079,54080,54081,54082,54083,54084,54085,54086,54087,54088,54089,54090,54091,54092,54093,54094,54095,54096,54097,54098,54099,54100,54101,54102,54103,54104,54105,54106,54107,54108,54109,54110,54111,54112,54113,54114,54115,54116,54117,54118,54119,54120,54121,54122,54123,54124,54125,54126,54127,54128,54129,54130,54131,54132,54133,54134,54135,54136,54137,54138,54139,54140,54141,54142,54143,54144,54145,54146,54147,54148,54149,54150,54151,54152,54153,54154,54155,54156,54157,54158,54159,54160,54161,54162,54163,54164,54165,54166,54167,54168,54169,54170,54171,54172,54173,54174,54175,54176,54177,54178,54179,54180,54181,54182,54183,54184,54185,54186,54187,54188,54189,54190,54191,54192,54193,54194,54195,54196,54197,54198,54199,54200,54201,54202,54203,54204,54205,54206,54207,54208,54209,54210,54211,54212,54213,54214,54215,54216,54217,54218,54219,54220,54221,54222,54223,54224,54225,54226,542
 27,54228,54229,54230,54231,54232,54233,54234,54235,54236,54237,54238,54239,54240,54241,54242,54243,54244,54245,54246,54247,54248,54249,54250,54251,54252,54253,54254,54255,54256,54257,54258,54259,54260,54261,54262,54263,54264,54265,54266,54267,54268,54269,54270,54271,54272,54273,54274,54275,54276,54277,54278,54279,54280,54281,54282,54283,54284,54285,54286,54287,54288,54289,54290,54291,54292,54293,54294,54295,54296,54297,54298,54299,54300,54301,54302,54303,54304,54305,54306,54307,54308,54309,54310,54311,54312,54313,54314,54315,54316,54317,54318,54319,54320,54321,54322,54323,54324,54325,54326,54327,54328,54329,54330,54331,54332,54333,54334,54335,54336,54337,54338,54339,54340,54341,54342,54343,54344,54345,54346,54347,54348,54349,54350,54351,54352,54353,54354,54355,54356,54357,54358,54359,54360,54361,54362,54363,54364,54365,54366,54367,54368,54369,54370,54371,54372,54373,54374,54375,54376,54377,54378,54379,54380,54381,54382,54383,54384,54385,54386,54387,54388,54389,54390,54391,54392,5439
 3,54394,54395,54396,54397,54398,54399,54400,54401,54402,54403,54404,54405,54406,54407,54408,54409,54410,54411,54412,54413,54414,54415,54416,54417,54418,54419,54420,54421,54422,54423,54424,54425,54426,54427,54428,54429,54430,54431,54432,54433,54434,54435,54436,54437,54438,54439,54440,54441,54442,54443,54444,54445,54446,54447,54448,54449,54450,54451,54452,54453,54454,54455,54456,54457,54458,54459,54460,54461,54462,54463,54464,54465,54466,54467,54468,54469,54470,54471,54472,54473,54474,54475,54476,54477,54478,54479,54480,54481,54482,54483,54484,54485,54486,54487,54488,54489,54490,54491,54492,54493,54494,54495,54496,54497,54498,54499,54500,54501,54502,54503,54504,54505,54506,54507,54508,54509,54510,54511,54512,54513,54514,54515,54516,54517,54518,54519,54520,54521,54522,54523,54524,54525,54526,54527,54528,54529,54530,54531,54532,54533,54534,54535,54536,54537,54538,54539,54540,54541,54542,54543,54544,54545,54546,54547,54548,54549,54550,54551,54552,54553,54554,54555,54556,54557,54558,54559
 ,54560,54561,54562,54563,54564,54565,54566,54567,54568,54569,54570,54571,54572,54573,54574,54575,54576,54577,54578,54579,54580,54581,54582,54583,54584,54585,54586,54587,54588,54589,54590,54591,54592,54593,54594,54595,54596,54597,54598,54599,54600,54601,54602,54603,54604,54605,54606,54607,54608,54609,54610,54611,54612,54613,54614,54615,54616,54617,54618,54619,54620,54621,54622,54623,54624,54625,54626,54627,54628,54629,54630,54631,54632,54633,54634,54635,54636,54637,54638,54639,54640,54641,54642,54643,54644,54645,54646,54647,54648,54649,54650,54651,54652,54653,54654,54655,54656,54657,54658,54659,54660,54661,54662,54663,54664,54665,54666,54667,54668,54669,54670,54671,54672,54673,54674,54675,54676,54677,54678,54679,54680,54681,54682,54683,54684,54685,54686,54687,54688,54689,54690,54691,54692,54693,54694,54695,54696,54697,54698,54699,54700,54701,54702,54703,54704,54705,54706,54707,54708,54709,54710,54711,54712,54713,54714,54715,54716,54717,54718,54719,54720,54721,54722,54723,54724,54725,
 54726,54727,54728,54729,54730,54731,54732,54733,54734,54735,54736,54737,54738,54739,54740,54741,54742,54743,54744,54745,54746,54747,54748,54749,54750,54751,54752,54753,54754,54755,54756,54757,54758,54759,54760,54761,54762,54763,54764,54765,54766,54767,54768,54769,54770,54771,54772,54773,54774,54775,54776,54777,54778,54779,54780,54781,54782,54783,54784,54785,54786,54787,54788,54789,54790,54791,54792,54793,54794,54795,54796,54797,54798,54799,54800,54801,54802,54803,54804,54805,54806,54807,54808,54809,54810,54811,54812,54813,54814,54815,54816,54817,54818,54819,54820,54821,54822,54823,54824,54825,54826,54827,54828,54829,54830,54831,54832,54833,54834,54835,54836,54837,54838,54839,54840,54841,54842,54843,54844,54845,54846,54847,54848,54849,54850,54851,54852,54853,54854,54855,54856,54857,54858,54859,54860,54861,54862,54863,54864,54865,54866,54867,54868,54869,54870,54871,54872,54873,54874,54875,54876,54877,54878,54879,54880,54881,54882,54883,54884,54885,54886,54887,54888,54889,54890,54891,5
 4892,54893,54894,54895,54896,54897,54898,54899,54900,54901,54902,54903,54904,54905,54906,54907,54908,54909,54910,54911,54912,54913,54914,54915,54916,54917,54918,54919,54920,54921,54922,54923,54924,54925,54926,54927,54928,54929,54930,54931,54932,54933,54934,54935,54936,54937,54938,54939,54940,54941,54942,54943,54944,54945,54946,54947,54948,54949,54950,54951,54952,54953,54954,54955,54956,54957,54958,54959,54960,54961,54962,54963,54964,54965,54966,54967,54968,54969,54970,54971,54972,54973,54974,54975,54976,54977,54978,54979,54980,54981,54982,54983,54984,54985,54986,54987,54988,54989,54990,54991,54992,54993,54994,54995,54996,54997,54998,54999,55000,55001,55002,55003,55004,55005,55006,55007,55008,55009,55010,55011,55012,55013,55014,55015,55016,55017,55018,55019,55020,55021,55022,55023,55024,55025,55026,55027,55028,55029,55030,55031,55032,55033,55034,55035,55036,55037,55038,55039,55040,55041,55042,55043,55044,55045,55046,55047,55048,55049,55050,55051,55052,55053,55054,55055,55056,55057,55
 058,55059,55060,55061,55062,55063,55064,55065,55066,55067,55068,55069,55070,55071,55072,55073,55074,55075,55076,55077,55078,55079,55080,55081,55082,55083,55084,55085,55086,55087,55088,55089,55090,55091,55092,55093,55094,55095,55096,55097,55098,55099,55100,55101,55102,55103,55104,55105,55106,55107,55108,55109,55110,55111,55112,55113,55114,55115,55116,55117,55118,55119,55120,55121,55122,55123,55124,55125,55126,55127,55128,55129,55130,55131,55132,55133,55134,55135,55136,55137,55138,55139,55140,55141,55142,55143,55144,55145,55146,55147,55148,55149,55150,55151,55152,55153,55154,55155,55156,55157,55158,55159,55160,55161,55162,55163,55164,55165,55166,55167,55168,55169,55170,55171,55172,55173,55174,55175,55176,55177,55178,55179,55180,55181,55182,55183,55184,55185,55186,55187,55188,55189,55190,55191,55192,55193,55194,55195,55196,55197,55198,55199,55200,55201,55202,55203,55216,55217,55218,55219,55220,55221,55222,55223,55224,55225,55226,55227,55228,55229,55230,55231,55232,55233,55234,55235,552
 36,55237,55238,55243,55244,55245,55246,55247,55248,55249,55250,55251,55252,55253,55254,55255,55256,55257,55258,55259,55260,55261,55262,55263,55264,55265,55266,55267,55268,55269,55270,55271,55272,55273,55274,55275,55276,55277,55278,55279,55280,55281,55282,55283,55284,55285,55286,55287,55288,55289,55290,55291,63744,63745,63746,63747,63748,63749,63750,63751,63752,63753,63754,63755,63756,63757,63758,63759,63760,63761,63762,63763,63764,63765,63766,63767,63768,63769,63770,63771,63772,63773,63774,63775,63776,63777,63778,63779,63780,63781,63782,63783,63784,63785,63786,63787,63788,63789,63790,63791,63792,63793,63794,63795,63796,63797,63798,63799,63800,63801,63802,63803,63804,63805,63806,63807,63808,63809,63810,63811,63812,63813,63814,63815,63816,63817,63818,63819,63820,63821,63822,63823,63824,63825,63826,63827,63828,63829,63830,63831,63832,63833,63834,63835,63836,63837,63838,63839,63840,63841,63842,63843,63844,63845,63846,63847,63848,63849,63850,63851,63852,63853,63854,63855,63856,63857,6385
 8,63859,63860,63861,63862,63863,63864,63865,63866,63867,63868,63869,63870,63871,63872,63873,63874,63875,63876,63877,63878,63879,63880,63881,63882,63883,63884,63885,63886,63887,63888,63889,63890,63891,63892,63893,63894,63895,63896,63897,63898,63899,63900,63901,63902,63903,63904,63905,63906,63907,63908,63909,63910,63911,63912,63913,63914,63915,63916,63917,63918,63919,63920,63921,63922,63923,63924,63925,63926,63927,63928,63929,63930,63931,63932,63933,63934,63935,63936,63937,63938,63939,63940,63941,63942,63943,63944,63945,63946,63947,63948,63949,63950,63951,63952,63953,63954,63955,63956,63957,63958,63959,63960,63961,63962,63963,63964,63965,63966,63967,63968,63969,63970,63971,63972,63973,63974,63975,63976,63977,63978,63979,63980,63981,63982,63983,63984,63985,63986,63987,63988,63989,63990,63991,63992,63993,63994,63995,63996,63997,63998,63999,64000,64001,64002,64003,64004,64005,64006,64007,64008,64009,64010,64011,64012,64013,64014,64015,64016,64017,64018,64019,64020,64021,64022,64023,64024
 ,64025,64026,64027,64028,64029,64030,64031,64032,64033,64034,64035,64036,64037,64038,64039,64040,64041,64042,64043,64044,64045,64046,64047,64048,64049,64050,64051,64052,64053,64054,64055,64056,64057,64058,64059,64060,64061,64062,64063,64064,64065,64066,64067,64068,64069,64070,64071,64072,64073,64074,64075,64076,64077,64078,64079,64080,64081,64082,64083,64084,64085,64086,64087,64088,64089,64090,64091,64092,64093,64094,64095,64096,64097,64098,64099,64100,64101,64102,64103,64104,64105,64106,64107,64108,64109,64112,64113,64114,64115,64116,64117,64118,64119,64120,64121,64122,64123,64124,64125,64126,64127,64128,64129,64130,64131,64132,64133,64134,64135,64136,64137,64138,64139,64140,64141,64142,64143,64144,64145,64146,64147,64148,64149,64150,64151,64152,64153,64154,64155,64156,64157,64158,64159,64160,64161,64162,64163,64164,64165,64166,64167,64168,64169,64170,64171,64172,64173,64174,64175,64176,64177,64178,64179,64180,64181,64182,64183,64184,64185,64186,64187,64188,64189,64190,64191,64192,
 64193,64194,64195,64196,64197,64198,64199,64200,64201,64202,64203,64204,64205,64206,64207,64208,64209,64210,64211,64212,64213,64214,64215,64216,64217,64256,64257,64258,64259,64260,64261,64262,64275,64276,64277,64278,64279,64285,64287,64288,64289,64290,64291,64292,64293,64294,64295,64296,64298,64299,64300,64301,64302,64303,64304,64305,64306,64307,64308,64309,64310,64312,64313,64314,64315,64316,64318,64320,64321,64323,64324,64326,64327,64328,64329,64330,64331,64332,64333,64334,64335,64336,64337,64338,64339,64340,64341,64342,64343,64344,64345,64346,64347,64348,64349,64350,64351,64352,64353,64354,64355,64356,64357,64358,64359,64360,64361,64362,64363,64364,64365,64366,64367,64368,64369,64370,64371,64372,64373,64374,64375,64376,64377,64378,64379,64380,64381,64382,64383,64384,64385,64386,64387,64388,64389,64390,64391,64392,64393,64394,64395,64396,64397,64398,64399,64400,64401,64402,64403,64404,64405,64406,64407,64408,64409,64410,64411,64412,64413,64414,64415,64416,64417,64418,64419,64420,6
 4421,64422,64423,64424,64425,64426,64427,64428,64429,64430,64431,64432,64433,64467,64468,64469,64470,64471,64472,64473,64474,64475,64476,64477,64478,64479,64480,64481,64482,64483,64484,64485,64486,64487,64488,64489,64490,64491,64492,64493,64494,64495,64496,64497,64498,64499,64500,64501,64502,64503,64504,64505,64506,64507,64508,64509,64510,64511,64512,64513,64514,64515,64516,64517,64518,64519,64520,64521,64522,64523,64524,64525,64526,64527,64528,64529,64530,64531,64532,64533,64534,64535,64536,64537,64538,64539,64540,64541,64542,64543,64544,64545,64546,64547,64548,64549,64550,64551,64552,64553,64554,64555,64556,64557,64558,64559,64560,64561,64562,64563,64564,64565,64566,64567,64568,64569,64570,64571,64572,64573,64574,64575,64576,64577,64578,64579,64580,64581,64582,64583,64584,64585,64586,64587,64588,64589,64590,64591,64592,64593,64594,64595,64596,64597,64598,64599,64600,64601,64602,64603,64604,64605,64606,64607,64608,64609,64610,64611,64612,64613,64614,64615,64616,64617,64618,64619,64
 620,64621,64622,64623,64624,64625,64626,64627,64628,64629,64630,64631,64632,64633,64634,64635,64636,64637,64638,64639,64640,64641,64642,64643,64644,64645,64646,64647,64648,64649,64650,64651,64652,64653,64654,64655,64656,64657,64658,64659,64660,64661,64662,64663,64664,64665,64666,64667,64668,64669,64670,64671,64672,64673,64674,64675,64676,64677,64678,64679,64680,64681,64682,64683,64684,64685,64686,64687,64688,64689,64690,64691,64692,64693,64694,64695,64696,64697,64698,64699,64700,64701,64702,64703,64704,64705,64706,64707,64708,64709,64710,64711,64712,64713,64714,64715,64716,64717,64718,64719,64720,64721,64722,64723,64724,64725,64726,64727,64728,64729,64730,64731,64732,64733,64734,64735,64736,64737,64738,64739,64740,64741,64742,64743,64744,64745,64746,64747,64748,64749,64750,64751,64752,64753,64754,64755,64756,64757,64758,64759,64760,64761,64762,64763,64764,64765,64766,64767,64768,64769,64770,64771,64772,64773,64774,64775,64776,64777,64778,64779,64780,64781,64782,64783,64784,64785,647
 86,64787,64788,64789,64790,64791,64792,64793,64794,64795,64796,64797,64798,64799,64800,64801,64802,64803,64804,64805,64806,64807,64808,64809,64810,64811,64812,64813,64814,64815,64816,64817,64818,64819,64820,64821,64822,64823,64824,64825,64826,64827,64828,64829,64848,64849,64850,64851,64852,64853,64854,64855,64856,64857,64858,64859,64860,64861,64862,64863,64864,64865,64866,64867,64868,64869,64870,64871,64872,64873,64874,64875,64876,64877,64878,64879,64880,64881,64882,64883,64884,64885,64886,64887,64888,64889,64890,64891,64892,64893,64894,64895,64896,64897,64898,64899,64900,64901,64902,64903,64904,64905,64906,64907,64908,64909,64910,64911,64914,64915,64916,64917,64918,64919,64920,64921,64922,64923,64924,64925,64926,64927,64928,64929,64930,64931,64932,64933,64934,64935,64936,64937,64938,64939,64940,64941,64942,64943,64944,64945,64946,64947,64948,64949,64950,64951,64952,64953,64954,64955,64956,64957,64958,64959,64960,64961,64962,64963,64964,64965,64966,64967,65008,65009,65010,65011,6501
 2,65013,65014,65015,65016,65017,65018,65019,65136,65137,65138,65139,65140,65142,65143,65144,65145,65146,65147,65148,65149,65150,65151,65152,65153,65154,65155,65156,65157,65158,65159,65160,65161,65162,65163,65164,65165,65166,65167,65168,65169,65170,65171,65172,65173,65174,65175,65176,65177,65178,65179,65180,65181,65182,65183,65184,65185,65186,65187,65188,65189,65190,65191,65192,65193,65194,65195,65196,65197,65198,65199,65200,65201,65202,65203,65204,65205,65206,65207,65208,65209,65210,65211,65212,65213,65214,65215,65216,65217,65218,65219,65220,65221,65222,65223,65224,65225,65226,65227,65228,65229,65230,65231,65232,65233,65234,65235,65236,65237,65238,65239,65240,65241,65242,65243,65244,65245,65246,65247,65248,65249,65250,65251,65252,65253,65254,65255,65256,65257,65258,65259,65260,65261,65262,65263,65264,65265,65266,65267,65268,65269,65270,65271,65272,65273,65274,65275,65276,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331
 ,65332,65333,65334,65335,65336,65337,65338,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,65382,65383,65384,65385,65386,65387,65388,65389,65390,65391,65392,65393,65394,65395,65396,65397,65398,65399,65400,65401,65402,65403,65404,65405,65406,65407,65408,65409,65410,65411,65412,65413,65414,65415,65416,65417,65418,65419,65420,65421,65422,65423,65424,65425,65426,65427,65428,65429,65430,65431,65432,65433,65434,65435,65436,65437,65438,65439,65440,65441,65442,65443,65444,65445,65446,65447,65448,65449,65450,65451,65452,65453,65454,65455,65456,65457,65458,65459,65460,65461,65462,65463,65464,65465,65466,65467,65468,65469,65470,65474,65475,65476,65477,65478,65479,65482,65483,65484,65485,65486,65487,65490,65491,65492,65493,65494,65495,65498,65499,65500';
+var arr = str.split(',').map(function(code) {
+  return parseInt(code, 10);
+});
+module.exports = arr;
+},{}],4:[function(require,module,exports){
+// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
+//
+// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
+//
+// Originally from narwhal.js (http://narwhaljs.org)
+// Copyright (c) 2009 Thomas Robinson <280north.com>
+//
+// 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 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.
+
+// when used in node, this will actually load the util module we depend on
+// versus loading the builtin util module as happens otherwise
+// this is a bug in node module loading as far as I am concerned
+var util = require('util/');
+
+var pSlice = Array.prototype.slice;
+var hasOwn = Object.prototype.hasOwnProperty;
+
+// 1. The assert module provides functions that throw
+// AssertionError's when particular conditions are not met. The
+// assert module must conform to the following interface.
+
+var assert = module.exports = ok;
+
+// 2. The AssertionError is defined in assert.
+// new assert.AssertionError({ message: message,
+//                             actual: actual,
+//                             expected: expected })
+
+assert.AssertionError = function AssertionError(options) {
+  this.name = 'AssertionError';
+  this.actual = options.actual;
+  this.expected = options.expected;
+  this.operator = options.operator;
+  if (options.message) {
+    this.message = options.message;
+    this.generatedMessage = false;
+  } else {
+    this.message = getMessage(this);
+    this.generatedMessage = true;
+  }
+  var stackStartFunction = options.stackStartFunction || fail;
+
+  if (Error.captureStackTrace) {
+    Error.captureStackTrace(this, stackStartFunction);
+  }
+  else {
+    // non v8 browsers so we can have a stacktrace
+    var err = new Error();
+    if (err.stack) {
+      var out = err.stack;
+
+      // try to strip useless frames
+      var fn_name = stackStartFunction.name;
+      var idx = out.indexOf('\n' + fn_name);
+      if (idx >= 0) {
+        // once we have located the function frame
+        // we need to strip out everything before it (and its line)
+        var next_line = out.indexOf('\n', idx + 1);
+        out = out.substring(next_line + 1);
+      }
+
+      this.stack = out;
+    }
+  }
+};
+
+// assert.AssertionError instanceof Error
+util.inherits(assert.AssertionError, Error);
+
+function replacer(key, value) {
+  if (util.isUndefined(value)) {
+    return '' + value;
+  }
+  if (util.isNumber(value) && !isFinite(value)) {
+    return value.toString();
+  }
+  if (util.isFunction(value) || util.isRegExp(value)) {
+    return value.toString();
+  }
+  return value;
+}
+
+function truncate(s, n) {
+  if (util.isString(s)) {
+    return s.length < n ? s : s.slice(0, n);
+  } else {
+    return s;
+  }
+}
+
+function getMessage(self) {
+  return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +
+         self.operator + ' ' +
+         truncate(JSON.stringify(self.expected, replacer), 128);
+}
+
+// At present only the three keys mentioned above are used and
+// understood by the spec. Implementations or sub modules can pass
+// other keys to the AssertionError's constructor - they will be
+// ignored.
+
+// 3. All of the following functions must throw an AssertionError
+// when a corresponding condition is not met, with a message that
+// may be undefined if not provided.  All assertion methods provide
+// both the actual and expected values to the assertion error for
+// display purposes.
+
+function fail(actual, expected, message, operator, stackStartFunction) {
+  throw new assert.AssertionError({
+    message: message,
+    actual: actual,
+    expected: expected,
+    operator: operator,
+    stackStartFunction: stackStartFunction
+  });
+}
+
+// EXTENSION! allows for well behaved errors defined elsewhere.
+assert.fail = fail;
+
+// 4. Pure assertion tests whether a value is truthy, as determined
+// by !!guard.
+// assert.ok(guard, message_opt);
+// This statement is equivalent to assert.equal(true, !!guard,
+// message_opt);. To test strictly for the value true, use
+// assert.strictEqual(true, guard, message_opt);.
+
+function ok(value, message) {
+  if (!value) fail(value, true, message, '==', assert.ok);
+}
+assert.ok = ok;
+
+// 5. The equality assertion tests shallow, coercive equality with
+// ==.
+// assert.equal(actual, expected, message_opt);
+
+assert.equal = function equal(actual, expected, message) {
+  if (actual != expected) fail(actual, expected, message, '==', assert.equal);
+};
+
+// 6. The non-equality assertion tests for whether two objects are not equal
+// with != assert.notEqual(actual, expected, message_opt);
+
+assert.notEqual = function notEqual(actual, expected, message) {
+  if (actual == expected) {
+    fail(actual, expected, message, '!=', assert.notEqual);
+  }
+};
+
+// 7. The equivalence assertion tests a deep equality relation.
+// assert.deepEqual(actual, expected, message_opt);
+
+assert.deepEqual = function deepEqual(actual, expected, message) {
+  if (!_deepEqual(actual, expected)) {
+    fail(actual, expected, message, 'deepEqual', assert.deepEqual);
+  }
+};
+
+function _deepEqual(actual, expected) {
+  // 7.1. All identical values are equivalent, as determined by ===.
+  if (actual === expected) {
+    return true;
+
+  } else if (util.isBuffer(actual) && util.isBuffer(expected)) {
+    if (actual.length != expected.length) return false;
+
+    for (var i = 0; i < actual.length; i++) {
+      if (actual[i] !== expected[i]) return false;
+    }
+
+    return true;
+
+  // 7.2. If the expected value is a Date object, the actual value is
+  // equivalent if it is also a Date object that refers to the same time.
+  } else if (util.isDate(actual) && util.isDate(expected)) {
+    return actual.getTime() === expected.getTime();
+
+  // 7.3 If the expected value is a RegExp object, the actual value is
+  // equivalent if it is also a RegExp object with the same source and
+  // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
+  } else if (util.isRegExp(actual) && util.isRegExp(expected)) {
+    return actual.source === expected.source &&
+           actual.global === expected.global &&
+           actual.multiline === expected.multiline &&
+           actual.lastIndex === expected.lastIndex &&
+           actual.ignoreCase === expected.ignoreCase;
+
+  // 7.4. Other pairs that do not both pass typeof value == 'object',
+  // equivalence is determined by ==.
+  } else if (!util.isObject(actual) && !util.isObject(expected)) {
+    return actual == expected;
+
+  // 7.5 For all other Object pairs, including Array objects, equivalence is
+  // determined by having the same number of owned properties (as verified
+  // with Object.prototype.hasOwnProperty.call), the same set of keys
+  // (although not necessarily the same order), equivalent values for every
+  // corresponding key, and an identical 'prototype' property. Note: this
+  // accounts for both named and indexed properties on Arrays.
+  } else {
+    return objEquiv(actual, expected);
+  }
+}
+
+function isArguments(object) {
+  return Object.prototype.toString.call(object) == '[object Arguments]';
+}
+
+function objEquiv(a, b) {
+  if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))
+    return false;
+  // an identical 'prototype' property.
+  if (a.prototype !== b.prototype) return false;
+  // if one is a primitive, the other must be same
+  if (util.isPrimitive(a) || util.isPrimitive(b)) {
+    return a === b;
+  }
+  var aIsArgs = isArguments(a),
+      bIsArgs = isArguments(b);
+  if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs))
+    return false;
+  if (aIsArgs) {
+    a = pSlice.call(a);
+    b = pSlice.call(b);
+    return _deepEqual(a, b);
+  }
+  var ka = objectKeys(a),
+      kb = objectKeys(b),
+      key, i;
+  // having the same number of owned properties (keys incorporates
+  // hasOwnProperty)
+  if (ka.length != kb.length)
+    return false;
+  //the same set of keys (although not necessarily the same order),
+  ka.sort();
+  kb.sort();
+  //~~~cheap key test
+  for (i = ka.length - 1; i >= 0; i--) {
+    if (ka[i] != kb[i])
+      return false;
+  }
+  //equivalent values for every corresponding key, and
+  //~~~possibly expensive deep test
+  for (i = ka.length - 1; i >= 0; i--) {
+    key = ka[i];
+    if (!_deepEqual(a[key], b[key])) return false;
+  }
+  return true;
+}
+
+// 8. The non-equivalence assertion tests for any deep inequality.
+// assert.notDeepEqual(actual, expected, message_opt);
+
+assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
+  if (_deepEqual(actual, expected)) {
+    fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
+  }
+};
+
+// 9. The strict equality assertion tests strict equality, as determined by ===.
+// assert.strictEqual(actual, expected, message_opt);
+
+assert.strictEqual = function strictEqual(actual, expected, message) {
+  if (actual !== expected) {
+    fail(actual, expected, message, '===', assert.strictEqual);
+  }
+};
+
+// 10. The strict non-equality assertion tests for strict inequality, as
+// determined by !==.  assert.notStrictEqual(actual, expected, message_opt);
+
+assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
+  if (actual === expected) {
+    fail(actual, expected, message, '!==', assert.notStrictEqual);
+  }
+};
+
+function expectedException(actual, expected) {
+  if (!actual || !expected) {
+    return false;
+  }
+
+  if (Object.prototype.toString.call(expected) == '[object RegExp]') {
+    return expected.test(actual);
+  } else if (actual instanceof expected) {
+    return true;
+  } else if (expected.call({}, actual) === true) {
+    return true;
+  }
+
+  return false;
+}
+
+function _throws(shouldThrow, block, expected, message) {
+  var actual;
+
+  if (util.isString(expected)) {
+    message = expected;
+    expected = null;
+  }
+
+  try {
+    block();
+  } catch (e) {
+    actual = e;
+  }
+
+  message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
+            (message ? ' ' + message : '.');
+
+  if (shouldThrow && !actual) {
+    fail(actual, expected, 'Missing expected exception' + message);
+  }
+
+  if (!shouldThrow && expectedException(actual, expected)) {
+    fail(actual, expected, 'Got unwanted exception' + message);
+  }
+
+  if ((shouldThrow && actual && expected &&
+      !expectedException(actual, expected)) || (!shouldThrow && actual)) {
+    throw actual;
+  }
+}
+
+// 11. Expected to throw an error:
+// assert.throws(block, Error_opt, message_opt);
+
+assert.throws = function(block, /*optional*/error, /*optional*/message) {
+  _throws.apply(this, [true].concat(pSlice.call(arguments)));
+};
+
+// EXTENSION! This is annoying to write outside this module.
+assert.doesNotThrow = function(block, /*optional*/message) {
+  _throws.apply(this, [false].concat(pSlice.call(arguments)));
+};
+
+assert.ifError = function(err) { if (err) {throw err;}};
+
+var objectKeys = Object.keys || function (obj) {
+  var keys = [];
+  for (var key in obj) {
+    if (hasOwn.call(obj, key)) keys.push(key);
+  }
+  return keys;
+};
+
+},{"util/":9}],5:[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:
+        len = arguments.length;
+        args = new Array(len - 1);
+        for (i = 1; i < len; i++)
+          args[i - 1] = arguments[i];
+        handler.apply(this, args);
+    }
+  } else if (isObject(handler)) {
+    len = arguments.length;
+    args = new Array(len - 1);
+    for (i = 1; i < len; i++)
+      args[i - 1] = arguments[i];
+
+    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) {
+    var m;
+    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 {
+    // 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.listenerCount = function(emitter, type) {
+  var ret;
+  if (!emitter._events || !emitter._events[type])
+    ret = 0;
+  else if (isFunction(emitter._events[type]))
+    ret = 1;
+  else
+    ret = emitter._events[type].length;
+  return ret;
+};
+
+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;
+}
+
+},{}],6:[function(require,module,exports){
+// shim for using process in browser
+
+var process = module.exports = {};
+var queue = [];
+var draining = false;
+
+function drainQueue() {
+    if (draining) {
+        return;
+    }
+    draining = true;
+    var currentQueue;
+    var len = queue.length;
+    while(len) {
+        currentQueue = queue;
+        queue = [];
+        var i = -1;
+        while (++i < len) {
+            currentQueue[i]();
+        }
+        len = queue.length;
+    }
+    draining = false;
+}
+process.nextTick = function (fun) {
+    queue.push(fun);
+    if (!draining) {
+        setTimeout(drainQueue, 0);
+    }
+};
+
+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');
+};
+
+// TODO(shtylman)
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+    throw new Error('process.chdir is not supported');
+};
+process.umask = function() { return 0; };
+
+},{}],7:[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
+  }
+}
+
+},{}],8:[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';
+}
+},{}],9:[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":8,"_process":6,"inherits":7}],10:[function(require,module,exports){
+(function (global){
+/*global window, global*/
+var util = require("util")
+var assert = require("assert")
+var now = require("date-now")
+
+var slice = Array.prototype.slice
+var console
+var times = {}
+
+if (typeof global !== "undefined" && global.console) {
+    console = global.console
+} else if (typeof window !== "undefined" && window.console) {
+    console = window.console
+} else {
+    console = {}
+}
+
+var functions = [
+    [log, "log"],
+    [info, "info"],
+    [warn, "warn"],
+    [error, "error"],
+    [time, "time"],
+    [timeEnd, "timeEnd"],
+    [trace, "trace"],
+    [dir, "dir"],
+    [consoleAssert, "assert"]
+]
+
+for (var i = 0; i < functions.length; i++) {
+    var tuple = functions[i]
+    var f = tuple[0]
+    var name = tuple[1]
+
+    if (!console[name]) {
+        console[name] = f
+    }
+}
+
+module.exports = console
+
+function log() {}
+
+function info() {
+    console.log.apply(console, arguments)
+}
+
+function warn() {
+    console.log.apply(console, arguments)
+}
+
+function error() {
+    console.warn.apply(console, arguments)
+}
+
+function time(label) {
+    times[label] = now()
+}
+
+function timeEnd(label) {
+    var time = times[label]
+    if (!time) {
+        throw new Error("No such label: " + label)
+    }
+
+    var duration = now() - time
+    console.log(label + ": " + duration + "ms")
+}
+
+function trace() {
+    var err = new Error()
+    err.name = "Trace"
+    err.message = util.format.apply(null, arguments)
+    console.error(err.stack)
+}
+
+function dir(object) {
+    console.log(util.inspect(object) + "\n")
+}
+
+function consoleAssert(expression) {
+    if (!expression) {
+        var arr = slice.call(arguments, 1)
+        assert.ok(false, util.format.apply(null, arr))
+    }
+}
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{"assert":4,"date-now":11,"util":9}],11:[function(require,module,exports){
+module.exports = now
+
+function now() {
+    return new Date().getTime()
+}
+
+},{}],12:[function(require,module,exports){
+(function (global){
+/**
+ * @license
+ * lodash 3.7.0 (Custom Build) <https://lodash.com/>
+ * Build: `lodash modern -d -o ./index.js`
+ * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
+ * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
+ * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license <https://lodash.com/license>
+ */
+;(function() {
+
+  /** Used as a safe reference for `undefined` in pre-ES5 environments. */
+  var undefined;
+
+  /** Used as the semantic version number. */
+  var VERSION = '3.7.0';
+
+  /** Used to compose bitmasks for wrapper metadata. */
+  var BIND_FLAG = 1,
+      BIND_KEY_FLAG = 2,
+      CURRY_BOUND_FLAG = 4,
+      CURRY_FLAG = 8,
+      CURRY_RIGHT_FLAG = 16,
+      PARTIAL_FLAG = 32,
+      PARTIAL_RIGHT_FLAG = 64,
+      ARY_FLAG = 128,
+      REARG_FLAG = 256;
+
+  /** Used as default options for `_.trunc`. */
+  var DEFAULT_TRUNC_LENGTH = 30,
+      DEFAULT_TRUNC_OMISSION = '...';
+
+  /** Used to detect when a function becomes hot. */
+  var HOT_COUNT = 150,
+      HOT_SPAN = 16;
+
+  /** Used to indicate the type of lazy iteratees. */
+  var LAZY_DROP_WHILE_FLAG = 0,
+      LAZY_FILTER_FLAG = 1,
+      LAZY_MAP_FLAG = 2;
+
+  /** Used as the `TypeError` message for "Functions" methods. */
+  var FUNC_ERROR_TEXT = 'Expected a function';
+
+  /** Used as the internal argument placeholder. */
+  var PLACEHOLDER = '__lodash_placeholder__';
+
+  /** `Object#toString` result references. */
+  var argsTag = '[object Arguments]',
+      arrayTag = '[object Array]',
+      boolTag = '[object Boolean]',
+      dateTag = '[object Date]',
+      errorTag = '[object Error]',
+      funcTag = '[object Function]',
+      mapTag = '[object Map]',
+      numberTag = '[object Number]',
+      objectTag = '[object Object]',
+      regexpTag = '[object RegExp]',
+      setTag = '[object Set]',
+      stringTag = '[object String]',
+      weakMapTag = '[object WeakMap]';
+
+  var arrayBufferTag = '[object ArrayBuffer]',
+      float32Tag = '[object Float32Array]',
+      float64Tag = '[object Float64Array]',
+      int8Tag = '[object Int8Array]',
+      int16Tag = '[object Int16Array]',
+      int32Tag = '[object Int32Array]',
+      uint8Tag = '[object Uint8Array]',
+      uint8ClampedTag = '[object Uint8ClampedArray]',
+      uint16Tag = '[object Uint16Array]',
+      uint32Tag = '[object Uint32Array]';
+
+  /** Used to match empty string literals in compiled template source. */
+  var reEmptyStringLeading = /\b__p \+= '';/g,
+      reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
+      reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
+
+  /** Used to match HTML entities and HTML characters. */
+  var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g,
+      reUnescapedHtml = /[&<>"'`]/g,
+      reHasEscapedHtml = RegExp(reEscapedHtml.source),
+      reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
+
+  /** Used to match template delimiters. */
+  var reEscape = /<%-([\s\S]+?)%>/g,
+      reEvaluate = /<%([\s\S]+?)%>/g,
+      reInterpolate = /<%=([\s\S]+?)%>/g;
+
+  /** Used to match property names within property paths. */
+  var reIsDeepProp = /\.|\[(?:[^[\]]+|(["'])(?:(?!\1)[^\n\\]|\\.)*?)\1\]/,
+      reIsPlainProp = /^\w*$/,
+      rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g;
+
+  /**
+   * Used to match `RegExp` [special characters](http://www.regular-expressions.info/characters.html#special).
+   * In addition to special characters the forward slash is escaped to allow for
+   * easier `eval` use and `Function` compilation.
+   */
+  var reRegExpChars = /[.*+?^${}()|[\]\/\\]/g,
+      reHasRegExpChars = RegExp(reRegExpChars.source);
+
+  /** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */
+  var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g;
+
+  /** Used to match backslashes in property paths. */
+  var reEscapeChar = /\\(\\)?/g;
+
+  /** Used to match [ES template delimiters](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-template-literal-lexical-components). */
+  var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
+
+  /** Used to match `RegExp` flags from their coerced string values. */
+  var reFlags = /\w*$/;
+
+  /** Used to detect hexadecimal string values. */
+  var reHasHexPrefix = /^0[xX]/;
+
+  /** Used to detect host constructors (Safari > 5). */
+  var reIsHostCtor = /^\[object .+?Constructor\]$/;
+
+  /** Used to match latin-1 supplementary letters (excluding mathematical operators). */
+  var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g;
+
+  /** Used to ensure capturing order of template delimiters. */
+  var reNoMatch = /($^)/;
+
+  /** Used to match unescaped characters in compiled string literals. */
+  var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
+
+  /** Used to match words to create compound words. */
+  var reWords = (function() {
+    var upper = '[A-Z\\xc0-\\xd6\\xd8-\\xde]',
+        lower = '[a-z\\xdf-\\xf6\\xf8-\\xff]+';
+
+    return RegExp(upper + '+(?=' + upper + lower + ')|' + upper + '?' + lower + '|' + upper + '+|[0-9]+', 'g');
+  }());
+
+  /** Used to detect and test for whitespace. */
+  var whitespace = (
+    // Basic whitespace characters.
+    ' \t\x0b\f\xa0\ufeff' +
+
+    // Line terminators.
+    '\n\r\u2028\u2029' +
+
+    // Unicode category "Zs" space separators.
+    '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'
+  );
+
+  /** Used to assign default `context` object properties. */
+  var contextProps = [
+    'Array', 'ArrayBuffer', 'Date', 'Error', 'Float32Array', 'Float64Array',
+    'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number',
+    'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'document',
+    'isFinite', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array',
+    'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',
+    'window'
+  ];
+
+  /** Used to make template sourceURLs easier to identify. */
+  var templateCounter = -1;
+
+  /** Used to identify `toStringTag` values of typed arrays. */
+  var typedArrayTags = {};
+  typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
+  typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
+  typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
+  typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
+  typedArrayTags[uint32Tag] = true;
+  typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
+  typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
+  typedArrayTags[dateTag] = typedArrayTags[errorTag] =
+  typedArrayTags[funcTag] = typedArrayTags[mapTag] =
+  typedArrayTags[numberTag] = typedArrayTags[objectTag] =
+  typedArrayTags[regexpTag] = typedArrayTags[setTag] =
+  typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
+
+  /** Used to identify `toStringTag` values supported by `_.clone`. */
+  var cloneableTags = {};
+  cloneableTags[argsTag] = cloneableTags[arrayTag] =
+  cloneableTags[arrayBufferTag] = cloneableTags[boolTag] =
+  cloneableTags[dateTag] = cloneableTags[float32Tag] =
+  cloneableTags[float64Tag] = cloneableTags[int8Tag] =
+  cloneableTags[int16Tag] = cloneableTags[int32Tag] =
+  cloneableTags[numberTag] = cloneableTags[objectTag] =
+  cloneableTags[regexpTag] = cloneableTags[stringTag] =
+  cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
+  cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
+  cloneableTags[errorTag] = cloneableTags[funcTag] =
+  cloneableTags[mapTag] = cloneableTags[setTag] =
+  cloneableTags[weakMapTag] = false;
+
+  /** Used as an internal `_.debounce` options object by `_.throttle`. */
+  var debounceOptions = {
+    'leading': false,
+    'maxWait': 0,
+    'trailing': false
+  };
+
+  /** Used to map latin-1 supplementary letters to basic latin letters. */
+  var deburredLetters = {
+    '\xc0': 'A',  '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
+    '\xe0': 'a',  '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
+    '\xc7': 'C',  '\xe7': 'c',
+    '\xd0': 'D',  '\xf0': 'd',
+    '\xc8': 'E',  '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
+    '\xe8': 'e',  '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
+    '\xcC': 'I',  '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
+    '\xeC': 'i',  '\xed': 'i', '\xee': 'i', '\xef': 'i',
+    '\xd1': 'N',  '\xf1': 'n',
+    '\xd2': 'O',  '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
+    '\xf2': 'o',  '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
+    '\xd9': 'U',  '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
+    '\xf9': 'u',  '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
+    '\xdd': 'Y',  '\xfd': 'y', '\xff': 'y',
+    '\xc6': 'Ae', '\xe6': 'ae',
+    '\xde': 'Th', '\xfe': 'th',
+    '\xdf': 'ss'
+  };
+
+  /** Used to map characters to HTML entities. */
+  var htmlEscapes = {
+    '&': '&amp;',
+    '<': '&lt;',
+    '>': '&gt;',
+    '"': '&quot;',
+    "'": '&#39;',
+    '`': '&#96;'
+  };
+
+  /** Used to map HTML entities to characters. */
+  var htmlUnescapes = {
+    '&amp;': '&',
+    '&lt;': '<',
+    '&gt;': '>',
+    '&quot;': '"',
+    '&#39;': "'",
+    '&#96;': '`'
+  };
+
+  /** Used to determine if values are of the language type `Object`. */
+  var objectTypes = {
+    'function': true,
+    'object': true
+  };
+
+  /** Used to escape characters for inclusion in compiled string literals. */
+  var stringEscapes = {
+    '\\': '\\',
+    "'": "'",
+    '\n': 'n',
+    '\r': 'r',
+    '\u2028': 'u2028',
+    '\u2029': 'u2029'
+  };
+
+  /** Detect free variable `exports`. */
+  var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
+
+  /** Detect free variable `module`. */
+  var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
+
+  /** Detect free variable `global` from Node.js. */
+  var freeGlobal = freeExports && freeModule && typeof global == 'object' && global && global.Object && global;
+
+  /** Detect free variable `self`. */
+  var freeSelf = objectTypes[typeof self] && self && self.Object && self;
+
+  /** Detect free variable `window`. */
+  var freeWindow = objectTypes[typeof window] && window && window.Object && window;
+
+  /** Detect the popular CommonJS extension `module.exports`. */
+  var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
+
+  /**
+   * Used as a reference to the global object.
+   *
+   * The `this` value is used if it is the global object to avoid Greasemonkey's
+   * restricted `window` object, otherwise the `window` object is used.
+   */
+  var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || freeSelf || this;
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * The base implementation of `compareAscending` which compares values and
+   * sorts them in ascending order without guaranteeing a stable sort.
+   *
+   * @private
+   * @param {*} value The value to compare to `other`.
+   * @param {*} other The value to compare to `value`.
+   * @returns {number} Returns the sort order indicator for `value`.
+   */
+  function baseCompareAscending(value, other) {
+    if (value !== other) {
+      var valIsReflexive = value === value,
+          othIsReflexive = other === other;
+
+      if (value > other || !valIsReflexive || (value === undefined && othIsReflexive)) {
+        return 1;
+      }
+      if (value < other || !othIsReflexive || (other === undefined && valIsReflexive)) {
+        return -1;
+      }
+    }
+    return 0;
+  }
+
+  /**
+   * The base implementation of `_.findIndex` and `_.findLastIndex` without
+   * support for callback shorthands and `this` binding.
+   *
+   * @private
+   * @param {Array} array The array to search.
+   * @param {Function} predicate The function invoked per iteration.
+   * @param {boolean} [fromRight] Specify iterating from right to left.
+   * @returns {number} Returns the index of the matched value, else `-1`.
+   */
+  function baseFindIndex(array, predicate, fromRight) {
+    var length = array.length,
+        index = fromRight ? length : -1;
+
+    while ((fromRight ? index-- : ++index < length)) {
+      if (predicate(array[index], index, array)) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * The base implementation of `_.indexOf` without support for binary searches.
+   *
+   * @private
+   * @param {Array} array The array to search.
+   * @param {*} value The value to search for.
+   * @param {number} fromIndex The index to search from.
+   * @returns {number} Returns the index of the matched value, else `-1`.
+   */
+  function baseIndexOf(array, value, fromIndex) {
+    if (value !== value) {
+      return indexOfNaN(array, fromIndex);
+    }
+    var index = fromIndex - 1,
+        length = array.length;
+
+    while (++index < length) {
+      if (array[index] === value) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * The base implementation of `_.isFunction` without support for environments
+   * with incorrect `typeof` results.
+   *
+   * @private
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+   */
+  function baseIsFunction(value) {
+    // Avoid a Chakra JIT bug in compatibility modes of IE 11.
+    // See https://github.com/jashkenas/underscore/issues/1621 for more details.
+    return typeof value == 'function' || false;
+  }
+
+  /**
+   * Converts `value` to a string if it is not one. An empty string is returned
+   * for `null` or `undefined` values.
+   *
+   * @private
+   * @param {*} value The value to process.
+   * @returns {string} Returns the string.
+   */
+  function baseToString(value) {
+    if (typeof value == 'string') {
+      return value;
+    }
+    return value == null ? '' : (value + '');
+  }
+
+  /**
+   * Used by `_.max` and `_.min` as the default callback for string values.
+   *
+   * @private
+   * @param {string} string The string to inspect.
+   * @returns {number} Returns the code unit of the first character of the string.
+   */
+  function charAtCallback(string) {
+    return string.charCodeAt(0);
+  }
+
+  /**
+   * Used by `_.trim` and `_.trimLeft` to get the index of the first character
+   * of `string` that is not found in `chars`.
+   *
+   * @private
+   * @param {string} string The string to inspect.
+   * @param {string} chars The characters to find.
+   * @returns {number} Returns the index of the first character not found in `chars`.
+   */
+  function charsLeftIndex(string, chars) {
+    var index = -1,
+        length = string.length;
+
+    while (++index < length && chars.indexOf(string.charAt(index)) > -1) {}
+    return index;
+  }
+
+  /**
+   * Used by `_.trim` and `_.trimRight` to get the index of the last character
+   * of `string` that is not found in `chars`.
+   *
+   * @private
+   * @param {string} string The string to inspect.
+   * @param {string} chars The characters to find.
+   * @returns {number} Returns the index of the last character not found in `chars`.
+   */
+  function charsRightIndex(string, chars) {
+    var index = string.length;
+
+    while (index-- && chars.indexOf(string.charAt(index)) > -1) {}
+    return index;
+  }
+
+  /**
+   * Used by `_.sortBy` to compare transformed elements of a collection and stable
+   * sort them in ascending order.
+   *
+   * @private
+   * @param {Object} object The object to compare to `other`.
+   * @param {Object} other The object to compare to `object`.
+   * @returns {number} Returns the sort order indicator for `object`.
+   */
+  function compareAscending(object, other) {
+    return baseCompareAscending(object.criteria, other.criteria) || (object.index - other.index);
+  }
+
+  /**
+   * Used by `_.sortByOrder` to compare multiple properties of each element
+   * in a collection and stable sort them in the following order:
+   *
+   * If `orders` is unspecified, sort in ascending order for all properties.
+   * Otherwise, for each property, sort in ascending order if its corresponding value in
+   * orders is true, and descending order if false.
+   *
+   * @private
+   * @param {Object} object The object to compare to `other`.
+   * @param {Object} other The object to compare to `object`.
+   * @param {boolean[]} orders The order to sort by for each property.
+   * @returns {number} Returns the sort order indicator for `object`.
+   */
+  function compareMultiple(object, other, orders) {
+    var index = -1,
+        objCriteria = object.criteria,
+        othCriteria = other.criteria,
+        length = objCriteria.length,
+        ordersLength = orders.length;
+
+    while (++index < length) {
+      var result = baseCompareAscending(objCriteria[index], othCriteria[index]);
+      if (result) {
+        if (index >= ordersLength) {
+          return result;
+        }
+        return result * (orders[index] ? 1 : -1);
+      }
+    }
+    // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
+    // that causes it, under certain circumstances, to provide the same value for
+    // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
+    // for more details.
+    //
+    // This also ensures a stable sort in V8 and other engines.
+    // See https://code.google.com/p/v8/issues/detail?id=90 for more details.
+    return object.index - other.index;
+  }
+
+  /**
+   * Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters.
+   *
+   * @private
+   * @param {string} letter The matched letter to deburr.
+   * @returns {string} Returns the deburred letter.
+   */
+  function deburrLetter(letter) {
+    return deburredLetters[letter];
+  }
+
+  /**
+   * Used by `_.escape` to convert characters to HTML entities.
+   *
+   * @private
+   * @param {string} chr The matched character to escape.
+   * @returns {string} Returns the escaped character.
+   */
+  function escapeHtmlChar(chr) {
+    return htmlEscapes[chr];
+  }
+
+  /**
+   * Used by `_.template` to escape characters for inclusion in compiled
+   * string literals.
+   *
+   * @private
+   * @param {string} chr The matched character to escape.
+   * @returns {string} Returns the escaped character.
+   */
+  function escapeStringChar(chr) {
+    return '\\' + stringEscapes[chr];
+  }
+
+  /**
+   * Gets the index at which the first occurrence of `NaN` is found in `array`.
+   *
+   * @private
+   * @param {Array} array The array to search.
+   * @param {number} fromIndex The index to search from.
+   * @param {boolean} [fromRight] Specify iterating from right to left.
+   * @returns {number} Returns the index of the matched `NaN`, else `-1`.
+   */
+  function indexOfNaN(array, fromIndex, fromRight) {
+    var length = array.length,
+        index = fromIndex + (fromRight ? 0 : -1);
+
+    while ((fromRight ? index-- : ++index < length)) {
+      var other = array[index];
+      if (other !== other) {
+        return index;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Checks if `value` is object-like.
+   *
+   * @private
+   * @param {*} value The value to check.
+   * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+   */
+  function isObjectLike(value) {
+    return !!value && typeof value == 'object';
+  }
+
+  /**
+   * Used by `trimmedLeftIndex` and `trimmedRightIndex` to determine if a
+   * character code is whitespace.
+   *
+   * @private
+   * @param {number} charCode The character code to inspect.
+   * @returns {boolean} Returns `true` if `charCode` is whitespace, else `false`.
+   */
+  function isSpace(charCode) {
+    return ((charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160) || charCode == 5760 || charCode == 6158 ||
+      (charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279)));
+  }
+
+  /**
+   * Replaces all `placeholder` elements in `array` with an internal placeholder
+   * and returns an array of their indexes.
+   *
+   * @private
+   * @param {Array} array The array to modify.
+   * @param {*} placeholder The placeholder to replace.
+   * @returns {Array} Returns the new array of placeholder indexes.
+   */
+  function replaceHolders(array, placeholder) {
+    var index = -1,
+        length = array.length,
+        resIndex = -1,
+        result = [];
+
+    while (++index < length) {
+      if (array[index] === placeholder) {
+        array[index] = PLACEHOLDER;
+        result[++resIndex] = index;
+      }
+    }
+    return result;
+  }
+
+  /**
+   * An implementation of `_.uniq` optimized for sorted arrays without support
+   * for callback shorthands and `this` binding.
+   *
+   * @private
+   * @param {Array} array The array to inspect.
+   * @param {Function} [iteratee] The function invoked per iteration.
+   * @returns {Array} Returns the new duplicate-value-free array.
+   */
+  function sortedUniq(array, iteratee) {
+    var seen,
+        index = -1,
+        length = array.length,
+        resIndex = -1,
+        result = [];
+
+    while (++index < length) {
+      var value = array[index],
+          computed = iteratee ? iteratee(value, index, array) : value;
+
+      if (!index || seen !== computed) {
+        seen = computed;
+        result[++resIndex] = value;
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Used by `_.trim` and `_.trimLeft` to get the index of the first non-whitespace
+   * character of `string`.
+   *
+   * @private
+   * @param {string} string The string to inspect.
+   * @returns {number} Returns the index of the first non-whitespace character.
+   */
+  function trimmedLeftIndex(string) {
+    var index = -1,
+        length = string.length;
+
+    while (++index < length && isSpace(string.charCodeAt(index))) {}
+    return index;
+  }
+
+  /**
+   * Used by `_.trim` and `_.trimRight` to get the index of the last non-whitespace
+   * character of `string`.
+   *
+   * @private
+   * @param {string} string The string to inspect.
+   * @returns {number} Returns the index of the last non-whitespace character.
+   */
+  function trimmedRightIndex(string) {
+    var index = string.length;
+
+    while (index-- && isSpace(string.charCodeAt(index))) {}
+    return index;
+  }
+
+  /**
+   * Used by `_.unescape` to convert HTML entities to characters.
+   *
+   * @private
+   * @param {string} chr The matched character to unescape.
+   * @returns {string} Returns the unescaped character.
+   */
+  function unescapeHtmlChar(chr) {
+    return htmlUnescapes[chr];
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  /**
+   * Create a new pristine `lodash` function using the given `context` object.
+   *
+   * @static
+   * @memberOf _
+   * @category Utility
+   * @param {Object} [context=root] The context object.
+   * @returns {Function} Returns a new `lodash` function.
+   * @example
+   *
+   * _.mixin({ 'foo': _.constant('foo') });
+   *
+   * var lodash = _.runInContext();
+   * lodash.mixin({ 'bar': lodash.constant('bar') });
+   *
+   * _.isFunction(_.foo);
+   * // => true
+   * _.isFunction(_.bar);
+   * // => false
+   *
+   * lodash.isFunction(lodash.foo);
+   * // => false
+   * lodash.isFunction(lodash.bar);
+   * // => true
+   *
+   * // using `context` to mock `Date#getTime` use in `_.now`
+   * var mock = _.runInContext({
+   *   'Date': function() {
+   *     return { 'getTime': getTimeMock };
+   *   }
+   * });
+   *
+   * // or creating a suped-up `defer` in Node.js
+   * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
+   */
+  function runInContext(context) {
+    // Avoid issues with some ES3 environments that attempt to use values, named
+    // after built-in constructors like `Object`, for the creation of literals.
+    // ES5 clears this up by stating that literals must use built-in constructors.
+    // See https://es5.github.io/#x11.1.5 for more details.
+    context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
+
+    /** Native constructor references. */
+    var Array = context.Array,
+        Date = context.Date,
+        Error = context.Error,
+        Function = context.Function,
+        Math = context.Math,
+        Number = context.Number,
+        Object = context.Object,
+        RegExp = context.RegExp,
+        String = context.String,
+        TypeError = context.TypeError;
+
+    /** Used for native method references. */
+    var arrayProto = Array.prototype,
+        objectProto = Object.prototype,
+        stringProto = String.prototype;
+
+    /** Used to detect DOM support. */
+    var document = (document = context.window) && document.document;
+
+    /** Used to resolve the decompiled source of functions. */
+    var fnToString = Function.prototype.toString;
+
+    /** Used to check objects for own properties. */
+    var hasOwnProperty = objectProto.hasOwnProperty;
+
+    /** Used to generate unique IDs. */
+    var idCounter = 0;
+
+    /**
+     * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)
+     * of values.
+     */
+    var objToString = objectProto.toString;
+
+    /** Used to restore the original `_` reference in `_.noConflict`. */
+    var oldDash = context._;
+
+    /** Used to detect if a method is native. */
+    var reIsNative = RegExp('^' +
+      escapeRegExp(objToString)
+      .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
+    );
+
+    /** Native method references. */
+    var ArrayBuffer = isNative(ArrayBuffer = context.ArrayBuffer) && ArrayBuffer,
+        bufferSlice = isNative(bufferSlice = ArrayBuffer && new ArrayBuffer(0).slice) && bufferSlice,
+        ceil = Math.ceil,
+        clearTimeout = context.clearTimeout,
+        floor = Math.floor,
+        getOwnPropertySymbols = isNative(getOwnPropertySymbols = Object.getOwnPropertySymbols) && getOwnPropertySymbols,
+        getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
+        push = arrayProto.push,
+        preventExtensions = isNative(Object.preventExtensions = Object.preventExtensions) && preventExtensions,
+        propertyIsEnumerable = objectProto.propertyIsEnumerable,
+        Set = isNative(Set = context.Set) && Set,
+        setTimeout = context.setTimeout,
+        splice = arrayProto.splice,
+        Uint8Array = isNative(Uint8Array = context.Uint8Array) && Uint8Array,
+        WeakMap = isNative(WeakMap = context.WeakMap) && WeakMap;
+
+    /** Used to clone array buffers. */
+    var Float64Array = (function() {
+      // Safari 5 errors when using an array buffer to initialize a typed array
+      // where the array buffer's `byteLength` is not a multiple of the typed
+      // array's `BYTES_PER_ELEMENT`.
+      try {
+        var func = isNative(func = context.Float64Array) && func,
+            result = new func(new ArrayBuffer(10), 0, 1) && func;
+      } catch(e) {}
+      return result;
+    }());
+
+    /** Used as `baseAssign`. */
+    var nativeAssign = (function() {
+      // Avoid `Object.assign` in Firefox 34-37 which have an early implementation
+      // with a now defunct try/catch behavior. See https://bugzilla.mozilla.org/show_bug.cgi?id=1103344
+      // for more details.
+      //
+      // Use `Object.preventExtensions` on a plain object instead of simply using
+      // `Object('x')` because Chrome and IE fail to throw an error when attempting
+      // to assign values to readonly indexes of strings in strict mode.
+      var object = { '1': 0 },
+          func = preventExtensions && isNative(func = Object.assign) && func;
+
+      try { func(preventExtensions(object), 'xo'); } catch(e) {}
+      return !object[1] && func;
+    }());
+
+    /* Native method references for those with the same name as other `lodash` methods. */
+    var nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray,
+        nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate,
+        nativeIsFinite = context.isFinite,
+        nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys,
+        nativeMax = Math.max,
+        nativeMin = Math.min,
+        nativeNow = isNative(nativeNow = Date.now) && nativeNow,
+        nativeNumIsFinite = isNative(nativeNumIsFinite = Number.isFinite) && nativeNumIsFinite,
+        nativeParseInt = context.parseInt,
+        nativeRandom = Math.random;
+
+    /** Used as references for `-Infinity` and `Infinity`. */
+    var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY,
+        POSITIVE_INFINITY = Number.POSITIVE_INFINITY;
+
+    /** Used as references for the maximum length and index of an array. */
+    var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1,
+        MAX_ARRAY_INDEX =  MAX_ARRAY_LENGTH - 1,
+        HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
+
+    /** Used as the size, in bytes, of each `Float64Array` element. */
+    var FLOAT64_BYTES_PER_ELEMENT = Float64Array ? Float64Array.BYTES_PER_ELEMENT : 0;
+
+    /**
+     * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)
+     * of an array-like value.
+     */
+    var MAX_SAFE_INTEGER = Math.pow(2, 53) - 1;
+
+    /** Used to store function metadata. */
+    var metaMap = WeakMap && new WeakMap;
+
+    /** Used to lookup unminified function names. */
+    var realNames = {};
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * Creates a `lodash` object which wraps `value` to enable implicit chaining.
+     * Methods that operate on and return arrays, collections, and functions can
+     * be chained together. Methods that return a boolean or single value will
+     * automatically end the chain returning the unwrapped value. Explicit chaining
+     * may be enabled using `_.chain`. The execution of chained methods is lazy,
+     * that is, execution is deferred until `_#value` is implicitly or explicitly
+     * called.
+     *
+     * Lazy evaluation allows several methods to support shortcut fusion. Shortcut
+     * fusion is an optimization that merges iteratees to avoid creating intermediate
+     * arrays and reduce the number of iteratee executions.
+     *
+     * Chaining is supported in custom builds as long as the `_#value` method is
+     * directly or indirectly included in the build.
+     *
+     * In addition to lodash methods, wrappers have `Array` and `String` methods.
+     *
+     * The wrapper `Array` methods are:
+     * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`,
+     * `splice`, and `unshift`
+     *
+     * The wrapper `String` methods are:
+     * `replace` and `split`
+     *
+     * The wrapper methods that support shortcut fusion are:
+     * `compact`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`,
+     * `first`, `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`,
+     * `slice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `toArray`,
+     * and `where`
+     *
+     * The chainable wrapper methods are:
+     * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`,
+     * `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`,
+     * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defer`, `delay`,
+     * `difference`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `fill`,
+     * `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, `forEach`,
+     * `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `functions`,
+     * `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, `invoke`, `keys`,
+     * `keysIn`, `map`, `mapValues`, `matches`, `matchesProperty`, `memoize`,
+     * `merge`, `mixin`, `negate`, `omit`, `once`, `pairs`, `partial`, `partialRight`,
+     * `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`,
+     * `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `reverse`,
+     * `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`, `sortByOrder`, `splice`,
+     * `spread`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `tap`,
+     * `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, `transform`,
+     * `union`, `uniq`, `unshift`, `unzip`, `values`, `valuesIn`, `where`,
+     * `without`, `wrap`, `xor`, `zip`, and `zipObject`
+     *
+     * The wrapper methods that are **not** chainable by default are:
+     * `add`, `attempt`, `camelCase`, `capitalize`, `clone`, `cloneDeep`, `deburr`,
+     * `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`,
+     * `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, `has`,
+     * `identity`, `includes`, `indexOf`, `inRange`, `isArguments`, `isArray`,
+     * `isBoolean`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isError`, `isFinite`
+     * `isFunction`, `isMatch`, `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`,
+     * `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `isTypedArray`,
+     * `join`, `kebabCase`, `last`, `lastIndexOf`, `max`, `min`, `noConflict`,
+     * `noop`, `now`, `pad`, `padLeft`, `padRight`, `parseInt`, `pop`, `random`,
+     * `reduce`, `reduceRight`, `repeat`, `result`, `runInContext`, `shift`, `size`,
+     * `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, `startCase`, `startsWith`,
+     * `sum`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`, `unescape`,
+     * `uniqueId`, `value`, and `words`
+     *
+     * The wrapper method `sample` will return a wrapped value when `n` is provided,
+     * otherwise an unwrapped value is returned.
+     *
+     * @name _
+     * @constructor
+     * @category Chain
+     * @param {*} value The value to wrap in a `lodash` instance.
+     * @returns {Object} Returns the new `lodash` wrapper instance.
+     * @example
+     *
+     * var wrapped = _([1, 2, 3]);
+     *
+     * // returns an unwrapped value
+     * wrapped.reduce(function(total, n) {
+     *   return total + n;
+     * });
+     * // => 6
+     *
+     * // returns a wrapped value
+     * var squares = wrapped.map(function(n) {
+     *   return n * n;
+     * });
+     *
+     * _.isArray(squares);
+     * // => false
+     *
+     * _.isArray(squares.value());
+     * // => true
+     */
+    function lodash(value) {
+      if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
+        if (value instanceof LodashWrapper) {
+          return value;
+        }
+        if (hasOwnProperty.call(value, '__chain__') && hasOwnProperty.call(value, '__wrapped__')) {
+          return wrapperClone(value);
+        }
+      }
+      return new LodashWrapper(value);
+    }
+
+    /**
+     * The function whose prototype all chaining wrappers inherit from.
+     *
+     * @private
+     */
+    function baseLodash() {
+      // No operation performed.
+    }
+
+    /**
+     * The base constructor for creating `lodash` wrapper objects.
+     *
+     * @private
+     * @param {*} value The value to wrap.
+     * @param {boolean} [chainAll] Enable chaining for all wrapper methods.
+     * @param {Array} [actions=[]] Actions to peform to resolve the unwrapped value.
+     */
+    function LodashWrapper(value, chainAll, actions) {
+      this.__wrapped__ = value;
+      this.__actions__ = actions || [];
+      this.__chain__ = !!chainAll;
+    }
+
+    /**
+     * An object environment feature flags.
+     *
+     * @static
+     * @memberOf _
+     * @type Object
+     */
+    var support = lodash.support = {};
+
+    (function(x) {
+      var Ctor = function() { this.x = x; },
+          object = { '0': x, 'length': x },
+          props = [];
+
+      Ctor.prototype = { 'valueOf': x, 'y': x };
+      for (var key in new Ctor) { props.push(key); }
+
+      /**
+       * Detect if functions can be decompiled by `Function#toString`
+       * (all but Firefox OS certified apps, older Opera mobile browsers, and
+       * the PlayStation 3; forced `false` for Windows 8 apps).
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.funcDecomp = /\bthis\b/.test(function() { return this; });
+
+      /**
+       * Detect if `Function#name` is supported (all but IE).
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      support.funcNames = typeof Function.name == 'string';
+
+      /**
+       * Detect if the DOM is supported.
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      try {
+        support.dom = document.createDocumentFragment().nodeType === 11;
+      } catch(e) {
+        support.dom = false;
+      }
+
+      /**
+       * Detect if `arguments` object indexes are non-enumerable.
+       *
+       * In Firefox < 4, IE < 9, PhantomJS, and Safari < 5.1 `arguments` object
+       * indexes are non-enumerable. Chrome < 25 and Node.js < 0.11.0 treat
+       * `arguments` object indexes as non-enumerable and fail `hasOwnProperty`
+       * checks for indexes that exceed the number of function parameters and
+       * whose associated argument values are `0`.
+       *
+       * @memberOf _.support
+       * @type boolean
+       */
+      try {
+        support.nonEnumArgs = !propertyIsEnumerable.call(arguments, 1);
+      } catch(e) {
+        support.nonEnumArgs = true;
+      }
+    }(1, 0));
+
+    /**
+     * By default, the template delimiters used by lodash are like those in
+     * embedded Ruby (ERB). Change the following template settings to use
+     * alternative delimiters.
+     *
+     * @static
+     * @memberOf _
+     * @type Object
+     */
+    lodash.templateSettings = {
+
+      /**
+       * Used to detect `data` property values to be HTML-escaped.
+       *
+       * @memberOf _.templateSettings
+       * @type RegExp
+       */
+      'escape': reEscape,
+
+      /**
+       * Used to detect code to be evaluated.
+       *
+       * @memberOf _.templateSettings
+       * @type RegExp
+       */
+      'evaluate': reEvaluate,
+
+      /**
+       * Used to detect `data` property values to inject.
+       *
+       * @memberOf _.templateSettings
+       * @type RegExp
+       */
+      'interpolate': reInterpolate,
+
+      /**
+       * Used to reference the data object in the template text.
+       *
+       * @memberOf _.templateSettings
+       * @type string
+       */
+      'variable': '',
+
+      /**
+       * Used to import variables into the compiled template.
+       *
+       * @memberOf _.templateSettings
+       * @type Object
+       */
+      'imports': {
+
+        /**
+         * A reference to the `lodash` function.
+         *
+         * @memberOf _.templateSettings.imports
+         * @type Function
+         */
+        '_': lodash
+      }
+    };
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
+     *
+     * @private
+     * @param {*} value The value to wrap.
+     */
+    function LazyWrapper(value) {
+      this.__wrapped__ = value;
+      this.__actions__ = null;
+      this.__dir__ = 1;
+      this.__dropCount__ = 0;
+      this.__filtered__ = false;
+      this.__iteratees__ = null;
+      this.__takeCount__ = POSITIVE_INFINITY;
+      this.__views__ = null;
+    }
+
+    /**
+     * Creates a clone of the lazy wrapper object.
+     *
+     * @private
+     * @name clone
+     * @memberOf LazyWrapper
+     * @returns {Object} Returns the cloned `LazyWrapper` object.
+     */
+    function lazyClone() {
+      var actions = this.__actions__,
+          iteratees = this.__iteratees__,
+          views = this.__views__,
+          result = new LazyWrapper(this.__wrapped__);
+
+      result.__actions__ = actions ? arrayCopy(actions) : null;
+      result.__dir__ = this.__dir__;
+      result.__filtered__ = this.__filtered__;
+      result.__iteratees__ = iteratees ? arrayCopy(iteratees) : null;
+      result.__takeCount__ = this.__takeCount__;
+      result.__views__ = views ? arrayCopy(views) : null;
+      return result;
+    }
+
+    /**
+     * Reverses the direction of lazy iteration.
+     *
+     * @private
+     * @name reverse
+     * @memberOf LazyWrapper
+     * @returns {Object} Returns the new reversed `LazyWrapper` object.
+     */
+    function lazyReverse() {
+      if (this.__filtered__) {
+        var result = new LazyWrapper(this);
+        result.__dir__ = -1;
+        result.__filtered__ = true;
+      } else {
+        result = this.clone();
+        result.__dir__ *= -1;
+      }
+      return result;
+    }
+
+    /**
+     * Extracts the unwrapped value from its lazy wrapper.
+     *
+     * @private
+     * @name value
+     * @memberOf LazyWrapper
+     * @returns {*} Returns the unwrapped value.
+     */
+    function lazyValue() {
+      var array = this.__wrapped__.value();
+      if (!isArray(array)) {
+        return baseWrapperValue(array, this.__actions__);
+      }
+      var dir = this.__dir__,
+          isRight = dir < 0,
+          view = getView(0, array.length, this.__views__),
+          start = view.start,
+          end = view.end,
+          length = end - start,
+          index = isRight ? end : (start - 1),
+          takeCount = nativeMin(length, this.__takeCount__),
+          iteratees = this.__iteratees__,
+          iterLength = iteratees ? iteratees.length : 0,
+          resIndex = 0,
+          result = [];
+
+      outer:
+      while (length-- && resIndex < takeCount) {
+        index += dir;
+
+        var iterIndex = -1,
+            value = array[index];
+
+        while (++iterIndex < iterLength) {
+          var data = iteratees[iterIndex],
+              iteratee = data.iteratee,
+              type = data.type;
+
+          if (type == LAZY_DROP_WHILE_FLAG) {
+            if (data.done && (isRight ? (index > data.index) : (index < data.index))) {
+              data.count = 0;
+              data.done = false;
+            }
+            data.index = index;
+            if (!data.done) {
+              var limit = data.limit;
+              if (!(data.done = limit > -1 ? (data.count++ >= limit) : !iteratee(value))) {
+                continue outer;
+              }
+            }
+          } else {
+            var computed = iteratee(value);
+            if (type == LAZY_MAP_FLAG) {
+              value = computed;
+            } else if (!computed) {
+              if (type == LAZY_FILTER_FLAG) {
+                continue outer;
+              } else {
+                break outer;
+              }
+            }
+          }
+        }
+        result[resIndex++] = value;
+      }
+      return result;
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * Creates a cache object to store key/value pairs.
+     *
+     * @private
+     * @static
+     * @name Cache
+     * @memberOf _.memoize
+     */
+    function MapCache() {
+      this.__data__ = {};
+    }
+
+    /**
+     * Removes `key` and its value from the cache.
+     *
+     * @private
+     * @name delete
+     * @memberOf _.memoize.Cache
+     * @param {string} key The key of the value to remove.
+     * @returns {boolean} Returns `true` if the entry was removed successfully, else `false`.
+     */
+    function mapDelete(key) {
+      return this.has(key) && delete this.__data__[key];
+    }
+
+    /**
+     * Gets the cached value for `key`.
+     *
+     * @private
+     * @name get
+     * @memberOf _.memoize.Cache
+     * @param {string} key The key of the value to get.
+     * @returns {*} Returns the cached value.
+     */
+    function mapGet(key) {
+      return key == '__proto__' ? undefined : this.__data__[key];
+    }
+
+    /**
+     * Checks if a cached value for `key` exists.
+     *
+     * @private
+     * @name has
+     * @memberOf _.memoize.Cache
+     * @param {string} key The key of the entry to check.
+     * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+     */
+    function mapHas(key) {
+      return key != '__proto__' && hasOwnProperty.call(this.__data__, key);
+    }
+
+    /**
+     * Sets `value` to `key` of the cache.
+     *
+     * @private
+     * @name set
+     * @memberOf _.memoize.Cache
+     * @param {string} key The key of the value to cache.
+     * @param {*} value The value to cache.
+     * @returns {Object} Returns the cache object.
+     */
+    function mapSet(key, value) {
+      if (key != '__proto__') {
+        this.__data__[key] = value;
+      }
+      return this;
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     *
+     * Creates a cache object to store unique values.
+     *
+     * @private
+     * @param {Array} [values] The values to cache.
+     */
+    function SetCache(values) {
+      var length = values ? values.length : 0;
+
+      this.data = { 'hash': nativeCreate(null), 'set': new Set };
+      while (length--) {
+        this.push(values[length]);
+      }
+    }
+
+    /**
+     * Checks if `value` is in `cache` mimicking the return signature of
+     * `_.indexOf` by returning `0` if the value is found, else `-1`.
+     *
+     * @private
+     * @param {Object} cache The cache to search.
+     * @param {*} value The value to search for.
+     * @returns {number} Returns `0` if `value` is found, else `-1`.
+     */
+    function cacheIndexOf(cache, value) {
+      var data = cache.data,
+          result = (typeof value == 'string' || isObject(value)) ? data.set.has(value) : data.hash[value];
+
+      return result ? 0 : -1;
+    }
+
+    /**
+     * Adds `value` to the cache.
+     *
+     * @private
+     * @name push
+     * @memberOf SetCache
+     * @param {*} value The value to cache.
+     */
+    function cachePush(value) {
+      var data = this.data;
+      if (typeof value == 'string' || isObject(value)) {
+        data.set.add(value);
+      } else {
+        data.hash[value] = true;
+      }
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * Copies the values of `source` to `array`.
+     *
+     * @private
+     * @param {Array} source The array to copy values from.
+     * @param {Array} [array=[]] The array to copy values to.
+     * @returns {Array} Returns `array`.
+     */
+    function arrayCopy(source, array) {
+      var index = -1,
+          length = source.length;
+
+      array || (array = Array(length));
+      while (++index < length) {
+        array[index] = source[index];
+      }
+      return array;
+    }
+
+    /**
+     * A specialized version of `_.forEach` for arrays without support for callback
+     * shorthands and `this` binding.
+     *
+     * @private
+     * @param {Array} array The array to iterate over.
+     * @param {Function} iteratee The function invoked per iteration.
+     * @returns {Array} Returns `array`.
+     */
+    function arrayEach(array, iteratee) {
+      var index = -1,
+          length = array.length;
+
+      while (++index < length) {
+        if (iteratee(array[index], index, array) === false) {
+          break;
+        }
+      }
+      return array;
+    }
+
+    /**
+     * A specialized version of `_.forEachRight` for arrays without support for
+     * callback shorthands and `this` binding.
+     *
+     * @private
+     * @param {Array} array The array to iterate over.
+     * @param {Function} iteratee The function invoked per iteration.
+     * @returns {Array} Returns `array`.
+     */
+    function arrayEachRight(array, iteratee) {
+      var length = array.length;
+
+      while (length--) {
+        if (iteratee(array[length], length, array) === false) {
+          break;
+        }
+      }
+      return array;
+    }
+
+    /**
+     * A specialized version of `_.every` for arrays without support for callback
+     * shorthands and `this` binding.
+     *
+     * @private
+     * @param {Array} array The array to iterate over.
+     * @param {Function} predicate The function invoked per iteration.
+     * @returns {boolean} Returns `true` if all elements pass the predicate check,
+     *  else `false`.
+     */
+    function arrayEvery(array, predicate) {
+      var index = -1,
+          length = array.length;
+
+      while (++index < length) {
+        if (!predicate(array[index], index, array)) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    /**
+     * A specialized version of `_.filter` for arrays without support for callback
+     * shorthands and `this` binding.
+     *
+     * @private
+     * @param {Array} array The array to iterate over.
+     * @param {Function} predicate The function invoked per iteration.
+     * @returns {Array} Returns the new filtered array.
+     */
+    function arrayFilter(array, predicate) {
+      var index = -1,
+          length = array.length,
+          resIndex = -1,
+          result = [];
+
+      while (++index < length) {
+        var value = array[index];
+        if (predicate(value, index, array)) {
+          result[++resIndex] = value;
+        }
+      }
+      return result;
+    }
+
+    /**
+     * A specialized version of `_.map` for arrays without support for callback
+     * shorthands and `this` binding.
+     *
+     * @private
+     * @param {Array} array The array to iterate over.
+     * @param {Function} iteratee The function invoked per iteration.
+     * @returns {Array} Returns the new mapped array.
+     */
+    function arrayMap(array, iteratee) {
+      var index = -1,
+          length = array.length,
+          result = Array(length);
+
+      while (++index < length) {
+        result[index] = iteratee(array[index], index, array);
+      }
+      return result;
+    }
+
+    /**
+     * A specialized version of `_.max` for arrays without support for iteratees.
+     *
+     * @private
+     * @param {Array} array The array to iterate over.
+     * @returns {*} Returns the maximum value.
+     */
+    function arrayMax(array) {
+      var index = -1,
+          length = array.length,
+          result = NEGATIVE_INFINITY;
+
+      while (++index < length) {
+        var value = array[index];
+        if (value > result) {
+          result = value;
+        }
+      }
+      return result;
+    }
+
+    /**
+     * A specialized version of `_.min` for arrays without support for iteratees.
+     *
+     * @private
+     * @param {Array} array The array to iterate over.
+     * @returns {*} Returns the minimum value.
+     */
+    function arrayMin(array) {
+      var index = -1,
+          length = array.length,
+          result = POSITIVE_INFINITY;
+
+      while (++index < length) {
+        var value = array[index];
+        if (value < result) {
+          result = value;
+        }
+      }
+      return result;
+    }
+
+    /**
+     * A specialized version of `_.reduce` for arrays without support for callback
+     * shorthands and `this` binding.
+     *
+     * @private
+     * @param {Array} array The array to iterate over.
+     * @param {Function} iteratee The function invoked per iteration.
+     * @param {*} [accumulator] The initial value.
+     * @param {boolean} [initFromArray] Specify using the first element of `array`
+     *  as the initial value.
+     * @returns {*} Returns the accumulated value.
+     */
+    function arrayReduce(array, iteratee, accumulator, initFromArray) {
+      var index = -1,
+          length = array.length;
+
+      if (initFromArray && length) {
+        accumulator = array[++index];
+      }
+      while (++index < length) {
+        accumulator = iteratee(accumulator, array[index], index, array);
+      }
+      return accumulator;
+    }
+
+    /**
+     * A specialized version of `_.reduceRight` for arrays without support for
+     * callback shorthands and `this` binding.
+     *
+     * @private
+     * @param {Array} array The array to iterate over.
+     * @param {Function} iteratee The function invoked per iteration.
+     * @param {*} [accumulator] The initial value.
+     * @param {boolean} [initFromArray] Specify using the last element of `array`
+     *  as the initial value.
+     * @returns {*} Returns the accumulated value.
+     */
+    function arrayReduceRight(array, iteratee, accumulator, initFromArray) {
+      var length = array.length;
+      if (initFromArray && length) {
+        accumulator = array[--length];
+      }
+      while (length--) {
+        accumulator = iteratee(accumulator, array[length], length, array);
+      }
+      return accumulator;
+    }
+
+    /**
+     * A specialized version of `_.some` for arrays without support for callback
+     * shorthands and `this` binding.
+     *
+     * @private
+     * @param {Array} array The array to iterate over.
+     * @param {Function} predicate The function invoked per iteration.
+     * @returns {boolean} Returns `true` if any element passes the predicate check,
+     *  else `false`.
+     */
+    function arraySome(array, predicate) {
+      var index = -1,
+          length = array.length;
+
+      while (++index < length) {
+        if (predicate(array[index], index, array)) {
+          return true;
+        }
+      }
+      return false;
+    }
+
+    /**
+     * A specialized version of `_.sum` for arrays without support for iteratees.
+     *
+     * @private
+     * @param {Array} array The array to iterate over.
+     * @returns {number} Returns the sum.
+     */
+    function arraySum(array) {
+      var length = array.length,
+          result = 0;
+
+      while (length--) {
+        result += +array[length] || 0;
+      }
+      return result;
+    }
+
+    /**
+     * Used by `_.defaults` to customize its `_.assign` use.
+     *
+     * @private
+     * @param {*} objectValue The destination object property value.
+     * @param {*} sourceValue The source object property value.
+     * @returns {*} Returns the value to assign to the destination object.
+     */
+    function assignDefaults(objectValue, sourceValue) {
+      return objectValue === undefined ? sourceValue : objectValue;
+    }
+
+    /**
+     * Used by `_.template` to customize its `_.assign` use.
+     *
+     * **Note:** This function is like `assignDefaults` except that it ignores
+     * inherited property values when checking if a property is `undefined`.
+     *
+     * @private
+     * @param {*} objectValue The destination object property value.
+     * @param {*} sourceValue The source object property value.
+     * @param {string} key The key associated with the object and source values.
+     * @param {Object} object The destination object.
+     * @returns {*} Returns the value to assign to the destination object.
+     */
+    function assignOwnDefaults(objectValue, sourceValue, key, object) {
+      return (objectValue === undefined || !hasOwnProperty.call(object, key))
+        ? sourceValue
+        : objectValue;
+    }
+
+    /**
+     * A specialized version of `_.assign` for customizing assigned values without
+     * support for argument juggling, multiple sources, and `this` binding `customizer`
+     * functions.
+     *
+     * @private
+     * @param {Object} object The destination object.
+     * @param {Object} source The source object.
+     * @param {Function} customizer The function to customize assigned values.
+     * @returns {Object} Returns `object`.
+     */
+    function assignWith(object, source, customizer) {
+      var props = keys(source);
+      push.apply(props, getSymbols(source));
+
+      var index = -1,
+          length = props.length;
+
+      while (++index < length) {
+        var key = props[index],
+            value = object[key],
+            result = customizer(value, source[key], key, object, source);
+
+        if ((result === result ? (result !== value) : (value === value)) ||
+            (value === undefined && !(key in object))) {
+          object[key] = result;
+        }
+      }
+      return object;
+    }
+
+    /**
+     * The base implementation of `_.assign` without support for argument juggling,
+     * multiple sources, and `customizer` functions.
+     *
+     * @private
+     * @param {Object} object The destination object.
+     * @param {Object} source The source object.
+     * @returns {Object} Returns `object`.
+     */
+    var baseAssign = nativeAssign || function(object, source) {
+      return source == null
+        ? object
+        : baseCopy(source, getSymbols(source), baseCopy(source, keys(source), object));
+    };
+
+    /**
+     * The base implementation of `_.at` without support for string collections
+     * and individual key arguments.
+     *
+     * @private
+     * @param {Array|Object} collection The collection to iterate over.
+     * @param {number[]|string[]} props The property names or indexes of elements to pick.
+     * @returns {Array} Returns the new array of picked elements.
+     */
+    function baseAt(collection, props) {
+      var index = -1,
+          length = collection.length,
+          isArr = isLength(length),
+          propsLength = props.length,
+          result = Array(propsLength);
+
+      while(++index < propsLength) {
+        var key = props[index];
+        if (isArr) {
+          result[index] = isIndex(key, length) ? collection[key] : undefined;
+        } else {
+          result[index] = collection[key];
+        }
+      }
+      return result;
+    }
+
+    /**
+     * Copies properties of `source` to `object`.
+     *
+     * @private
+     * @param {Object} source The object to copy properties from.
+     * @param {Array} props The property names to copy.
+     * @param {Object} [object={}] The object to copy properties to.
+     * @returns {Object} Returns `object`.
+     */
+    function baseCopy(source, props, object) {
+      object || (object = {});
+
+      var index = -1,
+          length = props.length;
+
+      while (++index < length) {
+        var key = props[index];
+        object[key] = source[key];
+      }
+      return object;
+    }
+
+    /**
+     * The base implementation of `_.callback` which supports specifying the
+     * number of arguments to provide to `func`.
+     *
+     * @private
+     * @param {*} [func=_.identity] The value to convert to a callback.
+     * @param {*} [thisArg] The `this` binding of `func`.
+     * @param {number} [argCount] The number of arguments to provide to `func`.
+     * @returns {Function} Returns the callback.
+     */
+    function baseCallback(func, thisArg, argCount) {
+      var type = typeof func;
+      if (type == 'function') {
+        return thisArg === undefined
+          ? func
+          : bindCallback(func, thisArg, argCount);
+      }
+      if (func == null) {
+        return identity;
+      }
+      if (type == 'object') {
+        return baseMatches(func);
+      }
+      return thisArg === undefined
+        ? property(func)
+        : baseMatchesProperty(func, thisArg);
+    }
+
+    /**
+     * The base implementation of `_.clone` without support for argument juggling
+     * and `this` binding `customizer` functions.
+     *
+     * @private
+     * @param {*} value The value to clone.
+     * @param {boolean} [isDeep] Specify a deep clone.
+     * @param {Function} [customizer] The function to customize cloning values.
+     * @param {string} [key] The key of `value`.
+     * @param {Object} [object] The object `value` belongs to.
+     * @param {Array} [stackA=[]] Tracks traversed source objects.
+     * @param {Array} [stackB=[]] Associates clones with source counterparts.
+     * @returns {*} Returns the cloned value.
+     */
+    function baseClone(value, isDeep, customizer, key, object, stackA, stackB) {
+      var result;
+      if (customizer) {
+        result = object ? customizer(value, key, object) : customizer(value);
+      }
+      if (result !== undefined) {
+        return result;
+      }
+      if (!isObject(value)) {
+        return value;
+      }
+      var isArr = isArray(value);
+      if (isArr) {
+        result = initCloneArray(value);
+        if (!isDeep) {
+          return arrayCopy(value, result);
+        }
+      } else {
+        var tag = objToString.call(value),
+            isFunc = tag == funcTag;
+
+        if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
+          result = initCloneObject(isFunc ? {} : value);
+          if (!isDeep) {
+            return baseAssign(result, value);
+          }
+        } else {
+          return cloneableTags[tag]
+            ? initCloneByTag(value, tag, isDeep)
+            : (object ? value : {});
+        }
+      }
+      // Check for circular references and return corresponding clone.
+      stackA || (stackA = []);
+      stackB || (stackB = []);
+
+      var length = stackA.length;
+      while (length--) {
+        if (stackA[length] == value) {
+          return stackB[length];
+        }
+      }
+      // Add the source value to the stack of traversed objects and associate it with its clone.
+      stackA.push(value);
+      stackB.push(result);
+
+      // Recursively populate clone (susceptible to call stack limits).
+      (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) {
+        result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB);
+      });
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.create` without support for assigning
+     * properties to the created object.
+     *
+     * @private
+     * @param {Object} prototype The object to inherit from.
+     * @returns {Object} Returns the new object.
+     */
+    var baseCreate = (function() {
+      function Object() {}
+      return function(prototype) {
+        if (isObject(prototype)) {
+          Object.prototype = prototype;
+          var result = new Object;
+          Object.prototype = null;
+        }
+        return result || context.Object();
+      };
+    }());
+
+    /**
+     * The base implementation of `_.delay` and `_.defer` which accepts an index
+     * of where to slice the arguments to provide to `func`.
+     *
+     * @private
+     * @param {Function} func The function to delay.
+     * @param {number} wait The number of milliseconds to delay invocation.
+     * @param {Object} args The arguments provide to `func`.
+     * @returns {number} Returns the timer id.
+     */
+    function baseDelay(func, wait, args) {
+      if (typeof func != 'function') {
+        throw new TypeError(FUNC_ERROR_TEXT);
+      }
+      return setTimeout(function() { func.apply(undefined, args); }, wait);
+    }
+
+    /**
+     * The base implementation of `_.difference` which accepts a single array
+     * of values to exclude.
+     *
+     * @private
+     * @param {Array} array The array to inspect.
+     * @param {Array} values The values to exclude.
+     * @returns {Array} Returns the new array of filtered values.
+     */
+    function baseDifference(array, values) {
+      var length = array ? array.length : 0,
+          result = [];
+
+      if (!length) {
+        return result;
+      }
+      var index = -1,
+          indexOf = getIndexOf(),
+          isCommon = indexOf == baseIndexOf,
+          cache = (isCommon && values.length >= 200) ? createCache(values) : null,
+          valuesLength = values.length;
+
+      if (cache) {
+        indexOf = cacheIndexOf;
+        isCommon = false;
+        values = cache;
+      }
+      outer:
+      while (++index < length) {
+        var value = array[index];
+
+        if (isCommon && value === value) {
+          var valuesIndex = valuesLength;
+          while (valuesIndex--) {
+            if (values[valuesIndex] === value) {
+              continue outer;
+            }
+          }
+          result.push(value);
+        }
+        else if (indexOf(values, value, 0) < 0) {
+          result.push(value);
+        }
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.forEach` without support for callback
+     * shorthands and `this` binding.
+     *
+     * @private
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} iteratee The function invoked per iteration.
+     * @returns {Array|Object|string} Returns `collection`.
+     */
+    var baseEach = createBaseEach(baseForOwn);
+
+    /**
+     * The base implementation of `_.forEachRight` without support for callback
+     * shorthands and `this` binding.
+     *
+     * @private
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} iteratee The function invoked per iteration.
+     * @returns {Array|Object|string} Returns `collection`.
+     */
+    var baseEachRight = createBaseEach(baseForOwnRight, true);
+
+    /**
+     * The base implementation of `_.every` without support for callback
+     * shorthands and `this` binding.
+     *
+     * @private
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} predicate The function invoked per iteration.
+     * @returns {boolean} Returns `true` if all elements pass the predicate check,
+     *  else `false`
+     */
+    function baseEvery(collection, predicate) {
+      var result = true;
+      baseEach(collection, function(value, index, collection) {
+        result = !!predicate(value, index, collection);
+        return result;
+      });
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.fill` without an iteratee call guard.
+     *
+     * @private
+     * @param {Array} array The array to fill.
+     * @param {*} value The value to fill `array` with.
+     * @param {number} [start=0] The start position.
+     * @param {number} [end=array.length] The end position.
+     * @returns {Array} Returns `array`.
+     */
+    function baseFill(array, value, start, end) {
+      var length = array.length;
+
+      start = start == null ? 0 : (+start || 0);
+      if (start < 0) {
+        start = -start > length ? 0 : (length + start);
+      }
+      end = (end === undefined || end > length) ? length : (+end || 0);
+      if (end < 0) {
+        end += length;
+      }
+      length = start > end ? 0 : (end >>> 0);
+      start >>>= 0;
+
+      while (start < length) {
+        array[start++] = value;
+      }
+      return array;
+    }
+
+    /**
+     * The base implementation of `_.filter` without support for callback
+     * shorthands and `this` binding.
+     *
+     * @private
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} predicate The function invoked per iteration.
+     * @returns {Array} Returns the new filtered array.
+     */
+    function baseFilter(collection, predicate) {
+      var result = [];
+      baseEach(collection, function(value, index, collection) {
+        if (predicate(value, index, collection)) {
+          result.push(value);
+        }
+      });
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey`,
+     * without support for callback shorthands and `this` binding, which iterates
+     * over `collection` using the provided `eachFunc`.
+     *
+     * @private
+     * @param {Array|Object|string} collection The collection to search.
+     * @param {Function} predicate The function invoked per iteration.
+     * @param {Function} eachFunc The function to iterate over `collection`.
+     * @param {boolean} [retKey] Specify returning the key of the found element
+     *  instead of the element itself.
+     * @returns {*} Returns the found element or its key, else `undefined`.
+     */
+    function baseFind(collection, predicate, eachFunc, retKey) {
+      var result;
+      eachFunc(collection, function(value, key, collection) {
+        if (predicate(value, key, collection)) {
+          result = retKey ? key : value;
+          return false;
+        }
+      });
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.flatten` with added support for restricting
+     * flattening and specifying the start index.
+     *
+     * @private
+     * @param {Array} array The array to flatten.
+     * @param {boolean} isDeep Specify a deep flatten.
+     * @param {boolean} isStrict Restrict flattening to arrays and `arguments` objects.
+     * @returns {Array} Returns the new flattened array.
+     */
+    function baseFlatten(array, isDeep, isStrict) {
+      var index = -1,
+          length = array.length,
+          resIndex = -1,
+          result = [];
+
+      while (++index < length) {
+        var value = array[index];
+
+        if (isObjectLike(value) && isLength(value.length) && (isArray(value) || isArguments(value))) {
+          if (isDeep) {
+            // Recursively flatten arrays (susceptible to call stack limits).
+            value = baseFlatten(value, isDeep, isStrict);
+          }
+          var valIndex = -1,
+              valLength = value.length;
+
+          result.length += valLength;
+          while (++valIndex < valLength) {
+            result[++resIndex] = value[valIndex];
+          }
+        } else if (!isStrict) {
+          result[++resIndex] = value;
+        }
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `baseForIn` and `baseForOwn` which iterates
+     * over `object` properties returned by `keysFunc` invoking `iteratee` for
+     * each property. Iteratee functions may exit iteration early by explicitly
+     * returning `false`.
+     *
+     * @private
+     * @param {Object} object The object to iterate over.
+     * @param {Function} iteratee The function invoked per iteration.
+     * @param {Function} keysFunc The function to get the keys of `object`.
+     * @returns {Object} Returns `object`.
+     */
+    var baseFor = createBaseFor();
+
+    /**
+     * This function is like `baseFor` except that it iterates over properties
+     * in the opposite order.
+     *
+     * @private
+     * @param {Object} object The object to iterate over.
+     * @param {Function} iteratee The function invoked per iteration.
+     * @param {Function} keysFunc The function to get the keys of `object`.
+     * @returns {Object} Returns `object`.
+     */
+    var baseForRight = createBaseFor(true);
+
+    /**
+     * The base implementation of `_.forIn` without support for callback
+     * shorthands and `this` binding.
+     *
+     * @private
+     * @param {Object} object The object to iterate over.
+     * @param {Function} iteratee The function invoked per iteration.
+     * @returns {Object} Returns `object`.
+     */
+    function baseForIn(object, iteratee) {
+      return baseFor(object, iteratee, keysIn);
+    }
+
+    /**
+     * The base implementation of `_.forOwn` without support for callback
+     * shorthands and `this` binding.
+     *
+     * @private
+     * @param {Object} object The object to iterate over.
+     * @param {Function} iteratee The function invoked per iteration.
+     * @returns {Object} Returns `object`.
+     */
+    function baseForOwn(object, iteratee) {
+      return baseFor(object, iteratee, keys);
+    }
+
+    /**
+     * The base implementation of `_.forOwnRight` without support for callback
+     * shorthands and `this` binding.
+     *
+     * @private
+     * @param {Object} object The object to iterate over.
+     * @param {Function} iteratee The function invoked per iteration.
+     * @returns {Object} Returns `object`.
+     */
+    function baseForOwnRight(object, iteratee) {
+      return baseForRight(object, iteratee, keys);
+    }
+
+    /**
+     * The base implementation of `_.functions` which creates an array of
+     * `object` function property names filtered from those provided.
+     *
+     * @private
+     * @param {Object} object The object to inspect.
+     * @param {Array} props The property names to filter.
+     * @returns {Array} Returns the new array of filtered property names.
+     */
+    function baseFunctions(object, props) {
+      var index = -1,
+          length = props.length,
+          resIndex = -1,
+          result = [];
+
+      while (++index < length) {
+        var key = props[index];
+        if (isFunction(object[key])) {
+          result[++resIndex] = key;
+        }
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `get` without support for string paths
+     * and default values.
+     *
+     * @private
+     * @param {Object} object The object to query.
+     * @param {Array} path The path of the property to get.
+     * @param {string} [pathKey] The key representation of path.
+     * @returns {*} Returns the resolved value.
+     */
+    function baseGet(object, path, pathKey) {
+      if (object == null) {
+        return;
+      }
+      if (pathKey !== undefined && pathKey in toObject(object)) {
+        path = [pathKey];
+      }
+      var index = -1,
+          length = path.length;
+
+      while (object != null && ++index < length) {
+        var result = object = object[path[index]];
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.isEqual` without support for `this` binding
+     * `customizer` functions.
+     *
+     * @private
+     * @param {*} value The value to compare.
+     * @param {*} other The other value to compare.
+     * @param {Function} [customizer] The function to customize comparing values.
+     * @param {boolean} [isLoose] Specify performing partial comparisons.
+     * @param {Array} [stackA] Tracks traversed `value` objects.
+     * @param {Array} [stackB] Tracks traversed `other` objects.
+     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+     */
+    function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) {
+      // Exit early for identical values.
+      if (value === other) {
+        // Treat `+0` vs. `-0` as not equal.
+        return value !== 0 || (1 / value == 1 / other);
+      }
+      var valType = typeof value,
+          othType = typeof other;
+
+      // Exit early for unlike primitive values.
+      if ((valType != 'function' && valType != 'object' && othType != 'function' && othType != 'object') ||
+          value == null || other == null) {
+        // Return `false` unless both values are `NaN`.
+        return value !== value && other !== other;
+      }
+      return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB);
+    }
+
+    /**
+     * A specialized version of `baseIsEqual` for arrays and objects which performs
+     * deep comparisons and tracks traversed objects enabling objects with circular
+     * references to be compared.
+     *
+     * @private
+     * @param {Object} object The object to compare.
+     * @param {Object} other The other object to compare.
+     * @param {Function} equalFunc The function to determine equivalents of values.
+     * @param {Function} [customizer] The function to customize comparing objects.
+     * @param {boolean} [isLoose] Specify performing partial comparisons.
+     * @param {Array} [stackA=[]] Tracks traversed `value` objects.
+     * @param {Array} [stackB=[]] Tracks traversed `other` objects.
+     * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+     */
+    function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
+      var objIsArr = isArray(object),
+          othIsArr = isArray(other),
+          objTag = arrayTag,
+          othTag = arrayTag;
+
+      if (!objIsArr) {
+        objTag = objToString.call(object);
+        if (objTag == argsTag) {
+          objTag = objectTag;
+        } else if (objTag != objectTag) {
+          objIsArr = isTypedArray(object);
+        }
+      }
+      if (!othIsArr) {
+        othTag = objToString.call(other);
+        if (othTag == argsTag) {
+          othTag = objectTag;
+        } else if (othTag != objectTag) {
+          othIsArr = isTypedArray(other);
+        }
+      }
+      var objIsObj = objTag == objectTag,
+          othIsObj = othTag == objectTag,
+          isSameTag = objTag == othTag;
+
+      if (isSameTag && !(objIsArr || objIsObj)) {
+        return equalByTag(object, other, objTag);
+      }
+      if (!isLoose) {
+        var valWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
+            othWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
+
+        if (valWrapped || othWrapped) {
+          return equalFunc(valWrapped ? object.value() : object, othWrapped ? other.value() : other, customizer, isLoose, stackA, stackB);
+        }
+      }
+      if (!isSameTag) {
+        return false;
+      }
+      // Assume cyclic values are equal.
+      // For more information on detecting circular references see https://es5.github.io/#JO.
+      stackA || (stackA = []);
+      stackB || (stackB = []);
+
+      var length = stackA.length;
+      while (length--) {
+        if (stackA[length] == object) {
+          return stackB[length] == other;
+        }
+      }
+      // Add `object` and `other` to the stack of traversed objects.
+      stackA.push(object);
+      stackB.push(other);
+
+      var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB);
+
+      stackA.pop();
+      stackB.pop();
+
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.isMatch` without support for callback
+     * shorthands and `this` binding.
+     *
+     * @private
+     * @param {Object} object The object to inspect.
+     * @param {Array} props The source property names to match.
+     * @param {Array} values The source values to match.
+     * @param {Array} strictCompareFlags Strict comparison flags for source values.
+     * @param {Function} [customizer] The function to customize comparing objects.
+     * @returns {boolean} Returns `true` if `object` is a match, else `false`.
+     */
+    function baseIsMatch(object, props, values, strictCompareFlags, customizer) {
+      var index = -1,
+          length = props.length,
+          noCustomizer = !customizer;
+
+      while (++index < length) {
+        if ((noCustomizer && strictCompareFlags[index])
+              ? values[index] !== object[props[index]]
+              : !(props[index] in object)
+            ) {
+          return false;
+        }
+      }
+      index = -1;
+      while (++index < length) {
+        var key = props[index],
+            objValue = object[key],
+            srcValue = values[index];
+
+        if (noCustomizer && strictCompareFlags[index]) {
+          var result = objValue !== undefined || (key in object);
+        } else {
+          result = customizer ? customizer(objValue, srcValue, key) : undefined;
+          if (result === undefined) {
+            result = baseIsEqual(srcValue, objValue, customizer, true);
+          }
+        }
+        if (!result) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    /**
+     * The base implementation of `_.map` without support for callback shorthands
+     * and `this` binding.
+     *
+     * @private
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} iteratee The function invoked per iteration.
+     * @returns {Array} Returns the new mapped array.
+     */
+    function baseMap(collection, iteratee) {
+      var index = -1,
+          length = getLength(collection),
+          result = isLength(length) ? Array(length) : [];
+
+      baseEach(collection, function(value, key, collection) {
+        result[++index] = iteratee(value, key, collection);
+      });
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.matches` which does not clone `source`.
+     *
+     * @private
+     * @param {Object} source The object of property values to match.
+     * @returns {Function} Returns the new function.
+     */
+    function baseMatches(source) {
+      var props = keys(source),
+          length = props.length;
+
+      if (!length) {
+        return constant(true);
+      }
+      if (length == 1) {
+        var key = props[0],
+            value = source[key];
+
+        if (isStrictComparable(value)) {
+          return function(object) {
+            if (object == null) {
+              return false;
+            }
+            return object[key] === value && (value !== undefined || (key in toObject(object)));
+          };
+        }
+      }
+      var values = Array(length),
+          strictCompareFlags = Array(length);
+
+      while (length--) {
+        value = source[props[length]];
+        values[length] = value;
+        strictCompareFlags[length] = isStrictComparable(value);
+      }
+      return function(object) {
+        return object != null && baseIsMatch(toObject(object), props, values, strictCompareFlags);
+      };
+    }
+
+    /**
+     * The base implementation of `_.matchesProperty` which does not which does
+     * not clone `value`.
+     *
+     * @private
+     * @param {string} path The path of the property to get.
+     * @param {*} value The value to compare.
+     * @returns {Function} Returns the new function.
+     */
+    function baseMatchesProperty(path, value) {
+      var isArr = isArray(path),
+          isCommon = isKey(path) && isStrictComparable(value),
+          pathKey = (path + '');
+
+      path = toPath(path);
+      return function(object) {
+        if (object == null) {
+          return false;
+        }
+        var key = pathKey;
+        object = toObject(object);
+        if ((isArr || !isCommon) && !(key in object)) {
+          object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
+          if (object == null) {
+            return false;
+          }
+          key = last(path);
+          object = toObject(object);
+        }
+        return object[key] === value
+          ? (value !== undefined || (key in object))
+          : baseIsEqual(value, object[key], null, true);
+      };
+    }
+
+    /**
+     * The base implementation of `_.merge` without support for argument juggling,
+     * multiple sources, and `this` binding `customizer` functions.
+     *
+     * @private
+     * @param {Object} object The destination object.
+     * @param {Object} source The source object.
+     * @param {Function} [customizer] The function to customize merging properties.
+     * @param {Array} [stackA=[]] Tracks traversed source objects.
+     * @param {Array} [stackB=[]] Associates values with source counterparts.
+     * @returns {Object} Returns `object`.
+     */
+    function baseMerge(object, source, customizer, stackA, stackB) {
+      if (!isObject(object)) {
+        return object;
+      }
+      var isSrcArr = isLength(source.length) && (isArray(source) || isTypedArray(source));
+      if (!isSrcArr) {
+        var props = keys(source);
+        push.apply(props, getSymbols(source));
+      }
+      arrayEach(props || source, function(srcValue, key) {
+        if (props) {
+          key = srcValue;
+          srcValue = source[key];
+        }
+        if (isObjectLike(srcValue)) {
+          stackA || (stackA = []);
+          stackB || (stackB = []);
+          baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB);
+        }
+        else {
+          var value = object[key],
+              result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
+              isCommon = result === undefined;
+
+          if (isCommon) {
+            result = srcValue;
+          }
+          if ((isSrcArr || result !== undefined) &&
+              (isCommon || (result === result ? (result !== value) : (value === value)))) {
+            object[key] = result;
+          }
+        }
+      });
+      return object;
+    }
+
+    /**
+     * A specialized version of `baseMerge` for arrays and objects which performs
+     * deep merges and tracks traversed objects enabling objects with circular
+     * references to be merged.
+     *
+     * @private
+     * @param {Object} object The destination object.
+     * @param {Object} source The source object.
+     * @param {string} key The key of the value to merge.
+     * @param {Function} mergeFunc The function to merge values.
+     * @param {Function} [customizer] The function to customize merging properties.
+     * @param {Array} [stackA=[]] Tracks traversed source objects.
+     * @param {Array} [stackB=[]] Associates values with source counterparts.
+     * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+     */
+    function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) {
+      var length = stackA.length,
+          srcValue = source[key];
+
+      while (length--) {
+        if (stackA[length] == srcValue) {
+          object[key] = stackB[length];
+          return;
+        }
+      }
+      var value = object[key],
+          result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
+          isCommon = result === undefined;
+
+      if (isCommon) {
+        result = srcValue;
+        if (isLength(srcValue.length) && (isArray(srcValue) || isTypedArray(srcValue))) {
+          result = isArray(value)
+            ? value
+            : (getLength(value) ? arrayCopy(value) : []);
+        }
+        else if (isPlainObject(srcValue) || isArguments(srcValue)) {
+          result = isArguments(value)
+            ? toPlainObject(value)
+            : (isPlainObject(value) ? value : {});
+        }
+        else {
+          isCommon = false;
+        }
+      }
+      // Add the source value to the stack of traversed objects and associate
+      // it with its merged value.
+      stackA.push(srcValue);
+      stackB.push(result);
+
+      if (isCommon) {
+        // Recursively merge objects and arrays (susceptible to call stack limits).
+        object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB);
+      } else if (result === result ? (result !== value) : (value === value)) {
+        object[key] = result;
+      }
+    }
+
+    /**
+     * The base implementation of `_.property` without support for deep paths.
+     *
+     * @private
+     * @param {string} key The key of the property to get.
+     * @returns {Function} Returns the new function.
+     */
+    function baseProperty(key) {
+      return function(object) {
+        return object == null ? undefined : object[key];
+      };
+    }
+
+    /**
+     * A specialized version of `baseProperty` which supports deep paths.
+     *
+     * @private
+     * @param {Array|string} path The path of the property to get.
+     * @returns {Function} Returns the new function.
+     */
+    function basePropertyDeep(path) {
+      var pathKey = (path + '');
+      path = toPath(path);
+      return function(object) {
+        return baseGet(object, path, pathKey);
+      };
+    }
+
+    /**
+     * The base implementation of `_.pullAt` without support for individual
+     * index arguments and capturing the removed elements.
+     *
+     * @private
+     * @param {Array} array The array to modify.
+     * @param {number[]} indexes The indexes of elements to remove.
+     * @returns {Array} Returns `array`.
+     */
+    function basePullAt(array, indexes) {
+      var length = indexes.length;
+      while (length--) {
+        var index = parseFloat(indexes[length]);
+        if (index != previous && isIndex(index)) {
+          var previous = index;
+          splice.call(array, index, 1);
+        }
+      }
+      return array;
+    }
+
+    /**
+     * The base implementation of `_.random` without support for argument juggling
+     * and returning floating-point numbers.
+     *
+     * @private
+     * @param {number} min The minimum possible value.
+     * @param {number} max The maximum possible value.
+     * @returns {number} Returns the random number.
+     */
+    function baseRandom(min, max) {
+      return min + floor(nativeRandom() * (max - min + 1));
+    }
+
+    /**
+     * The base implementation of `_.reduce` and `_.reduceRight` without support
+     * for callback shorthands and `this` binding, which iterates over `collection`
+     * using the provided `eachFunc`.
+     *
+     * @private
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} iteratee The function invoked per iteration.
+     * @param {*} accumulator The initial value.
+     * @param {boolean} initFromCollection Specify using the first or last element
+     *  of `collection` as the initial value.
+     * @param {Function} eachFunc The function to iterate over `collection`.
+     * @returns {*} Returns the accumulated value.
+     */
+    function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) {
+      eachFunc(collection, function(value, index, collection) {
+        accumulator = initFromCollection
+          ? (initFromCollection = false, value)
+          : iteratee(accumulator, value, index, collection);
+      });
+      return accumulator;
+    }
+
+    /**
+     * The base implementation of `setData` without support for hot loop detection.
+     *
+     * @private
+     * @param {Function} func The function to associate metadata with.
+     * @param {*} data The metadata.
+     * @returns {Function} Returns `func`.
+     */
+    var baseSetData = !metaMap ? identity : function(func, data) {
+      metaMap.set(func, data);
+      return func;
+    };
+
+    /**
+     * The base implementation of `_.slice` without an iteratee call guard.
+     *
+     * @private
+     * @param {Array} array The array to slice.
+     * @param {number} [start=0] The start position.
+     * @param {number} [end=array.length] The end position.
+     * @returns {Array} Returns the slice of `array`.
+     */
+    function baseSlice(array, start, end) {
+      var index = -1,
+          length = array.length;
+
+      start = start == null ? 0 : (+start || 0);
+      if (start < 0) {
+        start = -start > length ? 0 : (length + start);
+      }
+      end = (end === undefined || end > length) ? length : (+end || 0);
+      if (end < 0) {
+        end += length;
+      }
+      length = start > end ? 0 : ((end - start) >>> 0);
+      start >>>= 0;
+
+      var result = Array(length);
+      while (++index < length) {
+        result[index] = array[index + start];
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.some` without support for callback shorthands
+     * and `this` binding.
+     *
+     * @private
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} predicate The function invoked per iteration.
+     * @returns {boolean} Returns `true` if any element passes the predicate check,
+     *  else `false`.
+     */
+    function baseSome(collection, predicate) {
+      var result;
+
+      baseEach(collection, function(value, index, collection) {
+        result = predicate(value, index, collection);
+        return !result;
+      });
+      return !!result;
+    }
+
+    /**
+     * The base implementation of `_.sortBy` which uses `comparer` to define
+     * the sort order of `array` and replaces criteria objects with their
+     * corresponding values.
+     *
+     * @private
+     * @param {Array} array The array to sort.
+     * @param {Function} comparer The function to define sort order.
+     * @returns {Array} Returns `array`.
+     */
+    function baseSortBy(array, comparer) {
+      var length = array.length;
+
+      array.sort(comparer);
+      while (length--) {
+        array[length] = array[length].value;
+      }
+      return array;
+    }
+
+    /**
+     * The base implementation of `_.sortByOrder` without param guards.
+     *
+     * @private
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
+     * @param {boolean[]} orders The sort orders of `iteratees`.
+     * @returns {Array} Returns the new sorted array.
+     */
+    function baseSortByOrder(collection, iteratees, orders) {
+      var callback = getCallback(),
+          index = -1;
+
+      iteratees = arrayMap(iteratees, function(iteratee) { return callback(iteratee); });
+
+      var result = baseMap(collection, function(value) {
+        var criteria = arrayMap(iteratees, function(iteratee) { return iteratee(value); });
+        return { 'criteria': criteria, 'index': ++index, 'value': value };
+      });
+
+      return baseSortBy(result, function(object, other) {
+        return compareMultiple(object, other, orders);
+      });
+    }
+
+    /**
+     * The base implementation of `_.sum` without support for callback shorthands
+     * and `this` binding.
+     *
+     * @private
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} iteratee The function invoked per iteration.
+     * @returns {number} Returns the sum.
+     */
+    function baseSum(collection, iteratee) {
+      var result = 0;
+      baseEach(collection, function(value, index, collection) {
+        result += +iteratee(value, index, collection) || 0;
+      });
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.uniq` without support for callback shorthands
+     * and `this` binding.
+     *
+     * @private
+     * @param {Array} array The array to inspect.
+     * @param {Function} [iteratee] The function invoked per iteration.
+     * @returns {Array} Returns the new duplicate-value-free array.
+     */
+    function baseUniq(array, iteratee) {
+      var index = -1,
+          indexOf = getIndexOf(),
+          length = array.length,
+          isCommon = indexOf == baseIndexOf,
+          isLarge = isCommon && length >= 200,
+          seen = isLarge ? createCache() : null,
+          result = [];
+
+      if (seen) {
+        indexOf = cacheIndexOf;
+        isCommon = false;
+      } else {
+        isLarge = false;
+        seen = iteratee ? [] : result;
+      }
+      outer:
+      while (++index < length) {
+        var value = array[index],
+            computed = iteratee ? iteratee(value, index, array) : value;
+
+        if (isCommon && value === value) {
+          var seenIndex = seen.length;
+          while (seenIndex--) {
+            if (seen[seenIndex] === computed) {
+              continue outer;
+            }
+          }
+          if (iteratee) {
+            seen.push(computed);
+          }
+          result.push(value);
+        }
+        else if (indexOf(seen, computed, 0) < 0) {
+          if (iteratee || isLarge) {
+            seen.push(computed);
+          }
+          result.push(value);
+        }
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.values` and `_.valuesIn` which creates an
+     * array of `object` property values corresponding to the property names
+     * of `props`.
+     *
+     * @private
+     * @param {Object} object The object to query.
+     * @param {Array} props The property names to get values for.
+     * @returns {Object} Returns the array of property values.
+     */
+    function baseValues(object, props) {
+      var index = -1,
+          length = props.length,
+          result = Array(length);
+
+      while (++index < length) {
+        result[index] = object[props[index]];
+      }
+      return result;
+    }
+
+    /**
+     * The base implementation of `_.dropRightWhile`, `_.dropWhile`, `_.takeRightWhile`,
+     * and `_.takeWhile` without support for callback shorthands and `this` binding.
+     *
+     * @private
+     * @param {Array} array The array to query.
+     * @param {Function} predicate The function invoked per iteration.
+     * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
+     * @param {boolean} [fromRight] Specify iterating from right to left.
+     * @returns {Array} Returns the slice of `array`.
+     */
+    function baseWhile(array, predicate, isDrop, fromRight) {
+      var length = array.length,
+          index = fromRight ? length : -1;
+
+      while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {}
+      return isDrop
+        ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
+        : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
+    }
+
+    /**
+     * The base implementation of `wrapperValue` which returns the result of
+     * performing a sequence of actions on the unwrapped `value`, where each
+     * successive action is supplied the return value of the previous.
+     *
+     * @private
+     * @param {*} value The unwrapped value.
+     * @param {Array} actions Actions to peform to resolve the unwrapped value.
+     * @returns {*} Returns the resolved value.
+     */
+    function baseWrapperValue(value, actions) {
+      var result = value;
+      if (result instanceof LazyWrapper) {
+        result = result.value();
+      }
+      var index = -1,
+          length = actions.length;
+
+      while (++index < length) {
+        var args = [result],
+            action = actions[index];
+
+        push.apply(args, action.args);
+        result = action.func.apply(action.thisArg, args);
+      }
+      return result;
+    }
+
+    /**
+     * Performs a binary search of `array` to determine the index at which `value`
+     * should be inserted into `array` in order to maintain its sort order.
+     *
+     * @private
+     * @param {Array} array The sorted array to inspect.
+     * @param {*} value The value to evaluate.
+     * @param {boolean} [retHighest] Specify returning the highest qualified index.
+     * @returns {number} Returns the index at which `value` should be inserted
+     *  into `array`.
+     */
+    function binaryIndex(array, value, retHighest) {
+      var low = 0,
+          high = array ? array.length : low;
+
+      if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
+        while (low < high) {
+          var mid = (low + high) >>> 1,
+              computed = array[mid];
+
+          if (retHighest ? (computed <= value) : (computed < value)) {
+            low = mid + 1;
+          } else {
+            high = mid;
+          }
+        }
+        return high;
+      }
+      return binaryIndexBy(array, value, identity, retHighest);
+    }
+
+    /**
+     * This function is like `binaryIndex` except that it invokes `iteratee` for
+     * `value` and each element of `array` to compute their sort ranking. The
+     * iteratee is invoked with one argument; (value).
+     *
+     * @private
+     * @param {Array} array The sorted array to inspect.
+     * @param {*} value The value to evaluate.
+     * @param {Function} iteratee The function invoked per iteration.
+     * @param {boolean} [retHighest] Specify returning the highest qualified index.
+     * @returns {number} Returns the index at which `value` should be inserted
+     *  into `array`.
+     */
+    function binaryIndexBy(array, value, iteratee, retHighest) {
+      value = iteratee(value);
+
+      var low = 0,
+          high = array ? array.length : 0,
+          valIsNaN = value !== value,
+          valIsUndef = value === undefined;
+
+      while (low < high) {
+        var mid = floor((low + high) / 2),
+            computed = iteratee(array[mid]),
+            isReflexive = computed === computed;
+
+        if (valIsNaN) {
+          var setLow = isReflexive || retHighest;
+        } else if (valIsUndef) {
+          setLow = isReflexive && (retHighest || computed !== undefined);
+        } else {
+          setLow = retHighest ? (computed <= value) : (computed < value);
+        }
+        if (setLow) {
+          low = mid + 1;
+        } else {
+          high = mid;
+        }
+      }
+      return nativeMin(high, MAX_ARRAY_INDEX);
+    }
+
+    /**
+     * A specialized version of `baseCallback` which only supports `this` binding
+     * and specifying the number of arguments to provide to `func`.
+     *
+     * @private
+     * @param {Function} func The function to bind.
+     * @param {*} thisArg The `this` binding of `func`.
+     * @param {number} [argCount] The number of arguments to provide to `func`.
+     * @returns {Function} Returns the callback.
+     */
+    function bindCallback(func, thisArg, argCount) {
+      if (typeof func != 'function') {
+        return identity;
+      }
+      if (thisArg === undefined) {
+        return func;
+      }
+      switch (argCount) {
+        case 1: return function(value) {
+          return func.call(thisArg, value);
+        };
+        case 3: return function(value, index, collection) {
+          return func.call(thisArg, value, index, collection);
+        };
+        case 4: return function(accumulator, value, index, collection) {
+          return func.call(thisArg, accumulator, value, index, collection);
+        };
+        case 5: return function(value, other, key, object, source) {
+          return func.call(thisArg, value, other, key, object, source);
+        };
+      }
+      return function() {
+        return func.apply(thisArg, arguments);
+      };
+    }
+
+    /**
+     * Creates a clone of the given array buffer.
+     *
+     * @private
+     * @param {ArrayBuffer} buffer The array buffer to clone.
+     * @returns {ArrayBuffer} Returns the cloned array buffer.
+     */
+    function bufferClone(buffer) {
+      return bufferSlice.call(buffer, 0);
+    }
+    if (!bufferSlice) {
+      // PhantomJS has `ArrayBuffer` and `Uint8Array` but not `Float64Array`.
+      bufferClone = !(ArrayBuffer && Uint8Array) ? constant(null) : function(buffer) {
+        var byteLength = buffer.byteLength,
+            floatLength = Float64Array ? floor(byteLength / FLOAT64_BYTES_PER_ELEMENT) : 0,
+            offset = floatLength * FLOAT64_BYTES_PER_ELEMENT,
+            result = new ArrayBuffer(byteLength);
+
+        if (floatLength) {
+          var view = new Float64Array(result, 0, floatLength);
+          view.set(new Float64Array(buffer, 0, floatLength));
+        }
+        if (byteLength != offset) {
+          view = new Uint8Array(result, offset);
+          view.set(new Uint8Array(buffer, offset));
+        }
+        return result;
+      };
+    }
+
+    /**
+     * Creates an array that is the composition of partially applied arguments,
+     * placeholders, and provided arguments into a single array of arguments.
+     *
+     * @private
+     * @param {Array|Object} args The provided arguments.
+     * @param {Array} partials The arguments to prepend to those provided.
+     * @param {Array} holders The `partials` placeholder indexes.
+     * @returns {Array} Returns the new array of composed arguments.
+     */
+    function composeArgs(args, partials, holders) {
+      var holdersLength = holders.length,
+          argsIndex = -1,
+          argsLength = nativeMax(args.length - holdersLength, 0),
+          leftIndex = -1,
+          leftLength = partials.length,
+          result = Array(argsLength + leftLength);
+
+      while (++leftIndex < leftLength) {
+        result[leftIndex] = partials[leftIndex];
+      }
+      while (++argsIndex < holdersLength) {
+        result[holders[argsIndex]] = args[argsIndex];
+      }
+      while (argsLength--) {
+        result[leftIndex++] = args[argsIndex++];
+      }
+      return result;
+    }
+
+    /**
+     * This function is like `composeArgs` except that the arguments composition
+     * is tailored for `_.partialRight`.
+     *
+     * @private
+     * @param {Array|Object} args The provided arguments.
+     * @param {Array} partials The arguments to append to those provided.
+     * @param {Array} holders The `partials` placeholder indexes.
+     * @returns {Array} Returns the new array of composed arguments.
+     */
+    function composeArgsRight(args, partials, holders) {
+      var holdersIndex = -1,
+          holdersLength = holders.length,
+          argsIndex = -1,
+          argsLength = nativeMax(args.length - holdersLength, 0),
+          rightIndex = -1,
+          rightLength = partials.length,
+          result = Array(argsLength + rightLength);
+
+      while (++argsIndex < argsLength) {
+        result[argsIndex] = args[argsIndex];
+      }
+      var pad = argsIndex;
+      while (++rightIndex < rightLength) {
+        result[pad + rightIndex] = partials[rightIndex];
+      }
+      while (++holdersIndex < holdersLength) {
+        result[pad + holders[holdersIndex]] = args[argsIndex++];
+      }
+      return result;
+    }
+
+    /**
+     * Creates a function that aggregates a collection, creating an accumulator
+     * object composed from the results of running each element in the collection
+     * through an iteratee.
+     *
+     * **Note:** This function is used to create `_.countBy`, `_.groupBy`, `_.indexBy`,
+     * and `_.partition`.
+     *
+     * @private
+     * @param {Function} setter The function to set keys and values of the accumulator object.
+     * @param {Function} [initializer] The function to initialize the accumulator object.
+     * @returns {Function} Returns the new aggregator function.
+     */
+    function createAggregator(setter, initializer) {
+      return function(collection, iteratee, thisArg) {
+        var result = initializer ? initializer() : {};
+        iteratee = getCallback(iteratee, thisArg, 3);
+
+        if (isArray(collection)) {
+          var index = -1,
+              length = collection.length;
+
+          while (++index < length) {
+            var value = collection[index];
+            setter(result, value, iteratee(value, index, collection), collection);
+          }
+        } else {
+          baseEach(collection, function(value, key, collection) {
+            setter(result, value, iteratee(value, key, collection), collection);
+          });
+        }
+        return result;
+      };
+    }
+
+    /**
+     * Creates a function that assigns properties of source object(s) to a given
+     * destination object.
+     *
+     * **Note:** This function is used to create `_.assign`, `_.defaults`, and `_.merge`.
+     *
+     * @private
+     * @param {Function} assigner The function to assign values.
+     * @returns {Function} Returns the new assigner function.
+     */
+    function createAssigner(assigner) {
+      return restParam(function(object, sources) {
+        var index = -1,
+            length = object == null ? 0 : sources.length,
+            customizer = length > 2 && sources[length - 2],
+            guard = length > 2 && sources[2],
+            thisArg = length > 1 && sources[length - 1];
+
+        if (typeof customizer == 'function') {
+          customizer = bindCallback(customizer, thisArg, 5);
+          length -= 2;
+        } else {
+          customizer = typeof thisArg == 'function' ? thisArg : null;
+          length -= (customizer ? 1 : 0);
+        }
+        if (guard && isIterateeCall(sources[0], sources[1], guard)) {
+          customizer = length < 3 ? null : customizer;
+          length = 1;
+        }
+        while (++index < length) {
+          var source = sources[index];
+          if (source) {
+            assigner(object, source, customizer);
+          }
+        }
+        return object;
+      });
+    }
+
+    /**
+     * Creates a `baseEach` or `baseEachRight` function.
+     *
+     * @private
+     * @param {Function} eachFunc The function to iterate over a collection.
+     * @param {boolean} [fromRight] Specify iterating from right to left.
+     * @returns {Function} Returns the new base function.
+     */
+    function createBaseEach(eachFunc, fromRight) {
+      return function(collection, iteratee) {
+        var length = collection ? getLength(collection) : 0;
+        if (!isLength(length)) {
+          return eachFunc(collection, iteratee);
+        }
+        var index = fromRight ? length : -1,
+            iterable = toObject(collection);
+
+        while ((fromRight ? index-- : ++index < length)) {
+          if (iteratee(iterable[index], index, iterable) === false) {
+            break;
+          }
+        }
+        return collection;
+      };
+    }
+
+    /**
+     * Creates a base function for `_.forIn` or `_.forInRight`.
+     *
+     * @private
+     * @param {boolean} [fromRight] Specify iterating from right to left.
+     * @returns {Function} Returns the new base function.
+     */
+    function createBaseFor(fromRight) {
+      return function(object, iteratee, keysFunc) {
+        var iterable = toObject(object),
+            props = keysFunc(object),
+            length = props.length,
+            index = fromRight ? length : -1;
+
+        while ((fromRight ? index-- : ++index < length)) {
+          var key = props[index];
+          if (iteratee(iterable[key], key, iterable) === false) {
+            break;
+          }
+        }
+        return object;
+      };
+    }
+
+    /**
+     * Creates a function that wraps `func` and invokes it with the `this`
+     * binding of `thisArg`.
+     *
+     * @private
+     * @param {Function} func The function to bind.
+     * @param {*} [thisArg] The `this` binding of `func`.
+     * @returns {Function} Returns the new bound function.
+     */
+    function createBindWrapper(func, thisArg) {
+      var Ctor = createCtorWrapper(func);
+
+      function wrapper() {
+        var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
+        return fn.apply(thisArg, arguments);
+      }
+      return wrapper;
+    }
+
+    /**
+     * Creates a `Set` cache object to optimize linear searches of large arrays.
+     *
+     * @private
+     * @param {Array} [values] The values to cache.
+     * @returns {null|Object} Returns the new cache object if `Set` is supported, else `null`.
+     */
+    var createCache = !(nativeCreate && Set) ? constant(null) : function(values) {
+      return new SetCache(values);
+    };
+
+    /**
+     * Creates a function that produces compound words out of the words in a
+     * given string.
+     *
+     * @private
+     * @param {Function} callback The function to combine each word.
+     * @returns {Function} Returns the new compounder function.
+     */
+    function createCompounder(callback) {
+      return function(string) {
+        var index = -1,
+            array = words(deburr(string)),
+            length = array.length,
+            result = '';
+
+        while (++index < length) {
+          result = callback(result, array[index], index);
+        }
+        return result;
+      };
+    }
+
+    /**
+     * Creates a function that produces an instance of `Ctor` regardless of
+     * whether it was invoked as part of a `new` expression or by `call` or `apply`.
+     *
+     * @private
+     * @param {Function} Ctor The constructor to wrap.
+     * @returns {Function} Returns the new wrapped function.
+     */
+    function createCtorWrapper(Ctor) {
+      return function() {
+        var thisBinding = baseCreate(Ctor.prototype),
+            result = Ctor.apply(thisBinding, arguments);
+
+        // Mimic the constructor's `return` behavior.
+        // See https://es5.github.io/#x13.2.2 for more details.
+        return isObject(result) ? result : thisBinding;
+      };
+    }
+
+    /**
+     * Creates a `_.curry` or `_.curryRight` function.
+     *
+     * @private
+     * @param {boolean} flag The curry bit flag.
+     * @returns {Function} Returns the new curry function.
+     */
+    function createCurry(flag) {
+      function curryFunc(func, arity, guard) {
+        if (guard && isIterateeCall(func, arity, guard)) {
+          arity = null;
+        }
+        var result = createWrapper(func, flag, null, null, null, null, null, arity);
+        result.placeholder = curryFunc.placeholder;
+        return result;
+      }
+      return curryFunc;
+    }
+
+    /**
+     * Creates a `_.max` or `_.min` function.
+     *
+     * @private
+     * @param {Function} arrayFunc The function to get the extremum value from an array.
+     * @param {boolean} [isMin] Specify returning the minimum, instead of the maximum,
+     *  extremum value.
+     * @returns {Function} Returns the new extremum function.
+     */
+    function createExtremum(arrayFunc, isMin) {
+      return function(collection, iteratee, thisArg) {
+        if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {
+          iteratee = null;
+        }
+        var func = getCallback(),
+            noIteratee = iteratee == null;
+
+        if (!(func === baseCallback && noIteratee)) {
+          noIteratee = false;
+          iteratee = func(iteratee, thisArg, 3);
+        }
+        if (noIteratee) {
+          var isArr = isArray(collection);
+          if (!isArr && isString(collection)) {
+            iteratee = charAtCallback;
+          } else {
+            return arrayFunc(isArr ? collection : toIterable(collection));
+          }
+        }
+        return extremumBy(collection, iteratee, isMin);
+      };
+    }
+
+    /**
+     * Creates a `_.find` or `_.findLast` function.
+     *
+     * @private
+     * @param {Function} eachFunc The function to iterate over a collection.
+     * @param {boolean} [fromRight] Specify iterating from right to left.
+     * @returns {Function} Returns the new find function.
+     */
+    function createFind(eachFunc, fromRight) {
+      return function(collection, predicate, thisArg) {
+        predicate = getCallback(predicate, thisArg, 3);
+        if (isArray(collection)) {
+          var index = baseFindIndex(collection, predicate, fromRight);
+          return index > -1 ? collection[index] : undefined;
+        }
+        return baseFind(collection, predicate, eachFunc);
+      }
+    }
+
+    /**
+     * Creates a `_.findIndex` or `_.findLastIndex` function.
+     *
+     * @private
+     * @param {boolean} [fromRight] Specify iterating from right to left.
+     * @returns {Function} Returns the new find function.
+     */
+    function createFindIndex(fromRight) {
+      return function(array, predicate, thisArg) {
+        if (!(array && array.length)) {
+          return -1;
+        }
+        predicate = getCallback(predicate, thisArg, 3);
+        return baseFindIndex(array, predicate, fromRight);
+      };
+    }
+
+    /**
+     * Creates a `_.findKey` or `_.findLastKey` function.
+     *
+     * @private
+     * @param {Function} objectFunc The function to iterate over an object.
+     * @returns {Function} Returns the new find function.
+     */
+    function createFindKey(objectFunc) {
+      return function(object, predicate, thisArg) {
+        predicate = getCallback(predicate, thisArg, 3);
+        return baseFind(object, predicate, objectFunc, true);
+      };
+    }
+
+    /**
+     * Creates a `_.flow` or `_.flowRight` function.
+     *
+     * @private
+     * @param {boolean} [fromRight] Specify iterating from right to left.
+     * @returns {Function} Returns the new flow function.
+     */
+    function createFlow(fromRight) {
+      return function() {
+        var length = arguments.length;
+        if (!length) {
+          return function() { return arguments[0]; };
+        }
+        var wrapper,
+            index = fromRight ? length : -1,
+            leftIndex = 0,
+            funcs = Array(length);
+
+        while ((fromRight ? index-- : ++index < length)) {
+          var func = funcs[leftIndex++] = arguments[index];
+          if (typeof func != 'function') {
+            throw new TypeError(FUNC_ERROR_TEXT);
+          }
+          var funcName = wrapper ? '' : getFuncName(func);
+          wrapper = funcName == 'wrapper' ? new LodashWrapper([]) : wrapper;
+        }
+        index = wrapper ? -1 : length;
+        while (++index < length) {
+          func = funcs[index];
+          funcName = getFuncName(func);
+
+          var data = funcName == 'wrapper' ? getData(func) : null;
+          if (data && isLaziable(data[0])) {
+            wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
+          } else {
+            wrapper = (func.length == 1 && isLaziable(func)) ? wrapper[funcName]() : wrapper.thru(func);
+          }
+        }
+        return function() {
+          var args = arguments;
+          if (wrapper && args.length == 1 && isArray(args[0])) {
+            return wrapper.plant(args[0]).value();
+          }
+          var index = 0,
+              result = funcs[index].apply(this, args);
+
+          while (++index < length) {
+            result = funcs[index].call(this, result);
+          }
+          return result;
+        };
+      };
+    }
+
+    /**
+     * Creates a function for `_.forEach` or `_.forEachRight`.
+     *
+     * @private
+     * @param {Function} arrayFunc The function to iterate over an array.
+     * @param {Function} eachFunc The function to iterate over a collection.
+     * @returns {Function} Returns the new each function.
+     */
+    function createForEach(arrayFunc, eachFunc) {
+      return function(collection, iteratee, thisArg) {
+        return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))
+          ? arrayFunc(collection, iteratee)
+          : eachFunc(collection, bindCallback(iteratee, thisArg, 3));
+      };
+    }
+
+    /**
+     * Creates a function for `_.forIn` or `_.forInRight`.
+     *
+     * @private
+     * @param {Function} objectFunc The function to iterate over an object.
+     * @returns {Function} Returns the new each function.
+     */
+    function createForIn(objectFunc) {
+      return function(object, iteratee, thisArg) {
+        if (typeof iteratee != 'function' || thisArg !== undefined) {
+          iteratee = bindCallback(iteratee, thisArg, 3);
+        }
+        return objectFunc(object, iteratee, keysIn);
+      };
+    }
+
+    /**
+     * Creates a function for `_.forOwn` or `_.forOwnRight`.
+     *
+     * @private
+     * @param {Function} objectFunc The function to iterate over an object.
+     * @returns {Function} Returns the new each function.
+     */
+    function createForOwn(objectFunc) {
+      return function(object, iteratee, thisArg) {
+        if (typeof iteratee != 'function' || thisArg !== undefined) {
+          iteratee = bindCallback(iteratee, thisArg, 3);
+        }
+        return objectFunc(object, iteratee);
+      };
+    }
+
+    /**
+     * Creates a function for `_.padLeft` or `_.padRight`.
+     *
+     * @private
+     * @param {boolean} [fromRight] Specify padding from the right.
+     * @returns {Function} Returns the new pad function.
+     */
+    function createPadDir(fromRight) {
+      return function(string, length, chars) {
+        string = baseToString(string);
+        return string && ((fromRight ? string : '') + createPadding(string, length, chars) + (fromRight ? '' : string));
+      };
+    }
+
+    /**
+     * Creates a `_.partial` or `_.partialRight` function.
+     *
+     * @private
+     * @param {boolean} flag The partial bit flag.
+     * @returns {Function} Returns the new partial function.
+     */
+    function createPartial(flag) {
+      var partialFunc = restParam(function(func, partials) {
+        var holders = replaceHolders(partials, partialFunc.placeholder);
+        return createWrapper(func, flag, null, partials, holders);
+      });
+      return partialFunc;
+    }
+
+    /**
+     * Creates a function for `_.reduce` or `_.reduceRight`.
+     *
+     * @private
+     * @param {Function} arrayFunc The function to iterate over an array.
+     * @param {Function} eachFunc The function to iterate over a collection.
+     * @returns {Function} Returns the new each function.
+     */
+    function createReduce(arrayFunc, eachFunc) {
+      return function(collection, iteratee, accumulator, thisArg) {
+        var initFromArray = arguments.length < 3;
+        return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))
+          ? arrayFunc(collection, iteratee, accumulator, initFromArray)
+          : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc);
+      };
+    }
+
+    /**
+     * Creates a function that wraps `func` and invokes it with optional `this`
+     * binding of, partial application, and currying.
+     *
+     * @private
+     * @param {Function|string} func The function or method name to reference.
+     * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details.
+     * @param {*} [thisArg] The `this` binding of `func`.
+     * @param {Array} [partials] The arguments to prepend to those provided to the new function.
+     * @param {Array} [holders] The `partials` placeholder indexes.
+     * @param {Array} [partialsRight] The arguments to append to those provided to the new function.
+     * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
+     * @param {Array} [argPos] The argument positions of the new function.
+     * @param {number} [ary] The arity cap of `func`.
+     * @param {number} [arity] The arity of `func`.
+     * @returns {Function} Returns the new wrapped function.
+     */
+    function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
+      var isAry = bitmask & ARY_FLAG,
+          isBind = bitmask & BIND_FLAG,
+          isBindKey = bitmask & BIND_KEY_FLAG,
+          isCurry = bitmask & CURRY_FLAG,
+          isCurryBound = bitmask & CURRY_BOUND_FLAG,
+          isCurryRight = bitmask & CURRY_RIGHT_FLAG;
+
+      var Ctor = !isBindKey && createCtorWrapper(func),
+          key = func;
+
+      function wrapper() {
+        // Avoid `arguments` object use disqualifying optimizations by
+        // converting it to an array before providing it to other functions.
+        var length = arguments.length,
+            index = length,
+            args = Array(length);
+
+        while (index--) {
+          args[index] = arguments[index];
+        }
+        if (partials) {
+          args = composeArgs(args, partials, holders);
+        }
+        if (partialsRight) {
+          args = composeArgsRight(args, partialsRight, holdersRight);
+        }
+        if (isCurry || isCurryRight) {
+          var placeholder = wrapper.placeholder,
+              argsHolders = replaceHolders(args, placeholder);
+
+          length -= argsHolders.length;
+          if (length < arity) {
+            var newArgPos = argPos ? arrayCopy(argPos) : null,
+                newArity = nativeMax(arity - length, 0),
+                newsHolders = isCurry ? argsHolders : null,
+                newHoldersRight = isCurry ? null : argsHolders,
+                newPartials = isCurry ? args : null,
+                newPartialsRight = isCurry ? null : args;
+
+            bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG);
+            bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG);
+
+            if (!isCurryBound) {
+              bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
+            }
+            var newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity],
+                result = createHybridWrapper.apply(undefined, newData);
+
+            if (isLaziable(func)) {
+              setData(result, newData);
+            }
+            result.placeholder = placeholder;
+            return result;
+          }
+        }
+        var thisBinding = isBind ? thisArg : this;
+        if (isBindKey) {
+          func = thisBinding[key];
+        }
+        if (argPos) {
+          args = reorder(args, argPos);
+        }
+        if (isAry && ary < args.length) {
+          args.length = ary;
+        }
+        var fn = (this && this !== root && this instanceof wrapper) ? (Ctor || createCtorWrapper(func)) : func;
+        return fn.apply(thisBinding, args);
+      }
+      return wrapper;
+    }
+
+    /**
+     * Creates the padding required for `string` based on the given `length`.
+     * The `chars` string is truncated if the number of characters exceeds `length`.
+     *
+     * @private
+     * @param {string} string The string to create padding for.
+     * @param {number} [length=0] The padding length.
+     * @param {string} [chars=' '] The string used as padding.
+     * @returns {string} Returns the pad for `string`.
+     */
+    function createPadding(string, length, chars) {
+      var strLength = string.length;
+      length = +length;
+
+      if (strLength >= length || !nativeIsFinite(length)) {
+        return '';
+      }
+      var padLength = length - strLength;
+      chars = chars == null ? ' ' : (chars + '');
+      return repeat(chars, ceil(padLength / chars.length)).slice(0, padLength);
+    }
+
+    /**
+     * Creates a function that wraps `func` and invokes it with the optional `this`
+     * binding of `thisArg` and the `partials` prepended to those provided to
+     * the wrapper.
+     *
+     * @private
+     * @param {Function} func The function to partially apply arguments to.
+     * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details.
+     * @param {*} thisArg The `this` binding of `func`.
+     * @param {Array} partials The arguments to prepend to those provided to the new function.
+     * @returns {Function} Returns the new bound function.
+     */
+    function createPartialWrapper(func, bitmask, thisArg, partials) {
+      var isBind = bitmask & BIND_FLAG,
+          Ctor = createCtorWrapper(func);
+
+      function wrapper() {
+        // Avoid `arguments` object use disqualifying optimizations by
+        // converting it to an array before providing it `func`.
+        var argsIndex = -1,
+            argsLength = arguments.length,
+            leftIndex = -1,
+            leftLength = partials.length,
+            args = Array(argsLength + leftLength);
+
+        while (++leftIndex < leftLength) {
+          args[leftIndex] = partials[leftIndex];
+        }
+        while (argsLength--) {
+          args[leftIndex++] = arguments[++argsIndex];
+        }
+        var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
+        return fn.apply(isBind ? thisArg : this, args);
+      }
+      return wrapper;
+    }
+
+    /**
+     * Creates a `_.sortedIndex` or `_.sortedLastIndex` function.
+     *
+     * @private
+     * @param {boolean} [retHighest] Specify returning the highest qualified index.
+     * @returns {Function} Returns the new index function.
+     */
+    function createSortedIndex(retHighest) {
+      return function(array, value, iteratee, thisArg) {
+        var func = getCallback(iteratee);
+        return (func === baseCallback && iteratee == null)
+          ? binaryIndex(array, value, retHighest)
+          : binaryIndexBy(array, value, func(iteratee, thisArg, 1), retHighest);
+      };
+    }
+
+    /**
+     * Creates a function that either curries or invokes `func` with optional
+     * `this` binding and partially applied arguments.
+     *
+     * @private
+     * @param {Function|string} func The function or method name to reference.
+     * @param {number} bitmask The bitmask of flags.
+     *  The bitmask may be composed of the following flags:
+     *     1 - `_.bind`
+     *     2 - `_.bindKey`
+     *     4 - `_.curry` or `_.curryRight` of a bound function
+     *     8 - `_.curry`
+     *    16 - `_.curryRight`
+     *    32 - `_.partial`
+     *    64 - `_.partialRight`
+     *   128 - `_.rearg`
+     *   256 - `_.ary`
+     * @param {*} [thisArg] The `this` binding of `func`.
+     * @param {Array} [partials] The arguments to be partially applied.
+     * @param {Array} [holders] The `partials` placeholder indexes.
+     * @param {Array} [argPos] The argument positions of the new function.
+     * @param {number} [ary] The arity cap of `func`.
+     * @param {number} [arity] The arity of `func`.
+     * @returns {Function} Returns the new wrapped function.
+     */
+    function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
+      var isBindKey = bitmask & BIND_KEY_FLAG;
+      if (!isBindKey && typeof func != 'function') {
+        throw new TypeError(FUNC_ERROR_TEXT);
+      }
+      var length = partials ? partials.length : 0;
+      if (!length) {
+        bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG);
+        partials = holders = null;
+      }
+      length -= (holders ? holders.length : 0);
+      if (bitmask & PARTIAL_RIGHT_FLAG) {
+        var partialsRight = partials,
+            holdersRight = holders;
+
+        partials = holders = null;
+      }
+      var data = isBindKey ? null : getData(func),
+          newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity];
+
+      if (data) {
+        mergeData(newData, data);
+        bitmask = newData[1];
+        arity = newData[9];
+      }
+      newData[9] = arity == null
+        ? (isBindKey ? 0 : func.length)
+        : (nativeMax(arity - length, 0) || 0);
+
+      if (bitmask == BIND_FLAG) {
+        var result = createBindWrapper(newData[0], newData[2]);
+      } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) {
+        result = createPartialWrapper.apply(undefined, newData);
+      } else {
+        result = createHybridWrapper.apply(undefined, newData);
+      }
+      var setter = data ? baseSetData : setData;
+      return setter(result, newData);
+    }
+
+    /**
+     * A specialized version of `baseIsEqualDeep` for arrays with support for
+     * partial deep comparisons.
+     *
+     * @private
+     * @param {Array} array The array to compare.
+     * @param {Array} other The other array to compare.
+     * @param {Function} equalFunc The function to determine equivalents of values.
+     * @param {Function} [customizer] The function to customize comparing arrays.
+     * @param {boolean} [isLoose] Specify performing partial comparisons.
+     * @param {Array} [stackA] Tracks traversed `value` objects.
+     * @param {Array} [stackB] Tracks traversed `other` objects.
+     * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
+     */
+    function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) {
+      var index = -1,
+          arrLength = array.length,
+          othLength = other.length,
+          result = true;
+
+      if (arrLength != othLength && !(isLoose && othLength > arrLength)) {
+        return false;
+      }
+      // Deep compare the contents, ignoring non-numeric properties.
+      while (result && ++index < arrLength) {
+        var arrValue = array[index],
+            othValue = other[index];
+
+        result = undefined;
+        if (customizer) {
+          result = isLoose
+            ? customizer(othValue, arrValue, index)
+            : customizer(arrValue, othValue, index);
+        }
+        if (result === undefined) {
+          // Recursively compare arrays (susceptible to call stack limits).
+          if (isLoose) {
+            var othIndex = othLength;
+            while (othIndex--) {
+              othValue = other[othIndex];
+              result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);
+              if (result) {
+                break;
+              }
+            }
+          } else {
+            result = (arrValue && arrValue === othValue) || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);
+          }
+        }
+      }
+      return !!result;
+    }
+
+    /**
+     * A specialized version of `baseIsEqualDeep` for comparing objects of
+     * the same `toStringTag`.
+     *
+     * **Note:** This function only supports comparing values with tags of
+     * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
+     *
+     * @private
+     * @param {Object} value The object to compare.
+     * @param {Object} other The other object to compare.
+     * @param {string} tag The `toStringTag` of the objects to compare.
+     * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+     */
+    function equalByTag(object, other, tag) {
+      switch (tag) {
+        case boolTag:
+        case dateTag:
+          // Coerce dates and booleans to numbers, dates to milliseconds and booleans
+          // to `1` or `0` treating invalid dates coerced to `NaN` as not equal.
+          return +object == +other;
+
+        case errorTag:
+          return object.name == other.name && object.message == other.message;
+
+        case numberTag:
+          // Treat `NaN` vs. `NaN` as equal.
+          return (object != +object)
+            ? other != +other
+            // But, treat `-0` vs. `+0` as not equal.
+            : (object == 0 ? ((1 / object) == (1 / other)) : object == +other);
+
+        case regexpTag:
+        case stringTag:
+          // Coerce regexes to strings and treat strings primitives and string
+          // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details.
+          return object == (other + '');
+      }
+      return false;
+    }
+
+    /**
+     * A specialized version of `baseIsEqualDeep` for objects with support for
+     * partial deep comparisons.
+     *
+     * @private
+     * @param {Object} object The object to compare.
+     * @param {Object} other The other object to compare.
+     * @param {Function} equalFunc The function to determine equivalents of values.
+     * @param {Function} [customizer] The function to customize comparing values.
+     * @param {boolean} [isLoose] Specify performing partial comparisons.
+     * @param {Array} [stackA] Tracks traversed `value` objects.
+     * @param {Array} [stackB] Tracks traversed `other` objects.
+     * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+     */
+    function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
+      var objProps = keys(object),
+          objLength = objProps.length,
+          othProps = keys(other),
+          othLength = othProps.length;
+
+      if (objLength != othLength && !isLoose) {
+        return false;
+      }
+      var skipCtor = isLoose,
+          index = -1;
+
+      while (++index < objLength) {
+        var key = objProps[index],
+            result = isLoose ? key in other : hasOwnProperty.call(other, key);
+
+        if (result) {
+          var objValue = object[key],
+              othValue = other[key];
+
+          result = undefined;
+          if (customizer) {
+            result = isLoose
+              ? customizer(othValue, objValue, key)
+              : customizer(objValue, othValue, key);
+          }
+          if (result === undefined) {
+            // Recursively compare objects (susceptible to call stack limits).
+            result = (objValue && objValue === othValue) || equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB);
+          }
+        }
+        if (!result) {
+          return false;
+        }
+        skipCtor || (skipCtor = key == 'constructor');
+      }
+      if (!skipCtor) {
+        var objCtor = object.constructor,
+            othCtor = other.constructor;
+
+        // Non `Object` object instances with different constructors are not equal.
+        if (objCtor != othCtor &&
+            ('constructor' in object && 'constructor' in other) &&
+            !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
+              typeof othCtor == 'function' && othCtor instanceof othCtor)) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    /**
+     * Gets the extremum value of `collection` invoking `iteratee` for each value
+     * in `collection` to generate the criterion by which the value is ranked.
+     * The `iteratee` is invoked with three arguments: (value, index, collection).
+     *
+     * @private
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} iteratee The function invoked per iteration.
+     * @param {boolean} [isMin] Specify returning the minimum, instead of the
+     *  maximum, extremum value.
+     * @returns {*} Returns the extremum value.
+     */
+    function extremumBy(collection, iteratee, isMin) {
+      var exValue = isMin ? POSITIVE_INFINITY : NEGATIVE_INFINITY,
+          computed = exValue,
+          result = computed;
+
+      baseEach(collection, function(value, index, collection) {
+        var current = iteratee(value, index, collection);
+        if ((isMin ? (current < computed) : (current > computed)) ||
+            (current === exValue && current === result)) {
+          computed = current;
+          result = value;
+        }
+      });
+      return result;
+    }
+
+    /**
+     * Gets the appropriate "callback" function. If the `_.callback` method is
+     * customized this function returns the custom method, otherwise it returns
+     * the `baseCallback` function. If arguments are provided the chosen function
+     * is invoked with them and its result is returned.
+     *
+     * @private
+     * @returns {Function} Returns the chosen function or its result.
+     */
+    function getCallback(func, thisArg, argCount) {
+      var result = lodash.callback || callback;
+      result = result === callback ? baseCallback : result;
+      return argCount ? result(func, thisArg, argCount) : result;
+    }
+
+    /**
+     * Gets metadata for `func`.
+     *
+     * @private
+     * @param {Function} func The function to query.
+     * @returns {*} Returns the metadata for `func`.
+     */
+    var getData = !metaMap ? noop : function(func) {
+      return metaMap.get(func);
+    };
+
+    /**
+     * Gets the name of `func`.
+     *
+     * @private
+     * @param {Function} func The function to query.
+     * @returns {string} Returns the function name.
+     */
+    var getFuncName = (function() {
+      if (!support.funcNames) {
+        return constant('');
+      }
+      if (constant.name == 'constant') {
+        return baseProperty('name');
+      }
+      return function(func) {
+        var result = func.name,
+            array = realNames[result],
+            length = array ? array.length : 0;
+
+        while (length--) {
+          var data = array[length],
+              otherFunc = data.func;
+
+          if (otherFunc == null || otherFunc == func) {
+            return data.name;
+          }
+        }
+        return result;
+      };
+    }());
+
+    /**
+     * Gets the appropriate "indexOf" function. If the `_.indexOf` method is
+     * customized this function returns the custom method, otherwise it returns
+     * the `baseIndexOf` function. If arguments are provided the chosen function
+     * is invoked with them and its result is returned.
+     *
+     * @private
+     * @returns {Function|number} Returns the chosen function or its result.
+     */
+    function getIndexOf(collection, target, fromIndex) {
+      var result = lodash.indexOf || indexOf;
+      result = result === indexOf ? baseIndexOf : result;
+      return collection ? result(collection, target, fromIndex) : result;
+    }
+
+    /**
+     * Gets the "length" property value of `object`.
+     *
+     * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
+     * in Safari on iOS 8.1 ARM64.
+     *
+     * @private
+     * @param {Object} object The object to query.
+     * @returns {*} Returns the "length" value.
+     */
+    var getLength = baseProperty('length');
+
+    /**
+     * Creates an array of the own symbols of `object`.
+     *
+     * @private
+     * @param {Object} object The object to query.
+     * @returns {Array} Returns the array of symbols.
+     */
+    var getSymbols = !getOwnPropertySymbols ? constant([]) : function(object) {
+      return getOwnPropertySymbols(toObject(object));
+    };
+
+    /**
+     * Gets the view, applying any `transforms` to the `start` and `end` positions.
+     *
+     * @private
+     * @param {number} start The start of the view.
+     * @param {number} end The end of the view.
+     * @param {Array} [transforms] The transformations to apply to the view.
+     * @returns {Object} Returns an object containing the `start` and `end`
+     *  positions of the view.
+     */
+    function getView(start, end, transforms) {
+      var index = -1,
+          length = transforms ? transforms.length : 0;
+
+      while (++index < length) {
+        var data = transforms[index],
+            size = data.size;
+
+        switch (data.type) {
+          case 'drop':      start += size; break;
+          case 'dropRight': end -= size; break;
+          case 'take':      end = nativeMin(end, start + size); break;
+          case 'takeRight': start = nativeMax(start, end - size); break;
+        }
+      }
+      return { 'start': start, 'end': end };
+    }
+
+    /**
+     * Initializes an array clone.
+     *
+     * @private
+     * @param {Array} array The array to clone.
+     * @returns {Array} Returns the initialized clone.
+     */
+    function initCloneArray(array) {
+      var length = array.length,
+          result = new array.constructor(length);
+
+      // Add array properties assigned by `RegExp#exec`.
+      if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
+        result.index = array.index;
+        result.input = array.input;
+      }
+      return result;
+    }
+
+    /**
+     * Initializes an object clone.
+     *
+     * @private
+     * @param {Object} object The object to clone.
+     * @returns {Object} Returns the initialized clone.
+     */
+    function initCloneObject(object) {
+      var Ctor = object.constructor;
+      if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) {
+        Ctor = Object;
+      }
+      return new Ctor;
+    }
+
+    /**
+     * Initializes an object clone based on its `toStringTag`.
+     *
+     * **Note:** This function only supports cloning values with tags of
+     * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
+     *
+     * @private
+     * @param {Object} object The object to clone.
+     * @param {string} tag The `toStringTag` of the object to clone.
+     * @param {boolean} [isDeep] Specify a deep clone.
+     * @returns {Object} Returns the initialized clone.
+     */
+    function initCloneByTag(object, tag, isDeep) {
+      var Ctor = object.constructor;
+      switch (tag) {
+        case arrayBufferTag:
+          return bufferClone(object);
+
+        case boolTag:
+        case dateTag:
+          return new Ctor(+object);
+
+        case float32Tag: case float64Tag:
+        case int8Tag: case int16Tag: case int32Tag:
+        case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
+          var buffer = object.buffer;
+          return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length);
+
+        case numberTag:
+        case stringTag:
+          return new Ctor(object);
+
+        case regexpTag:
+          var result = new Ctor(object.source, reFlags.exec(object));
+          result.lastIndex = object.lastIndex;
+      }
+      return result;
+    }
+
+    /**
+     * Invokes the method at `path` on `object`.
+     *
+     * @private
+     * @param {Object} object The object to query.
+     * @param {Array|string} path The path of the method to invoke.
+     * @param {Array} args The arguments to invoke the method with.
+     * @returns {*} Returns the result of the invoked method.
+     */
+    function invokePath(object, path, args) {
+      if (object != null && !isKey(path, object)) {
+        path = toPath(path);
+        object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
+        path = last(path);
+      }
+      var func = object == null ? object : object[path];
+      return func == null ? undefined : func.apply(object, args);
+    }
+
+    /**
+     * Checks if `value` is a valid array-like index.
+     *
+     * @private
+     * @param {*} value The value to check.
+     * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
+     * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
+     */
+    function isIndex(value, length) {
+      value = +value;
+      length = length == null ? MAX_SAFE_INTEGER : length;
+      return value > -1 && value % 1 == 0 && value < length;
+    }
+
+    /**
+     * Checks if the provided arguments are from an iteratee call.
+     *
+     * @private
+     * @param {*} value The potential iteratee value argument.
+     * @param {*} index The potential iteratee index or key argument.
+     * @param {*} object The potential iteratee object argument.
+     * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`.
+     */
+    function isIterateeCall(value, index, object) {
+      if (!isObject(object)) {
+        return false;
+      }
+      var type = typeof index;
+      if (type == 'number') {
+        var length = getLength(object),
+            prereq = isLength(length) && isIndex(index, length);
+      } else {
+        prereq = type == 'string' && index in object;
+      }
+      if (prereq) {
+        var other = object[index];
+        return value === value ? (value === other) : (other !== other);
+      }
+      return false;
+    }
+
+    /**
+     * Checks if `value` is a property name and not a property path.
+     *
+     * @private
+     * @param {*} value The value to check.
+     * @param {Object} [object] The object to query keys on.
+     * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
+     */
+    function isKey(value, object) {
+      var type = typeof value;
+      if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') {
+        return true;
+      }
+      if (isArray(value)) {
+        return false;
+      }
+      var result = !reIsDeepProp.test(value);
+      return result || (object != null && value in toObject(object));
+    }
+
+    /**
+     * Checks if `func` has a lazy counterpart.
+     *
+     * @private
+     * @param {Function} func The function to check.
+     * @returns {boolean} Returns `true` if `func` has a lazy counterpart, else `false`.
+     */
+    function isLaziable(func) {
+      var funcName = getFuncName(func);
+      return !!funcName && func === lodash[funcName] && funcName in LazyWrapper.prototype;
+    }
+
+    /**
+     * Checks if `value` is a valid array-like length.
+     *
+     * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength).
+     *
+     * @private
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
+     */
+    function isLength(value) {
+      return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
+    }
+
+    /**
+     * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
+     *
+     * @private
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` if suitable for strict
+     *  equality comparisons, else `false`.
+     */
+    function isStrictComparable(value) {
+      return value === value && (value === 0 ? ((1 / value) > 0) : !isObject(value));
+    }
+
+    /**
+     * Merges the function metadata of `source` into `data`.
+     *
+     * Merging metadata reduces the number of wrappers required to invoke a function.
+     * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
+     * may be applied regardless of execution order. Methods like `_.ary` and `_.rearg`
+     * augment function arguments, making the order in which they are executed important,
+     * preventing the merging of metadata. However, we make an exception for a safe
+     * common case where curried functions have `_.ary` and or `_.rearg` applied.
+     *
+     * @private
+     * @param {Array} data The destination metadata.
+     * @param {Array} source The source metadata.
+     * @returns {Array} Returns `data`.
+     */
+    function mergeData(data, source) {
+      var bitmask = data[1],
+          srcBitmask = source[1],
+          newBitmask = bitmask | srcBitmask,
+          isCommon = newBitmask < ARY_FLAG;
+
+      var isCombo =
+        (srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG) ||
+        (srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8]) ||
+        (srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG);
+
+      // Exit early if metadata can't be merged.
+      if (!(isCommon || isCombo)) {
+        return data;
+      }
+      // Use source `thisArg` if available.
+      if (srcBitmask & BIND_FLAG) {
+        data[2] = source[2];
+        // Set when currying a bound function.
+        newBitmask |= (bitmask & BIND_FLAG) ? 0 : CURRY_BOUND_FLAG;
+      }
+      // Compose partial arguments.
+      var value = source[3];
+      if (value) {
+        var partials = data[3];
+        data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value);
+        data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]);
+      }
+      // Compose partial right arguments.
+      value = source[5];
+      if (value) {
+        partials = data[5];
+        data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value);
+        data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]);
+      }
+      // Use source `argPos` if available.
+      value = source[7];
+      if (value) {
+        data[7] = arrayCopy(value);
+      }
+      // Use source `ary` if it's smaller.
+      if (srcBitmask & ARY_FLAG) {
+        data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
+      }
+      // Use source `arity` if one is not provided.
+      if (data[9] == null) {
+        data[9] = source[9];
+      }
+      // Use source `func` and merge bitmasks.
+      data[0] = source[0];
+      data[1] = newBitmask;
+
+      return data;
+    }
+
+    /**
+     * A specialized version of `_.pick` that picks `object` properties specified
+     * by `props`.
+     *
+     * @private
+     * @param {Object} object The source object.
+     * @param {string[]} props The property names to pick.
+     * @returns {Object} Returns the new object.
+     */
+    function pickByArray(object, props) {
+      object = toObject(object);
+
+      var index = -1,
+          length = props.length,
+          result = {};
+
+      while (++index < length) {
+        var key = props[index];
+        if (key in object) {
+          result[key] = object[key];
+        }
+      }
+      return result;
+    }
+
+    /**
+     * A specialized version of `_.pick` that picks `object` properties `predicate`
+     * returns truthy for.
+     *
+     * @private
+     * @param {Object} object The source object.
+     * @param {Function} predicate The function invoked per iteration.
+     * @returns {Object} Returns the new object.
+     */
+    function pickByCallback(object, predicate) {
+      var result = {};
+      baseForIn(object, function(value, key, object) {
+        if (predicate(value, key, object)) {
+          result[key] = value;
+        }
+      });
+      return result;
+    }
+
+    /**
+     * Reorder `array` according to the specified indexes where the element at
+     * the first index is assigned as the first element, the element at
+     * the second index is assigned as the second element, and so on.
+     *
+     * @private
+     * @param {Array} array The array to reorder.
+     * @param {Array} indexes The arranged array indexes.
+     * @returns {Array} Returns `array`.
+     */
+    function reorder(array, indexes) {
+      var arrLength = array.length,
+          length = nativeMin(indexes.length, arrLength),
+          oldArray = arrayCopy(array);
+
+      while (length--) {
+        var index = indexes[length];
+        array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
+      }
+      return array;
+    }
+
+    /**
+     * Sets metadata for `func`.
+     *
+     * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
+     * period of time, it will trip its breaker and transition to an identity function
+     * to avoid garbage collection pauses in V8. See [V8 issue 2070](https://code.google.com/p/v8/issues/detail?id=2070)
+     * for more details.
+     *
+     * @private
+     * @param {Function} func The function to associate metadata with.
+     * @param {*} data The metadata.
+     * @returns {Function} Returns `func`.
+     */
+    var setData = (function() {
+      var count = 0,
+          lastCalled = 0;
+
+      return function(key, value) {
+        var stamp = now(),
+            remaining = HOT_SPAN - (stamp - lastCalled);
+
+        lastCalled = stamp;
+        if (remaining > 0) {
+          if (++count >= HOT_COUNT) {
+            return key;
+          }
+        } else {
+          count = 0;
+        }
+        return baseSetData(key, value);
+      };
+    }());
+
+    /**
+     * A fallback implementation of `_.isPlainObject` which checks if `value`
+     * is an object created by the `Object` constructor or has a `[[Prototype]]`
+     * of `null`.
+     *
+     * @private
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
+     */
+    function shimIsPlainObject(value) {
+      var Ctor,
+          support = lodash.support;
+
+      // Exit early for non `Object` objects.
+      if (!(isObjectLike(value) && objToString.call(value) == objectTag) ||
+          (!hasOwnProperty.call(value, 'constructor') &&
+            (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) {
+        return false;
+      }
+      // IE < 9 iterates inherited properties before own properties. If the first
+      // iterated property is an object's own property then there are no inherited
+      // enumerable properties.
+      var result;
+      // In most environments an object's own properties are iterated before
+      // its inherited properties. If the last iterated property is an object's
+      // own property then there are no inherited enumerable properties.
+      baseForIn(value, function(subValue, key) {
+        result = key;
+      });
+      return result === undefined || hasOwnProperty.call(value, result);
+    }
+
+    /**
+     * A fallback implementation of `Object.keys` which creates an array of the
+     * own enumerable property names of `object`.
+     *
+     * @private
+     * @param {Object} object The object to query.
+     * @returns {Array} Returns the array of property names.
+     */
+    function shimKeys(object) {
+      var props = keysIn(object),
+          propsLength = props.length,
+          length = propsLength && object.length,
+          support = lodash.support;
+
+      var allowIndexes = length && isLength(length) &&
+        (isArray(object) || (support.nonEnumArgs && isArguments(object)));
+
+      var index = -1,
+          result = [];
+
+      while (++index < propsLength) {
+        var key = props[index];
+        if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) {
+          result.push(key);
+        }
+      }
+      return result;
+    }
+
+    /**
+     * Converts `value` to an array-like object if it is not one.
+     *
+     * @private
+     * @param {*} value The value to process.
+     * @returns {Array|Object} Returns the array-like object.
+     */
+    function toIterable(value) {
+      if (value == null) {
+        return [];
+      }
+      if (!isLength(getLength(value))) {
+        return values(value);
+      }
+      return isObject(value) ? value : Object(value);
+    }
+
+    /**
+     * Converts `value` to an object if it is not one.
+     *
+     * @private
+     * @param {*} value The value to process.
+     * @returns {Object} Returns the object.
+     */
+    function toObject(value) {
+      return isObject(value) ? value : Object(value);
+    }
+
+    /**
+     * Converts `value` to property path array if it is not one.
+     *
+     * @private
+     * @param {*} value The value to process.
+     * @returns {Array} Returns the property path array.
+     */
+    function toPath(value) {
+      if (isArray(value)) {
+        return value;
+      }
+      var result = [];
+      baseToString(value).replace(rePropName, function(match, number, quote, string) {
+        result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
+      });
+      return result;
+    }
+
+    /**
+     * Creates a clone of `wrapper`.
+     *
+     * @private
+     * @param {Object} wrapper The wrapper to clone.
+     * @returns {Object} Returns the cloned wrapper.
+     */
+    function wrapperClone(wrapper) {
+      return wrapper instanceof LazyWrapper
+        ? wrapper.clone()
+        : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__));
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * Creates an array of elements split into groups the length of `size`.
+     * If `collection` can't be split evenly, the final chunk will be the remaining
+     * elements.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to process.
+     * @param {number} [size=1] The length of each chunk.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {Array} Returns the new array containing chunks.
+     * @example
+     *
+     * _.chunk(['a', 'b', 'c', 'd'], 2);
+     * // => [['a', 'b'], ['c', 'd']]
+     *
+     * _.chunk(['a', 'b', 'c', 'd'], 3);
+     * // => [['a', 'b', 'c'], ['d']]
+     */
+    function chunk(array, size, guard) {
+      if (guard ? isIterateeCall(array, size, guard) : size == null) {
+        size = 1;
+      } else {
+        size = nativeMax(+size || 1, 1);
+      }
+      var index = 0,
+          length = array ? array.length : 0,
+          resIndex = -1,
+          result = Array(ceil(length / size));
+
+      while (index < length) {
+        result[++resIndex] = baseSlice(array, index, (index += size));
+      }
+      return result;
+    }
+
+    /**
+     * Creates an array with all falsey values removed. The values `false`, `null`,
+     * `0`, `""`, `undefined`, and `NaN` are falsey.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to compact.
+     * @returns {Array} Returns the new array of filtered values.
+     * @example
+     *
+     * _.compact([0, 1, false, 2, '', 3]);
+     * // => [1, 2, 3]
+     */
+    function compact(array) {
+      var index = -1,
+          length = array ? array.length : 0,
+          resIndex = -1,
+          result = [];
+
+      while (++index < length) {
+        var value = array[index];
+        if (value) {
+          result[++resIndex] = value;
+        }
+      }
+      return result;
+    }
+
+    /**
+     * Creates an array excluding all values of the provided arrays using
+     * `SameValueZero` for equality comparisons.
+     *
+     * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
+     * comparisons are like strict equality comparisons, e.g. `===`, except that
+     * `NaN` matches `NaN`.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to inspect.
+     * @param {...Array} [values] The arrays of values to exclude.
+     * @returns {Array} Returns the new array of filtered values.
+     * @example
+     *
+     * _.difference([1, 2, 3], [4, 2]);
+     * // => [1, 3]
+     */
+    var difference = restParam(function(array, values) {
+      return (isArray(array) || isArguments(array))
+        ? baseDifference(array, baseFlatten(values, false, true))
+        : [];
+    });
+
+    /**
+     * Creates a slice of `array` with `n` elements dropped from the beginning.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to query.
+     * @param {number} [n=1] The number of elements to drop.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {Array} Returns the slice of `array`.
+     * @example
+     *
+     * _.drop([1, 2, 3]);
+     * // => [2, 3]
+     *
+     * _.drop([1, 2, 3], 2);
+     * // => [3]
+     *
+     * _.drop([1, 2, 3], 5);
+     * // => []
+     *
+     * _.drop([1, 2, 3], 0);
+     * // => [1, 2, 3]
+     */
+    function drop(array, n, guard) {
+      var length = array ? array.length : 0;
+      if (!length) {
+        return [];
+      }
+      if (guard ? isIterateeCall(array, n, guard) : n == null) {
+        n = 1;
+      }
+      return baseSlice(array, n < 0 ? 0 : n);
+    }
+
+    /**
+     * Creates a slice of `array` with `n` elements dropped from the end.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to query.
+     * @param {number} [n=1] The number of elements to drop.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {Array} Returns the slice of `array`.
+     * @example
+     *
+     * _.dropRight([1, 2, 3]);
+     * // => [1, 2]
+     *
+     * _.dropRight([1, 2, 3], 2);
+     * // => [1]
+     *
+     * _.dropRight([1, 2, 3], 5);
+     * // => []
+     *
+     * _.dropRight([1, 2, 3], 0);
+     * // => [1, 2, 3]
+     */
+    function dropRight(array, n, guard) {
+      var length = array ? array.length : 0;
+      if (!length) {
+        return [];
+      }
+      if (guard ? isIterateeCall(array, n, guard) : n == null) {
+        n = 1;
+      }
+      n = length - (+n || 0);
+      return baseSlice(array, 0, n < 0 ? 0 : n);
+    }
+
+    /**
+     * Creates a slice of `array` excluding elements dropped from the end.
+     * Elements are dropped until `predicate` returns falsey. The predicate is
+     * bound to `thisArg` and invoked with three arguments: (value, index, array).
+     *
+     * If a property name is provided for `predicate` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `predicate` the created `_.matches` style
+     * callback returns `true` for elements that match the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to query.
+     * @param {Function|Object|string} [predicate=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {Array} Returns the slice of `array`.
+     * @example
+     *
+     * _.dropRightWhile([1, 2, 3], function(n) {
+     *   return n > 1;
+     * });
+     * // => [1]
+     *
+     * var users = [
+     *   { 'user': 'barney',  'active': true },
+     *   { 'user': 'fred',    'active': false },
+     *   { 'user': 'pebbles', 'active': false }
+     * ];
+     *
+     * // using the `_.matches` callback shorthand
+     * _.pluck(_.dropRightWhile(users, { 'user': 'pebbles', 'active': false }), 'user');
+     * // => ['barney', 'fred']
+     *
+     * // using the `_.matchesProperty` callback shorthand
+     * _.pluck(_.dropRightWhile(users, 'active', false), 'user');
+     * // => ['barney']
+     *
+     * // using the `_.property` callback shorthand
+     * _.pluck(_.dropRightWhile(users, 'active'), 'user');
+     * // => ['barney', 'fred', 'pebbles']
+     */
+    function dropRightWhile(array, predicate, thisArg) {
+      return (array && array.length)
+        ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true)
+        : [];
+    }
+
+    /**
+     * Creates a slice of `array` excluding elements dropped from the beginning.
+     * Elements are dropped until `predicate` returns falsey. The predicate is
+     * bound to `thisArg` and invoked with three arguments: (value, index, array).
+     *
+     * If a property name is provided for `predicate` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `predicate` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to query.
+     * @param {Function|Object|string} [predicate=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {Array} Returns the slice of `array`.
+     * @example
+     *
+     * _.dropWhile([1, 2, 3], function(n) {
+     *   return n < 3;
+     * });
+     * // => [3]
+     *
+     * var users = [
+     *   { 'user': 'barney',  'active': false },
+     *   { 'user': 'fred',    'active': false },
+     *   { 'user': 'pebbles', 'active': true }
+     * ];
+     *
+     * // using the `_.matches` callback shorthand
+     * _.pluck(_.dropWhile(users, { 'user': 'barney', 'active': false }), 'user');
+     * // => ['fred', 'pebbles']
+     *
+     * // using the `_.matchesProperty` callback shorthand
+     * _.pluck(_.dropWhile(users, 'active', false), 'user');
+     * // => ['pebbles']
+     *
+     * // using the `_.property` callback shorthand
+     * _.pluck(_.dropWhile(users, 'active'), 'user');
+     * // => ['barney', 'fred', 'pebbles']
+     */
+    function dropWhile(array, predicate, thisArg) {
+      return (array && array.length)
+        ? baseWhile(array, getCallback(predicate, thisArg, 3), true)
+        : [];
+    }
+
+    /**
+     * Fills elements of `array` with `value` from `start` up to, but not
+     * including, `end`.
+     *
+     * **Note:** This method mutates `array`.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to fill.
+     * @param {*} value The value to fill `array` with.
+     * @param {number} [start=0] The start position.
+     * @param {number} [end=array.length] The end position.
+     * @returns {Array} Returns `array`.
+     * @example
+     *
+     * var array = [1, 2, 3];
+     *
+     * _.fill(array, 'a');
+     * console.log(array);
+     * // => ['a', 'a', 'a']
+     *
+     * _.fill(Array(3), 2);
+     * // => [2, 2, 2]
+     *
+     * _.fill([4, 6, 8], '*', 1, 2);
+     * // => [4, '*', 8]
+     */
+    function fill(array, value, start, end) {
+      var length = array ? array.length : 0;
+      if (!length) {
+        return [];
+      }
+      if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
+        start = 0;
+        end = length;
+      }
+      return baseFill(array, value, start, end);
+    }
+
+    /**
+     * This method is like `_.find` except that it returns the index of the first
+     * element `predicate` returns truthy for instead of the element itself.
+     *
+     * If a property name is provided for `predicate` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `predicate` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to search.
+     * @param {Function|Object|string} [predicate=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {number} Returns the index of the found element, else `-1`.
+     * @example
+     *
+     * var users = [
+     *   { 'user': 'barney',  'active': false },
+     *   { 'user': 'fred',    'active': false },
+     *   { 'user': 'pebbles', 'active': true }
+     * ];
+     *
+     * _.findIndex(users, function(chr) {
+     *   return chr.user == 'barney';
+     * });
+     * // => 0
+     *
+     * // using the `_.matches` callback shorthand
+     * _.findIndex(users, { 'user': 'fred', 'active': false });
+     * // => 1
+     *
+     * // using the `_.matchesProperty` callback shorthand
+     * _.findIndex(users, 'active', false);
+     * // => 0
+     *
+     * // using the `_.property` callback shorthand
+     * _.findIndex(users, 'active');
+     * // => 2
+     */
+    var findIndex = createFindIndex();
+
+    /**
+     * This method is like `_.findIndex` except that it iterates over elements
+     * of `collection` from right to left.
+     *
+     * If a property name is provided for `predicate` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `predicate` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to search.
+     * @param {Function|Object|string} [predicate=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {number} Returns the index of the found element, else `-1`.
+     * @example
+     *
+     * var users = [
+     *   { 'user': 'barney',  'active': true },
+     *   { 'user': 'fred',    'active': false },
+     *   { 'user': 'pebbles', 'active': false }
+     * ];
+     *
+     * _.findLastIndex(users, function(chr) {
+     *   return chr.user == 'pebbles';
+     * });
+     * // => 2
+     *
+     * // using the `_.matches` callback shorthand
+     * _.findLastIndex(users, { 'user': 'barney', 'active': true });
+     * // => 0
+     *
+     * // using the `_.matchesProperty` callback shorthand
+     * _.findLastIndex(users, 'active', false);
+     * // => 2
+     *
+     * // using the `_.property` callback shorthand
+     * _.findLastIndex(users, 'active');
+     * // => 0
+     */
+    var findLastIndex = createFindIndex(true);
+
+    /**
+     * Gets the first element of `array`.
+     *
+     * @static
+     * @memberOf _
+     * @alias head
+     * @category Array
+     * @param {Array} array The array to query.
+     * @returns {*} Returns the first element of `array`.
+     * @example
+     *
+     * _.first([1, 2, 3]);
+     * // => 1
+     *
+     * _.first([]);
+     * // => undefined
+     */
+    function first(array) {
+      return array ? array[0] : undefined;
+    }
+
+    /**
+     * Flattens a nested array. If `isDeep` is `true` the array is recursively
+     * flattened, otherwise it is only flattened a single level.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to flatten.
+     * @param {boolean} [isDeep] Specify a deep flatten.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {Array} Returns the new flattened array.
+     * @example
+     *
+     * _.flatten([1, [2, 3, [4]]]);
+     * // => [1, 2, 3, [4]]
+     *
+     * // using `isDeep`
+     * _.flatten([1, [2, 3, [4]]], true);
+     * // => [1, 2, 3, 4]
+     */
+    function flatten(array, isDeep, guard) {
+      var length = array ? array.length : 0;
+      if (guard && isIterateeCall(array, isDeep, guard)) {
+        isDeep = false;
+      }
+      return length ? baseFlatten(array, isDeep) : [];
+    }
+
+    /**
+     * Recursively flattens a nested array.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to recursively flatten.
+     * @returns {Array} Returns the new flattened array.
+     * @example
+     *
+     * _.flattenDeep([1, [2, 3, [4]]]);
+     * // => [1, 2, 3, 4]
+     */
+    function flattenDeep(array) {
+      var length = array ? array.length : 0;
+      return length ? baseFlatten(array, true) : [];
+    }
+
+    /**
+     * Gets the index at which the first occurrence of `value` is found in `array`
+     * using `SameValueZero` for equality comparisons. If `fromIndex` is negative,
+     * it is used as the offset from the end of `array`. If `array` is sorted
+     * providing `true` for `fromIndex` performs a faster binary search.
+     *
+     * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
+     * comparisons are like strict equality comparisons, e.g. `===`, except that
+     * `NaN` matches `NaN`.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to search.
+     * @param {*} value The value to search for.
+     * @param {boolean|number} [fromIndex=0] The index to search from or `true`
+     *  to perform a binary search on a sorted array.
+     * @returns {number} Returns the index of the matched value, else `-1`.
+     * @example
+     *
+     * _.indexOf([1, 2, 1, 2], 2);
+     * // => 1
+     *
+     * // using `fromIndex`
+     * _.indexOf([1, 2, 1, 2], 2, 2);
+     * // => 3
+     *
+     * // performing a binary search
+     * _.indexOf([1, 1, 2, 2], 2, true);
+     * // => 2
+     */
+    function indexOf(array, value, fromIndex) {
+      var length = array ? array.length : 0;
+      if (!length) {
+        return -1;
+      }
+      if (typeof fromIndex == 'number') {
+        fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex;
+      } else if (fromIndex) {
+        var index = binaryIndex(array, value),
+            other = array[index];
+
+        if (value === value ? (value === other) : (other !== other)) {
+          return index;
+        }
+        return -1;
+      }
+      return baseIndexOf(array, value, fromIndex || 0);
+    }
+
+    /**
+     * Gets all but the last element of `array`.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to query.
+     * @returns {Array} Returns the slice of `array`.
+     * @example
+     *
+     * _.initial([1, 2, 3]);
+     * // => [1, 2]
+     */
+    function initial(array) {
+      return dropRight(array, 1);
+    }
+
+    /**
+     * Creates an array of unique values in all provided arrays using `SameValueZero`
+     * for equality comparisons.
+     *
+     * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
+     * comparisons are like strict equality comparisons, e.g. `===`, except that
+     * `NaN` matches `NaN`.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {...Array} [arrays] The arrays to inspect.
+     * @returns {Array} Returns the new array of shared values.
+     * @example
+     * _.intersection([1, 2], [4, 2], [2, 1]);
+     * // => [2]
+     */
+    function intersection() {
+      var args = [],
+          argsIndex = -1,
+          argsLength = arguments.length,
+          caches = [],
+          indexOf = getIndexOf(),
+          isCommon = indexOf == baseIndexOf,
+          result = [];
+
+      while (++argsIndex < argsLength) {
+        var value = arguments[argsIndex];
+        if (isArray(value) || isArguments(value)) {
+          args.push(value);
+          caches.push((isCommon && value.length >= 120) ? createCache(argsIndex && value) : null);
+        }
+      }
+      argsLength = args.length;
+      if (argsLength < 2) {
+        return result;
+      }
+      var array = args[0],
+          index = -1,
+          length = array ? array.length : 0,
+          seen = caches[0];
+
+      outer:
+      while (++index < length) {
+        value = array[index];
+        if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) {
+          argsIndex = argsLength;
+          while (--argsIndex) {
+            var cache = caches[argsIndex];
+            if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value, 0)) < 0) {
+              continue outer;
+            }
+          }
+          if (seen) {
+            seen.push(value);
+          }
+          result.push(value);
+        }
+      }
+      return result;
+    }
+
+    /**
+     * Gets the last element of `array`.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to query.
+     * @returns {*} Returns the last element of `array`.
+     * @example
+     *
+     * _.last([1, 2, 3]);
+     * // => 3
+     */
+    function last(array) {
+      var length = array ? array.length : 0;
+      return length ? array[length - 1] : undefined;
+    }
+
+    /**
+     * This method is like `_.indexOf` except that it iterates over elements of
+     * `array` from right to left.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to search.
+     * @param {*} value The value to search for.
+     * @param {boolean|number} [fromIndex=array.length-1] The index to search from
+     *  or `true` to perform a binary search on a sorted array.
+     * @returns {number} Returns the index of the matched value, else `-1`.
+     * @example
+     *
+     * _.lastIndexOf([1, 2, 1, 2], 2);
+     * // => 3
+     *
+     * // using `fromIndex`
+     * _.lastIndexOf([1, 2, 1, 2], 2, 2);
+     * // => 1
+     *
+     * // performing a binary search
+     * _.lastIndexOf([1, 1, 2, 2], 2, true);
+     * // => 3
+     */
+    function lastIndexOf(array, value, fromIndex) {
+      var length = array ? array.length : 0;
+      if (!length) {
+        return -1;
+      }
+      var index = length;
+      if (typeof fromIndex == 'number') {
+        index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1;
+      } else if (fromIndex) {
+        index = binaryIndex(array, value, true) - 1;
+        var other = array[index];
+        if (value === value ? (value === other) : (other !== other)) {
+          return index;
+        }
+        return -1;
+      }
+      if (value !== value) {
+        return indexOfNaN(array, index, true);
+      }
+      while (index--) {
+        if (array[index] === value) {
+          return index;
+        }
+      }
+      return -1;
+    }
+
+    /**
+     * Removes all provided values from `array` using `SameValueZero` for equality
+     * comparisons.
+     *
+     * **Notes:**
+     *  - Unlike `_.without`, this method mutates `array`
+     *  - [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
+     *    comparisons are like strict equality comparisons, e.g. `===`, except
+     *    that `NaN` matches `NaN`
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to modify.
+     * @param {...*} [values] The values to remove.
+     * @returns {Array} Returns `array`.
+     * @example
+     *
+     * var array = [1, 2, 3, 1, 2, 3];
+     *
+     * _.pull(array, 2, 3);
+     * console.log(array);
+     * // => [1, 1]
+     */
+    function pull() {
+      var args = arguments,
+          array = args[0];
+
+      if (!(array && array.length)) {
+        return array;
+      }
+      var index = 0,
+          indexOf = getIndexOf(),
+          length = args.length;
+
+      while (++index < length) {
+        var fromIndex = 0,
+            value = args[index];
+
+        while ((fromIndex = indexOf(array, value, fromIndex)) > -1) {
+          splice.call(array, fromIndex, 1);
+        }
+      }
+      return array;
+    }
+
+    /**
+     * Removes elements from `array` corresponding to the given indexes and returns
+     * an array of the removed elements. Indexes may be specified as an array of
+     * indexes or as individual arguments.
+     *
+     * **Note:** Unlike `_.at`, this method mutates `array`.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to modify.
+     * @param {...(number|number[])} [indexes] The indexes of elements to remove,
+     *  specified as individual indexes or arrays of indexes.
+     * @returns {Array} Returns the new array of removed elements.
+     * @example
+     *
+     * var array = [5, 10, 15, 20];
+     * var evens = _.pullAt(array, 1, 3);
+     *
+     * console.log(array);
+     * // => [5, 15]
+     *
+     * console.log(evens);
+     * // => [10, 20]
+     */
+    var pullAt = restParam(function(array, indexes) {
+      array || (array = []);
+      indexes = baseFlatten(indexes);
+
+      var result = baseAt(array, indexes);
+      basePullAt(array, indexes.sort(baseCompareAscending));
+      return result;
+    });
+
+    /**
+     * Removes all elements from `array` that `predicate` returns truthy for
+     * and returns an array of the removed elements. The predicate is bound to
+     * `thisArg` and invoked with three arguments: (value, index, array).
+     *
+     * If a property name is provided for `predicate` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `predicate` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * **Note:** Unlike `_.filter`, this method mutates `array`.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to modify.
+     * @param {Function|Object|string} [predicate=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {Array} Returns the new array of removed elements.
+     * @example
+     *
+     * var array = [1, 2, 3, 4];
+     * var evens = _.remove(array, function(n) {
+     *   return n % 2 == 0;
+     * });
+     *
+     * console.log(array);
+     * // => [1, 3]
+     *
+     * console.log(evens);
+     * // => [2, 4]
+     */
+    function remove(array, predicate, thisArg) {
+      var result = [];
+      if (!(array && array.length)) {
+        return result;
+      }
+      var index = -1,
+          indexes = [],
+          length = array.length;
+
+      predicate = getCallback(predicate, thisArg, 3);
+      while (++index < length) {
+        var value = array[index];
+        if (predicate(value, index, array)) {
+          result.push(value);
+          indexes.push(index);
+        }
+      }
+      basePullAt(array, indexes);
+      return result;
+    }
+
+    /**
+     * Gets all but the first element of `array`.
+     *
+     * @static
+     * @memberOf _
+     * @alias tail
+     * @category Array
+     * @param {Array} array The array to query.
+     * @returns {Array} Returns the slice of `array`.
+     * @example
+     *
+     * _.rest([1, 2, 3]);
+     * // => [2, 3]
+     */
+    function rest(array) {
+      return drop(array, 1);
+    }
+
+    /**
+     * Creates a slice of `array` from `start` up to, but not including, `end`.
+     *
+     * **Note:** This method is used instead of `Array#slice` to support node
+     * lists in IE < 9 and to ensure dense arrays are returned.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to slice.
+     * @param {number} [start=0] The start position.
+     * @param {number} [end=array.length] The end position.
+     * @returns {Array} Returns the slice of `array`.
+     */
+    function slice(array, start, end) {
+      var length = array ? array.length : 0;
+      if (!length) {
+        return [];
+      }
+      if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
+        start = 0;
+        end = length;
+      }
+      return baseSlice(array, start, end);
+    }
+
+    /**
+     * Uses a binary search to determine the lowest index at which `value` should
+     * be inserted into `array` in order to maintain its sort order. If an iteratee
+     * function is provided it is invoked for `value` and each element of `array`
+     * to compute their sort ranking. The iteratee is bound to `thisArg` and
+     * invoked with one argument; (value).
+     *
+     * If a property name is provided for `iteratee` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `iteratee` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The sorted array to inspect.
+     * @param {*} value The value to evaluate.
+     * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {number} Returns the index at which `value` should be inserted
+     *  into `array`.
+     * @example
+     *
+     * _.sortedIndex([30, 50], 40);
+     * // => 1
+     *
+     * _.sortedIndex([4, 4, 5, 5], 5);
+     * // => 2
+     *
+     * var dict = { 'data': { 'thirty': 30, 'forty': 40, 'fifty': 50 } };
+     *
+     * // using an iteratee function
+     * _.sortedIndex(['thirty', 'fifty'], 'forty', function(word) {
+     *   return this.data[word];
+     * }, dict);
+     * // => 1
+     *
+     * // using the `_.property` callback shorthand
+     * _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
+     * // => 1
+     */
+    var sortedIndex = createSortedIndex();
+
+    /**
+     * This method is like `_.sortedIndex` except that it returns the highest
+     * index at which `value` should be inserted into `array` in order to
+     * maintain its sort order.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The sorted array to inspect.
+     * @param {*} value The value to evaluate.
+     * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {number} Returns the index at which `value` should be inserted
+     *  into `array`.
+     * @example
+     *
+     * _.sortedLastIndex([4, 4, 5, 5], 5);
+     * // => 4
+     */
+    var sortedLastIndex = createSortedIndex(true);
+
+    /**
+     * Creates a slice of `array` with `n` elements taken from the beginning.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to query.
+     * @param {number} [n=1] The number of elements to take.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {Array} Returns the slice of `array`.
+     * @example
+     *
+     * _.take([1, 2, 3]);
+     * // => [1]
+     *
+     * _.take([1, 2, 3], 2);
+     * // => [1, 2]
+     *
+     * _.take([1, 2, 3], 5);
+     * // => [1, 2, 3]
+     *
+     * _.take([1, 2, 3], 0);
+     * // => []
+     */
+    function take(array, n, guard) {
+      var length = array ? array.length : 0;
+      if (!length) {
+        return [];
+      }
+      if (guard ? isIterateeCall(array, n, guard) : n == null) {
+        n = 1;
+      }
+      return baseSlice(array, 0, n < 0 ? 0 : n);
+    }
+
+    /**
+     * Creates a slice of `array` with `n` elements taken from the end.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to query.
+     * @param {number} [n=1] The number of elements to take.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {Array} Returns the slice of `array`.
+     * @example
+     *
+     * _.takeRight([1, 2, 3]);
+     * // => [3]
+     *
+     * _.takeRight([1, 2, 3], 2);
+     * // => [2, 3]
+     *
+     * _.takeRight([1, 2, 3], 5);
+     * // => [1, 2, 3]
+     *
+     * _.takeRight([1, 2, 3], 0);
+     * // => []
+     */
+    function takeRight(array, n, guard) {
+      var length = array ? array.length : 0;
+      if (!length) {
+        return [];
+      }
+      if (guard ? isIterateeCall(array, n, guard) : n == null) {
+        n = 1;
+      }
+      n = length - (+n || 0);
+      return baseSlice(array, n < 0 ? 0 : n);
+    }
+
+    /**
+     * Creates a slice of `array` with elements taken from the end. Elements are
+     * taken until `predicate` returns falsey. The predicate is bound to `thisArg`
+     * and invoked with three arguments: (value, index, array).
+     *
+     * If a property name is provided for `predicate` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `predicate` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to query.
+     * @param {Function|Object|string} [predicate=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {Array} Returns the slice of `array`.
+     * @example
+     *
+     * _.takeRightWhile([1, 2, 3], function(n) {
+     *   return n > 1;
+     * });
+     * // => [2, 3]
+     *
+     * var users = [
+     *   { 'user': 'barney',  'active': true },
+     *   { 'user': 'fred',    'active': false },
+     *   { 'user': 'pebbles', 'active': false }
+     * ];
+     *
+     * // using the `_.matches` callback shorthand
+     * _.pluck(_.takeRightWhile(users, { 'user': 'pebbles', 'active': false }), 'user');
+     * // => ['pebbles']
+     *
+     * // using the `_.matchesProperty` callback shorthand
+     * _.pluck(_.takeRightWhile(users, 'active', false), 'user');
+     * // => ['fred', 'pebbles']
+     *
+     * // using the `_.property` callback shorthand
+     * _.pluck(_.takeRightWhile(users, 'active'), 'user');
+     * // => []
+     */
+    function takeRightWhile(array, predicate, thisArg) {
+      return (array && array.length)
+        ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true)
+        : [];
+    }
+
+    /**
+     * Creates a slice of `array` with elements taken from the beginning. Elements
+     * are taken until `predicate` returns falsey. The predicate is bound to
+     * `thisArg` and invoked with three arguments: (value, index, array).
+     *
+     * If a property name is provided for `predicate` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `predicate` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to query.
+     * @param {Function|Object|string} [predicate=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {Array} Returns the slice of `array`.
+     * @example
+     *
+     * _.takeWhile([1, 2, 3], function(n) {
+     *   return n < 3;
+     * });
+     * // => [1, 2]
+     *
+     * var users = [
+     *   { 'user': 'barney',  'active': false },
+     *   { 'user': 'fred',    'active': false},
+     *   { 'user': 'pebbles', 'active': true }
+     * ];
+     *
+     * // using the `_.matches` callback shorthand
+     * _.pluck(_.takeWhile(users, { 'user': 'barney', 'active': false }), 'user');
+     * // => ['barney']
+     *
+     * // using the `_.matchesProperty` callback shorthand
+     * _.pluck(_.takeWhile(users, 'active', false), 'user');
+     * // => ['barney', 'fred']
+     *
+     * // using the `_.property` callback shorthand
+     * _.pluck(_.takeWhile(users, 'active'), 'user');
+     * // => []
+     */
+    function takeWhile(array, predicate, thisArg) {
+      return (array && array.length)
+        ? baseWhile(array, getCallback(predicate, thisArg, 3))
+        : [];
+    }
+
+    /**
+     * Creates an array of unique values, in order, of the provided arrays using
+     * `SameValueZero` for equality comparisons.
+     *
+     * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
+     * comparisons are like strict equality comparisons, e.g. `===`, except that
+     * `NaN` matches `NaN`.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {...Array} [arrays] The arrays to inspect.
+     * @returns {Array} Returns the new array of combined values.
+     * @example
+     *
+     * _.union([1, 2], [4, 2], [2, 1]);
+     * // => [1, 2, 4]
+     */
+    var union = restParam(function(arrays) {
+      return baseUniq(baseFlatten(arrays, false, true));
+    });
+
+    /**
+     * Creates a duplicate-free version of an array, using `SameValueZero` for
+     * equality comparisons, in which only the first occurence of each element
+     * is kept. Providing `true` for `isSorted` performs a faster search algorithm
+     * for sorted arrays. If an iteratee function is provided it is invoked for
+     * each element in the array to generate the criterion by which uniqueness
+     * is computed. The `iteratee` is bound to `thisArg` and invoked with three
+     * arguments: (value, index, array).
+     *
+     * If a property name is provided for `iteratee` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `iteratee` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
+     * comparisons are like strict equality comparisons, e.g. `===`, except that
+     * `NaN` matches `NaN`.
+     *
+     * @static
+     * @memberOf _
+     * @alias unique
+     * @category Array
+     * @param {Array} array The array to inspect.
+     * @param {boolean} [isSorted] Specify the array is sorted.
+     * @param {Function|Object|string} [iteratee] The function invoked per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {Array} Returns the new duplicate-value-free array.
+     * @example
+     *
+     * _.uniq([2, 1, 2]);
+     * // => [2, 1]
+     *
+     * // using `isSorted`
+     * _.uniq([1, 1, 2], true);
+     * // => [1, 2]
+     *
+     * // using an iteratee function
+     * _.uniq([1, 2.5, 1.5, 2], function(n) {
+     *   return this.floor(n);
+     * }, Math);
+     * // => [1, 2.5]
+     *
+     * // using the `_.property` callback shorthand
+     * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+     * // => [{ 'x': 1 }, { 'x': 2 }]
+     */
+    function uniq(array, isSorted, iteratee, thisArg) {
+      var length = array ? array.length : 0;
+      if (!length) {
+        return [];
+      }
+      if (isSorted != null && typeof isSorted != 'boolean') {
+        thisArg = iteratee;
+        iteratee = isIterateeCall(array, isSorted, thisArg) ? null : isSorted;
+        isSorted = false;
+      }
+      var func = getCallback();
+      if (!(func === baseCallback && iteratee == null)) {
+        iteratee = func(iteratee, thisArg, 3);
+      }
+      return (isSorted && getIndexOf() == baseIndexOf)
+        ? sortedUniq(array, iteratee)
+        : baseUniq(array, iteratee);
+    }
+
+    /**
+     * This method is like `_.zip` except that it accepts an array of grouped
+     * elements and creates an array regrouping the elements to their pre-`_.zip`
+     * configuration.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array of grouped elements to process.
+     * @returns {Array} Returns the new array of regrouped elements.
+     * @example
+     *
+     * var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]);
+     * // => [['fred', 30, true], ['barney', 40, false]]
+     *
+     * _.unzip(zipped);
+     * // => [['fred', 'barney'], [30, 40], [true, false]]
+     */
+    function unzip(array) {
+      var index = -1,
+          length = (array && array.length && arrayMax(arrayMap(array, getLength))) >>> 0,
+          result = Array(length);
+
+      while (++index < length) {
+        result[index] = arrayMap(array, baseProperty(index));
+      }
+      return result;
+    }
+
+    /**
+     * Creates an array excluding all provided values using `SameValueZero` for
+     * equality comparisons.
+     *
+     * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
+     * comparisons are like strict equality comparisons, e.g. `===`, except that
+     * `NaN` matches `NaN`.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {Array} array The array to filter.
+     * @param {...*} [values] The values to exclude.
+     * @returns {Array} Returns the new array of filtered values.
+     * @example
+     *
+     * _.without([1, 2, 1, 3], 1, 2);
+     * // => [3]
+     */
+    var without = restParam(function(array, values) {
+      return (isArray(array) || isArguments(array))
+        ? baseDifference(array, values)
+        : [];
+    });
+
+    /**
+     * Creates an array that is the [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
+     * of the provided arrays.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {...Array} [arrays] The arrays to inspect.
+     * @returns {Array} Returns the new array of values.
+     * @example
+     *
+     * _.xor([1, 2], [4, 2]);
+     * // => [1, 4]
+     */
+    function xor() {
+      var index = -1,
+          length = arguments.length;
+
+      while (++index < length) {
+        var array = arguments[index];
+        if (isArray(array) || isArguments(array)) {
+          var result = result
+            ? baseDifference(result, array).concat(baseDifference(array, result))
+            : array;
+        }
+      }
+      return result ? baseUniq(result) : [];
+    }
+
+    /**
+     * Creates an array of grouped elements, the first of which contains the first
+     * elements of the given arrays, the second of which contains the second elements
+     * of the given arrays, and so on.
+     *
+     * @static
+     * @memberOf _
+     * @category Array
+     * @param {...Array} [arrays] The arrays to process.
+     * @returns {Array} Returns the new array of grouped elements.
+     * @example
+     *
+     * _.zip(['fred', 'barney'], [30, 40], [true, false]);
+     * // => [['fred', 30, true], ['barney', 40, false]]
+     */
+    var zip = restParam(unzip);
+
+    /**
+     * The inverse of `_.pairs`; this method returns an object composed from arrays
+     * of property names and values. Provide either a single two dimensional array,
+     * e.g. `[[key1, value1], [key2, value2]]` or two arrays, one of property names
+     * and one of corresponding values.
+     *
+     * @static
+     * @memberOf _
+     * @alias object
+     * @category Array
+     * @param {Array} props The property names.
+     * @param {Array} [values=[]] The property values.
+     * @returns {Object} Returns the new object.
+     * @example
+     *
+     * _.zipObject([['fred', 30], ['barney', 40]]);
+     * // => { 'fred': 30, 'barney': 40 }
+     *
+     * _.zipObject(['fred', 'barney'], [30, 40]);
+     * // => { 'fred': 30, 'barney': 40 }
+     */
+    function zipObject(props, values) {
+      var index = -1,
+          length = props ? props.length : 0,
+          result = {};
+
+      if (length && !values && !isArray(props[0])) {
+        values = [];
+      }
+      while (++index < length) {
+        var key = props[index];
+        if (values) {
+          result[key] = values[index];
+        } else if (key) {
+          result[key[0]] = key[1];
+        }
+      }
+      return result;
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * Creates a `lodash` object that wraps `value` with explicit method
+     * chaining enabled.
+     *
+     * @static
+     * @memberOf _
+     * @category Chain
+     * @param {*} value The value to wrap.
+     * @returns {Object} Returns the new `lodash` wrapper instance.
+     * @example
+     *
+     * var users = [
+     *   { 'user': 'barney',  'age': 36 },
+     *   { 'user': 'fred',    'age': 40 },
+     *   { 'user': 'pebbles', 'age': 1 }
+     * ];
+     *
+     * var youngest = _.chain(users)
+     *   .sortBy('age')
+     *   .map(function(chr) {
+     *     return chr.user + ' is ' + chr.age;
+     *   })
+     *   .first()
+     *   .value();
+     * // => 'pebbles is 1'
+     */
+    function chain(value) {
+      var result = lodash(value);
+      result.__chain__ = true;
+      return result;
+    }
+
+    /**
+     * This method invokes `interceptor` and returns `value`. The interceptor is
+     * bound to `thisArg` and invoked with one argument; (value). The purpose of
+     * this method is to "tap into" a method chain in order to perform operations
+     * on intermediate results within the chain.
+     *
+     * @static
+     * @memberOf _
+     * @category Chain
+     * @param {*} value The value to provide to `interceptor`.
+     * @param {Function} interceptor The function to invoke.
+     * @param {*} [thisArg] The `this` binding of `interceptor`.
+     * @returns {*} Returns `value`.
+     * @example
+     *
+     * _([1, 2, 3])
+     *  .tap(function(array) {
+     *    array.pop();
+     *  })
+     *  .reverse()
+     *  .value();
+     * // => [2, 1]
+     */
+    function tap(value, interceptor, thisArg) {
+      interceptor.call(thisArg, value);
+      return value;
+    }
+
+    /**
+     * This method is like `_.tap` except that it returns the result of `interceptor`.
+     *
+     * @static
+     * @memberOf _
+     * @category Chain
+     * @param {*} value The value to provide to `interceptor`.
+     * @param {Function} interceptor The function to invoke.
+     * @param {*} [thisArg] The `this` binding of `interceptor`.
+     * @returns {*} Returns the result of `interceptor`.
+     * @example
+     *
+     * _('  abc  ')
+     *  .chain()
+     *  .trim()
+     *  .thru(function(value) {
+     *    return [value];
+     *  })
+     *  .value();
+     * // => ['abc']
+     */
+    function thru(value, interceptor, thisArg) {
+      return interceptor.call(thisArg, value);
+    }
+
+    /**
+     * Enables explicit method chaining on the wrapper object.
+     *
+     * @name chain
+     * @memberOf _
+     * @category Chain
+     * @returns {Object} Returns the new `lodash` wrapper instance.
+     * @example
+     *
+     * var users = [
+     *   { 'user': 'barney', 'age': 36 },
+     *   { 'user': 'fred',   'age': 40 }
+     * ];
+     *
+     * // without explicit chaining
+     * _(users).first();
+     * // => { 'user': 'barney', 'age': 36 }
+     *
+     * // with explicit chaining
+     * _(users).chain()
+     *   .first()
+     *   .pick('user')
+     *   .value();
+     * // => { 'user': 'barney' }
+     */
+    function wrapperChain() {
+      return chain(this);
+    }
+
+    /**
+     * Executes the chained sequence and returns the wrapped result.
+     *
+     * @name commit
+     * @memberOf _
+     * @category Chain
+     * @returns {Object} Returns the new `lodash` wrapper instance.
+     * @example
+     *
+     * var array = [1, 2];
+     * var wrapper = _(array).push(3);
+     *
+     * console.log(array);
+     * // => [1, 2]
+     *
+     * wrapper = wrapper.commit();
+     * console.log(array);
+     * // => [1, 2, 3]
+     *
+     * wrapper.last();
+     * // => 3
+     *
+     * console.log(array);
+     * // => [1, 2, 3]
+     */
+    function wrapperCommit() {
+      return new LodashWrapper(this.value(), this.__chain__);
+    }
+
+    /**
+     * Creates a clone of the chained sequence planting `value` as the wrapped value.
+     *
+     * @name plant
+     * @memberOf _
+     * @category Chain
+     * @returns {Object} Returns the new `lodash` wrapper instance.
+     * @example
+     *
+     * var array = [1, 2];
+     * var wrapper = _(array).map(function(value) {
+     *   return Math.pow(value, 2);
+     * });
+     *
+     * var other = [3, 4];
+     * var otherWrapper = wrapper.plant(other);
+     *
+     * otherWrapper.value();
+     * // => [9, 16]
+     *
+     * wrapper.value();
+     * // => [1, 4]
+     */
+    function wrapperPlant(value) {
+      var result,
+          parent = this;
+
+      while (parent instanceof baseLodash) {
+        var clone = wrapperClone(parent);
+        if (result) {
+          previous.__wrapped__ = clone;
+        } else {
+          result = clone;
+        }
+        var previous = clone;
+        parent = parent.__wrapped__;
+      }
+      previous.__wrapped__ = value;
+      return result;
+    }
+
+    /**
+     * Reverses the wrapped array so the first element becomes the last, the
+     * second element becomes the second to last, and so on.
+     *
+     * **Note:** This method mutates the wrapped array.
+     *
+     * @name reverse
+     * @memberOf _
+     * @category Chain
+     * @returns {Object} Returns the new reversed `lodash` wrapper instance.
+     * @example
+     *
+     * var array = [1, 2, 3];
+     *
+     * _(array).reverse().value()
+     * // => [3, 2, 1]
+     *
+     * console.log(array);
+     * // => [3, 2, 1]
+     */
+    function wrapperReverse() {
+      var value = this.__wrapped__;
+      if (value instanceof LazyWrapper) {
+        if (this.__actions__.length) {
+          value = new LazyWrapper(this);
+        }
+        return new LodashWrapper(value.reverse(), this.__chain__);
+      }
+      return this.thru(function(value) {
+        return value.reverse();
+      });
+    }
+
+    /**
+     * Produces the result of coercing the unwrapped value to a string.
+     *
+     * @name toString
+     * @memberOf _
+     * @category Chain
+     * @returns {string} Returns the coerced string value.
+     * @example
+     *
+     * _([1, 2, 3]).toString();
+     * // => '1,2,3'
+     */
+    function wrapperToString() {
+      return (this.value() + '');
+    }
+
+    /**
+     * Executes the chained sequence to extract the unwrapped value.
+     *
+     * @name value
+     * @memberOf _
+     * @alias run, toJSON, valueOf
+     * @category Chain
+     * @returns {*} Returns the resolved unwrapped value.
+     * @example
+     *
+     * _([1, 2, 3]).value();
+     * // => [1, 2, 3]
+     */
+    function wrapperValue() {
+      return baseWrapperValue(this.__wrapped__, this.__actions__);
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * Creates an array of elements corresponding to the given keys, or indexes,
+     * of `collection`. Keys may be specified as individual arguments or as arrays
+     * of keys.
+     *
+     * @static
+     * @memberOf _
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {...(number|number[]|string|string[])} [props] The property names
+     *  or indexes of elements to pick, specified individually or in arrays.
+     * @returns {Array} Returns the new array of picked elements.
+     * @example
+     *
+     * _.at(['a', 'b', 'c'], [0, 2]);
+     * // => ['a', 'c']
+     *
+     * _.at(['barney', 'fred', 'pebbles'], 0, 2);
+     * // => ['barney', 'pebbles']
+     */
+    var at = restParam(function(collection, props) {
+      var length = collection ? getLength(collection) : 0;
+      if (isLength(length)) {
+        collection = toIterable(collection);
+      }
+      return baseAt(collection, baseFlatten(props));
+    });
+
+    /**
+     * Creates an object composed of keys generated from the results of running
+     * each element of `collection` through `iteratee`. The corresponding value
+     * of each key is the number of times the key was returned by `iteratee`.
+     * The `iteratee` is bound to `thisArg` and invoked with three arguments:
+     * (value, index|key, collection).
+     *
+     * If a property name is provided for `iteratee` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `iteratee` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {Object} Returns the composed aggregate object.
+     * @example
+     *
+     * _.countBy([4.3, 6.1, 6.4], function(n) {
+     *   return Math.floor(n);
+     * });
+     * // => { '4': 1, '6': 2 }
+     *
+     * _.countBy([4.3, 6.1, 6.4], function(n) {
+     *   return this.floor(n);
+     * }, Math);
+     * // => { '4': 1, '6': 2 }
+     *
+     * _.countBy(['one', 'two', 'three'], 'length');
+     * // => { '3': 2, '5': 1 }
+     */
+    var countBy = createAggregator(function(result, value, key) {
+      hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1);
+    });
+
+    /**
+     * Checks if `predicate` returns truthy for **all** elements of `collection`.
+     * The predicate is bound to `thisArg` and invoked with three arguments:
+     * (value, index|key, collection).
+     *
+     * If a property name is provided for `predicate` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `predicate` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias all
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [predicate=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {boolean} Returns `true` if all elements pass the predicate check,
+     *  else `false`.
+     * @example
+     *
+     * _.every([true, 1, null, 'yes'], Boolean);
+     * // => false
+     *
+     * var users = [
+     *   { 'user': 'barney', 'active': false },
+     *   { 'user': 'fred',   'active': false }
+     * ];
+     *
+     * // using the `_.matches` callback shorthand
+     * _.every(users, { 'user': 'barney', 'active': false });
+     * // => false
+     *
+     * // using the `_.matchesProperty` callback shorthand
+     * _.every(users, 'active', false);
+     * // => true
+     *
+     * // using the `_.property` callback shorthand
+     * _.every(users, 'active');
+     * // => false
+     */
+    function every(collection, predicate, thisArg) {
+      var func = isArray(collection) ? arrayEvery : baseEvery;
+      if (thisArg && isIterateeCall(collection, predicate, thisArg)) {
+        predicate = null;
+      }
+      if (typeof predicate != 'function' || thisArg !== undefined) {
+        predicate = getCallback(predicate, thisArg, 3);
+      }
+      return func(collection, predicate);
+    }
+
+    /**
+     * Iterates over elements of `collection`, returning an array of all elements
+     * `predicate` returns truthy for. The predicate is bound to `thisArg` and
+     * invoked with three arguments: (value, index|key, collection).
+     *
+     * If a property name is provided for `predicate` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `predicate` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias select
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [predicate=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {Array} Returns the new filtered array.
+     * @example
+     *
+     * _.filter([4, 5, 6], function(n) {
+     *   return n % 2 == 0;
+     * });
+     * // => [4, 6]
+     *
+     * var users = [
+     *   { 'user': 'barney', 'age': 36, 'active': true },
+     *   { 'user': 'fred',   'age': 40, 'active': false }
+     * ];
+     *
+     * // using the `_.matches` callback shorthand
+     * _.pluck(_.filter(users, { 'age': 36, 'active': true }), 'user');
+     * // => ['barney']
+     *
+     * // using the `_.matchesProperty` callback shorthand
+     * _.pluck(_.filter(users, 'active', false), 'user');
+     * // => ['fred']
+     *
+     * // using the `_.property` callback shorthand
+     * _.pluck(_.filter(users, 'active'), 'user');
+     * // => ['barney']
+     */
+    function filter(collection, predicate, thisArg) {
+      var func = isArray(collection) ? arrayFilter : baseFilter;
+      predicate = getCallback(predicate, thisArg, 3);
+      return func(collection, predicate);
+    }
+
+    /**
+     * Iterates over elements of `collection`, returning the first element
+     * `predicate` returns truthy for. The predicate is bound to `thisArg` and
+     * invoked with three arguments: (value, index|key, collection).
+     *
+     * If a property name is provided for `predicate` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `predicate` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias detect
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to search.
+     * @param {Function|Object|string} [predicate=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {*} Returns the matched element, else `undefined`.
+     * @example
+     *
+     * var users = [
+     *   { 'user': 'barney',  'age': 36, 'active': true },
+     *   { 'user': 'fred',    'age': 40, 'active': false },
+     *   { 'user': 'pebbles', 'age': 1,  'active': true }
+     * ];
+     *
+     * _.result(_.find(users, function(chr) {
+     *   return chr.age < 40;
+     * }), 'user');
+     * // => 'barney'
+     *
+     * // using the `_.matches` callback shorthand
+     * _.result(_.find(users, { 'age': 1, 'active': true }), 'user');
+     * // => 'pebbles'
+     *
+     * // using the `_.matchesProperty` callback shorthand
+     * _.result(_.find(users, 'active', false), 'user');
+     * // => 'fred'
+     *
+     * // using the `_.property` callback shorthand
+     * _.result(_.find(users, 'active'), 'user');
+     * // => 'barney'
+     */
+    var find = createFind(baseEach);
+
+    /**
+     * This method is like `_.find` except that it iterates over elements of
+     * `collection` from right to left.
+     *
+     * @static
+     * @memberOf _
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to search.
+     * @param {Function|Object|string} [predicate=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {*} Returns the matched element, else `undefined`.
+     * @example
+     *
+     * _.findLast([1, 2, 3, 4], function(n) {
+     *   return n % 2 == 1;
+     * });
+     * // => 3
+     */
+    var findLast = createFind(baseEachRight, true);
+
+    /**
+     * Performs a deep comparison between each element in `collection` and the
+     * source object, returning the first element that has equivalent property
+     * values.
+     *
+     * **Note:** This method supports comparing arrays, booleans, `Date` objects,
+     * numbers, `Object` objects, regexes, and strings. Objects are compared by
+     * their own, not inherited, enumerable properties. For comparing a single
+     * own or inherited property value see `_.matchesProperty`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to search.
+     * @param {Object} source The object of property values to match.
+     * @returns {*} Returns the matched element, else `undefined`.
+     * @example
+     *
+     * var users = [
+     *   { 'user': 'barney', 'age': 36, 'active': true },
+     *   { 'user': 'fred',   'age': 40, 'active': false }
+     * ];
+     *
+     * _.result(_.findWhere(users, { 'age': 36, 'active': true }), 'user');
+     * // => 'barney'
+     *
+     * _.result(_.findWhere(users, { 'age': 40, 'active': false }), 'user');
+     * // => 'fred'
+     */
+    function findWhere(collection, source) {
+      return find(collection, baseMatches(source));
+    }
+
+    /**
+     * Iterates over elements of `collection` invoking `iteratee` for each element.
+     * The `iteratee` is bound to `thisArg` and invoked with three arguments:
+     * (value, index|key, collection). Iteratee functions may exit iteration early
+     * by explicitly returning `false`.
+     *
+     * **Note:** As with other "Collections" methods, objects with a "length" property
+     * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
+     * may be used for object iteration.
+     *
+     * @static
+     * @memberOf _
+     * @alias each
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {Array|Object|string} Returns `collection`.
+     * @example
+     *
+     * _([1, 2]).forEach(function(n) {
+     *   console.log(n);
+     * }).value();
+     * // => logs each value from left to right and returns the array
+     *
+     * _.forEach({ 'a': 1, 'b': 2 }, function(n, key) {
+     *   console.log(n, key);
+     * });
+     * // => logs each value-key pair and returns the object (iteration order is not guaranteed)
+     */
+    var forEach = createForEach(arrayEach, baseEach);
+
+    /**
+     * This method is like `_.forEach` except that it iterates over elements of
+     * `collection` from right to left.
+     *
+     * @static
+     * @memberOf _
+     * @alias eachRight
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {Array|Object|string} Returns `collection`.
+     * @example
+     *
+     * _([1, 2]).forEachRight(function(n) {
+     *   console.log(n);
+     * }).value();
+     * // => logs each value from right to left and returns the array
+     */
+    var forEachRight = createForEach(arrayEachRight, baseEachRight);
+
+    /**
+     * Creates an object composed of keys generated from the results of running
+     * each element of `collection` through `iteratee`. The corresponding value
+     * of each key is an array of the elements responsible for generating the key.
+     * The `iteratee` is bound to `thisArg` and invoked with three arguments:
+     * (value, index|key, collection).
+     *
+     * If a property name is provided for `iteratee` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `iteratee` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {Object} Returns the composed aggregate object.
+     * @example
+     *
+     * _.groupBy([4.2, 6.1, 6.4], function(n) {
+     *   return Math.floor(n);
+     * });
+     * // => { '4': [4.2], '6': [6.1, 6.4] }
+     *
+     * _.groupBy([4.2, 6.1, 6.4], function(n) {
+     *   return this.floor(n);
+     * }, Math);
+     * // => { '4': [4.2], '6': [6.1, 6.4] }
+     *
+     * // using the `_.property` callback shorthand
+     * _.groupBy(['one', 'two', 'three'], 'length');
+     * // => { '3': ['one', 'two'], '5': ['three'] }
+     */
+    var groupBy = createAggregator(function(result, value, key) {
+      if (hasOwnProperty.call(result, key)) {
+        result[key].push(value);
+      } else {
+        result[key] = [value];
+      }
+    });
+
+    /**
+     * Checks if `value` is in `collection` using `SameValueZero` for equality
+     * comparisons. If `fromIndex` is negative, it is used as the offset from
+     * the end of `collection`.
+     *
+     * **Note:** [`SameValueZero`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero)
+     * comparisons are like strict equality comparisons, e.g. `===`, except that
+     * `NaN` matches `NaN`.
+     *
+     * @static
+     * @memberOf _
+     * @alias contains, include
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to search.
+     * @param {*} target The value to search for.
+     * @param {number} [fromIndex=0] The index to search from.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`.
+     * @returns {boolean} Returns `true` if a matching element is found, else `false`.
+     * @example
+     *
+     * _.includes([1, 2, 3], 1);
+     * // => true
+     *
+     * _.includes([1, 2, 3], 1, 2);
+     * // => false
+     *
+     * _.includes({ 'user': 'fred', 'age': 40 }, 'fred');
+     * // => true
+     *
+     * _.includes('pebbles', 'eb');
+     * // => true
+     */
+    function includes(collection, target, fromIndex, guard) {
+      var length = collection ? getLength(collection) : 0;
+      if (!isLength(length)) {
+        collection = values(collection);
+        length = collection.length;
+      }
+      if (!length) {
+        return false;
+      }
+      if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) {
+        fromIndex = 0;
+      } else {
+        fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0);
+      }
+      return (typeof collection == 'string' || !isArray(collection) && isString(collection))
+        ? (fromIndex < length && collection.indexOf(target, fromIndex) > -1)
+        : (getIndexOf(collection, target, fromIndex) > -1);
+    }
+
+    /**
+     * Creates an object composed of keys generated from the results of running
+     * each element of `collection` through `iteratee`. The corresponding value
+     * of each key is the last element responsible for generating the key. The
+     * iteratee function is bound to `thisArg` and invoked with three arguments:
+     * (value, index|key, collection).
+     *
+     * If a property name is provided for `iteratee` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `iteratee` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {Object} Returns the composed aggregate object.
+     * @example
+     *
+     * var keyData = [
+     *   { 'dir': 'left', 'code': 97 },
+     *   { 'dir': 'right', 'code': 100 }
+     * ];
+     *
+     * _.indexBy(keyData, 'dir');
+     * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
+     *
+     * _.indexBy(keyData, function(object) {
+     *   return String.fromCharCode(object.code);
+     * });
+     * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+     *
+     * _.indexBy(keyData, function(object) {
+     *   return this.fromCharCode(object.code);
+     * }, String);
+     * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+     */
+    var indexBy = createAggregator(function(result, value, key) {
+      result[key] = value;
+    });
+
+    /**
+     * Invokes the method at `path` on each element in `collection`, returning
+     * an array of the results of each invoked method. Any additional arguments
+     * are provided to each invoked method. If `methodName` is a function it is
+     * invoked for, and `this` bound to, each element in `collection`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Array|Function|string} path The path of the method to invoke or
+     *  the function invoked per iteration.
+     * @param {...*} [args] The arguments to invoke the method with.
+     * @returns {Array} Returns the array of results.
+     * @example
+     *
+     * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+     * // => [[1, 5, 7], [1, 2, 3]]
+     *
+     * _.invoke([123, 456], String.prototype.split, '');
+     * // => [['1', '2', '3'], ['4', '5', '6']]
+     */
+    var invoke = restParam(function(collection, path, args) {
+      var index = -1,
+          isFunc = typeof path == 'function',
+          isProp = isKey(path),
+          length = getLength(collection),
+          result = isLength(length) ? Array(length) : [];
+
+      baseEach(collection, function(value) {
+        var func = isFunc ? path : (isProp && value != null && value[path]);
+        result[++index] = func ? func.apply(value, args) : invokePath(value, path, args);
+      });
+      return result;
+    });
+
+    /**
+     * Creates an array of values by running each element in `collection` through
+     * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three
+     * arguments: (value, index|key, collection).
+     *
+     * If a property name is provided for `iteratee` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `iteratee` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * Many lodash methods are guarded to work as interatees for methods like
+     * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
+     *
+     * The guarded methods are:
+     * `ary`, `callback`, `chunk`, `clone`, `create`, `curry`, `curryRight`, `drop`,
+     * `dropRight`, `every`, `fill`, `flatten`, `invert`, `max`, `min`, `parseInt`,
+     * `slice`, `sortBy`, `take`, `takeRight`, `template`, `trim`, `trimLeft`,
+     * `trimRight`, `trunc`, `random`, `range`, `sample`, `some`, `uniq`, and `words`
+     *
+     * @static
+     * @memberOf _
+     * @alias collect
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {Array} Returns the new mapped array.
+     * @example
+     *
+     * function timesThree(n) {
+     *   return n * 3;
+     * }
+     *
+     * _.map([1, 2], timesThree);
+     * // => [3, 6]
+     *
+     * _.map({ 'a': 1, 'b': 2 }, timesThree);
+     * // => [3, 6] (iteration order is not guaranteed)
+     *
+     * var users = [
+     *   { 'user': 'barney' },
+     *   { 'user': 'fred' }
+     * ];
+     *
+     * // using the `_.property` callback shorthand
+     * _.map(users, 'user');
+     * // => ['barney', 'fred']
+     */
+    function map(collection, iteratee, thisArg) {
+      var func = isArray(collection) ? arrayMap : baseMap;
+      iteratee = getCallback(iteratee, thisArg, 3);
+      return func(collection, iteratee);
+    }
+
+    /**
+     * Creates an array of elements split into two groups, the first of which
+     * contains elements `predicate` returns truthy for, while the second of which
+     * contains elements `predicate` returns falsey for. The predicate is bound
+     * to `thisArg` and invoked with three arguments: (value, index|key, collection).
+     *
+     * If a property name is provided for `predicate` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `predicate` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [predicate=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {Array} Returns the array of grouped elements.
+     * @example
+     *
+     * _.partition([1, 2, 3], function(n) {
+     *   return n % 2;
+     * });
+     * // => [[1, 3], [2]]
+     *
+     * _.partition([1.2, 2.3, 3.4], function(n) {
+     *   return this.floor(n) % 2;
+     * }, Math);
+     * // => [[1.2, 3.4], [2.3]]
+     *
+     * var users = [
+     *   { 'user': 'barney',  'age': 36, 'active': false },
+     *   { 'user': 'fred',    'age': 40, 'active': true },
+     *   { 'user': 'pebbles', 'age': 1,  'active': false }
+     * ];
+     *
+     * var mapper = function(array) {
+     *   return _.pluck(array, 'user');
+     * };
+     *
+     * // using the `_.matches` callback shorthand
+     * _.map(_.partition(users, { 'age': 1, 'active': false }), mapper);
+     * // => [['pebbles'], ['barney', 'fred']]
+     *
+     * // using the `_.matchesProperty` callback shorthand
+     * _.map(_.partition(users, 'active', false), mapper);
+     * // => [['barney', 'pebbles'], ['fred']]
+     *
+     * // using the `_.property` callback shorthand
+     * _.map(_.partition(users, 'active'), mapper);
+     * // => [['fred'], ['barney', 'pebbles']]
+     */
+    var partition = createAggregator(function(result, value, key) {
+      result[key ? 0 : 1].push(value);
+    }, function() { return [[], []]; });
+
+    /**
+     * Gets the property value of `path` from all elements in `collection`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Array|string} path The path of the property to pluck.
+     * @returns {Array} Returns the property values.
+     * @example
+     *
+     * var users = [
+     *   { 'user': 'barney', 'age': 36 },
+     *   { 'user': 'fred',   'age': 40 }
+     * ];
+     *
+     * _.pluck(users, 'user');
+     * // => ['barney', 'fred']
+     *
+     * var userIndex = _.indexBy(users, 'user');
+     * _.pluck(userIndex, 'age');
+     * // => [36, 40] (iteration order is not guaranteed)
+     */
+    function pluck(collection, path) {
+      return map(collection, property(path));
+    }
+
+    /**
+     * Reduces `collection` to a value which is the accumulated result of running
+     * each element in `collection` through `iteratee`, where each successive
+     * invocation is supplied the return value of the previous. If `accumulator`
+     * is not provided the first element of `collection` is used as the initial
+     * value. The `iteratee` is bound to `thisArg` and invoked with four arguments:
+     * (accumulator, value, index|key, collection).
+     *
+     * Many lodash methods are guarded to work as interatees for methods like
+     * `_.reduce`, `_.reduceRight`, and `_.transform`.
+     *
+     * The guarded methods are:
+     * `assign`, `defaults`, `includes`, `merge`, `sortByAll`, and `sortByOrder`
+     *
+     * @static
+     * @memberOf _
+     * @alias foldl, inject
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+     * @param {*} [accumulator] The initial value.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {*} Returns the accumulated value.
+     * @example
+     *
+     * _.reduce([1, 2], function(total, n) {
+     *   return total + n;
+     * });
+     * // => 3
+     *
+     * _.reduce({ 'a': 1, 'b': 2 }, function(result, n, key) {
+     *   result[key] = n * 3;
+     *   return result;
+     * }, {});
+     * // => { 'a': 3, 'b': 6 } (iteration order is not guaranteed)
+     */
+    var reduce = createReduce(arrayReduce, baseEach);
+
+    /**
+     * This method is like `_.reduce` except that it iterates over elements of
+     * `collection` from right to left.
+     *
+     * @static
+     * @memberOf _
+     * @alias foldr
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+     * @param {*} [accumulator] The initial value.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {*} Returns the accumulated value.
+     * @example
+     *
+     * var array = [[0, 1], [2, 3], [4, 5]];
+     *
+     * _.reduceRight(array, function(flattened, other) {
+     *   return flattened.concat(other);
+     * }, []);
+     * // => [4, 5, 2, 3, 0, 1]
+     */
+    var reduceRight =  createReduce(arrayReduceRight, baseEachRight);
+
+    /**
+     * The opposite of `_.filter`; this method returns the elements of `collection`
+     * that `predicate` does **not** return truthy for.
+     *
+     * If a property name is provided for `predicate` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `predicate` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [predicate=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {Array} Returns the new filtered array.
+     * @example
+     *
+     * _.reject([1, 2, 3, 4], function(n) {
+     *   return n % 2 == 0;
+     * });
+     * // => [1, 3]
+     *
+     * var users = [
+     *   { 'user': 'barney', 'age': 36, 'active': false },
+     *   { 'user': 'fred',   'age': 40, 'active': true }
+     * ];
+     *
+     * // using the `_.matches` callback shorthand
+     * _.pluck(_.reject(users, { 'age': 40, 'active': true }), 'user');
+     * // => ['barney']
+     *
+     * // using the `_.matchesProperty` callback shorthand
+     * _.pluck(_.reject(users, 'active', false), 'user');
+     * // => ['fred']
+     *
+     * // using the `_.property` callback shorthand
+     * _.pluck(_.reject(users, 'active'), 'user');
+     * // => ['barney']
+     */
+    function reject(collection, predicate, thisArg) {
+      var func = isArray(collection) ? arrayFilter : baseFilter;
+      predicate = getCallback(predicate, thisArg, 3);
+      return func(collection, function(value, index, collection) {
+        return !predicate(value, index, collection);
+      });
+    }
+
+    /**
+     * Gets a random element or `n` random elements from a collection.
+     *
+     * @static
+     * @memberOf _
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to sample.
+     * @param {number} [n] The number of elements to sample.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {*} Returns the random sample(s).
+     * @example
+     *
+     * _.sample([1, 2, 3, 4]);
+     * // => 2
+     *
+     * _.sample([1, 2, 3, 4], 2);
+     * // => [3, 1]
+     */
+    function sample(collection, n, guard) {
+      if (guard ? isIterateeCall(collection, n, guard) : n == null) {
+        collection = toIterable(collection);
+        var length = collection.length;
+        return length > 0 ? collection[baseRandom(0, length - 1)] : undefined;
+      }
+      var result = shuffle(collection);
+      result.length = nativeMin(n < 0 ? 0 : (+n || 0), result.length);
+      return result;
+    }
+
+    /**
+     * Creates an array of shuffled values, using a version of the
+     * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
+     *
+     * @static
+     * @memberOf _
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to shuffle.
+     * @returns {Array} Returns the new shuffled array.
+     * @example
+     *
+     * _.shuffle([1, 2, 3, 4]);
+     * // => [4, 1, 3, 2]
+     */
+    function shuffle(collection) {
+      collection = toIterable(collection);
+
+      var index = -1,
+          length = collection.length,
+          result = Array(length);
+
+      while (++index < length) {
+        var rand = baseRandom(0, index);
+        if (index != rand) {
+          result[index] = result[rand];
+        }
+        result[rand] = collection[index];
+      }
+      return result;
+    }
+
+    /**
+     * Gets the size of `collection` by returning its length for array-like
+     * values or the number of own enumerable properties for objects.
+     *
+     * @static
+     * @memberOf _
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to inspect.
+     * @returns {number} Returns the size of `collection`.
+     * @example
+     *
+     * _.size([1, 2, 3]);
+     * // => 3
+     *
+     * _.size({ 'a': 1, 'b': 2 });
+     * // => 2
+     *
+     * _.size('pebbles');
+     * // => 7
+     */
+    function size(collection) {
+      var length = collection ? getLength(collection) : 0;
+      return isLength(length) ? length : keys(collection).length;
+    }
+
+    /**
+     * Checks if `predicate` returns truthy for **any** element of `collection`.
+     * The function returns as soon as it finds a passing value and does not iterate
+     * over the entire collection. The predicate is bound to `thisArg` and invoked
+     * with three arguments: (value, index|key, collection).
+     *
+     * If a property name is provided for `predicate` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `predicate` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias any
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [predicate=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {boolean} Returns `true` if any element passes the predicate check,
+     *  else `false`.
+     * @example
+     *
+     * _.some([null, 0, 'yes', false], Boolean);
+     * // => true
+     *
+     * var users = [
+     *   { 'user': 'barney', 'active': true },
+     *   { 'user': 'fred',   'active': false }
+     * ];
+     *
+     * // using the `_.matches` callback shorthand
+     * _.some(users, { 'user': 'barney', 'active': false });
+     * // => false
+     *
+     * // using the `_.matchesProperty` callback shorthand
+     * _.some(users, 'active', false);
+     * // => true
+     *
+     * // using the `_.property` callback shorthand
+     * _.some(users, 'active');
+     * // => true
+     */
+    function some(collection, predicate, thisArg) {
+      var func = isArray(collection) ? arraySome : baseSome;
+      if (thisArg && isIterateeCall(collection, predicate, thisArg)) {
+        predicate = null;
+      }
+      if (typeof predicate != 'function' || thisArg !== undefined) {
+        predicate = getCallback(predicate, thisArg, 3);
+      }
+      return func(collection, predicate);
+    }
+
+    /**
+     * Creates an array of elements, sorted in ascending order by the results of
+     * running each element in a collection through `iteratee`. This method performs
+     * a stable sort, that is, it preserves the original sort order of equal elements.
+     * The `iteratee` is bound to `thisArg` and invoked with three arguments:
+     * (value, index|key, collection).
+     *
+     * If a property name is provided for `iteratee` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `iteratee` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {Array} Returns the new sorted array.
+     * @example
+     *
+     * _.sortBy([1, 2, 3], function(n) {
+     *   return Math.sin(n);
+     * });
+     * // => [3, 1, 2]
+     *
+     * _.sortBy([1, 2, 3], function(n) {
+     *   return this.sin(n);
+     * }, Math);
+     * // => [3, 1, 2]
+     *
+     * var users = [
+     *   { 'user': 'fred' },
+     *   { 'user': 'pebbles' },
+     *   { 'user': 'barney' }
+     * ];
+     *
+     * // using the `_.property` callback shorthand
+     * _.pluck(_.sortBy(users, 'user'), 'user');
+     * // => ['barney', 'fred', 'pebbles']
+     */
+    function sortBy(collection, iteratee, thisArg) {
+      if (collection == null) {
+        return [];
+      }
+      if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {
+        iteratee = null;
+      }
+      var index = -1;
+      iteratee = getCallback(iteratee, thisArg, 3);
+
+      var result = baseMap(collection, function(value, key, collection) {
+        return { 'criteria': iteratee(value, key, collection), 'index': ++index, 'value': value };
+      });
+      return baseSortBy(result, compareAscending);
+    }
+
+    /**
+     * This method is like `_.sortBy` except that it can sort by multiple iteratees
+     * or property names.
+     *
+     * If a property name is provided for an iteratee the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If an object is provided for an iteratee the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {...(Function|Function[]|Object|Object[]|string|string[])} iteratees
+     *  The iteratees to sort by, specified as individual values or arrays of values.
+     * @returns {Array} Returns the new sorted array.
+     * @example
+     *
+     * var users = [
+     *   { 'user': 'fred',   'age': 48 },
+     *   { 'user': 'barney', 'age': 36 },
+     *   { 'user': 'fred',   'age': 42 },
+     *   { 'user': 'barney', 'age': 34 }
+     * ];
+     *
+     * _.map(_.sortByAll(users, ['user', 'age']), _.values);
+     * // => [['barney', 34], ['barney', 36], ['fred', 42], ['fred', 48]]
+     *
+     * _.map(_.sortByAll(users, 'user', function(chr) {
+     *   return Math.floor(chr.age / 10);
+     * }), _.values);
+     * // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
+     */
+    var sortByAll = restParam(function(collection, iteratees) {
+      if (collection == null) {
+        return [];
+      }
+      var guard = iteratees[2];
+      if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) {
+        iteratees.length = 1;
+      }
+      return baseSortByOrder(collection, baseFlatten(iteratees), []);
+    });
+
+    /**
+     * This method is like `_.sortByAll` except that it allows specifying the
+     * sort orders of the iteratees to sort by. A truthy value in `orders` will
+     * sort the corresponding property name in ascending order while a falsey
+     * value will sort it in descending order.
+     *
+     * If a property name is provided for an iteratee the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If an object is provided for an iteratee the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
+     * @param {boolean[]} orders The sort orders of `iteratees`.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`.
+     * @returns {Array} Returns the new sorted array.
+     * @example
+     *
+     * var users = [
+     *   { 'user': 'fred',   'age': 48 },
+     *   { 'user': 'barney', 'age': 34 },
+     *   { 'user': 'fred',   'age': 42 },
+     *   { 'user': 'barney', 'age': 36 }
+     * ];
+     *
+     * // sort by `user` in ascending order and by `age` in descending order
+     * _.map(_.sortByOrder(users, ['user', 'age'], [true, false]), _.values);
+     * // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
+     */
+    function sortByOrder(collection, iteratees, orders, guard) {
+      if (collection == null) {
+        return [];
+      }
+      if (guard && isIterateeCall(iteratees, orders, guard)) {
+        orders = null;
+      }
+      if (!isArray(iteratees)) {
+        iteratees = iteratees == null ? [] : [iteratees];
+      }
+      if (!isArray(orders)) {
+        orders = orders == null ? [] : [orders];
+      }
+      return baseSortByOrder(collection, iteratees, orders);
+    }
+
+    /**
+     * Performs a deep comparison between each element in `collection` and the
+     * source object, returning an array of all elements that have equivalent
+     * property values.
+     *
+     * **Note:** This method supports comparing arrays, booleans, `Date` objects,
+     * numbers, `Object` objects, regexes, and strings. Objects are compared by
+     * their own, not inherited, enumerable properties. For comparing a single
+     * own or inherited property value see `_.matchesProperty`.
+     *
+     * @static
+     * @memberOf _
+     * @category Collection
+     * @param {Array|Object|string} collection The collection to search.
+     * @param {Object} source The object of property values to match.
+     * @returns {Array} Returns the new filtered array.
+     * @example
+     *
+     * var users = [
+     *   { 'user': 'barney', 'age': 36, 'active': false, 'pets': ['hoppy'] },
+     *   { 'user': 'fred',   'age': 40, 'active': true, 'pets': ['baby puss', 'dino'] }
+     * ];
+     *
+     * _.pluck(_.where(users, { 'age': 36, 'active': false }), 'user');
+     * // => ['barney']
+     *
+     * _.pluck(_.where(users, { 'pets': ['dino'] }), 'user');
+     * // => ['fred']
+     */
+    function where(collection, source) {
+      return filter(collection, baseMatches(source));
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * Gets the number of milliseconds that have elapsed since the Unix epoch
+     * (1 January 1970 00:00:00 UTC).
+     *
+     * @static
+     * @memberOf _
+     * @category Date
+     * @example
+     *
+     * _.defer(function(stamp) {
+     *   console.log(_.now() - stamp);
+     * }, _.now());
+     * // => logs the number of milliseconds it took for the deferred function to be invoked
+     */
+    var now = nativeNow || function() {
+      return new Date().getTime();
+    };
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * The opposite of `_.before`; this method creates a function that invokes
+     * `func` once it is called `n` or more times.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {number} n The number of calls before `func` is invoked.
+     * @param {Function} func The function to restrict.
+     * @returns {Function} Returns the new restricted function.
+     * @example
+     *
+     * var saves = ['profile', 'settings'];
+     *
+     * var done = _.after(saves.length, function() {
+     *   console.log('done saving!');
+     * });
+     *
+     * _.forEach(saves, function(type) {
+     *   asyncSave({ 'type': type, 'complete': done });
+     * });
+     * // => logs 'done saving!' after the two async saves have completed
+     */
+    function after(n, func) {
+      if (typeof func != 'function') {
+        if (typeof n == 'function') {
+          var temp = n;
+          n = func;
+          func = temp;
+        } else {
+          throw new TypeError(FUNC_ERROR_TEXT);
+        }
+      }
+      n = nativeIsFinite(n = +n) ? n : 0;
+      return function() {
+        if (--n < 1) {
+          return func.apply(this, arguments);
+        }
+      };
+    }
+
+    /**
+     * Creates a function that accepts up to `n` arguments ignoring any
+     * additional arguments.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Function} func The function to cap arguments for.
+     * @param {number} [n=func.length] The arity cap.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * _.map(['6', '8', '10'], _.ary(parseInt, 1));
+     * // => [6, 8, 10]
+     */
+    function ary(func, n, guard) {
+      if (guard && isIterateeCall(func, n, guard)) {
+        n = null;
+      }
+      n = (func && n == null) ? func.length : nativeMax(+n || 0, 0);
+      return createWrapper(func, ARY_FLAG, null, null, null, null, n);
+    }
+
+    /**
+     * Creates a function that invokes `func`, with the `this` binding and arguments
+     * of the created function, while it is called less than `n` times. Subsequent
+     * calls to the created function return the result of the last `func` invocation.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {number} n The number of calls at which `func` is no longer invoked.
+     * @param {Function} func The function to restrict.
+     * @returns {Function} Returns the new restricted function.
+     * @example
+     *
+     * jQuery('#add').on('click', _.before(5, addContactToList));
+     * // => allows adding up to 4 contacts to the list
+     */
+    function before(n, func) {
+      var result;
+      if (typeof func != 'function') {
+        if (typeof n == 'function') {
+          var temp = n;
+          n = func;
+          func = temp;
+        } else {
+          throw new TypeError(FUNC_ERROR_TEXT);
+        }
+      }
+      return function() {
+        if (--n > 0) {
+          result = func.apply(this, arguments);
+        }
+        if (n <= 1) {
+          func = null;
+        }
+        return result;
+      };
+    }
+
+    /**
+     * Creates a function that invokes `func` with the `this` binding of `thisArg`
+     * and prepends any additional `_.bind` arguments to those provided to the
+     * bound function.
+     *
+     * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
+     * may be used as a placeholder for partially applied arguments.
+     *
+     * **Note:** Unlike native `Function#bind` this method does not set the "length"
+     * property of bound functions.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Function} func The function to bind.
+     * @param {*} thisArg The `this` binding of `func`.
+     * @param {...*} [partials] The arguments to be partially applied.
+     * @returns {Function} Returns the new bound function.
+     * @example
+     *
+     * var greet = function(greeting, punctuation) {
+     *   return greeting + ' ' + this.user + punctuation;
+     * };
+     *
+     * var object = { 'user': 'fred' };
+     *
+     * var bound = _.bind(greet, object, 'hi');
+     * bound('!');
+     * // => 'hi fred!'
+     *
+     * // using placeholders
+     * var bound = _.bind(greet, object, _, '!');
+     * bound('hi');
+     * // => 'hi fred!'
+     */
+    var bind = restParam(function(func, thisArg, partials) {
+      var bitmask = BIND_FLAG;
+      if (partials.length) {
+        var holders = replaceHolders(partials, bind.placeholder);
+        bitmask |= PARTIAL_FLAG;
+      }
+      return createWrapper(func, bitmask, thisArg, partials, holders);
+    });
+
+    /**
+     * Binds methods of an object to the object itself, overwriting the existing
+     * method. Method names may be specified as individual arguments or as arrays
+     * of method names. If no method names are provided all enumerable function
+     * properties, own and inherited, of `object` are bound.
+     *
+     * **Note:** This method does not set the "length" property of bound functions.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Object} object The object to bind and assign the bound methods to.
+     * @param {...(string|string[])} [methodNames] The object method names to bind,
+     *  specified as individual method names or arrays of method names.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * var view = {
+     *   'label': 'docs',
+     *   'onClick': function() {
+     *     console.log('clicked ' + this.label);
+     *   }
+     * };
+     *
+     * _.bindAll(view);
+     * jQuery('#docs').on('click', view.onClick);
+     * // => logs 'clicked docs' when the element is clicked
+     */
+    var bindAll = restParam(function(object, methodNames) {
+      methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object);
+
+      var index = -1,
+          length = methodNames.length;
+
+      while (++index < length) {
+        var key = methodNames[index];
+        object[key] = createWrapper(object[key], BIND_FLAG, object);
+      }
+      return object;
+    });
+
+    /**
+     * Creates a function that invokes the method at `object[key]` and prepends
+     * any additional `_.bindKey` arguments to those provided to the bound function.
+     *
+     * This method differs from `_.bind` by allowing bound functions to reference
+     * methods that may be redefined or don't yet exist.
+     * See [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
+     * for more details.
+     *
+     * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
+     * builds, may be used as a placeholder for partially applied arguments.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Object} object The object the method belongs to.
+     * @param {string} key The key of the method.
+     * @param {...*} [partials] The arguments to be partially applied.
+     * @returns {Function} Returns the new bound function.
+     * @example
+     *
+     * var object = {
+     *   'user': 'fred',
+     *   'greet': function(greeting, punctuation) {
+     *     return greeting + ' ' + this.user + punctuation;
+     *   }
+     * };
+     *
+     * var bound = _.bindKey(object, 'greet', 'hi');
+     * bound('!');
+     * // => 'hi fred!'
+     *
+     * object.greet = function(greeting, punctuation) {
+     *   return greeting + 'ya ' + this.user + punctuation;
+     * };
+     *
+     * bound('!');
+     * // => 'hiya fred!'
+     *
+     * // using placeholders
+     * var bound = _.bindKey(object, 'greet', _, '!');
+     * bound('hi');
+     * // => 'hiya fred!'
+     */
+    var bindKey = restParam(function(object, key, partials) {
+      var bitmask = BIND_FLAG | BIND_KEY_FLAG;
+      if (partials.length) {
+        var holders = replaceHolders(partials, bindKey.placeholder);
+        bitmask |= PARTIAL_FLAG;
+      }
+      return createWrapper(key, bitmask, object, partials, holders);
+    });
+
+    /**
+     * Creates a function that accepts one or more arguments of `func` that when
+     * called either invokes `func` returning its result, if all `func` arguments
+     * have been provided, or returns a function that accepts one or more of the
+     * remaining `func` arguments, and so on. The arity of `func` may be specified
+     * if `func.length` is not sufficient.
+     *
+     * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
+     * may be used as a placeholder for provided arguments.
+     *
+     * **Note:** This method does not set the "length" property of curried functions.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Function} func The function to curry.
+     * @param {number} [arity=func.length] The arity of `func`.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {Function} Returns the new curried function.
+     * @example
+     *
+     * var abc = function(a, b, c) {
+     *   return [a, b, c];
+     * };
+     *
+     * var curried = _.curry(abc);
+     *
+     * curried(1)(2)(3);
+     * // => [1, 2, 3]
+     *
+     * curried(1, 2)(3);
+     * // => [1, 2, 3]
+     *
+     * curried(1, 2, 3);
+     * // => [1, 2, 3]
+     *
+     * // using placeholders
+     * curried(1)(_, 3)(2);
+     * // => [1, 2, 3]
+     */
+    var curry = createCurry(CURRY_FLAG);
+
+    /**
+     * This method is like `_.curry` except that arguments are applied to `func`
+     * in the manner of `_.partialRight` instead of `_.partial`.
+     *
+     * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
+     * builds, may be used as a placeholder for provided arguments.
+     *
+     * **Note:** This method does not set the "length" property of curried functions.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Function} func The function to curry.
+     * @param {number} [arity=func.length] The arity of `func`.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {Function} Returns the new curried function.
+     * @example
+     *
+     * var abc = function(a, b, c) {
+     *   return [a, b, c];
+     * };
+     *
+     * var curried = _.curryRight(abc);
+     *
+     * curried(3)(2)(1);
+     * // => [1, 2, 3]
+     *
+     * curried(2, 3)(1);
+     * // => [1, 2, 3]
+     *
+     * curried(1, 2, 3);
+     * // => [1, 2, 3]
+     *
+     * // using placeholders
+     * curried(3)(1, _)(2);
+     * // => [1, 2, 3]
+     */
+    var curryRight = createCurry(CURRY_RIGHT_FLAG);
+
+    /**
+     * Creates a function that delays invoking `func` until after `wait` milliseconds
+     * have elapsed since the last time it was invoked. The created function comes
+     * with a `cancel` method to cancel delayed invocations. Provide an options
+     * object to indicate that `func` should be invoked on the leading and/or
+     * trailing edge of the `wait` timeout. Subsequent calls to the debounced
+     * function return the result of the last `func` invocation.
+     *
+     * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
+     * on the trailing edge of the timeout only if the the debounced function is
+     * invoked more than once during the `wait` timeout.
+     *
+     * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
+     * for details over the differences between `_.debounce` and `_.throttle`.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Function} func The function to debounce.
+     * @param {number} [wait=0] The number of milliseconds to delay.
+     * @param {Object} [options] The options object.
+     * @param {boolean} [options.leading=false] Specify invoking on the leading
+     *  edge of the timeout.
+     * @param {number} [options.maxWait] The maximum time `func` is allowed to be
+     *  delayed before it is invoked.
+     * @param {boolean} [options.trailing=true] Specify invoking on the trailing
+     *  edge of the timeout.
+     * @returns {Function} Returns the new debounced function.
+     * @example
+     *
+     * // avoid costly calculations while the window size is in flux
+     * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
+     *
+     * // invoke `sendMail` when the click event is fired, debouncing subsequent calls
+     * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
+     *   'leading': true,
+     *   'trailing': false
+     * }));
+     *
+     * // ensure `batchLog` is invoked once after 1 second of debounced calls
+     * var source = new EventSource('/stream');
+     * jQuery(source).on('message', _.debounce(batchLog, 250, {
+     *   'maxWait': 1000
+     * }));
+     *
+     * // cancel a debounced call
+     * var todoChanges = _.debounce(batchLog, 1000);
+     * Object.observe(models.todo, todoChanges);
+     *
+     * Object.observe(models, function(changes) {
+     *   if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) {
+     *     todoChanges.cancel();
+     *   }
+     * }, ['delete']);
+     *
+     * // ...at some point `models.todo` is changed
+     * models.todo.completed = true;
+     *
+     * // ...before 1 second has passed `models.todo` is deleted
+     * // which cancels the debounced `todoChanges` call
+     * delete models.todo;
+     */
+    function debounce(func, wait, options) {
+      var args,
+          maxTimeoutId,
+          result,
+          stamp,
+          thisArg,
+          timeoutId,
+          trailingCall,
+          lastCalled = 0,
+          maxWait = false,
+          trailing = true;
+
+      if (typeof func != 'function') {
+        throw new TypeError(FUNC_ERROR_TEXT);
+      }
+      wait = wait < 0 ? 0 : (+wait || 0);
+      if (options === true) {
+        var leading = true;
+        trailing = false;
+      } else if (isObject(options)) {
+        leading = options.leading;
+        maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait);
+        trailing = 'trailing' in options ? options.trailing : trailing;
+      }
+
+      function cancel() {
+        if (timeoutId) {
+          clearTimeout(timeoutId);
+        }
+        if (maxTimeoutId) {
+          clearTimeout(maxTimeoutId);
+        }
+        maxTimeoutId = timeoutId = trailingCall = undefined;
+      }
+
+      function delayed() {
+        var remaining = wait - (now() - stamp);
+        if (remaining <= 0 || remaining > wait) {
+          if (maxTimeoutId) {
+            clearTimeout(maxTimeoutId);
+          }
+          var isCalled = trailingCall;
+          maxTimeoutId = timeoutId = trailingCall = undefined;
+          if (isCalled) {
+            lastCalled = now();
+            result = func.apply(thisArg, args);
+            if (!timeoutId && !maxTimeoutId) {
+              args = thisArg = null;
+            }
+          }
+        } else {
+          timeoutId = setTimeout(delayed, remaining);
+        }
+      }
+
+      function maxDelayed() {
+        if (timeoutId) {
+          clearTimeout(timeoutId);
+        }
+        maxTimeoutId = timeoutId = trailingCall = undefined;
+        if (trailing || (maxWait !== wait)) {
+          lastCalled = now();
+          result = func.apply(thisArg, args);
+          if (!timeoutId && !maxTimeoutId) {
+            args = thisArg = null;
+          }
+        }
+      }
+
+      function debounced() {
+        args = arguments;
+        stamp = now();
+        thisArg = this;
+        trailingCall = trailing && (timeoutId || !leading);
+
+        if (maxWait === false) {
+          var leadingCall = leading && !timeoutId;
+        } else {
+          if (!maxTimeoutId && !leading) {
+            lastCalled = stamp;
+          }
+          var remaining = maxWait - (stamp - lastCalled),
+              isCalled = remaining <= 0 || remaining > maxWait;
+
+          if (isCalled) {
+            if (maxTimeoutId) {
+              maxTimeoutId = clearTimeout(maxTimeoutId);
+            }
+            lastCalled = stamp;
+            result = func.apply(thisArg, args);
+          }
+          else if (!maxTimeoutId) {
+            maxTimeoutId = setTimeout(maxDelayed, remaining);
+          }
+        }
+        if (isCalled && timeoutId) {
+          timeoutId = clearTimeout(timeoutId);
+        }
+        else if (!timeoutId && wait !== maxWait) {
+          timeoutId = setTimeout(delayed, wait);
+        }
+        if (leadingCall) {
+          isCalled = true;
+          result = func.apply(thisArg, args);
+        }
+        if (isCalled && !timeoutId && !maxTimeoutId) {
+          args = thisArg = null;
+        }
+        return result;
+      }
+      debounced.cancel = cancel;
+      return debounced;
+    }
+
+    /**
+     * Defers invoking the `func` until the current call stack has cleared. Any
+     * additional arguments are provided to `func` when it is invoked.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Function} func The function to defer.
+     * @param {...*} [args] The arguments to invoke the function with.
+     * @returns {number} Returns the timer id.
+     * @example
+     *
+     * _.defer(function(text) {
+     *   console.log(text);
+     * }, 'deferred');
+     * // logs 'deferred' after one or more milliseconds
+     */
+    var defer = restParam(function(func, args) {
+      return baseDelay(func, 1, args);
+    });
+
+    /**
+     * Invokes `func` after `wait` milliseconds. Any additional arguments are
+     * provided to `func` when it is invoked.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Function} func The function to delay.
+     * @param {number} wait The number of milliseconds to delay invocation.
+     * @param {...*} [args] The arguments to invoke the function with.
+     * @returns {number} Returns the timer id.
+     * @example
+     *
+     * _.delay(function(text) {
+     *   console.log(text);
+     * }, 1000, 'later');
+     * // => logs 'later' after one second
+     */
+    var delay = restParam(function(func, wait, args) {
+      return baseDelay(func, wait, args);
+    });
+
+    /**
+     * Creates a function that returns the result of invoking the provided
+     * functions with the `this` binding of the created function, where each
+     * successive invocation is supplied the return value of the previous.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {...Function} [funcs] Functions to invoke.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * function square(n) {
+     *   return n * n;
+     * }
+     *
+     * var addSquare = _.flow(_.add, square);
+     * addSquare(1, 2);
+     * // => 9
+     */
+    var flow = createFlow();
+
+    /**
+     * This method is like `_.flow` except that it creates a function that
+     * invokes the provided functions from right to left.
+     *
+     * @static
+     * @memberOf _
+     * @alias backflow, compose
+     * @category Function
+     * @param {...Function} [funcs] Functions to invoke.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * function square(n) {
+     *   return n * n;
+     * }
+     *
+     * var addSquare = _.flowRight(square, _.add);
+     * addSquare(1, 2);
+     * // => 9
+     */
+    var flowRight = createFlow(true);
+
+    /**
+     * Creates a function that memoizes the result of `func`. If `resolver` is
+     * provided it determines the cache key for storing the result based on the
+     * arguments provided to the memoized function. By default, the first argument
+     * provided to the memoized function is coerced to a string and used as the
+     * cache key. The `func` is invoked with the `this` binding of the memoized
+     * function.
+     *
+     * **Note:** The cache is exposed as the `cache` property on the memoized
+     * function. Its creation may be customized by replacing the `_.memoize.Cache`
+     * constructor with one whose instances implement the [`Map`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-properties-of-the-map-prototype-object)
+     * method interface of `get`, `has`, and `set`.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Function} func The function to have its output memoized.
+     * @param {Function} [resolver] The function to resolve the cache key.
+     * @returns {Function} Returns the new memoizing function.
+     * @example
+     *
+     * var upperCase = _.memoize(function(string) {
+     *   return string.toUpperCase();
+     * });
+     *
+     * upperCase('fred');
+     * // => 'FRED'
+     *
+     * // modifying the result cache
+     * upperCase.cache.set('fred', 'BARNEY');
+     * upperCase('fred');
+     * // => 'BARNEY'
+     *
+     * // replacing `_.memoize.Cache`
+     * var object = { 'user': 'fred' };
+     * var other = { 'user': 'barney' };
+     * var identity = _.memoize(_.identity);
+     *
+     * identity(object);
+     * // => { 'user': 'fred' }
+     * identity(other);
+     * // => { 'user': 'fred' }
+     *
+     * _.memoize.Cache = WeakMap;
+     * var identity = _.memoize(_.identity);
+     *
+     * identity(object);
+     * // => { 'user': 'fred' }
+     * identity(other);
+     * // => { 'user': 'barney' }
+     */
+    function memoize(func, resolver) {
+      if (typeof func != 'function' || (resolver && typeof resolver != 'function')) {
+        throw new TypeError(FUNC_ERROR_TEXT);
+      }
+      var memoized = function() {
+        var args = arguments,
+            cache = memoized.cache,
+            key = resolver ? resolver.apply(this, args) : args[0];
+
+        if (cache.has(key)) {
+          return cache.get(key);
+        }
+        var result = func.apply(this, args);
+        cache.set(key, result);
+        return result;
+      };
+      memoized.cache = new memoize.Cache;
+      return memoized;
+    }
+
+    /**
+     * Creates a function that negates the result of the predicate `func`. The
+     * `func` predicate is invoked with the `this` binding and arguments of the
+     * created function.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Function} predicate The predicate to negate.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * function isEven(n) {
+     *   return n % 2 == 0;
+     * }
+     *
+     * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
+     * // => [1, 3, 5]
+     */
+    function negate(predicate) {
+      if (typeof predicate != 'function') {
+        throw new TypeError(FUNC_ERROR_TEXT);
+      }
+      return function() {
+        return !predicate.apply(this, arguments);
+      };
+    }
+
+    /**
+     * Creates a function that is restricted to invoking `func` once. Repeat calls
+     * to the function return the value of the first call. The `func` is invoked
+     * with the `this` binding and arguments of the created function.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Function} func The function to restrict.
+     * @returns {Function} Returns the new restricted function.
+     * @example
+     *
+     * var initialize = _.once(createApplication);
+     * initialize();
+     * initialize();
+     * // `initialize` invokes `createApplication` once
+     */
+    function once(func) {
+      return before(2, func);
+    }
+
+    /**
+     * Creates a function that invokes `func` with `partial` arguments prepended
+     * to those provided to the new function. This method is like `_.bind` except
+     * it does **not** alter the `this` binding.
+     *
+     * The `_.partial.placeholder` value, which defaults to `_` in monolithic
+     * builds, may be used as a placeholder for partially applied arguments.
+     *
+     * **Note:** This method does not set the "length" property of partially
+     * applied functions.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Function} func The function to partially apply arguments to.
+     * @param {...*} [partials] The arguments to be partially applied.
+     * @returns {Function} Returns the new partially applied function.
+     * @example
+     *
+     * var greet = function(greeting, name) {
+     *   return greeting + ' ' + name;
+     * };
+     *
+     * var sayHelloTo = _.partial(greet, 'hello');
+     * sayHelloTo('fred');
+     * // => 'hello fred'
+     *
+     * // using placeholders
+     * var greetFred = _.partial(greet, _, 'fred');
+     * greetFred('hi');
+     * // => 'hi fred'
+     */
+    var partial = createPartial(PARTIAL_FLAG);
+
+    /**
+     * This method is like `_.partial` except that partially applied arguments
+     * are appended to those provided to the new function.
+     *
+     * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
+     * builds, may be used as a placeholder for partially applied arguments.
+     *
+     * **Note:** This method does not set the "length" property of partially
+     * applied functions.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Function} func The function to partially apply arguments to.
+     * @param {...*} [partials] The arguments to be partially applied.
+     * @returns {Function} Returns the new partially applied function.
+     * @example
+     *
+     * var greet = function(greeting, name) {
+     *   return greeting + ' ' + name;
+     * };
+     *
+     * var greetFred = _.partialRight(greet, 'fred');
+     * greetFred('hi');
+     * // => 'hi fred'
+     *
+     * // using placeholders
+     * var sayHelloTo = _.partialRight(greet, 'hello', _);
+     * sayHelloTo('fred');
+     * // => 'hello fred'
+     */
+    var partialRight = createPartial(PARTIAL_RIGHT_FLAG);
+
+    /**
+     * Creates a function that invokes `func` with arguments arranged according
+     * to the specified indexes where the argument value at the first index is
+     * provided as the first argument, the argument value at the second index is
+     * provided as the second argument, and so on.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Function} func The function to rearrange arguments for.
+     * @param {...(number|number[])} indexes The arranged argument indexes,
+     *  specified as individual indexes or arrays of indexes.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var rearged = _.rearg(function(a, b, c) {
+     *   return [a, b, c];
+     * }, 2, 0, 1);
+     *
+     * rearged('b', 'c', 'a')
+     * // => ['a', 'b', 'c']
+     *
+     * var map = _.rearg(_.map, [1, 0]);
+     * map(function(n) {
+     *   return n * 3;
+     * }, [1, 2, 3]);
+     * // => [3, 6, 9]
+     */
+    var rearg = restParam(function(func, indexes) {
+      return createWrapper(func, REARG_FLAG, null, null, null, baseFlatten(indexes));
+    });
+
+    /**
+     * Creates a function that invokes `func` with the `this` binding of the
+     * created function and arguments from `start` and beyond provided as an array.
+     *
+     * **Note:** This method is based on the [rest parameter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters).
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Function} func The function to apply a rest parameter to.
+     * @param {number} [start=func.length-1] The start position of the rest parameter.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var say = _.restParam(function(what, names) {
+     *   return what + ' ' + _.initial(names).join(', ') +
+     *     (_.size(names) > 1 ? ', & ' : '') + _.last(names);
+     * });
+     *
+     * say('hello', 'fred', 'barney', 'pebbles');
+     * // => 'hello fred, barney, & pebbles'
+     */
+    function restParam(func, start) {
+      if (typeof func != 'function') {
+        throw new TypeError(FUNC_ERROR_TEXT);
+      }
+      start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0);
+      return function() {
+        var args = arguments,
+            index = -1,
+            length = nativeMax(args.length - start, 0),
+            rest = Array(length);
+
+        while (++index < length) {
+          rest[index] = args[start + index];
+        }
+        switch (start) {
+          case 0: return func.call(this, rest);
+          case 1: return func.call(this, args[0], rest);
+          case 2: return func.call(this, args[0], args[1], rest);
+        }
+        var otherArgs = Array(start + 1);
+        index = -1;
+        while (++index < start) {
+          otherArgs[index] = args[index];
+        }
+        otherArgs[start] = rest;
+        return func.apply(this, otherArgs);
+      };
+    }
+
+    /**
+     * Creates a function that invokes `func` with the `this` binding of the created
+     * function and an array of arguments much like [`Function#apply`](https://es5.github.io/#x15.3.4.3).
+     *
+     * **Note:** This method is based on the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator).
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Function} func The function to spread arguments over.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var say = _.spread(function(who, what) {
+     *   return who + ' says ' + what;
+     * });
+     *
+     * say(['fred', 'hello']);
+     * // => 'fred says hello'
+     *
+     * // with a Promise
+     * var numbers = Promise.all([
+     *   Promise.resolve(40),
+     *   Promise.resolve(36)
+     * ]);
+     *
+     * numbers.then(_.spread(function(x, y) {
+     *   return x + y;
+     * }));
+     * // => a Promise of 76
+     */
+    function spread(func) {
+      if (typeof func != 'function') {
+        throw new TypeError(FUNC_ERROR_TEXT);
+      }
+      return function(array) {
+        return func.apply(this, array);
+      };
+    }
+
+    /**
+     * Creates a function that only invokes `func` at most once per every `wait`
+     * milliseconds. The created function comes with a `cancel` method to cancel
+     * delayed invocations. Provide an options object to indicate that `func`
+     * should be invoked on the leading and/or trailing edge of the `wait` timeout.
+     * Subsequent calls to the throttled function return the result of the last
+     * `func` call.
+     *
+     * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
+     * on the trailing edge of the timeout only if the the throttled function is
+     * invoked more than once during the `wait` timeout.
+     *
+     * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
+     * for details over the differences between `_.throttle` and `_.debounce`.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {Function} func The function to throttle.
+     * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
+     * @param {Object} [options] The options object.
+     * @param {boolean} [options.leading=true] Specify invoking on the leading
+     *  edge of the timeout.
+     * @param {boolean} [options.trailing=true] Specify invoking on the trailing
+     *  edge of the timeout.
+     * @returns {Function} Returns the new throttled function.
+     * @example
+     *
+     * // avoid excessively updating the position while scrolling
+     * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
+     *
+     * // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes
+     * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
+     *   'trailing': false
+     * }));
+     *
+     * // cancel a trailing throttled call
+     * jQuery(window).on('popstate', throttled.cancel);
+     */
+    function throttle(func, wait, options) {
+      var leading = true,
+          trailing = true;
+
+      if (typeof func != 'function') {
+        throw new TypeError(FUNC_ERROR_TEXT);
+      }
+      if (options === false) {
+        leading = false;
+      } else if (isObject(options)) {
+        leading = 'leading' in options ? !!options.leading : leading;
+        trailing = 'trailing' in options ? !!options.trailing : trailing;
+      }
+      debounceOptions.leading = leading;
+      debounceOptions.maxWait = +wait;
+      debounceOptions.trailing = trailing;
+      return debounce(func, wait, debounceOptions);
+    }
+
+    /**
+     * Creates a function that provides `value` to the wrapper function as its
+     * first argument. Any additional arguments provided to the function are
+     * appended to those provided to the wrapper function. The wrapper is invoked
+     * with the `this` binding of the created function.
+     *
+     * @static
+     * @memberOf _
+     * @category Function
+     * @param {*} value The value to wrap.
+     * @param {Function} wrapper The wrapper function.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var p = _.wrap(_.escape, function(func, text) {
+     *   return '<p>' + func(text) + '</p>';
+     * });
+     *
+     * p('fred, barney, & pebbles');
+     * // => '<p>fred, barney, &amp; pebbles</p>'
+     */
+    function wrap(value, wrapper) {
+      wrapper = wrapper == null ? identity : wrapper;
+      return createWrapper(wrapper, PARTIAL_FLAG, null, [value], []);
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned,
+     * otherwise they are assigned by reference. If `customizer` is provided it is
+     * invoked to produce the cloned values. If `customizer` returns `undefined`
+     * cloning is handled by the method instead. The `customizer` is bound to
+     * `thisArg` and invoked with two argument; (value [, index|key, object]).
+     *
+     * **Note:** This method is loosely based on the
+     * [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm).
+     * The enumerable properties of `arguments` objects and objects created by
+     * constructors other than `Object` are cloned to plain `Object` objects. An
+     * empty object is returned for uncloneable values such as functions, DOM nodes,
+     * Maps, Sets, and WeakMaps.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to clone.
+     * @param {boolean} [isDeep] Specify a deep clone.
+     * @param {Function} [customizer] The function to customize cloning values.
+     * @param {*} [thisArg] The `this` binding of `customizer`.
+     * @returns {*} Returns the cloned value.
+     * @example
+     *
+     * var users = [
+     *   { 'user': 'barney' },
+     *   { 'user': 'fred' }
+     * ];
+     *
+     * var shallow = _.clone(users);
+     * shallow[0] === users[0];
+     * // => true
+     *
+     * var deep = _.clone(users, true);
+     * deep[0] === users[0];
+     * // => false
+     *
+     * // using a customizer callback
+     * var el = _.clone(document.body, function(value) {
+     *   if (_.isElement(value)) {
+     *     return value.cloneNode(false);
+     *   }
+     * });
+     *
+     * el === document.body
+     * // => false
+     * el.nodeName
+     * // => BODY
+     * el.childNodes.length;
+     * // => 0
+     */
+    function clone(value, isDeep, customizer, thisArg) {
+      if (isDeep && typeof isDeep != 'boolean' && isIterateeCall(value, isDeep, customizer)) {
+        isDeep = false;
+      }
+      else if (typeof isDeep == 'function') {
+        thisArg = customizer;
+        customizer = isDeep;
+        isDeep = false;
+      }
+      customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 1);
+      return baseClone(value, isDeep, customizer);
+    }
+
+    /**
+     * Creates a deep clone of `value`. If `customizer` is provided it is invoked
+     * to produce the cloned values. If `customizer` returns `undefined` cloning
+     * is handled by the method instead. The `customizer` is bound to `thisArg`
+     * and invoked with two argument; (value [, index|key, object]).
+     *
+     * **Note:** This method is loosely based on the
+     * [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm).
+     * The enumerable properties of `arguments` objects and objects created by
+     * constructors other than `Object` are cloned to plain `Object` objects. An
+     * empty object is returned for uncloneable values such as functions, DOM nodes,
+     * Maps, Sets, and WeakMaps.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to deep clone.
+     * @param {Function} [customizer] The function to customize cloning values.
+     * @param {*} [thisArg] The `this` binding of `customizer`.
+     * @returns {*} Returns the deep cloned value.
+     * @example
+     *
+     * var users = [
+     *   { 'user': 'barney' },
+     *   { 'user': 'fred' }
+     * ];
+     *
+     * var deep = _.cloneDeep(users);
+     * deep[0] === users[0];
+     * // => false
+     *
+     * // using a customizer callback
+     * var el = _.cloneDeep(document.body, function(value) {
+     *   if (_.isElement(value)) {
+     *     return value.cloneNode(true);
+     *   }
+     * });
+     *
+     * el === document.body
+     * // => false
+     * el.nodeName
+     * // => BODY
+     * el.childNodes.length;
+     * // => 20
+     */
+    function cloneDeep(value, customizer, thisArg) {
+      customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 1);
+      return baseClone(value, true, customizer);
+    }
+
+    /**
+     * Checks if `value` is classified as an `arguments` object.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+     * @example
+     *
+     * _.isArguments(function() { return arguments; }());
+     * // => true
+     *
+     * _.isArguments([1, 2, 3]);
+     * // => false
+     */
+    function isArguments(value) {
+      var length = isObjectLike(value) ? value.length : undefined;
+      return isLength(length) && objToString.call(value) == argsTag;
+    }
+
+    /**
+     * Checks if `value` is classified as an `Array` object.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+     * @example
+     *
+     * _.isArray([1, 2, 3]);
+     * // => true
+     *
+     * _.isArray(function() { return arguments; }());
+     * // => false
+     */
+    var isArray = nativeIsArray || function(value) {
+      return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;
+    };
+
+    /**
+     * Checks if `value` is classified as a boolean primitive or object.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+     * @example
+     *
+     * _.isBoolean(false);
+     * // => true
+     *
+     * _.isBoolean(null);
+     * // => false
+     */
+    function isBoolean(value) {
+      return value === true || value === false || (isObjectLike(value) && objToString.call(value) == boolTag);
+    }
+
+    /**
+     * Checks if `value` is classified as a `Date` object.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+     * @example
+     *
+     * _.isDate(new Date);
+     * // => true
+     *
+     * _.isDate('Mon April 23 2012');
+     * // => false
+     */
+    function isDate(value) {
+      return isObjectLike(value) && objToString.call(value) == dateTag;
+    }
+
+    /**
+     * Checks if `value` is a DOM element.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
+     * @example
+     *
+     * _.isElement(document.body);
+     * // => true
+     *
+     * _.isElement('<body>');
+     * // => false
+     */
+    function isElement(value) {
+      return !!value && value.nodeType === 1 && isObjectLike(value) &&
+        (objToString.call(value).indexOf('Element') > -1);
+    }
+    // Fallback for environments without DOM support.
+    if (!support.dom) {
+      isElement = function(value) {
+        return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value);
+      };
+    }
+
+    /**
+     * Checks if `value` is empty. A value is considered empty unless it is an
+     * `arguments` object, array, string, or jQuery-like collection with a length
+     * greater than `0` or an object with own enumerable properties.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {Array|Object|string} value The value to inspect.
+     * @returns {boolean} Returns `true` if `value` is empty, else `false`.
+     * @example
+     *
+     * _.isEmpty(null);
+     * // => true
+     *
+     * _.isEmpty(true);
+     * // => true
+     *
+     * _.isEmpty(1);
+     * // => true
+     *
+     * _.isEmpty([1, 2, 3]);
+     * // => false
+     *
+     * _.isEmpty({ 'a': 1 });
+     * // => false
+     */
+    function isEmpty(value) {
+      if (value == null) {
+        return true;
+      }
+      var length = getLength(value);
+      if (isLength(length) && (isArray(value) || isString(value) || isArguments(value) ||
+          (isObjectLike(value) && isFunction(value.splice)))) {
+        return !length;
+      }
+      return !keys(value).length;
+    }
+
+    /**
+     * Performs a deep comparison between two values to determine if they are
+     * equivalent. If `customizer` is provided it is invoked to compare values.
+     * If `customizer` returns `undefined` comparisons are handled by the method
+     * instead. The `customizer` is bound to `thisArg` and invoked with three
+     * arguments: (value, other [, index|key]).
+     *
+     * **Note:** This method supports comparing arrays, booleans, `Date` objects,
+     * numbers, `Object` objects, regexes, and strings. Objects are compared by
+     * their own, not inherited, enumerable properties. Functions and DOM nodes
+     * are **not** supported. Provide a customizer function to extend support
+     * for comparing other values.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to compare.
+     * @param {*} other The other value to compare.
+     * @param {Function} [customizer] The function to customize value comparisons.
+     * @param {*} [thisArg] The `this` binding of `customizer`.
+     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+     * @example
+     *
+     * var object = { 'user': 'fred' };
+     * var other = { 'user': 'fred' };
+     *
+     * object == other;
+     * // => false
+     *
+     * _.isEqual(object, other);
+     * // => true
+     *
+     * // using a customizer callback
+     * var array = ['hello', 'goodbye'];
+     * var other = ['hi', 'goodbye'];
+     *
+     * _.isEqual(array, other, function(value, other) {
+     *   if (_.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/)) {
+     *     return true;
+     *   }
+     * });
+     * // => true
+     */
+    function isEqual(value, other, customizer, thisArg) {
+      customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 3);
+      if (!customizer && isStrictComparable(value) && isStrictComparable(other)) {
+        return value === other;
+      }
+      var result = customizer ? customizer(value, other) : undefined;
+      return result === undefined ? baseIsEqual(value, other, customizer) : !!result;
+    }
+
+    /**
+     * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
+     * `SyntaxError`, `TypeError`, or `URIError` object.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
+     * @example
+     *
+     * _.isError(new Error);
+     * // => true
+     *
+     * _.isError(Error);
+     * // => false
+     */
+    function isError(value) {
+      return isObjectLike(value) && typeof value.message == 'string' && objToString.call(value) == errorTag;
+    }
+
+    /**
+     * Checks if `value` is a finite primitive number.
+     *
+     * **Note:** This method is based on [`Number.isFinite`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.isfinite).
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
+     * @example
+     *
+     * _.isFinite(10);
+     * // => true
+     *
+     * _.isFinite('10');
+     * // => false
+     *
+     * _.isFinite(true);
+     * // => false
+     *
+     * _.isFinite(Object(10));
+     * // => false
+     *
+     * _.isFinite(Infinity);
+     * // => false
+     */
+    var isFinite = nativeNumIsFinite || function(value) {
+      return typeof value == 'number' && nativeIsFinite(value);
+    };
+
+    /**
+     * Checks if `value` is classified as a `Function` object.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+     * @example
+     *
+     * _.isFunction(_);
+     * // => true
+     *
+     * _.isFunction(/abc/);
+     * // => false
+     */
+    var isFunction = !(baseIsFunction(/x/) || (Uint8Array && !baseIsFunction(Uint8Array))) ? baseIsFunction : function(value) {
+      // The use of `Object#toString` avoids issues with the `typeof` operator
+      // in older versions of Chrome and Safari which return 'function' for regexes
+      // and Safari 8 equivalents which return 'object' for typed array constructors.
+      return objToString.call(value) == funcTag;
+    };
+
+    /**
+     * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
+     * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is an object, else `false`.
+     * @example
+     *
+     * _.isObject({});
+     * // => true
+     *
+     * _.isObject([1, 2, 3]);
+     * // => true
+     *
+     * _.isObject(1);
+     * // => false
+     */
+    function isObject(value) {
+      // Avoid a V8 JIT bug in Chrome 19-20.
+      // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
+      var type = typeof value;
+      return type == 'function' || (!!value && type == 'object');
+    }
+
+    /**
+     * Performs a deep comparison between `object` and `source` to determine if
+     * `object` contains equivalent property values. If `customizer` is provided
+     * it is invoked to compare values. If `customizer` returns `undefined`
+     * comparisons are handled by the method instead. The `customizer` is bound
+     * to `thisArg` and invoked with three arguments: (value, other, index|key).
+     *
+     * **Note:** This method supports comparing properties of arrays, booleans,
+     * `Date` objects, numbers, `Object` objects, regexes, and strings. Functions
+     * and DOM nodes are **not** supported. Provide a customizer function to extend
+     * support for comparing other values.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {Object} object The object to inspect.
+     * @param {Object} source The object of property values to match.
+     * @param {Function} [customizer] The function to customize value comparisons.
+     * @param {*} [thisArg] The `this` binding of `customizer`.
+     * @returns {boolean} Returns `true` if `object` is a match, else `false`.
+     * @example
+     *
+     * var object = { 'user': 'fred', 'age': 40 };
+     *
+     * _.isMatch(object, { 'age': 40 });
+     * // => true
+     *
+     * _.isMatch(object, { 'age': 36 });
+     * // => false
+     *
+     * // using a customizer callback
+     * var object = { 'greeting': 'hello' };
+     * var source = { 'greeting': 'hi' };
+     *
+     * _.isMatch(object, source, function(value, other) {
+     *   return _.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/) || undefined;
+     * });
+     * // => true
+     */
+    function isMatch(object, source, customizer, thisArg) {
+      var props = keys(source),
+          length = props.length;
+
+      if (!length) {
+        return true;
+      }
+      if (object == null) {
+        return false;
+      }
+      customizer = typeof customizer == 'function' && bindCallback(customizer, thisArg, 3);
+      object = toObject(object);
+      if (!customizer && length == 1) {
+        var key = props[0],
+            value = source[key];
+
+        if (isStrictComparable(value)) {
+          return value === object[key] && (value !== undefined || (key in object));
+        }
+      }
+      var values = Array(length),
+          strictCompareFlags = Array(length);
+
+      while (length--) {
+        value = values[length] = source[props[length]];
+        strictCompareFlags[length] = isStrictComparable(value);
+      }
+      return baseIsMatch(object, props, values, strictCompareFlags, customizer);
+    }
+
+    /**
+     * Checks if `value` is `NaN`.
+     *
+     * **Note:** This method is not the same as [`isNaN`](https://es5.github.io/#x15.1.2.4)
+     * which returns `true` for `undefined` and other non-numeric values.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
+     * @example
+     *
+     * _.isNaN(NaN);
+     * // => true
+     *
+     * _.isNaN(new Number(NaN));
+     * // => true
+     *
+     * isNaN(undefined);
+     * // => true
+     *
+     * _.isNaN(undefined);
+     * // => false
+     */
+    function isNaN(value) {
+      // An `NaN` primitive is the only value that is not equal to itself.
+      // Perform the `toStringTag` check first to avoid errors with some host objects in IE.
+      return isNumber(value) && value != +value;
+    }
+
+    /**
+     * Checks if `value` is a native function.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
+     * @example
+     *
+     * _.isNative(Array.prototype.push);
+     * // => true
+     *
+     * _.isNative(_);
+     * // => false
+     */
+    function isNative(value) {
+      if (value == null) {
+        return false;
+      }
+      if (objToString.call(value) == funcTag) {
+        return reIsNative.test(fnToString.call(value));
+      }
+      return isObjectLike(value) && reIsHostCtor.test(value);
+    }
+
+    /**
+     * Checks if `value` is `null`.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
+     * @example
+     *
+     * _.isNull(null);
+     * // => true
+     *
+     * _.isNull(void 0);
+     * // => false
+     */
+    function isNull(value) {
+      return value === null;
+    }
+
+    /**
+     * Checks if `value` is classified as a `Number` primitive or object.
+     *
+     * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified
+     * as numbers, use the `_.isFinite` method.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+     * @example
+     *
+     * _.isNumber(8.4);
+     * // => true
+     *
+     * _.isNumber(NaN);
+     * // => true
+     *
+     * _.isNumber('8.4');
+     * // => false
+     */
+    function isNumber(value) {
+      return typeof value == 'number' || (isObjectLike(value) && objToString.call(value) == numberTag);
+    }
+
+    /**
+     * Checks if `value` is a plain object, that is, an object created by the
+     * `Object` constructor or one with a `[[Prototype]]` of `null`.
+     *
+     * **Note:** This method assumes objects created by the `Object` constructor
+     * have no inherited enumerable properties.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
+     * @example
+     *
+     * function Foo() {
+     *   this.a = 1;
+     * }
+     *
+     * _.isPlainObject(new Foo);
+     * // => false
+     *
+     * _.isPlainObject([1, 2, 3]);
+     * // => false
+     *
+     * _.isPlainObject({ 'x': 0, 'y': 0 });
+     * // => true
+     *
+     * _.isPlainObject(Object.create(null));
+     * // => true
+     */
+    var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
+      if (!(value && objToString.call(value) == objectTag)) {
+        return false;
+      }
+      var valueOf = value.valueOf,
+          objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
+
+      return objProto
+        ? (value == objProto || getPrototypeOf(value) == objProto)
+        : shimIsPlainObject(value);
+    };
+
+    /**
+     * Checks if `value` is classified as a `RegExp` object.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+     * @example
+     *
+     * _.isRegExp(/abc/);
+     * // => true
+     *
+     * _.isRegExp('/abc/');
+     * // => false
+     */
+    function isRegExp(value) {
+      return (isObjectLike(value) && objToString.call(value) == regexpTag) || false;
+    }
+
+    /**
+     * Checks if `value` is classified as a `String` primitive or object.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+     * @example
+     *
+     * _.isString('abc');
+     * // => true
+     *
+     * _.isString(1);
+     * // => false
+     */
+    function isString(value) {
+      return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag);
+    }
+
+    /**
+     * Checks if `value` is classified as a typed array.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+     * @example
+     *
+     * _.isTypedArray(new Uint8Array);
+     * // => true
+     *
+     * _.isTypedArray([]);
+     * // => false
+     */
+    function isTypedArray(value) {
+      return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)];
+    }
+
+    /**
+     * Checks if `value` is `undefined`.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to check.
+     * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
+     * @example
+     *
+     * _.isUndefined(void 0);
+     * // => true
+     *
+     * _.isUndefined(null);
+     * // => false
+     */
+    function isUndefined(value) {
+      return value === undefined;
+    }
+
+    /**
+     * Converts `value` to an array.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to convert.
+     * @returns {Array} Returns the converted array.
+     * @example
+     *
+     * (function() {
+     *   return _.toArray(arguments).slice(1);
+     * }(1, 2, 3));
+     * // => [2, 3]
+     */
+    function toArray(value) {
+      var length = value ? getLength(value) : 0;
+      if (!isLength(length)) {
+        return values(value);
+      }
+      if (!length) {
+        return [];
+      }
+      return arrayCopy(value);
+    }
+
+    /**
+     * Converts `value` to a plain object flattening inherited enumerable
+     * properties of `value` to own properties of the plain object.
+     *
+     * @static
+     * @memberOf _
+     * @category Lang
+     * @param {*} value The value to convert.
+     * @returns {Object} Returns the converted plain object.
+     * @example
+     *
+     * function Foo() {
+     *   this.b = 2;
+     * }
+     *
+     * Foo.prototype.c = 3;
+     *
+     * _.assign({ 'a': 1 }, new Foo);
+     * // => { 'a': 1, 'b': 2 }
+     *
+     * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
+     * // => { 'a': 1, 'b': 2, 'c': 3 }
+     */
+    function toPlainObject(value) {
+      return baseCopy(value, keysIn(value));
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * Assigns own enumerable properties of source object(s) to the destination
+     * object. Subsequent sources overwrite property assignments of previous sources.
+     * If `customizer` is provided it is invoked to produce the assigned values.
+     * The `customizer` is bound to `thisArg` and invoked with five arguments:
+     * (objectValue, sourceValue, key, object, source).
+     *
+     * **Note:** This method mutates `object` and is based on
+     * [`Object.assign`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.assign).
+     *
+     *
+     * @static
+     * @memberOf _
+     * @alias extend
+     * @category Object
+     * @param {Object} object The destination object.
+     * @param {...Object} [sources] The source objects.
+     * @param {Function} [customizer] The function to customize assigned values.
+     * @param {*} [thisArg] The `this` binding of `customizer`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * _.assign({ 'user': 'barney' }, { 'age': 40 }, { 'user': 'fred' });
+     * // => { 'user': 'fred', 'age': 40 }
+     *
+     * // using a customizer callback
+     * var defaults = _.partialRight(_.assign, function(value, other) {
+     *   return _.isUndefined(value) ? other : value;
+     * });
+     *
+     * defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' });
+     * // => { 'user': 'barney', 'age': 36 }
+     */
+    var assign = createAssigner(function(object, source, customizer) {
+      return customizer
+        ? assignWith(object, source, customizer)
+        : baseAssign(object, source);
+    });
+
+    /**
+     * Creates an object that inherits from the given `prototype` object. If a
+     * `properties` object is provided its own enumerable properties are assigned
+     * to the created object.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} prototype The object to inherit from.
+     * @param {Object} [properties] The properties to assign to the object.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {Object} Returns the new object.
+     * @example
+     *
+     * function Shape() {
+     *   this.x = 0;
+     *   this.y = 0;
+     * }
+     *
+     * function Circle() {
+     *   Shape.call(this);
+     * }
+     *
+     * Circle.prototype = _.create(Shape.prototype, {
+     *   'constructor': Circle
+     * });
+     *
+     * var circle = new Circle;
+     * circle instanceof Circle;
+     * // => true
+     *
+     * circle instanceof Shape;
+     * // => true
+     */
+    function create(prototype, properties, guard) {
+      var result = baseCreate(prototype);
+      if (guard && isIterateeCall(prototype, properties, guard)) {
+        properties = null;
+      }
+      return properties ? baseAssign(result, properties) : result;
+    }
+
+    /**
+     * Assigns own enumerable properties of source object(s) to the destination
+     * object for all destination properties that resolve to `undefined`. Once a
+     * property is set, additional values of the same property are ignored.
+     *
+     * **Note:** This method mutates `object`.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The destination object.
+     * @param {...Object} [sources] The source objects.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' });
+     * // => { 'user': 'barney', 'age': 36 }
+     */
+    var defaults = restParam(function(args) {
+      var object = args[0];
+      if (object == null) {
+        return object;
+      }
+      args.push(assignDefaults);
+      return assign.apply(undefined, args);
+    });
+
+    /**
+     * This method is like `_.find` except that it returns the key of the first
+     * element `predicate` returns truthy for instead of the element itself.
+     *
+     * If a property name is provided for `predicate` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `predicate` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The object to search.
+     * @param {Function|Object|string} [predicate=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {string|undefined} Returns the key of the matched element, else `undefined`.
+     * @example
+     *
+     * var users = {
+     *   'barney':  { 'age': 36, 'active': true },
+     *   'fred':    { 'age': 40, 'active': false },
+     *   'pebbles': { 'age': 1,  'active': true }
+     * };
+     *
+     * _.findKey(users, function(chr) {
+     *   return chr.age < 40;
+     * });
+     * // => 'barney' (iteration order is not guaranteed)
+     *
+     * // using the `_.matches` callback shorthand
+     * _.findKey(users, { 'age': 1, 'active': true });
+     * // => 'pebbles'
+     *
+     * // using the `_.matchesProperty` callback shorthand
+     * _.findKey(users, 'active', false);
+     * // => 'fred'
+     *
+     * // using the `_.property` callback shorthand
+     * _.findKey(users, 'active');
+     * // => 'barney'
+     */
+    var findKey = createFindKey(baseForOwn);
+
+    /**
+     * This method is like `_.findKey` except that it iterates over elements of
+     * a collection in the opposite order.
+     *
+     * If a property name is provided for `predicate` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `predicate` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The object to search.
+     * @param {Function|Object|string} [predicate=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {string|undefined} Returns the key of the matched element, else `undefined`.
+     * @example
+     *
+     * var users = {
+     *   'barney':  { 'age': 36, 'active': true },
+     *   'fred':    { 'age': 40, 'active': false },
+     *   'pebbles': { 'age': 1,  'active': true }
+     * };
+     *
+     * _.findLastKey(users, function(chr) {
+     *   return chr.age < 40;
+     * });
+     * // => returns `pebbles` assuming `_.findKey` returns `barney`
+     *
+     * // using the `_.matches` callback shorthand
+     * _.findLastKey(users, { 'age': 36, 'active': true });
+     * // => 'barney'
+     *
+     * // using the `_.matchesProperty` callback shorthand
+     * _.findLastKey(users, 'active', false);
+     * // => 'fred'
+     *
+     * // using the `_.property` callback shorthand
+     * _.findLastKey(users, 'active');
+     * // => 'pebbles'
+     */
+    var findLastKey = createFindKey(baseForOwnRight);
+
+    /**
+     * Iterates over own and inherited enumerable properties of an object invoking
+     * `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked
+     * with three arguments: (value, key, object). Iteratee functions may exit
+     * iteration early by explicitly returning `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The object to iterate over.
+     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * function Foo() {
+     *   this.a = 1;
+     *   this.b = 2;
+     * }
+     *
+     * Foo.prototype.c = 3;
+     *
+     * _.forIn(new Foo, function(value, key) {
+     *   console.log(key);
+     * });
+     * // => logs 'a', 'b', and 'c' (iteration order is not guaranteed)
+     */
+    var forIn = createForIn(baseFor);
+
+    /**
+     * This method is like `_.forIn` except that it iterates over properties of
+     * `object` in the opposite order.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The object to iterate over.
+     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * function Foo() {
+     *   this.a = 1;
+     *   this.b = 2;
+     * }
+     *
+     * Foo.prototype.c = 3;
+     *
+     * _.forInRight(new Foo, function(value, key) {
+     *   console.log(key);
+     * });
+     * // => logs 'c', 'b', and 'a' assuming `_.forIn ` logs 'a', 'b', and 'c'
+     */
+    var forInRight = createForIn(baseForRight);
+
+    /**
+     * Iterates over own enumerable properties of an object invoking `iteratee`
+     * for each property. The `iteratee` is bound to `thisArg` and invoked with
+     * three arguments: (value, key, object). Iteratee functions may exit iteration
+     * early by explicitly returning `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The object to iterate over.
+     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * function Foo() {
+     *   this.a = 1;
+     *   this.b = 2;
+     * }
+     *
+     * Foo.prototype.c = 3;
+     *
+     * _.forOwn(new Foo, function(value, key) {
+     *   console.log(key);
+     * });
+     * // => logs 'a' and 'b' (iteration order is not guaranteed)
+     */
+    var forOwn = createForOwn(baseForOwn);
+
+    /**
+     * This method is like `_.forOwn` except that it iterates over properties of
+     * `object` in the opposite order.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The object to iterate over.
+     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * function Foo() {
+     *   this.a = 1;
+     *   this.b = 2;
+     * }
+     *
+     * Foo.prototype.c = 3;
+     *
+     * _.forOwnRight(new Foo, function(value, key) {
+     *   console.log(key);
+     * });
+     * // => logs 'b' and 'a' assuming `_.forOwn` logs 'a' and 'b'
+     */
+    var forOwnRight = createForOwn(baseForOwnRight);
+
+    /**
+     * Creates an array of function property names from all enumerable properties,
+     * own and inherited, of `object`.
+     *
+     * @static
+     * @memberOf _
+     * @alias methods
+     * @category Object
+     * @param {Object} object The object to inspect.
+     * @returns {Array} Returns the new array of property names.
+     * @example
+     *
+     * _.functions(_);
+     * // => ['after', 'ary', 'assign', ...]
+     */
+    function functions(object) {
+      return baseFunctions(object, keysIn(object));
+    }
+
+    /**
+     * Gets the property value of `path` on `object`. If the resolved value is
+     * `undefined` the `defaultValue` is used in its place.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The object to query.
+     * @param {Array|string} path The path of the property to get.
+     * @param {*} [defaultValue] The value returned if the resolved value is `undefined`.
+     * @returns {*} Returns the resolved value.
+     * @example
+     *
+     * var object = { 'a': [{ 'b': { 'c': 3 } }] };
+     *
+     * _.get(object, 'a[0].b.c');
+     * // => 3
+     *
+     * _.get(object, ['a', '0', 'b', 'c']);
+     * // => 3
+     *
+     * _.get(object, 'a.b.c', 'default');
+     * // => 'default'
+     */
+    function get(object, path, defaultValue) {
+      var result = object == null ? undefined : baseGet(object, toPath(path), path + '');
+      return result === undefined ? defaultValue : result;
+    }
+
+    /**
+     * Checks if `path` is a direct property.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The object to query.
+     * @param {Array|string} path The path to check.
+     * @returns {boolean} Returns `true` if `path` is a direct property, else `false`.
+     * @example
+     *
+     * var object = { 'a': { 'b': { 'c': 3 } } };
+     *
+     * _.has(object, 'a');
+     * // => true
+     *
+     * _.has(object, 'a.b.c');
+     * // => true
+     *
+     * _.has(object, ['a', 'b', 'c']);
+     * // => true
+     */
+    function has(object, path) {
+      if (object == null) {
+        return false;
+      }
+      var result = hasOwnProperty.call(object, path);
+      if (!result && !isKey(path)) {
+        path = toPath(path);
+        object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
+        path = last(path);
+        result = object != null && hasOwnProperty.call(object, path);
+      }
+      return result;
+    }
+
+    /**
+     * Creates an object composed of the inverted keys and values of `object`.
+     * If `object` contains duplicate values, subsequent values overwrite property
+     * assignments of previous values unless `multiValue` is `true`.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The object to invert.
+     * @param {boolean} [multiValue] Allow multiple values per key.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {Object} Returns the new inverted object.
+     * @example
+     *
+     * var object = { 'a': 1, 'b': 2, 'c': 1 };
+     *
+     * _.invert(object);
+     * // => { '1': 'c', '2': 'b' }
+     *
+     * // with `multiValue`
+     * _.invert(object, true);
+     * // => { '1': ['a', 'c'], '2': ['b'] }
+     */
+    function invert(object, multiValue, guard) {
+      if (guard && isIterateeCall(object, multiValue, guard)) {
+        multiValue = null;
+      }
+      var index = -1,
+          props = keys(object),
+          length = props.length,
+          result = {};
+
+      while (++index < length) {
+        var key = props[index],
+            value = object[key];
+
+        if (multiValue) {
+          if (hasOwnProperty.call(result, value)) {
+            result[value].push(key);
+          } else {
+            result[value] = [key];
+          }
+        }
+        else {
+          result[value] = key;
+        }
+      }
+      return result;
+    }
+
+    /**
+     * Creates an array of the own enumerable property names of `object`.
+     *
+     * **Note:** Non-object values are coerced to objects. See the
+     * [ES spec](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.keys)
+     * for more details.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The object to query.
+     * @returns {Array} Returns the array of property names.
+     * @example
+     *
+     * function Foo() {
+     *   this.a = 1;
+     *   this.b = 2;
+     * }
+     *
+     * Foo.prototype.c = 3;
+     *
+     * _.keys(new Foo);
+     * // => ['a', 'b'] (iteration order is not guaranteed)
+     *
+     * _.keys('hi');
+     * // => ['0', '1']
+     */
+    var keys = !nativeKeys ? shimKeys : function(object) {
+      if (object) {
+        var Ctor = object.constructor,
+            length = object.length;
+      }
+      if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
+          (typeof object != 'function' && isLength(length))) {
+        return shimKeys(object);
+      }
+      return isObject(object) ? nativeKeys(object) : [];
+    };
+
+    /**
+     * Creates an array of the own and inherited enumerable property names of `object`.
+     *
+     * **Note:** Non-object values are coerced to objects.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The object to query.
+     * @returns {Array} Returns the array of property names.
+     * @example
+     *
+     * function Foo() {
+     *   this.a = 1;
+     *   this.b = 2;
+     * }
+     *
+     * Foo.prototype.c = 3;
+     *
+     * _.keysIn(new Foo);
+     * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
+     */
+    function keysIn(object) {
+      if (object == null) {
+        return [];
+      }
+      if (!isObject(object)) {
+        object = Object(object);
+      }
+      var length = object.length;
+      length = (length && isLength(length) &&
+        (isArray(object) || (support.nonEnumArgs && isArguments(object))) && length) || 0;
+
+      var Ctor = object.constructor,
+          index = -1,
+          isProto = typeof Ctor == 'function' && Ctor.prototype === object,
+          result = Array(length),
+          skipIndexes = length > 0;
+
+      while (++index < length) {
+        result[index] = (index + '');
+      }
+      for (var key in object) {
+        if (!(skipIndexes && isIndex(key, length)) &&
+            !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
+          result.push(key);
+        }
+      }
+      return result;
+    }
+
+    /**
+     * Creates an object with the same keys as `object` and values generated by
+     * running each own enumerable property of `object` through `iteratee`. The
+     * iteratee function is bound to `thisArg` and invoked with three arguments:
+     * (value, key, object).
+     *
+     * If a property name is provided for `iteratee` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `iteratee` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The object to iterate over.
+     * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+     *  per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {Object} Returns the new mapped object.
+     * @example
+     *
+     * _.mapValues({ 'a': 1, 'b': 2 }, function(n) {
+     *   return n * 3;
+     * });
+     * // => { 'a': 3, 'b': 6 }
+     *
+     * var users = {
+     *   'fred':    { 'user': 'fred',    'age': 40 },
+     *   'pebbles': { 'user': 'pebbles', 'age': 1 }
+     * };
+     *
+     * // using the `_.property` callback shorthand
+     * _.mapValues(users, 'age');
+     * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
+     */
+    function mapValues(object, iteratee, thisArg) {
+      var result = {};
+      iteratee = getCallback(iteratee, thisArg, 3);
+
+      baseForOwn(object, function(value, key, object) {
+        result[key] = iteratee(value, key, object);
+      });
+      return result;
+    }
+
+    /**
+     * Recursively merges own enumerable properties of the source object(s), that
+     * don't resolve to `undefined` into the destination object. Subsequent sources
+     * overwrite property assignments of previous sources. If `customizer` is
+     * provided it is invoked to produce the merged values of the destination and
+     * source properties. If `customizer` returns `undefined` merging is handled
+     * by the method instead. The `customizer` is bound to `thisArg` and invoked
+     * with five arguments: (objectValue, sourceValue, key, object, source).
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The destination object.
+     * @param {...Object} [sources] The source objects.
+     * @param {Function} [customizer] The function to customize assigned values.
+     * @param {*} [thisArg] The `this` binding of `customizer`.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * var users = {
+     *   'data': [{ 'user': 'barney' }, { 'user': 'fred' }]
+     * };
+     *
+     * var ages = {
+     *   'data': [{ 'age': 36 }, { 'age': 40 }]
+     * };
+     *
+     * _.merge(users, ages);
+     * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] }
+     *
+     * // using a customizer callback
+     * var object = {
+     *   'fruits': ['apple'],
+     *   'vegetables': ['beet']
+     * };
+     *
+     * var other = {
+     *   'fruits': ['banana'],
+     *   'vegetables': ['carrot']
+     * };
+     *
+     * _.merge(object, other, function(a, b) {
+     *   if (_.isArray(a)) {
+     *     return a.concat(b);
+     *   }
+     * });
+     * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] }
+     */
+    var merge = createAssigner(baseMerge);
+
+    /**
+     * The opposite of `_.pick`; this method creates an object composed of the
+     * own and inherited enumerable properties of `object` that are not omitted.
+     * Property names may be specified as individual arguments or as arrays of
+     * property names. If `predicate` is provided it is invoked for each property
+     * of `object` omitting the properties `predicate` returns truthy for. The
+     * predicate is bound to `thisArg` and invoked with three arguments:
+     * (value, key, object).
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The source object.
+     * @param {Function|...(string|string[])} [predicate] The function invoked per
+     *  iteration or property names to omit, specified as individual property
+     *  names or arrays of property names.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {Object} Returns the new object.
+     * @example
+     *
+     * var object = { 'user': 'fred', 'age': 40 };
+     *
+     * _.omit(object, 'age');
+     * // => { 'user': 'fred' }
+     *
+     * _.omit(object, _.isNumber);
+     * // => { 'user': 'fred' }
+     */
+    var omit = restParam(function(object, props) {
+      if (object == null) {
+        return {};
+      }
+      if (typeof props[0] != 'function') {
+        var props = arrayMap(baseFlatten(props), String);
+        return pickByArray(object, baseDifference(keysIn(object), props));
+      }
+      var predicate = bindCallback(props[0], props[1], 3);
+      return pickByCallback(object, function(value, key, object) {
+        return !predicate(value, key, object);
+      });
+    });
+
+    /**
+     * Creates a two dimensional array of the key-value pairs for `object`,
+     * e.g. `[[key1, value1], [key2, value2]]`.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The object to query.
+     * @returns {Array} Returns the new array of key-value pairs.
+     * @example
+     *
+     * _.pairs({ 'barney': 36, 'fred': 40 });
+     * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed)
+     */
+    function pairs(object) {
+      var index = -1,
+          props = keys(object),
+          length = props.length,
+          result = Array(length);
+
+      while (++index < length) {
+        var key = props[index];
+        result[index] = [key, object[key]];
+      }
+      return result;
+    }
+
+    /**
+     * Creates an object composed of the picked `object` properties. Property
+     * names may be specified as individual arguments or as arrays of property
+     * names. If `predicate` is provided it is invoked for each property of `object`
+     * picking the properties `predicate` returns truthy for. The predicate is
+     * bound to `thisArg` and invoked with three arguments: (value, key, object).
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The source object.
+     * @param {Function|...(string|string[])} [predicate] The function invoked per
+     *  iteration or property names to pick, specified as individual property
+     *  names or arrays of property names.
+     * @param {*} [thisArg] The `this` binding of `predicate`.
+     * @returns {Object} Returns the new object.
+     * @example
+     *
+     * var object = { 'user': 'fred', 'age': 40 };
+     *
+     * _.pick(object, 'user');
+     * // => { 'user': 'fred' }
+     *
+     * _.pick(object, _.isString);
+     * // => { 'user': 'fred' }
+     */
+    var pick = restParam(function(object, props) {
+      if (object == null) {
+        return {};
+      }
+      return typeof props[0] == 'function'
+        ? pickByCallback(object, bindCallback(props[0], props[1], 3))
+        : pickByArray(object, baseFlatten(props));
+    });
+
+    /**
+     * This method is like `_.get` except that if the resolved value is a function
+     * it is invoked with the `this` binding of its parent object and its result
+     * is returned.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The object to query.
+     * @param {Array|string} path The path of the property to resolve.
+     * @param {*} [defaultValue] The value returned if the resolved value is `undefined`.
+     * @returns {*} Returns the resolved value.
+     * @example
+     *
+     * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
+     *
+     * _.result(object, 'a[0].b.c1');
+     * // => 3
+     *
+     * _.result(object, 'a[0].b.c2');
+     * // => 4
+     *
+     * _.result(object, 'a.b.c', 'default');
+     * // => 'default'
+     *
+     * _.result(object, 'a.b.c', _.constant('default'));
+     * // => 'default'
+     */
+    function result(object, path, defaultValue) {
+      var result = object == null ? undefined : object[path];
+      if (result === undefined) {
+        if (object != null && !isKey(path, object)) {
+          path = toPath(path);
+          object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
+          result = object == null ? undefined : object[last(path)];
+        }
+        result = result === undefined ? defaultValue : result;
+      }
+      return isFunction(result) ? result.call(object) : result;
+    }
+
+    /**
+     * Sets the property value of `path` on `object`. If a portion of `path`
+     * does not exist it is created.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The object to augment.
+     * @param {Array|string} path The path of the property to set.
+     * @param {*} value The value to set.
+     * @returns {Object} Returns `object`.
+     * @example
+     *
+     * var object = { 'a': [{ 'b': { 'c': 3 } }] };
+     *
+     * _.set(object, 'a[0].b.c', 4);
+     * console.log(object.a[0].b.c);
+     * // => 4
+     *
+     * _.set(object, 'x[0].y.z', 5);
+     * console.log(object.x[0].y.z);
+     * // => 5
+     */
+    function set(object, path, value) {
+      if (object == null) {
+        return object;
+      }
+      var pathKey = (path + '');
+      path = (object[pathKey] != null || isKey(path, object)) ? [pathKey] : toPath(path);
+
+      var index = -1,
+          length = path.length,
+          endIndex = length - 1,
+          nested = object;
+
+      while (nested != null && ++index < length) {
+        var key = path[index];
+        if (isObject(nested)) {
+          if (index == endIndex) {
+            nested[key] = value;
+          } else if (nested[key] == null) {
+            nested[key] = isIndex(path[index + 1]) ? [] : {};
+          }
+        }
+        nested = nested[key];
+      }
+      return object;
+    }
+
+    /**
+     * An alternative to `_.reduce`; this method transforms `object` to a new
+     * `accumulator` object which is the result of running each of its own enumerable
+     * properties through `iteratee`, with each invocation potentially mutating
+     * the `accumulator` object. The `iteratee` is bound to `thisArg` and invoked
+     * with four arguments: (accumulator, value, key, object). Iteratee functions
+     * may exit iteration early by explicitly returning `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Array|Object} object The object to iterate over.
+     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+     * @param {*} [accumulator] The custom accumulator value.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {*} Returns the accumulated value.
+     * @example
+     *
+     * _.transform([2, 3, 4], function(result, n) {
+     *   result.push(n *= n);
+     *   return n % 2 == 0;
+     * });
+     * // => [4, 9]
+     *
+     * _.transform({ 'a': 1, 'b': 2 }, function(result, n, key) {
+     *   result[key] = n * 3;
+     * });
+     * // => { 'a': 3, 'b': 6 }
+     */
+    function transform(object, iteratee, accumulator, thisArg) {
+      var isArr = isArray(object) || isTypedArray(object);
+      iteratee = getCallback(iteratee, thisArg, 4);
+
+      if (accumulator == null) {
+        if (isArr || isObject(object)) {
+          var Ctor = object.constructor;
+          if (isArr) {
+            accumulator = isArray(object) ? new Ctor : [];
+          } else {
+            accumulator = baseCreate(isFunction(Ctor) && Ctor.prototype);
+          }
+        } else {
+          accumulator = {};
+        }
+      }
+      (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) {
+        return iteratee(accumulator, value, index, object);
+      });
+      return accumulator;
+    }
+
+    /**
+     * Creates an array of the own enumerable property values of `object`.
+     *
+     * **Note:** Non-object values are coerced to objects.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The object to query.
+     * @returns {Array} Returns the array of property values.
+     * @example
+     *
+     * function Foo() {
+     *   this.a = 1;
+     *   this.b = 2;
+     * }
+     *
+     * Foo.prototype.c = 3;
+     *
+     * _.values(new Foo);
+     * // => [1, 2] (iteration order is not guaranteed)
+     *
+     * _.values('hi');
+     * // => ['h', 'i']
+     */
+    function values(object) {
+      return baseValues(object, keys(object));
+    }
+
+    /**
+     * Creates an array of the own and inherited enumerable property values
+     * of `object`.
+     *
+     * **Note:** Non-object values are coerced to objects.
+     *
+     * @static
+     * @memberOf _
+     * @category Object
+     * @param {Object} object The object to query.
+     * @returns {Array} Returns the array of property values.
+     * @example
+     *
+     * function Foo() {
+     *   this.a = 1;
+     *   this.b = 2;
+     * }
+     *
+     * Foo.prototype.c = 3;
+     *
+     * _.valuesIn(new Foo);
+     * // => [1, 2, 3] (iteration order is not guaranteed)
+     */
+    function valuesIn(object) {
+      return baseValues(object, keysIn(object));
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * Checks if `n` is between `start` and up to but not including, `end`. If
+     * `end` is not specified it is set to `start` with `start` then set to `0`.
+     *
+     * @static
+     * @memberOf _
+     * @category Number
+     * @param {number} n The number to check.
+     * @param {number} [start=0] The start of the range.
+     * @param {number} end The end of the range.
+     * @returns {boolean} Returns `true` if `n` is in the range, else `false`.
+     * @example
+     *
+     * _.inRange(3, 2, 4);
+     * // => true
+     *
+     * _.inRange(4, 8);
+     * // => true
+     *
+     * _.inRange(4, 2);
+     * // => false
+     *
+     * _.inRange(2, 2);
+     * // => false
+     *
+     * _.inRange(1.2, 2);
+     * // => true
+     *
+     * _.inRange(5.2, 4);
+     * // => false
+     */
+    function inRange(value, start, end) {
+      start = +start || 0;
+      if (typeof end === 'undefined') {
+        end = start;
+        start = 0;
+      } else {
+        end = +end || 0;
+      }
+      return value >= nativeMin(start, end) && value < nativeMax(start, end);
+    }
+
+    /**
+     * Produces a random number between `min` and `max` (inclusive). If only one
+     * argument is provided a number between `0` and the given number is returned.
+     * If `floating` is `true`, or either `min` or `max` are floats, a floating-point
+     * number is returned instead of an integer.
+     *
+     * @static
+     * @memberOf _
+     * @category Number
+     * @param {number} [min=0] The minimum possible value.
+     * @param {number} [max=1] The maximum possible value.
+     * @param {boolean} [floating] Specify returning a floating-point number.
+     * @returns {number} Returns the random number.
+     * @example
+     *
+     * _.random(0, 5);
+     * // => an integer between 0 and 5
+     *
+     * _.random(5);
+     * // => also an integer between 0 and 5
+     *
+     * _.random(5, true);
+     * // => a floating-point number between 0 and 5
+     *
+     * _.random(1.2, 5.2);
+     * // => a floating-point number between 1.2 and 5.2
+     */
+    function random(min, max, floating) {
+      if (floating && isIterateeCall(min, max, floating)) {
+        max = floating = null;
+      }
+      var noMin = min == null,
+          noMax = max == null;
+
+      if (floating == null) {
+        if (noMax && typeof min == 'boolean') {
+          floating = min;
+          min = 1;
+        }
+        else if (typeof max == 'boolean') {
+          floating = max;
+          noMax = true;
+        }
+      }
+      if (noMin && noMax) {
+        max = 1;
+        noMax = false;
+      }
+      min = +min || 0;
+      if (noMax) {
+        max = min;
+        min = 0;
+      } else {
+        max = +max || 0;
+      }
+      if (floating || min % 1 || max % 1) {
+        var rand = nativeRandom();
+        return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand + '').length - 1)))), max);
+      }
+      return baseRandom(min, max);
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to convert.
+     * @returns {string} Returns the camel cased string.
+     * @example
+     *
+     * _.camelCase('Foo Bar');
+     * // => 'fooBar'
+     *
+     * _.camelCase('--foo-bar');
+     * // => 'fooBar'
+     *
+     * _.camelCase('__foo_bar__');
+     * // => 'fooBar'
+     */
+    var camelCase = createCompounder(function(result, word, index) {
+      word = word.toLowerCase();
+      return result + (index ? (word.charAt(0).toUpperCase() + word.slice(1)) : word);
+    });
+
+    /**
+     * Capitalizes the first character of `string`.
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to capitalize.
+     * @returns {string} Returns the capitalized string.
+     * @example
+     *
+     * _.capitalize('fred');
+     * // => 'Fred'
+     */
+    function capitalize(string) {
+      string = baseToString(string);
+      return string && (string.charAt(0).toUpperCase() + string.slice(1));
+    }
+
+    /**
+     * Deburrs `string` by converting [latin-1 supplementary letters](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
+     * to basic latin letters and removing [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to deburr.
+     * @returns {string} Returns the deburred string.
+     * @example
+     *
+     * _.deburr('déjà vu');
+     * // => 'deja vu'
+     */
+    function deburr(string) {
+      string = baseToString(string);
+      return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, '');
+    }
+
+    /**
+     * Checks if `string` ends with the given target string.
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to search.
+     * @param {string} [target] The string to search for.
+     * @param {number} [position=string.length] The position to search from.
+     * @returns {boolean} Returns `true` if `string` ends with `target`, else `false`.
+     * @example
+     *
+     * _.endsWith('abc', 'c');
+     * // => true
+     *
+     * _.endsWith('abc', 'b');
+     * // => false
+     *
+     * _.endsWith('abc', 'b', 2);
+     * // => true
+     */
+    function endsWith(string, target, position) {
+      string = baseToString(string);
+      target = (target + '');
+
+      var length = string.length;
+      position = position === undefined
+        ? length
+        : nativeMin(position < 0 ? 0 : (+position || 0), length);
+
+      position -= target.length;
+      return position >= 0 && string.indexOf(target, position) == position;
+    }
+
+    /**
+     * Converts the characters "&", "<", ">", '"', "'", and "\`", in `string` to
+     * their corresponding HTML entities.
+     *
+     * **Note:** No other characters are escaped. To escape additional characters
+     * use a third-party library like [_he_](https://mths.be/he).
+     *
+     * Though the ">" character is escaped for symmetry, characters like
+     * ">" and "/" don't require escaping in HTML and have no special meaning
+     * unless they're part of a tag or unquoted attribute value.
+     * See [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
+     * (under "semi-related fun fact") for more details.
+     *
+     * Backticks are escaped because in Internet Explorer < 9, they can break out
+     * of attribute values or HTML comments. See [#59](https://html5sec.org/#59),
+     * [#102](https://html5sec.org/#102), [#108](https://html5sec.org/#108), and
+     * [#133](https://html5sec.org/#133) of the [HTML5 Security Cheatsheet](https://html5sec.org/)
+     * for more details.
+     *
+     * When working with HTML you should always [quote attribute values](http://wonko.com/post/html-escaping)
+     * to reduce XSS vectors.
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to escape.
+     * @returns {string} Returns the escaped string.
+     * @example
+     *
+     * _.escape('fred, barney, & pebbles');
+     * // => 'fred, barney, &amp; pebbles'
+     */
+    function escape(string) {
+      // Reset `lastIndex` because in IE < 9 `String#replace` does not.
+      string = baseToString(string);
+      return (string && reHasUnescapedHtml.test(string))
+        ? string.replace(reUnescapedHtml, escapeHtmlChar)
+        : string;
+    }
+
+    /**
+     * Escapes the `RegExp` special characters "\", "/", "^", "$", ".", "|", "?",
+     * "*", "+", "(", ")", "[", "]", "{" and "}" in `string`.
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to escape.
+     * @returns {string} Returns the escaped string.
+     * @example
+     *
+     * _.escapeRegExp('[lodash](https://lodash.com/)');
+     * // => '\[lodash\]\(https:\/\/lodash\.com\/\)'
+     */
+    function escapeRegExp(string) {
+      string = baseToString(string);
+      return (string && reHasRegExpChars.test(string))
+        ? string.replace(reRegExpChars, '\\$&')
+        : string;
+    }
+
+    /**
+     * Converts `string` to [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to convert.
+     * @returns {string} Returns the kebab cased string.
+     * @example
+     *
+     * _.kebabCase('Foo Bar');
+     * // => 'foo-bar'
+     *
+     * _.kebabCase('fooBar');
+     * // => 'foo-bar'
+     *
+     * _.kebabCase('__foo_bar__');
+     * // => 'foo-bar'
+     */
+    var kebabCase = createCompounder(function(result, word, index) {
+      return result + (index ? '-' : '') + word.toLowerCase();
+    });
+
+    /**
+     * Pads `string` on the left and right sides if it is shorter than `length`.
+     * Padding characters are truncated if they can't be evenly divided by `length`.
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to pad.
+     * @param {number} [length=0] The padding length.
+     * @param {string} [chars=' '] The string used as padding.
+     * @returns {string} Returns the padded string.
+     * @example
+     *
+     * _.pad('abc', 8);
+     * // => '  abc   '
+     *
+     * _.pad('abc', 8, '_-');
+     * // => '_-abc_-_'
+     *
+     * _.pad('abc', 3);
+     * // => 'abc'
+     */
+    function pad(string, length, chars) {
+      string = baseToString(string);
+      length = +length;
+
+      var strLength = string.length;
+      if (strLength >= length || !nativeIsFinite(length)) {
+        return string;
+      }
+      var mid = (length - strLength) / 2,
+          leftLength = floor(mid),
+          rightLength = ceil(mid);
+
+      chars = createPadding('', rightLength, chars);
+      return chars.slice(0, leftLength) + string + chars;
+    }
+
+    /**
+     * Pads `string` on the left side if it is shorter than `length`. Padding
+     * characters are truncated if they exceed `length`.
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to pad.
+     * @param {number} [length=0] The padding length.
+     * @param {string} [chars=' '] The string used as padding.
+     * @returns {string} Returns the padded string.
+     * @example
+     *
+     * _.padLeft('abc', 6);
+     * // => '   abc'
+     *
+     * _.padLeft('abc', 6, '_-');
+     * // => '_-_abc'
+     *
+     * _.padLeft('abc', 3);
+     * // => 'abc'
+     */
+    var padLeft = createPadDir();
+
+    /**
+     * Pads `string` on the right side if it is shorter than `length`. Padding
+     * characters are truncated if they exceed `length`.
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to pad.
+     * @param {number} [length=0] The padding length.
+     * @param {string} [chars=' '] The string used as padding.
+     * @returns {string} Returns the padded string.
+     * @example
+     *
+     * _.padRight('abc', 6);
+     * // => 'abc   '
+     *
+     * _.padRight('abc', 6, '_-');
+     * // => 'abc_-_'
+     *
+     * _.padRight('abc', 3);
+     * // => 'abc'
+     */
+    var padRight = createPadDir(true);
+
+    /**
+     * Converts `string` to an integer of the specified radix. If `radix` is
+     * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal,
+     * in which case a `radix` of `16` is used.
+     *
+     * **Note:** This method aligns with the [ES5 implementation](https://es5.github.io/#E)
+     * of `parseInt`.
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} string The string to convert.
+     * @param {number} [radix] The radix to interpret `value` by.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {number} Returns the converted integer.
+     * @example
+     *
+     * _.parseInt('08');
+     * // => 8
+     *
+     * _.map(['6', '08', '10'], _.parseInt);
+     * // => [6, 8, 10]
+     */
+    function parseInt(string, radix, guard) {
+      if (guard && isIterateeCall(string, radix, guard)) {
+        radix = 0;
+      }
+      return nativeParseInt(string, radix);
+    }
+    // Fallback for environments with pre-ES5 implementations.
+    if (nativeParseInt(whitespace + '08') != 8) {
+      parseInt = function(string, radix, guard) {
+        // Firefox < 21 and Opera < 15 follow ES3 for `parseInt`.
+        // Chrome fails to trim leading <BOM> whitespace characters.
+        // See https://code.google.com/p/v8/issues/detail?id=3109 for more details.
+        if (guard ? isIterateeCall(string, radix, guard) : radix == null) {
+          radix = 0;
+        } else if (radix) {
+          radix = +radix;
+        }
+        string = trim(string);
+        return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10));
+      };
+    }
+
+    /**
+     * Repeats the given string `n` times.
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to repeat.
+     * @param {number} [n=0] The number of times to repeat the string.
+     * @returns {string} Returns the repeated string.
+     * @example
+     *
+     * _.repeat('*', 3);
+     * // => '***'
+     *
+     * _.repeat('abc', 2);
+     * // => 'abcabc'
+     *
+     * _.repeat('abc', 0);
+     * // => ''
+     */
+    function repeat(string, n) {
+      var result = '';
+      string = baseToString(string);
+      n = +n;
+      if (n < 1 || !string || !nativeIsFinite(n)) {
+        return result;
+      }
+      // Leverage the exponentiation by squaring algorithm for a faster repeat.
+      // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
+      do {
+        if (n % 2) {
+          result += string;
+        }
+        n = floor(n / 2);
+        string += string;
+      } while (n);
+
+      return result;
+    }
+
+    /**
+     * Converts `string` to [snake case](https://en.wikipedia.org/wiki/Snake_case).
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to convert.
+     * @returns {string} Returns the snake cased string.
+     * @example
+     *
+     * _.snakeCase('Foo Bar');
+     * // => 'foo_bar'
+     *
+     * _.snakeCase('fooBar');
+     * // => 'foo_bar'
+     *
+     * _.snakeCase('--foo-bar');
+     * // => 'foo_bar'
+     */
+    var snakeCase = createCompounder(function(result, word, index) {
+      return result + (index ? '_' : '') + word.toLowerCase();
+    });
+
+    /**
+     * Converts `string` to [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to convert.
+     * @returns {string} Returns the start cased string.
+     * @example
+     *
+     * _.startCase('--foo-bar');
+     * // => 'Foo Bar'
+     *
+     * _.startCase('fooBar');
+     * // => 'Foo Bar'
+     *
+     * _.startCase('__foo_bar__');
+     * // => 'Foo Bar'
+     */
+    var startCase = createCompounder(function(result, word, index) {
+      return result + (index ? ' ' : '') + (word.charAt(0).toUpperCase() + word.slice(1));
+    });
+
+    /**
+     * Checks if `string` starts with the given target string.
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to search.
+     * @param {string} [target] The string to search for.
+     * @param {number} [position=0] The position to search from.
+     * @returns {boolean} Returns `true` if `string` starts with `target`, else `false`.
+     * @example
+     *
+     * _.startsWith('abc', 'a');
+     * // => true
+     *
+     * _.startsWith('abc', 'b');
+     * // => false
+     *
+     * _.startsWith('abc', 'b', 1);
+     * // => true
+     */
+    function startsWith(string, target, position) {
+      string = baseToString(string);
+      position = position == null
+        ? 0
+        : nativeMin(position < 0 ? 0 : (+position || 0), string.length);
+
+      return string.lastIndexOf(target, position) == position;
+    }
+
+    /**
+     * Creates a compiled template function that can interpolate data properties
+     * in "interpolate" delimiters, HTML-escape interpolated data properties in
+     * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
+     * properties may be accessed as free variables in the template. If a setting
+     * object is provided it takes precedence over `_.templateSettings` values.
+     *
+     * **Note:** In the development build `_.template` utilizes
+     * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
+     * for easier debugging.
+     *
+     * For more information on precompiling templates see
+     * [lodash's custom builds documentation](https://lodash.com/custom-builds).
+     *
+     * For more information on Chrome extension sandboxes see
+     * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The template string.
+     * @param {Object} [options] The options object.
+     * @param {RegExp} [options.escape] The HTML "escape" delimiter.
+     * @param {RegExp} [options.evaluate] The "evaluate" delimiter.
+     * @param {Object} [options.imports] An object to import into the template as free variables.
+     * @param {RegExp} [options.interpolate] The "interpolate" delimiter.
+     * @param {string} [options.sourceURL] The sourceURL of the template's compiled source.
+     * @param {string} [options.variable] The data object variable name.
+     * @param- {Object} [otherOptions] Enables the legacy `options` param signature.
+     * @returns {Function} Returns the compiled template function.
+     * @example
+     *
+     * // using the "interpolate" delimiter to create a compiled template
+     * var compiled = _.template('hello <%= user %>!');
+     * compiled({ 'user': 'fred' });
+     * // => 'hello fred!'
+     *
+     * // using the HTML "escape" delimiter to escape data property values
+     * var compiled = _.template('<b><%- value %></b>');
+     * compiled({ 'value': '<script>' });
+     * // => '<b>&lt;script&gt;</b>'
+     *
+     * // using the "evaluate" delimiter to execute JavaScript and generate HTML
+     * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
+     * compiled({ 'users': ['fred', 'barney'] });
+     * // => '<li>fred</li><li>barney</li>'
+     *
+     * // using the internal `print` function in "evaluate" delimiters
+     * var compiled = _.template('<% print("hello " + user); %>!');
+     * compiled({ 'user': 'barney' });
+     * // => 'hello barney!'
+     *
+     * // using the ES delimiter as an alternative to the default "interpolate" delimiter
+     * var compiled = _.template('hello ${ user }!');
+     * compiled({ 'user': 'pebbles' });
+     * // => 'hello pebbles!'
+     *
+     * // using custom template delimiters
+     * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
+     * var compiled = _.template('hello {{ user }}!');
+     * compiled({ 'user': 'mustache' });
+     * // => 'hello mustache!'
+     *
+     * // using backslashes to treat delimiters as plain text
+     * var compiled = _.template('<%= "\\<%- value %\\>" %>');
+     * compiled({ 'value': 'ignored' });
+     * // => '<%- value %>'
+     *
+     * // using the `imports` option to import `jQuery` as `jq`
+     * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
+     * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
+     * compiled({ 'users': ['fred', 'barney'] });
+     * // => '<li>fred</li><li>barney</li>'
+     *
+     * // using the `sourceURL` option to specify a custom sourceURL for the template
+     * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
+     * compiled(data);
+     * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
+     *
+     * // using the `variable` option to ensure a with-statement isn't used in the compiled template
+     * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
+     * compiled.source;
+     * // => function(data) {
+     * //   var __t, __p = '';
+     * //   __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
+     * //   return __p;
+     * // }
+     *
+     * // using the `source` property to inline compiled templates for meaningful
+     * // line numbers in error messages and a stack trace
+     * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
+     *   var JST = {\
+     *     "main": ' + _.template(mainText).source + '\
+     *   };\
+     * ');
+     */
+    function template(string, options, otherOptions) {
+      // Based on John Resig's `tmpl` implementation (http://ejohn.org/blog/javascript-micro-templating/)
+      // and Laura Doktorova's doT.js (https://github.com/olado/doT).
+      var settings = lodash.templateSettings;
+
+      if (otherOptions && isIterateeCall(string, options, otherOptions)) {
+        options = otherOptions = null;
+      }
+      string = baseToString(string);
+      options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults);
+
+      var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults),
+          importsKeys = keys(imports),
+          importsValues = baseValues(imports, importsKeys);
+
+      var isEscaping,
+          isEvaluating,
+          index = 0,
+          interpolate = options.interpolate || reNoMatch,
+          source = "__p += '";
+
+      // Compile the regexp to match each delimiter.
+      var reDelimiters = RegExp(
+        (options.escape || reNoMatch).source + '|' +
+        interpolate.source + '|' +
+        (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
+        (options.evaluate || reNoMatch).source + '|$'
+      , 'g');
+
+      // Use a sourceURL for easier debugging.
+      var sourceURL = '//# sourceURL=' +
+        ('sourceURL' in options
+          ? options.sourceURL
+          : ('lodash.templateSources[' + (++templateCounter) + ']')
+        ) + '\n';
+
+      string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
+        interpolateValue || (interpolateValue = esTemplateValue);
+
+        // Escape characters that can't be included in string literals.
+        source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
+
+        // Replace delimiters with snippets.
+        if (escapeValue) {
+          isEscaping = true;
+          source += "' +\n__e(" + escapeValue + ") +\n'";
+        }
+        if (evaluateValue) {
+          isEvaluating = true;
+          source += "';\n" + evaluateValue + ";\n__p += '";
+        }
+        if (interpolateValue) {
+          source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
+        }
+        index = offset + match.length;
+
+        // The JS engine embedded in Adobe products requires returning the `match`
+        // string in order to produce the correct `offset` value.
+        return match;
+      });
+
+      source += "';\n";
+
+      // If `variable` is not specified wrap a with-statement around the generated
+      // code to add the data object to the top of the scope chain.
+      var variable = options.variable;
+      if (!variable) {
+        source = 'with (obj) {\n' + source + '\n}\n';
+      }
+      // Cleanup code by stripping empty strings.
+      source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
+        .replace(reEmptyStringMiddle, '$1')
+        .replace(reEmptyStringTrailing, '$1;');
+
+      // Frame code as the function body.
+      source = 'function(' + (variable || 'obj') + ') {\n' +
+        (variable
+          ? ''
+          : 'obj || (obj = {});\n'
+        ) +
+        "var __t, __p = ''" +
+        (isEscaping
+           ? ', __e = _.escape'
+           : ''
+        ) +
+        (isEvaluating
+          ? ', __j = Array.prototype.join;\n' +
+            "function print() { __p += __j.call(arguments, '') }\n"
+          : ';\n'
+        ) +
+        source +
+        'return __p\n}';
+
+      var result = attempt(function() {
+        return Function(importsKeys, sourceURL + 'return ' + source).apply(undefined, importsValues);
+      });
+
+      // Provide the compiled function's source by its `toString` method or
+      // the `source` property as a convenience for inlining compiled templates.
+      result.source = source;
+      if (isError(result)) {
+        throw result;
+      }
+      return result;
+    }
+
+    /**
+     * Removes leading and trailing whitespace or specified characters from `string`.
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to trim.
+     * @param {string} [chars=whitespace] The characters to trim.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {string} Returns the trimmed string.
+     * @example
+     *
+     * _.trim('  abc  ');
+     * // => 'abc'
+     *
+     * _.trim('-_-abc-_-', '_-');
+     * // => 'abc'
+     *
+     * _.map(['  foo  ', '  bar  '], _.trim);
+     * // => ['foo', 'bar']
+     */
+    function trim(string, chars, guard) {
+      var value = string;
+      string = baseToString(string);
+      if (!string) {
+        return string;
+      }
+      if (guard ? isIterateeCall(value, chars, guard) : chars == null) {
+        return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1);
+      }
+      chars = (chars + '');
+      return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1);
+    }
+
+    /**
+     * Removes leading whitespace or specified characters from `string`.
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to trim.
+     * @param {string} [chars=whitespace] The characters to trim.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {string} Returns the trimmed string.
+     * @example
+     *
+     * _.trimLeft('  abc  ');
+     * // => 'abc  '
+     *
+     * _.trimLeft('-_-abc-_-', '_-');
+     * // => 'abc-_-'
+     */
+    function trimLeft(string, chars, guard) {
+      var value = string;
+      string = baseToString(string);
+      if (!string) {
+        return string;
+      }
+      if (guard ? isIterateeCall(value, chars, guard) : chars == null) {
+        return string.slice(trimmedLeftIndex(string));
+      }
+      return string.slice(charsLeftIndex(string, (chars + '')));
+    }
+
+    /**
+     * Removes trailing whitespace or specified characters from `string`.
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to trim.
+     * @param {string} [chars=whitespace] The characters to trim.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {string} Returns the trimmed string.
+     * @example
+     *
+     * _.trimRight('  abc  ');
+     * // => '  abc'
+     *
+     * _.trimRight('-_-abc-_-', '_-');
+     * // => '-_-abc'
+     */
+    function trimRight(string, chars, guard) {
+      var value = string;
+      string = baseToString(string);
+      if (!string) {
+        return string;
+      }
+      if (guard ? isIterateeCall(value, chars, guard) : chars == null) {
+        return string.slice(0, trimmedRightIndex(string) + 1);
+      }
+      return string.slice(0, charsRightIndex(string, (chars + '')) + 1);
+    }
+
+    /**
+     * Truncates `string` if it is longer than the given maximum string length.
+     * The last characters of the truncated string are replaced with the omission
+     * string which defaults to "...".
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to truncate.
+     * @param {Object|number} [options] The options object or maximum string length.
+     * @param {number} [options.length=30] The maximum string length.
+     * @param {string} [options.omission='...'] The string to indicate text is omitted.
+     * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {string} Returns the truncated string.
+     * @example
+     *
+     * _.trunc('hi-diddly-ho there, neighborino');
+     * // => 'hi-diddly-ho there, neighbo...'
+     *
+     * _.trunc('hi-diddly-ho there, neighborino', 24);
+     * // => 'hi-diddly-ho there, n...'
+     *
+     * _.trunc('hi-diddly-ho there, neighborino', {
+     *   'length': 24,
+     *   'separator': ' '
+     * });
+     * // => 'hi-diddly-ho there,...'
+     *
+     * _.trunc('hi-diddly-ho there, neighborino', {
+     *   'length': 24,
+     *   'separator': /,? +/
+     * });
+     * // => 'hi-diddly-ho there...'
+     *
+     * _.trunc('hi-diddly-ho there, neighborino', {
+     *   'omission': ' [...]'
+     * });
+     * // => 'hi-diddly-ho there, neig [...]'
+     */
+    function trunc(string, options, guard) {
+      if (guard && isIterateeCall(string, options, guard)) {
+        options = null;
+      }
+      var length = DEFAULT_TRUNC_LENGTH,
+          omission = DEFAULT_TRUNC_OMISSION;
+
+      if (options != null) {
+        if (isObject(options)) {
+          var separator = 'separator' in options ? options.separator : separator;
+          length = 'length' in options ? (+options.length || 0) : length;
+          omission = 'omission' in options ? baseToString(options.omission) : omission;
+        } else {
+          length = +options || 0;
+        }
+      }
+      string = baseToString(string);
+      if (length >= string.length) {
+        return string;
+      }
+      var end = length - omission.length;
+      if (end < 1) {
+        return omission;
+      }
+      var result = string.slice(0, end);
+      if (separator == null) {
+        return result + omission;
+      }
+      if (isRegExp(separator)) {
+        if (string.slice(end).search(separator)) {
+          var match,
+              newEnd,
+              substring = string.slice(0, end);
+
+          if (!separator.global) {
+            separator = RegExp(separator.source, (reFlags.exec(separator) || '') + 'g');
+          }
+          separator.lastIndex = 0;
+          while ((match = separator.exec(substring))) {
+            newEnd = match.index;
+          }
+          result = result.slice(0, newEnd == null ? end : newEnd);
+        }
+      } else if (string.indexOf(separator, end) != end) {
+        var index = result.lastIndexOf(separator);
+        if (index > -1) {
+          result = result.slice(0, index);
+        }
+      }
+      return result + omission;
+    }
+
+    /**
+     * The inverse of `_.escape`; this method converts the HTML entities
+     * `&amp;`, `&lt;`, `&gt;`, `&quot;`, `&#39;`, and `&#96;` in `string` to their
+     * corresponding characters.
+     *
+     * **Note:** No other HTML entities are unescaped. To unescape additional HTML
+     * entities use a third-party library like [_he_](https://mths.be/he).
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to unescape.
+     * @returns {string} Returns the unescaped string.
+     * @example
+     *
+     * _.unescape('fred, barney, &amp; pebbles');
+     * // => 'fred, barney, & pebbles'
+     */
+    function unescape(string) {
+      string = baseToString(string);
+      return (string && reHasEscapedHtml.test(string))
+        ? string.replace(reEscapedHtml, unescapeHtmlChar)
+        : string;
+    }
+
+    /**
+     * Splits `string` into an array of its words.
+     *
+     * @static
+     * @memberOf _
+     * @category String
+     * @param {string} [string=''] The string to inspect.
+     * @param {RegExp|string} [pattern] The pattern to match words.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {Array} Returns the words of `string`.
+     * @example
+     *
+     * _.words('fred, barney, & pebbles');
+     * // => ['fred', 'barney', 'pebbles']
+     *
+     * _.words('fred, barney, & pebbles', /[^, ]+/g);
+     * // => ['fred', 'barney', '&', 'pebbles']
+     */
+    function words(string, pattern, guard) {
+      if (guard && isIterateeCall(string, pattern, guard)) {
+        pattern = null;
+      }
+      string = baseToString(string);
+      return string.match(pattern || reWords) || [];
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * Attempts to invoke `func`, returning either the result or the caught error
+     * object. Any additional arguments are provided to `func` when it is invoked.
+     *
+     * @static
+     * @memberOf _
+     * @category Utility
+     * @param {Function} func The function to attempt.
+     * @returns {*} Returns the `func` result or error object.
+     * @example
+     *
+     * // avoid throwing errors for invalid selectors
+     * var elements = _.attempt(function(selector) {
+     *   return document.querySelectorAll(selector);
+     * }, '>_>');
+     *
+     * if (_.isError(elements)) {
+     *   elements = [];
+     * }
+     */
+    var attempt = restParam(function(func, args) {
+      try {
+        return func.apply(undefined, args);
+      } catch(e) {
+        return isError(e) ? e : new Error(e);
+      }
+    });
+
+    /**
+     * Creates a function that invokes `func` with the `this` binding of `thisArg`
+     * and arguments of the created function. If `func` is a property name the
+     * created callback returns the property value for a given element. If `func`
+     * is an object the created callback returns `true` for elements that contain
+     * the equivalent object properties, otherwise it returns `false`.
+     *
+     * @static
+     * @memberOf _
+     * @alias iteratee
+     * @category Utility
+     * @param {*} [func=_.identity] The value to convert to a callback.
+     * @param {*} [thisArg] The `this` binding of `func`.
+     * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+     * @returns {Function} Returns the callback.
+     * @example
+     *
+     * var users = [
+     *   { 'user': 'barney', 'age': 36 },
+     *   { 'user': 'fred',   'age': 40 }
+     * ];
+     *
+     * // wrap to create custom callback shorthands
+     * _.callback = _.wrap(_.callback, function(callback, func, thisArg) {
+     *   var match = /^(.+?)__([gl]t)(.+)$/.exec(func);
+     *   if (!match) {
+     *     return callback(func, thisArg);
+     *   }
+     *   return function(object) {
+     *     return match[2] == 'gt'
+     *       ? object[match[1]] > match[3]
+     *       : object[match[1]] < match[3];
+     *   };
+     * });
+     *
+     * _.filter(users, 'age__gt36');
+     * // => [{ 'user': 'fred', 'age': 40 }]
+     */
+    function callback(func, thisArg, guard) {
+      if (guard && isIterateeCall(func, thisArg, guard)) {
+        thisArg = null;
+      }
+      return baseCallback(func, thisArg);
+    }
+
+    /**
+     * Creates a function that returns `value`.
+     *
+     * @static
+     * @memberOf _
+     * @category Utility
+     * @param {*} value The value to return from the new function.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var object = { 'user': 'fred' };
+     * var getter = _.constant(object);
+     *
+     * getter() === object;
+     * // => true
+     */
+    function constant(value) {
+      return function() {
+        return value;
+      };
+    }
+
+    /**
+     * This method returns the first argument provided to it.
+     *
+     * @static
+     * @memberOf _
+     * @category Utility
+     * @param {*} value Any value.
+     * @returns {*} Returns `value`.
+     * @example
+     *
+     * var object = { 'user': 'fred' };
+     *
+     * _.identity(object) === object;
+     * // => true
+     */
+    function identity(value) {
+      return value;
+    }
+
+    /**
+     * Creates a function which performs a deep comparison between a given object
+     * and `source`, returning `true` if the given object has equivalent property
+     * values, else `false`.
+     *
+     * **Note:** This method supports comparing arrays, booleans, `Date` objects,
+     * numbers, `Object` objects, regexes, and strings. Objects are compared by
+     * their own, not inherited, enumerable properties. For comparing a single
+     * own or inherited property value see `_.matchesProperty`.
+     *
+     * @static
+     * @memberOf _
+     * @category Utility
+     * @param {Object} source The object of property values to match.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var users = [
+     *   { 'user': 'barney', 'age': 36, 'active': true },
+     *   { 'user': 'fred',   'age': 40, 'active': false }
+     * ];
+     *
+     * _.filter(users, _.matches({ 'age': 40, 'active': false }));
+     * // => [{ 'user': 'fred', 'age': 40, 'active': false }]
+     */
+    function matches(source) {
+      return baseMatches(baseClone(source, true));
+    }
+
+    /**
+     * Creates a function which compares the property value of `path` on a given
+     * object to `value`.
+     *
+     * **Note:** This method supports comparing arrays, booleans, `Date` objects,
+     * numbers, `Object` objects, regexes, and strings. Objects are compared by
+     * their own, not inherited, enumerable properties.
+     *
+     * @static
+     * @memberOf _
+     * @category Utility
+     * @param {Array|string} path The path of the property to get.
+     * @param {*} value The value to compare.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var users = [
+     *   { 'user': 'barney' },
+     *   { 'user': 'fred' }
+     * ];
+     *
+     * _.find(users, _.matchesProperty('user', 'fred'));
+     * // => { 'user': 'fred' }
+     */
+    function matchesProperty(path, value) {
+      return baseMatchesProperty(path, baseClone(value, true));
+    }
+
+    /**
+     * Creates a function which invokes the method at `path` on a given object.
+     *
+     * @static
+     * @memberOf _
+     * @category Utility
+     * @param {Array|string} path The path of the method to invoke.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var objects = [
+     *   { 'a': { 'b': { 'c': _.constant(2) } } },
+     *   { 'a': { 'b': { 'c': _.constant(1) } } }
+     * ];
+     *
+     * _.map(objects, _.method('a.b.c'));
+     * // => [2, 1]
+     *
+     * _.invoke(_.sortBy(objects, _.method(['a', 'b', 'c'])), 'a.b.c');
+     * // => [1, 2]
+     */
+    var method = restParam(function(path, args) {
+      return function(object) {
+        return invokePath(object, path, args);
+      }
+    });
+
+    /**
+     * The opposite of `_.method`; this method creates a function which invokes
+     * the method at a given path on `object`.
+     *
+     * @static
+     * @memberOf _
+     * @category Utility
+     * @param {Object} object The object to query.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var array = _.times(3, _.constant),
+     *     object = { 'a': array, 'b': array, 'c': array };
+     *
+     * _.map(['a[2]', 'c[0]'], _.methodOf(object));
+     * // => [2, 0]
+     *
+     * _.map([['a', '2'], ['c', '0']], _.methodOf(object));
+     * // => [2, 0]
+     */
+    var methodOf = restParam(function(object, args) {
+      return function(path) {
+        return invokePath(object, path, args);
+      };
+    });
+
+    /**
+     * Adds all own enumerable function properties of a source object to the
+     * destination object. If `object` is a function then methods are added to
+     * its prototype as well.
+     *
+     * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
+     * avoid conflicts caused by modifying the original.
+     *
+     * @static
+     * @memberOf _
+     * @category Utility
+     * @param {Function|Object} [object=lodash] The destination object.
+     * @param {Object} source The object of functions to add.
+     * @param {Object} [options] The options object.
+     * @param {boolean} [options.chain=true] Specify whether the functions added
+     *  are chainable.
+     * @returns {Function|Object} Returns `object`.
+     * @example
+     *
+     * function vowels(string) {
+     *   return _.filter(string, function(v) {
+     *     return /[aeiou]/i.test(v);
+     *   });
+     * }
+     *
+     * // use `_.runInContext` to avoid conflicts (esp. in Node.js)
+     * var _ = require('lodash').runInContext();
+     *
+     * _.mixin({ 'vowels': vowels });
+     * _.vowels('fred');
+     * // => ['e']
+     *
+     * _('fred').vowels().value();
+     * // => ['e']
+     *
+     * _.mixin({ 'vowels': vowels }, { 'chain': false });
+     * _('fred').vowels();
+     * // => ['e']
+     */
+    function mixin(object, source, options) {
+      if (options == null) {
+        var isObj = isObject(source),
+            props = isObj && keys(source),
+            methodNames = props && props.length && baseFunctions(source, props);
+
+        if (!(methodNames ? methodNames.length : isObj)) {
+          methodNames = false;
+          options = source;
+          source = object;
+          object = this;
+        }
+      }
+      if (!methodNames) {
+        methodNames = baseFunctions(source, keys(source));
+      }
+      var chain = true,
+          index = -1,
+          isFunc = isFunction(object),
+          length = methodNames.length;
+
+      if (options === false) {
+        chain = false;
+      } else if (isObject(options) && 'chain' in options) {
+        chain = options.chain;
+      }
+      while (++index < length) {
+        var methodName = methodNames[index],
+            func = source[methodName];
+
+        object[methodName] = func;
+        if (isFunc) {
+          object.prototype[methodName] = (function(func) {
+            return function() {
+              var chainAll = this.__chain__;
+              if (chain || chainAll) {
+                var result = object(this.__wrapped__),
+                    actions = result.__actions__ = arrayCopy(this.__actions__);
+
+                actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
+                result.__chain__ = chainAll;
+                return result;
+              }
+              var args = [this.value()];
+              push.apply(args, arguments);
+              return func.apply(object, args);
+            };
+          }(func));
+        }
+      }
+      return object;
+    }
+
+    /**
+     * Reverts the `_` variable to its previous value and returns a reference to
+     * the `lodash` function.
+     *
+     * @static
+     * @memberOf _
+     * @category Utility
+     * @returns {Function} Returns the `lodash` function.
+     * @example
+     *
+     * var lodash = _.noConflict();
+     */
+    function noConflict() {
+      context._ = oldDash;
+      return this;
+    }
+
+    /**
+     * A no-operation function which returns `undefined` regardless of the
+     * arguments it receives.
+     *
+     * @static
+     * @memberOf _
+     * @category Utility
+     * @example
+     *
+     * var object = { 'user': 'fred' };
+     *
+     * _.noop(object) === undefined;
+     * // => true
+     */
+    function noop() {
+      // No operation performed.
+    }
+
+    /**
+     * Creates a function which returns the property value at `path` on a
+     * given object.
+     *
+     * @static
+     * @memberOf _
+     * @category Utility
+     * @param {Array|string} path The path of the property to get.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var objects = [
+     *   { 'a': { 'b': { 'c': 2 } } },
+     *   { 'a': { 'b': { 'c': 1 } } }
+     * ];
+     *
+     * _.map(objects, _.property('a.b.c'));
+     * // => [2, 1]
+     *
+     * _.pluck(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c');
+     * // => [1, 2]
+     */
+    function property(path) {
+      return isKey(path) ? baseProperty(path) : basePropertyDeep(path);
+    }
+
+    /**
+     * The opposite of `_.property`; this method creates a function which returns
+     * the property value at a given path on `object`.
+     *
+     * @static
+     * @memberOf _
+     * @category Utility
+     * @param {Object} object The object to query.
+     * @returns {Function} Returns the new function.
+     * @example
+     *
+     * var array = [0, 1, 2],
+     *     object = { 'a': array, 'b': array, 'c': array };
+     *
+     * _.map(['a[2]', 'c[0]'], _.propertyOf(object));
+     * // => [2, 0]
+     *
+     * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
+     * // => [2, 0]
+     */
+    function propertyOf(object) {
+      return function(path) {
+        return baseGet(object, toPath(path), path + '');
+      };
+    }
+
+    /**
+     * Creates an array of numbers (positive and/or negative) progressing from
+     * `start` up to, but not including, `end`. If `end` is not specified it is
+     * set to `start` with `start` then set to `0`. If `end` is less than `start`
+     * a zero-length range is created unless a negative `step` is specified.
+     *
+     * @static
+     * @memberOf _
+     * @category Utility
+     * @param {number} [start=0] The start of the range.
+     * @param {number} end The end of the range.
+     * @param {number} [step=1] The value to increment or decrement by.
+     * @returns {Array} Returns the new array of numbers.
+     * @example
+     *
+     * _.range(4);
+     * // => [0, 1, 2, 3]
+     *
+     * _.range(1, 5);
+     * // => [1, 2, 3, 4]
+     *
+     * _.range(0, 20, 5);
+     * // => [0, 5, 10, 15]
+     *
+     * _.range(0, -4, -1);
+     * // => [0, -1, -2, -3]
+     *
+     * _.range(1, 4, 0);
+     * // => [1, 1, 1]
+     *
+     * _.range(0);
+     * // => []
+     */
+    function range(start, end, step) {
+      if (step && isIterateeCall(start, end, step)) {
+        end = step = null;
+      }
+      start = +start || 0;
+      step = step == null ? 1 : (+step || 0);
+
+      if (end == null) {
+        end = start;
+        start = 0;
+      } else {
+        end = +end || 0;
+      }
+      // Use `Array(length)` so engines like Chakra and V8 avoid slower modes.
+      // See https://youtu.be/XAqIpGU8ZZk#t=17m25s for more details.
+      var index = -1,
+          length = nativeMax(ceil((end - start) / (step || 1)), 0),
+          result = Array(length);
+
+      while (++index < length) {
+        result[index] = start;
+        start += step;
+      }
+      return result;
+    }
+
+    /**
+     * Invokes the iteratee function `n` times, returning an array of the results
+     * of each invocation. The `iteratee` is bound to `thisArg` and invoked with
+     * one argument; (index).
+     *
+     * @static
+     * @memberOf _
+     * @category Utility
+     * @param {number} n The number of times to invoke `iteratee`.
+     * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {Array} Returns the array of results.
+     * @example
+     *
+     * var diceRolls = _.times(3, _.partial(_.random, 1, 6, false));
+     * // => [3, 6, 4]
+     *
+     * _.times(3, function(n) {
+     *   mage.castSpell(n);
+     * });
+     * // => invokes `mage.castSpell(n)` three times with `n` of `0`, `1`, and `2`
+     *
+     * _.times(3, function(n) {
+     *   this.cast(n);
+     * }, mage);
+     * // => also invokes `mage.castSpell(n)` three times
+     */
+    function times(n, iteratee, thisArg) {
+      n = floor(n);
+
+      // Exit early to avoid a JSC JIT bug in Safari 8
+      // where `Array(0)` is treated as `Array(1)`.
+      if (n < 1 || !nativeIsFinite(n)) {
+        return [];
+      }
+      var index = -1,
+          result = Array(nativeMin(n, MAX_ARRAY_LENGTH));
+
+      iteratee = bindCallback(iteratee, thisArg, 1);
+      while (++index < n) {
+        if (index < MAX_ARRAY_LENGTH) {
+          result[index] = iteratee(index);
+        } else {
+          iteratee(index);
+        }
+      }
+      return result;
+    }
+
+    /**
+     * Generates a unique ID. If `prefix` is provided the ID is appended to it.
+     *
+     * @static
+     * @memberOf _
+     * @category Utility
+     * @param {string} [prefix] The value to prefix the ID with.
+     * @returns {string} Returns the unique ID.
+     * @example
+     *
+     * _.uniqueId('contact_');
+     * // => 'contact_104'
+     *
+     * _.uniqueId();
+     * // => '105'
+     */
+    function uniqueId(prefix) {
+      var id = ++idCounter;
+      return baseToString(prefix) + id;
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * Adds two numbers.
+     *
+     * @static
+     * @memberOf _
+     * @category Math
+     * @param {number} augend The first number to add.
+     * @param {number} addend The second number to add.
+     * @returns {number} Returns the sum.
+     * @example
+     *
+     * _.add(6, 4);
+     * // => 10
+     */
+    function add(augend, addend) {
+      return (+augend || 0) + (+addend || 0);
+    }
+
+    /**
+     * Gets the maximum value of `collection`. If `collection` is empty or falsey
+     * `-Infinity` is returned. If an iteratee function is provided it is invoked
+     * for each value in `collection` to generate the criterion by which the value
+     * is ranked. The `iteratee` is bound to `thisArg` and invoked with three
+     * arguments: (value, index, collection).
+     *
+     * If a property name is provided for `iteratee` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `iteratee` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Math
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [iteratee] The function invoked per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {*} Returns the maximum value.
+     * @example
+     *
+     * _.max([4, 2, 8, 6]);
+     * // => 8
+     *
+     * _.max([]);
+     * // => -Infinity
+     *
+     * var users = [
+     *   { 'user': 'barney', 'age': 36 },
+     *   { 'user': 'fred',   'age': 40 }
+     * ];
+     *
+     * _.max(users, function(chr) {
+     *   return chr.age;
+     * });
+     * // => { 'user': 'fred', 'age': 40 }
+     *
+     * // using the `_.property` callback shorthand
+     * _.max(users, 'age');
+     * // => { 'user': 'fred', 'age': 40 }
+     */
+    var max = createExtremum(arrayMax);
+
+    /**
+     * Gets the minimum value of `collection`. If `collection` is empty or falsey
+     * `Infinity` is returned. If an iteratee function is provided it is invoked
+     * for each value in `collection` to generate the criterion by which the value
+     * is ranked. The `iteratee` is bound to `thisArg` and invoked with three
+     * arguments: (value, index, collection).
+     *
+     * If a property name is provided for `iteratee` the created `_.property`
+     * style callback returns the property value of the given element.
+     *
+     * If a value is also provided for `thisArg` the created `_.matchesProperty`
+     * style callback returns `true` for elements that have a matching property
+     * value, else `false`.
+     *
+     * If an object is provided for `iteratee` the created `_.matches` style
+     * callback returns `true` for elements that have the properties of the given
+     * object, else `false`.
+     *
+     * @static
+     * @memberOf _
+     * @category Math
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [iteratee] The function invoked per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {*} Returns the minimum value.
+     * @example
+     *
+     * _.min([4, 2, 8, 6]);
+     * // => 2
+     *
+     * _.min([]);
+     * // => Infinity
+     *
+     * var users = [
+     *   { 'user': 'barney', 'age': 36 },
+     *   { 'user': 'fred',   'age': 40 }
+     * ];
+     *
+     * _.min(users, function(chr) {
+     *   return chr.age;
+     * });
+     * // => { 'user': 'barney', 'age': 36 }
+     *
+     * // using the `_.property` callback shorthand
+     * _.min(users, 'age');
+     * // => { 'user': 'barney', 'age': 36 }
+     */
+    var min = createExtremum(arrayMin, true);
+
+    /**
+     * Gets the sum of the values in `collection`.
+     *
+     * @static
+     * @memberOf _
+     * @category Math
+     * @param {Array|Object|string} collection The collection to iterate over.
+     * @param {Function|Object|string} [iteratee] The function invoked per iteration.
+     * @param {*} [thisArg] The `this` binding of `iteratee`.
+     * @returns {number} Returns the sum.
+     * @example
+     *
+     * _.sum([4, 6]);
+     * // => 10
+     *
+     * _.sum({ 'a': 4, 'b': 6 });
+     * // => 10
+     *
+     * var objects = [
+     *   { 'n': 4 },
+     *   { 'n': 6 }
+     * ];
+     *
+     * _.sum(objects, function(object) {
+     *   return object.n;
+     * });
+     * // => 10
+     *
+     * // using the `_.property` callback shorthand
+     * _.sum(objects, 'n');
+     * // => 10
+     */
+    function sum(collection, iteratee, thisArg) {
+      if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {
+        iteratee = null;
+      }
+      var func = getCallback(),
+          noIteratee = iteratee == null;
+
+      if (!(func === baseCallback && noIteratee)) {
+        noIteratee = false;
+        iteratee = func(iteratee, thisArg, 3);
+      }
+      return noIteratee
+        ? arraySum(isArray(collection) ? collection : toIterable(collection))
+        : baseSum(collection, iteratee);
+    }
+
+    /*------------------------------------------------------------------------*/
+
+    // Ensure wrappers are instances of `baseLodash`.
+    lodash.prototype = baseLodash.prototype;
+
+    LodashWrapper.prototype = baseCreate(baseLodash.prototype);
+    LodashWrapper.prototype.constructor = LodashWrapper;
+
+    LazyWrapper.prototype = baseCreate(baseLodash.prototype);
+    LazyWrapper.prototype.constructor = LazyWrapper;
+
+    // Add functions to the `Map` cache.
+    MapCache.prototype['delete'] = mapDelete;
+    MapCache.prototype.get = mapGet;
+    MapCache.prototype.has = mapHas;
+    MapCache.prototype.set = mapSet;
+
+    // Add functions to the `Set` cache.
+    SetCache.prototype.push = cachePush;
+
+    // Assign cache to `_.memoize`.
+    memoize.Cache = MapCache;
+
+    // Add functions that return wrapped values when chaining.
+    lodash.after = after;
+    lodash.ary = ary;
+    lodash.assign = assign;
+    lodash.at = at;
+    lodash.before = before;
+    lodash.bind = bind;
+    lodash.bindAll = bindAll;
+    lodash.bindKey = bindKey;
+    lodash.callback = callback;
+    lodash.chain = chain;
+    lodash.chunk = chunk;
+    lodash.compact = compact;
+    lodash.constant = constant;
+    lodash.countBy = countBy;
+    lodash.create = create;
+    lodash.curry = curry;
+    lodash.curryRight = curryRight;
+    lodash.debounce = debounce;
+    lodash.defaults = defaults;
+    lodash.defer = defer;
+    lodash.delay = delay;
+    lodash.difference = difference;
+    lodash.drop = drop;
+    lodash.dropRight = dropRight;
+    lodash.dropRightWhile = dropRightWhile;
+    lodash.dropWhile = dropWhile;
+    lodash.fill = fill;
+    lodash.filter = filter;
+    lodash.flatten = flatten;
+    lodash.flattenDeep = flattenDeep;
+    lodash.flow = flow;
+    lodash.flowRight = flowRight;
+    lodash.forEach = forEach;
+    lodash.forEachRight = forEachRight;
+    lodash.forIn = forIn;
+    lodash.forInRight = forInRight;
+    lodash.forOwn = forOwn;
+    lodash.forOwnRight = forOwnRight;
+    lodash.functions = functions;
+    lodash.groupBy = groupBy;
+    lodash.indexBy = indexBy;
+    lodash.initial = initial;
+    lodash.intersection = intersection;
+    lodash.invert = invert;
+    lodash.invoke = invoke;
+    lodash.keys = keys;
+    lodash.keysIn = keysIn;
+    lodash.map = map;
+    lodash.mapValues = mapValues;
+    lodash.matches = matches;
+    lodash.matchesProperty = matchesProperty;
+    lodash.memoize = memoize;
+    lodash.merge = merge;
+    lodash.method = method;
+    lodash.methodOf = methodOf;
+    lodash.mixin = mixin;
+    lodash.negate = negate;
+    lodash.omit = omit;
+    lodash.once = once;
+    lodash.pairs = pairs;
+    lodash.partial = partial;
+    lodash.partialRight = partialRight;
+    lodash.partition = partition;
+    lodash.pick = pick;
+    lodash.pluck = pluck;
+    lodash.property = property;
+    lodash.propertyOf = propertyOf;
+    lodash.pull = pull;
+    lodash.pullAt = pullAt;
+    lodash.range = range;
+    lodash.rearg = rearg;
+    lodash.reject = reject;
+    lodash.remove = remove;
+    lodash.rest = rest;
+    lodash.restParam = restParam;
+    lodash.set = set;
+    lodash.shuffle = shuffle;
+    lodash.slice = slice;
+    lodash.sortBy = sortBy;
+    lodash.sortByAll = sortByAll;
+    lodash.sortByOrder = sortByOrder;
+    lodash.spread = spread;
+    lodash.take = take;
+    lodash.takeRight = takeRight;
+    lodash.takeRightWhile = takeRightWhile;
+    lodash.takeWhile = takeWhile;
+    lodash.tap = tap;
+    lodash.throttle = throttle;
+    lodash.thru = thru;
+    lodash.times = times;
+    lodash.toArray = toArray;
+    lodash.toPlainObject = toPlainObject;
+    lodash.transform = transform;
+    lodash.union = union;
+    lodash.uniq = uniq;
+    lodash.unzip = unzip;
+    lodash.values = values;
+    lodash.valuesIn = valuesIn;
+    lodash.where = where;
+    lodash.without = without;
+    lodash.wrap = wrap;
+    lodash.xor = xor;
+    lodash.zip = zip;
+    lodash.zipObject = zipObject;
+
+    // Add aliases.
+    lodash.backflow = flowRight;
+    lodash.collect = map;
+    lodash.compose = flowRight;
+    lodash.each = forEach;
+    lodash.eachRight = forEachRight;
+    lodash.extend = assign;
+    lodash.iteratee = callback;
+    lodash.methods = functions;
+    lodash.object = zipObject;
+    lodash.select = filter;
+    lodash.tail = rest;
+    lodash.unique = uniq;
+
+    // Add functions to `lodash.prototype`.
+    mixin(lodash, lodash);
+
+    /*------------------------------------------------------------------------*/
+
+    // Add functions that return unwrapped values when chaining.
+    lodash.add = add;
+    lodash.attempt = attempt;
+    lodash.camelCase = camelCase;
+    lodash.capitalize = capitalize;
+    lodash.clone = clone;
+    lodash.cloneDeep = cloneDeep;
+    lodash.deburr = deburr;
+    lodash.endsWith = endsWith;
+    lodash.escape = escape;
+    lodash.escapeRegExp = escapeRegExp;
+    lodash.every = every;
+    lodash.find = find;
+    lodash.findIndex = findIndex;
+    lodash.findKey = findKey;
+    lodash.findLast = findLast;
+    lodash.findLastIndex = findLastIndex;
+    lodash.findLastKey = findLastKey;
+    lodash.findWhere = findWhere;
+    lodash.first = first;
+    lodash.get = get;
+    lodash.has = has;
+    lodash.identity = identity;
+    lodash.includes = includes;
+    lodash.indexOf = indexOf;
+    lodash.inRange = inRange;
+    lodash.isArguments = isArguments;
+    lodash.isArray = isArray;
+    lodash.isBoolean = isBoolean;
+    lodash.isDate = isDate;
+    lodash.isElement = isElement;
+    lodash.isEmpty = isEmpty;
+    lodash.isEqual = isEqual;
+    lodash.isError = isError;
+    lodash.isFinite = isFinite;
+    lodash.isFunction = isFunction;
+    lodash.isMatch = isMatch;
+    lodash.isNaN = isNaN;
+    lodash.isNative = isNative;
+    lodash.isNull = isNull;
+    lodash.isNumber = isNumber;
+    lodash.isObject = isObject;
+    lodash.isPlainObject = isPlainObject;
+    lodash.isRegExp = isRegExp;
+    lodash.isString = isString;
+    lodash.isTypedArray = isTypedArray;
+    lodash.isUndefined = isUndefined;
+    lodash.kebabCase = kebabCase;
+    lodash.last = last;
+    lodash.lastIndexOf = lastIndexOf;
+    lodash.max = max;
+    lodash.min = min;
+    lodash.noConflict = noConflict;
+    lodash.noop = noop;
+    lodash.now = now;
+    lodash.pad = pad;
+    lodash.padLeft = padLeft;
+    lodash.padRight = padRight;
+    lodash.parseInt = parseInt;
+    lodash.random = random;
+    lodash.reduce = reduce;
+    lodash.reduceRight = reduceRight;
+    lodash.repeat = repeat;
+    lodash.result = result;
+    lodash.runInContext = runInContext;
+    lodash.size = size;
+    lodash.snakeCase = snakeCase;
+    lodash.some = some;
+    lodash.sortedIndex = sortedIndex;
+    lodash.sortedLastIndex = sortedLastIndex;
+    lodash.startCase = startCase;
+    lodash.startsWith = startsWith;
+    lodash.sum = sum;
+    lodash.template = template;
+    lodash.trim = trim;
+    lodash.trimLeft = trimLeft;
+    lodash.trimRight = trimRight;
+    lodash.trunc = trunc;
+    lodash.unescape = unescape;
+    lodash.uniqueId = uniqueId;
+    lodash.words = words;
+
+    // Add aliases.
+    lodash.all = every;
+    lodash.any = some;
+    lodash.contains = includes;
+    lodash.detect = find;
+    lodash.foldl = reduce;
+    lodash.foldr = reduceRight;
+    lodash.head = first;
+    lodash.include = includes;
+    lodash.inject = reduce;
+
+    mixin(lodash, (function() {
+      var source = {};
+      baseForOwn(lodash, function(func, methodName) {
+        if (!lodash.prototype[methodName]) {
+          source[methodName] = func;
+        }
+      });
+      return source;
+    }()), false);
+
+    /*------------------------------------------------------------------------*/
+
+    // Add functions capable of returning wrapped and unwrapped values when chaining.
+    lodash.sample = sample;
+
+    lodash.prototype.sample = function(n) {
+      if (!this.__chain__ && n == null) {
+        return sample(this.value());
+      }
+      return this.thru(function(value) {
+        return sample(value, n);
+      });
+    };
+
+    /*------------------------------------------------------------------------*/
+
+    /**
+     * The semantic version number.
+     *
+     * @static
+     * @memberOf _
+     * @type string
+     */
+    lodash.VERSION = VERSION;
+
+    // Assign default placeholders.
+    arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
+      lodash[methodName].placeholder = lodash;
+    });
+
+    // Add `LazyWrapper` methods that accept an `iteratee` value.
+    arrayEach(['dropWhile', 'filter', 'map', 'takeWhile'], function(methodName, type) {
+      var isFilter = type != LAZY_MAP_FLAG,
+          isDropWhile = type == LAZY_DROP_WHILE_FLAG;
+
+      LazyWrapper.prototype[methodName] = function(iteratee, thisArg) {
+        var filtered = this.__filtered__,
+            result = (filtered && isDropWhile) ? new LazyWrapper(this) : this.clone(),
+            iteratees = result.__iteratees__ || (result.__iteratees__ = []);
+
+        iteratees.push({
+          'done': false,
+          'count': 0,
+          'index': 0,
+          'iteratee': getCallback(iteratee, thisArg, 1),
+          'limit': -1,
+          'type': type
+        });
+
+        result.__filtered__ = filtered || isFilter;
+        return result;
+      };
+    });
+
+    // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
+    arrayEach(['drop', 'take'], function(methodName, index) {
+      var whileName = methodName + 'While';
+
+      LazyWrapper.prototype[methodName] = function(n) {
+        var filtered = this.__filtered__,
+            result = (filtered && !index) ? this.dropWhile() : this.clone();
+
+        n = n == null ? 1 : nativeMax(floor(n) || 0, 0);
+        if (filtered) {
+          if (index) {
+            result.__takeCount__ = nativeMin(result.__takeCount__, n);
+          } else {
+            last(result.__iteratees__).limit = n;
+          }
+        } else {
+          var views = result.__views__ || (result.__views__ = []);
+          views.push({ 'size': n, 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') });
+        }
+        return result;
+      };
+
+      LazyWrapper.prototype[methodName + 'Right'] = function(n) {
+        return this.reverse()[methodName](n).reverse();
+      };
+
+      LazyWrapper.prototype[methodName + 'RightWhile'] = function(predicate, thisArg) {
+        return this.reverse()[whileName](predicate, thisArg).reverse();
+      };
+    });
+
+    // Add `LazyWrapper` methods for `_.first` and `_.last`.
+    arrayEach(['first', 'last'], function(methodName, index) {
+      var takeName = 'take' + (index ? 'Right' : '');
+
+      LazyWrapper.prototype[methodName] = function() {
+        return this[takeName](1).value()[0];
+      };
+    });
+
+    // Add `LazyWrapper` methods for `_.initial` and `_.rest`.
+    arrayEach(['initial', 'rest'], function(methodName, index) {
+      var dropName = 'drop' + (index ? '' : 'Right');
+
+      LazyWrapper.prototype[methodName] = function() {
+        return this[dropName](1);
+      };
+    });
+
+    // Add `LazyWrapper` methods for `_.pluck` and `_.where`.
+    arrayEach(['pluck', 'where'], function(methodName, index) {
+      var operationName = index ? 'filter' : 'map',
+          createCallback = index ? baseMatches : property;
+
+      LazyWrapper.prototype[methodName] = function(value) {
+        return this[operationName](createCallback(value));
+      };
+    });
+
+    LazyWrapper.prototype.compact = function() {
+      return this.filter(identity);
+    };
+
+    LazyWrapper.prototype.reject = function(predicate, thisArg) {
+      predicate = getCallback(predicate, thisArg, 1);
+      return this.filter(function(value) {
+        return !predicate(value);
+      });
+    };
+
+    LazyWrapper.prototype.slice = function(start, end) {
+      start = start == null ? 0 : (+start || 0);
+      var result = start < 0 ? this.takeRight(-start) : this.drop(start);
+
+      if (end !== undefined) {
+        end = (+end || 0);
+        result = end < 0 ? result.dropRight(-end) : result.take(end - start);
+      }
+      return result;
+    };
+
+    LazyWrapper.prototype.toArray = function() {
+      return this.drop(0);
+    };
+
+    // Add `LazyWrapper` methods to `lodash.prototype`.
+    baseForOwn(LazyWrapper.prototype, function(func, methodName) {
+      var lodashFunc = lodash[methodName];
+      if (!lodashFunc) {
+        return;
+      }
+      var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName),
+          retUnwrapped = /^(?:first|last)$/.test(methodName);
+
+      lodash.prototype[methodName] = function() {
+        var args = arguments,
+            length = args.length,
+            chainAll = this.__chain__,
+            value = this.__wrapped__,
+            isHybrid = !!this.__actions__.length,
+            isLazy = value instanceof LazyWrapper,
+            iteratee = args[0],
+            useLazy = isLazy || isArray(value);
+
+        if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
+          // avoid lazy use if the iteratee has a "length" value other than `1`
+          isLazy = useLazy = false;
+        }
+        var onlyLazy = isLazy && !isHybrid;
+        if (retUnwrapped && !chainAll) {
+          return onlyLazy
+            ? func.call(value)
+            : lodashFunc.call(lodash, this.value());
+        }
+        var interceptor = function(value) {
+          var otherArgs = [value];
+          push.apply(otherArgs, args);
+          return lodashFunc.apply(lodash, otherArgs);
+        };
+        if (useLazy) {
+          var wrapper = onlyLazy ? value : new LazyWrapper(this),
+              result = func.apply(wrapper, args);
+
+          if (!retUnwrapped && (isHybrid || result.__actions__)) {
+            var actions = result.__actions__ || (result.__actions__ = []);
+            actions.push({ 'func': thru, 'args': [interceptor], 'thisArg': lodash });
+          }
+          return new LodashWrapper(result, chainAll);
+        }
+        return this.thru(interceptor);
+      };
+    });
+
+    // Add `Array` and `String` methods to `lodash.prototype`.
+    arrayEach(['concat', 'join', 'pop', 'push', 'replace', 'shift', 'sort', 'splice', 'split', 'unshift'], function(methodName) {
+      var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName],
+          chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
+          retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName);
+
+      lodash.prototype[methodName] = function() {
+        var args = arguments;
+        if (retUnwrapped && !this.__chain__) {
+          return func.apply(this.value(), args);
+        }
+        return this[chainName](function(value) {
+          return func.apply(value, args);
+        });
+      };
+    });
+
+    // Map minified function names to their real names.
+    baseForOwn(LazyWrapper.prototype, function(func, methodName) {
+      var lodashFunc = lodash[methodName];
+      if (lodashFunc) {
+        var key = lodashFunc.name,
+            names = realNames[key] || (realNames[key] = []);
+
+        names.push({ 'name': methodName, 'func': lodashFunc });
+      }
+    });
+
+    realNames[createHybridWrapper(null, BIND_KEY_FLAG).name] = [{ 'name': 'wrapper', 'func': null }];
+
+    // Add functions to the lazy wrapper.
+    LazyWrapper.prototype.clone = lazyClone;
+    LazyWrapper.prototype.reverse = lazyReverse;
+    LazyWrapper.prototype.value = lazyValue;
+
+    // Add chaining functions to the `lodash` wrapper.
+    lodash.prototype.chain = wrapperChain;
+    lodash.prototype.commit = wrapperCommit;
+    lodash.prototype.plant = wrapperPlant;
+    lodash.prototype.reverse = wrapperReverse;
+    lodash.prototype.toString = wrapperToString;
+    lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
+
+    // Add function aliases to the `lodash` wrapper.
+    lodash.prototype.collect = lodash.prototype.map;
+    lodash.prototype.head = lodash.prototype.first;
+    lodash.prototype.select = lodash.prototype.filter;
+    lodash.prototype.tail = lodash.prototype.rest;
+
+    return lodash;
+  }
+
+  /*--------------------------------------------------------------------------*/
+
+  // Export lodash.
+  var _ = runInContext();
+
+  // Some AMD build optimizers like r.js check for condition patterns like the following:
+  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+    // Expose lodash to the global object when an AMD loader is present to avoid
+    // errors in cases where lodash is loaded by a script tag and not intended
+    // as an AMD module. See http://requirejs.org/docs/errors.html#mismatch for
+    // more details.
+    root._ = _;
+
+    // Define as an anonymous module so, through path mapping, it can be
+    // referenced as the "underscore" module.
+    define(function() {
+      return _;
+    });
+  }
+  // Check for `exports` after `define` in case a build optimizer adds an `exports` object.
+  else if (freeExports && freeModule) {
+    // Export for Node.js or RingoJS.
+    if (moduleExports) {
+      (freeModule.exports = _)._ = _;
+    }
+    // Export for Narwhal or Rhino -require.
+    else {
+      freeExports._ = _;
+    }
+  }
+  else {
+    // Export for a browser or Rhino.
+    root._ = _;
+  }
+}.call(this));
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{}],13:[function(require,module,exports){
+/*
+ * Lexical analysis and token construction.
+ */
+
+"use strict";
+
+var _      = require("lodash");
+var events = require("events");
+var reg    = require("./reg.js");
+var state  = require("./state.js").state;
+
+var unicodeData = require("../data/ascii-identifier-data.js");
+var asciiIdentifierStartTable = unicodeData.asciiIdentifierStartTable;
+var asciiIdentifierPartTable = unicodeData.asciiIdentifierPartTable;
+var nonAsciiIdentifierStartTable = require("../data/non-ascii-identifier-start.js");
+var nonAsciiIdentifierPartTable = require("../data/non-ascii-identifier-part-only.js");
+
+// Some of these token types are from JavaScript Parser API
+// while others are specific to JSHint parser.
+// JS Parser API: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
+
+var Token = {
+  Identifier: 1,
+  Punctuator: 2,
+  NumericLiteral: 3,
+  StringLiteral: 4,
+  Comment: 5,
+  Keyword: 6,
+  NullLiteral: 7,
+  BooleanLiteral: 8,
+  RegExp: 9,
+  TemplateHead: 10,
+  TemplateMiddle: 11,
+  TemplateTail: 12,
+  NoSubstTemplate: 13
+};
+
+var Context = {
+  Block: 1,
+  Template: 2
+};
+
+function isHex(str) {
+  return /^[0-9a-fA-F]+$/.test(str);
+}
+
+function isHexDigit(str) {
+  return str.length === 1 && isHex(str);
+}
+
+// Object that handles postponed lexing verifications that checks the parsed
+// environment state.
+
+function asyncTrigger() {
+  var _checks = [];
+
+  return {
+    push: function(fn) {
+      _checks.push(fn);
+    },
+
+    check: function() {
+      for (var check = 0; check < _checks.length; ++check) {
+        _checks[check]();
+      }
+
+      _checks.splice(0, _checks.length);
+    }
+  };
+}
+
+/*
+ * Lexer for JSHint.
+ *
+ * This object does a char-by-char scan of the provided source code
+ * and produces a sequence of tokens.
+ *
+ *   var lex = new Lexer("var i = 0;");
+ *   lex.start();
+ *   lex.token(); // returns the next token
+ *
+ * You have to use the token() method to move the lexer forward
+ * but you don't have to use its return value to get tokens. In addition
+ * to token() method returning the next token, the Lexer object also
+ * emits events.
+ *
+ *   lex.on("Identifier", function(data) {
+ *     if (data.name.indexOf("_") >= 0) {
+ *       // Produce a warning.
+ *     }
+ *   });
+ *
+ * Note that the token() method returns tokens in a JSLint-compatible
+ * format while the event emitter uses a slightly modified version of
+ * Mozilla's JavaScript Parser API. Eventually, we will move away from
+ * JSLint format.
+ */
+function Lexer(source) {
+  var lines = source;
+
+  if (typeof lines === "string") {
+    lines = lines
+      .replace(/\r\n/g, "\n")
+      .replace(/\r/g, "\n")
+      .split("\n");
+  }
+
+  // If the first line is a shebang (#!), make it a blank and move on.
+  // Shebangs are used by Node scripts.
+
+  if (lines[0] && lines[0].substr(0, 2) === "#!") {
+    if (lines[0].indexOf("node") !== -1) {
+      state.option.node = true;
+    }
+    lines[0] = "";
+  }
+
+  this.emitter = new events.EventEmitter();
+  this.source = source;
+  this.setLines(lines);
+  this.prereg = true;
+
+  this.line = 0;
+  this.char = 1;
+  this.from = 1;
+  this.input = "";
+  this.inComment = false;
+  this.context = [];
+  this.templateStarts = [];
+
+  for (var i = 0; i < state.option.indent; i += 1) {
+    state.tab += " ";
+  }
+}
+
+Lexer.prototype = {
+  _lines: [],
+
+  inContext: function(ctxType) {
+    return this.context.length > 0 && this.context[this.context.length - 1].type === ctxType;
+  },
+
+  pushContext: function(ctxType) {
+    this.context.push({ type: ctxType });
+  },
+
+  popContext: function() {
+    return this.context.pop();
+  },
+
+  isContext: function(context) {
+    return this.context.length > 0 && this.context[this.context.length - 1] === context;
+  },
+
+  currentContext: function() {
+    return this.context.length > 0 && this.context[this.context.length - 1];
+  },
+
+  getLines: function() {
+    this._lines = state.lines;
+    return this._lines;
+  },
+
+  setLines: function(val) {
+    this._lines = val;
+    state.lines = this._lines;
+  },
+
+  /*
+   * Return the next i character without actually moving the
+   * char pointer.
+   */
+  peek: function(i) {
+    return this.input.charAt(i || 0);
+  },
+
+  /*
+   * Move the char pointer forward i times.
+   */
+  skip: function(i) {
+    i = i || 1;
+    this.char += i;
+    this.input = this.input.slice(i);
+  },
+
+  /*
+   * Subscribe to a token event. The API for this method is similar
+   * Underscore.js i.e. you can subscribe to multiple events with
+   * one call:
+   *
+   *   lex.on("Identifier Number", function(data) {
+   *     // ...
+   *   });
+   */
+  on: function(names, listener) {
+    names.split(" ").forEach(function(name) {
+      this.emitter.on(name, listener);
+    }.bind(this));
+  },
+
+  /*
+   * Trigger a token event. All arguments will be passed to each
+   * listener.
+   */
+  trigger: function() {
+    this.emitter.emit.apply(this.emitter, Array.prototype.slice.call(arguments));
+  },
+
+  /*
+   * Postpone a token event. the checking condition is set as
+   * last parameter, and the trigger function is called in a
+   * stored callback. To be later called using the check() function
+   * by the parser. This avoids parser's peek() to give the lexer
+   * a false context.
+   */
+  triggerAsync: function(type, args, checks, fn) {
+    checks.push(function() {
+      if (fn()) {
+        this.trigger(type, args);
+      }
+    }.bind(this));
+  },
+
+  /*
+   * Extract a punctuator out of the next sequence of characters
+   * or return 'null' if its not possible.
+   *
+   * This method's implementation was heavily influenced by the
+   * scanPunctuator function in the Esprima parser's source code.
+   */
+  scanPunctuator: function() {
+    var ch1 = this.peek();
+    var ch2, ch3, ch4;
+
+    switch (ch1) {
+    // Most common single-character punctuators
+    case ".":
+      if ((/^[0-9]$/).test(this.peek(1))) {
+        return null;
+      }
+      if (this.peek(1) === "." && this.peek(2) === ".") {
+        return {
+          type: Token.Punctuator,
+          value: "..."
+        };
+      }
+      /* falls through */
+    case "(":
+    case ")":
+    case ";":
+    case ",":
+    case "[":
+    case "]":
+    case ":":
+    case "~":
+    case "?":
+      return {
+        type: Token.Punctuator,
+        value: ch1
+      };
+
+    // A block/object opener
+    case "{":
+      this.pushContext(Context.Block);
+      return {
+        type: Token.Punctuator,
+        value: ch1
+      };
+
+    // A block/object closer
+    case "}":
+      if (this.inContext(Context.Block)) {
+        this.popContext();
+      }
+      return {
+        type: Token.Punctuator,
+        value: ch1
+      };
+
+    // A pound sign (for Node shebangs)
+    case "#":
+      return {
+        type: Token.Punctuator,
+        value: ch1
+      };
+
+    // We're at the end of input
+    case "":
+      return null;
+    }
+
+    // Peek more characters
+
+    ch2 = this.peek(1);
+    ch3 = this.peek(2);
+    ch4 = this.peek(3);
+
+    // 4-character punctuator: >>>=
+
+    if (ch1 === ">" && ch2 === ">" && ch3 === ">" && ch4 === "=") {
+      return {
+        type: Token.Punctuator,
+        value: ">>>="
+      };
+    }
+
+    // 3-character punctuators: === !== >>> <<= >>=
+
+    if (ch1 === "=" && ch2 === "=" && ch3 === "=") {
+      return {
+        type: Token.Punctuator,
+        value: "==="
+      };
+    }
+
+    if (ch1 === "!" && ch2 === "=" && ch3 === "=") {
+      return {
+        type: Token.Punctuator,
+        value: "!=="
+      };
+    }
+
+    if (ch1 === ">" && ch2 === ">" && ch3 === ">") {
+      return {
+        type: Token.Punctuator,
+        value: ">>>"
+      };
+    }
+
+    if (ch1 === "<" && ch2 === "<" && ch3 === "=") {
+      return {
+        type: Token.Punctuator,
+        value: "<<="
+      };
+    }
+
+    if (ch1 === ">" && ch2 === ">" && ch3 === "=") {
+      return {
+        type: Token.Punctuator,
+        value: ">>="
+      };
+    }
+
+    // Fat arrow punctuator
+    if (ch1 === "=" && ch2 === ">") {
+      return {
+        type: Token.Punctuator,
+        value: ch1 + ch2
+      };
+    }
+
+    // 2-character punctuators: <= >= == != ++ -- << >> && ||
+    // += -= *= %= &= |= ^= /=
+    if (ch1 === ch2 && ("+-<>&|".indexOf(ch1) >= 0)) {
+      return {
+        type: Token.Punctuator,
+        value: ch1 + ch2
+      };
+    }
+
+    if ("<>=!+-*%&|^/".indexOf(ch1) >= 0) {
+      if (ch2 === "=") {
+        return {
+          type: Token.Punctuator,
+          value: ch1 + ch2
+        };
+      }
+
+      return {
+        type: Token.Punctuator,
+        value: ch1
+      };
+    }
+
+    return null;
+  },
+
+  /*
+   * Extract a comment out of the next sequence of characters and/or
+   * lines or return 'null' if its not possible. Since comments can
+   * span across multiple lines this method has to move the char
+   * pointer.
+   *
+   * In addition to normal JavaScript comments (// and /*) this method
+   * also recognizes JSHint- and JSLint-specific comments such as
+   * /*jshint, /*jslint, /*globals and so on.
+   */
+  scanComments: function(checks) {
+    var ch1 = this.peek();
+    var ch2 = this.peek(1);
+    var rest = this.input.substr(2);
+    var startLine = this.line;
+    var startChar = this.char;
+    var self = this;
+
+    // Create a comment token object and make sure it
+    // has all the data JSHint needs to work with special
+    // comments.
+
+    function commentToken(label, body, opt) {
+      var special = ["jshint", "jslint", "members", "member", "globals", "global", "exported"];
+      var isSpecial = false;
+      var value = label + body;
+      var commentType = "plain";
+      opt = opt || {};
+
+      if (opt.isMultiline) {
+        value += "*/";
+      }
+
+      body = body.replace(/\n/g, " ");
+
+      if (label === "/*" && reg.fallsThrough.test(body)) {
+        isSpecial = true;
+        commentType = "falls through";
+      }
+
+      special.forEach(function(str) {
+        if (isSpecial) {
+          return;
+        }
+
+        // Don't recognize any special comments other than jshint for single-line
+        // comments. This introduced many problems with legit comments.
+        if (label === "//" && str !== "jshint") {
+          return;
+        }
+
+        if (body.charAt(str.length) === " " && body.substr(0, str.length) === str) {
+          isSpecial = true;
+          label = label + str;
+          body = body.substr(str.length);
+        }
+
+        if (!isSpecial && body.charAt(0) === " " && body.charAt(str.length + 1) === " " &&
+          body.substr(1, str.length) === str) {
+          isSpecial = true;
+          label = label + " " + str;
+          body = body.substr(str.length + 1);
+        }
+
+        if (!isSpecial) {
+          return;
+        }
+
+        switch (str) {
+        case "member":
+          commentType = "members";
+          break;
+        case "global":
+          commentType = "globals";
+          break;
+        default:
+          var options = body.split(":").map(function(v) {
+            return v.replace(/^\s+/, "").replace(/\s+$/, "");
+          });
+
+          if (options.length === 2) {
+            switch (options[0]) {
+            case "ignore":
+              switch (options[1]) {
+              case "start":
+                self.ignoringLinterErrors = true;
+                isSpecial = false;
+                break;
+              case "end":
+                self.ignoringLinterErrors = false;
+                isSpecial = false;
+                break;
+              }
+            }
+          }
+
+          commentType = str;
+        }
+      });
+
+      return {
+        type: Token.Comment,
+        commentType: commentType,
+        value: value,
+        body: body,
+        isSpecial: isSpecial,
+        isMultiline: opt.isMultiline || false,
+        isMalformed: opt.isMalformed || false
+      };
+    }
+
+    // End of unbegun comment. Raise an error and skip that input.
+    if (ch1 === "*" && ch2 === "/") {
+      this.trigger("error", {
+        code: "E018",
+        line: startLine,
+        character: startChar
+      });
+
+      this.skip(2);
+      return null;
+    }
+
+    // Comments must start either with // or /*
+    if (ch1 !== "/" || (ch2 !== "*" && ch2 !== "/")) {
+      return null;
+    }
+
+    // One-line comment
+    if (ch2 === "/") {
+      this.skip(this.input.length); // Skip to the EOL.
+      return commentToken("//", rest);
+    }
+
+    var body = "";
+
+    /* Multi-line comment */
+    if (ch2 === "*") {
+      this.inComment = true;
+      this.skip(2);
+
+      while (this.peek() !== "*" || this.peek(1) !== "/") {
+        if (this.peek() === "") { // End of Line
+          body += "\n";
+
+          // If we hit EOF and our comment is still unclosed,
+          // trigger an error and end the comment implicitly.
+          if (!this.nextLine(checks)) {
+            this.trigger("error", {
+              code: "E017",
+              line: startLine,
+              character: startChar
+            });
+
+            this.inComment = false;
+            return commentToken("/*", body, {
+              isMultiline: true,
+              isMalformed: true
+            });
+          }
+        } else {
+          body += this.peek();
+          this.skip();
+        }
+      }
+
+      this.skip(2);
+      this.inComment = false;
+      return commentToken("/*", body, { isMultiline: true });
+    }
+  },
+
+  /*
+   * Extract a keyword out of the next sequence of characters or
+   * return 'null' if its not possible.
+   */
+  scanKeyword: function() {
+    var result = /^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(this.input);
+    var keywords = [
+      "if", "in", "do", "var", "for", "new",
+      "try", "let", "this", "else", "case",
+      "void", "with", "enum", "while", "break",
+      "catch", "throw", "const", "yield", "class",
+      "super", "return", "typeof", "delete",
+      "switch", "export", "import", "default",
+      "finally", "extends", "function", "continue",
+      "debugger", "instanceof"
+    ];
+
+    if (result && keywords.indexOf(result[0]) >= 0) {
+      return {
+        type: Token.Keyword,
+        value: result[0]
+      };
+    }
+
+    return null;
+  },
+
+  /*
+   * Extract a JavaScript identifier out of the next sequence of
+   * characters or return 'null' if its not possible. In addition,
+   * to Identifier this method can also produce BooleanLiteral
+   * (true/false) and NullLiteral (null).
+   */
+  scanIdentifier: function() {
+    var id = "";
+    var index = 0;
+    var type, char;
+
+    function isNonAsciiIdentifierStart(code) {
+      return nonAsciiIdentifierStartTable.indexOf(code) > -1;
+    }
+
+    function isNonAsciiIdentifierPart(code) {
+      return isNonAsciiIdentifierStart(code) || nonAsciiIdentifierPartTable.indexOf(code) > -1;
+    }
+
+    var readUnicodeEscapeSequence = function() {
+      /*jshint validthis:true */
+      index += 1;
+
+      if (this.peek(index) !== "u") {
+        return null;
+      }
+
+      var sequence = this.peek(index + 1) + this.peek(index + 2) +
+        this.peek(index + 3) + this.peek(index + 4);
+      var code;
+
+      if (isHex(sequence)) {
+        code = parseInt(sequence, 16);
+
+        if (asciiIdentifierPartTable[code] || isNonAsciiIdentifierPart(code)) {
+          index += 5;
+          return "\\u" + sequence;
+        }
+
+        return null;
+      }
+
+      return null;
+    }.bind(this);
+
+    var getIdentifierStart = function() {
+      /*jshint validthis:true */
+      var chr = this.peek(index);
+      var code = chr.charCodeAt(0);
+
+      if (code === 92) {
+        return readUnicodeEscapeSequence();
+      }
+
+      if (code < 128) {
+        if (asciiIdentifierStartTable[code]) {
+          index += 1;
+          return chr;
+        }
+
+        return null;
+      }
+
+      if (isNonAsciiIdentifierStart(code)) {
+        index += 1;
+        return chr;
+      }
+
+      return null;
+    }.bind(this);
+
+    var getIdentifierPart = function() {
+      /*jshint validthis:true */
+      var chr = this.peek(index);
+      var code = chr.charCodeAt(0);
+
+      if (code === 92) {
+        return readUnicodeEscapeSequence();
+      }
+
+      if (code < 128) {
+        if (asciiIdentifierPartTable[code]) {
+          index += 1;
+          return chr;
+        }
+
+        return null;
+      }
+
+      if (isNonAsciiIdentifierPart(code)) {
+        index += 1;
+        return chr;
+      }
+
+      return null;
+    }.bind(this);
+
+    function removeEscapeSequences(id) {
+      return id.replace(/\\u([0-9a-fA-F]{4})/g, function(m0, codepoint) {
+        return String.fromCharCode(parseInt(codepoint, 16));
+      });
+    }
+
+    char = getIdentifierStart();
+    if (char === null) {
+      return null;
+    }
+
+    id = char;
+    for (;;) {
+      char = getIdentifierPart();
+
+      if (char === null) {
+        break;
+      }
+
+      id += char;
+    }
+
+    switch (id) {
+    case "true":
+    case "false":
+      type = Token.BooleanLiteral;
+      break;
+    case "null":
+      type = Token.NullLiteral;
+      break;
+    default:
+      type = Token.Identifier;
+    }
+
+    return {
+      type: type,
+      value: removeEscapeSequences(id),
+      text: id,
+      tokenLength: id.length
+    };
+  },
+
+  /*
+   * Extract a numeric literal out of the next sequence of
+   * characters or return 'null' if its not possible. This method
+   * supports all numeric literals described in section 7.8.3
+   * of the EcmaScript 5 specification.
+   *
+   * This method's implementation was heavily influenced by the
+   * scanNumericLiteral function in the Esprima parser's source code.
+   */
+  scanNumericLiteral: function(checks) {
+    var index = 0;
+    var value = "";
+    var length = this.input.length;
+    var char = this.peek(index);
+    var bad;
+    var isAllowedDigit = isDecimalDigit;
+    var base = 10;
+    var isLegacy = false;
+
+    function isDecimalDigit(str) {
+      return (/^[0-9]$/).test(str);
+    }
+
+    function isOctalDigit(str) {
+      return (/^[0-7]$/).test(str);
+    }
+
+    function isBinaryDigit(str) {
+      return (/^[01]$/).test(str);
+    }
+
+    function isIdentifierStart(ch) {
+      return (ch === "$") || (ch === "_") || (ch === "\\") ||
+        (ch >= "a" && ch <= "z") || (ch >= "A" && ch <= "Z");
+    }
+
+    // Numbers must start either with a decimal digit or a point.
+
+    if (char !== "." && !isDecimalDigit(char)) {
+      return null;
+    }
+
+    if (char !== ".") {
+      value = this.peek(index);
+      index += 1;
+      char = this.peek(index);
+
+      if (value === "0") {
+        // Base-16 numbers.
+        if (char === "x" || char === "X") {
+          isAllowedDigit = isHexDigit;
+          base = 16;
+
+          index += 1;
+          value += char;
+        }
+
+        // Base-8 numbers.
+        if (char === "o" || char === "O") {
+          isAllowedDigit = isOctalDigit;
+          base = 8;
+
+          if (!state.inES6(true)) {
+            this.triggerAsync(
+              "warning",
+              {
+                code: "W119",
+                line: this.line,
+                character: this.char,
+                data: [ "Octal integer literal", "6" ]
+              },
+              checks,
+              function() { return true; }
+            );
+          }
+
+          index += 1;
+          value += char;
+        }
+
+        // Base-2 numbers.
+        if (char === "b" || char === "B") {
+          isAllowedDigit = isBinaryDigit;
+          base = 2;
+
+          if (!state.inES6(true)) {
+            this.triggerAsync(
+              "warning",
+              {
+                code: "W119",
+                line: this.line,
+                character: this.char,
+                data: [ "Binary integer literal", "6" ]
+              },
+              checks,
+              function() { return true; }
+            );
+          }
+
+          index += 1;
+          value += char;
+        }
+
+        // Legacy base-8 numbers.
+        if (isOctalDigit(char)) {
+          isAllowedDigit = isOctalDigit;
+          base = 8;
+          isLegacy = true;
+          bad = false;
+
+          index += 1;
+          value += char;
+        }
+
+        // Decimal numbers that start with '0' such as '09' are illegal
+        // but we still parse them and return as malformed.
+
+        if (!isOctalDigit(char) && isDecimalDigit(char)) {
+          index += 1;
+          value += char;
+        }
+      }
+
+      while (index < length) {
+        char = this.peek(index);
+
+        if (isLegacy && isDecimalDigit(char)) {
+          // Numbers like '019' (note the 9) are not valid octals
+          // but we still parse them and mark as malformed.
+          bad = true;
+        } else if (!isAllowedDigit(char)) {
+          break;
+        }
+        value += char;
+        index += 1;
+      }
+
+      if (isAllowedDigit !== isDecimalDigit) {
+        if (!isLegacy && value.length <= 2) { // 0x
+          return {
+            type: Token.NumericLiteral,
+            value: value,
+            isMalformed: true
+          };
+        }
+
+        if (index < length) {
+          char = this.peek(index);
+          if (isIdentifierStart(char)) {
+            return null;
+          }
+        }
+
+        return {
+          type: Token.NumericLiteral,
+          value: value,
+          base: base,
+          isLegacy: isLegacy,
+          isMalformed: false
+        };
+      }
+    }
+
+    // Decimal digits.
+
+    if (char === ".") {
+      value += char;
+      index += 1;
+
+      while (index < length) {
+        char = this.peek(index);
+        if (!isDecimalDigit(char)) {
+          break;
+        }
+        value += char;
+        index += 1;
+      }
+    }
+
+    // Exponent part.
+
+    if (char === "e" || char === "E") {
+      value += char;
+      index += 1;
+      char = this.peek(index);
+
+      if (char === "+" || char === "-") {
+        value += this.peek(index);
+        index += 1;
+      }
+
+      char = this.peek(index);
+      if (isDecimalDigit(char)) {
+        value += char;
+        index += 1;
+
+        while (index < length) {
+          char = this.peek(index);
+          if (!isDecimalDigit(char)) {
+            break;
+          }
+          value += char;
+          index += 1;
+        }
+      } else {
+        return null;
+      }
+    }
+
+    if (index < length) {
+      char = this.peek(index);
+      if (isIdentifierStart(char)) {
+        return null;
+      }
+    }
+
+    return {
+      type: Token.NumericLiteral,
+      value: value,
+      base: base,
+      isMalformed: !isFinite(value)
+    };
+  },
+
+
+  // Assumes previously parsed character was \ (=== '\\') and was not skipped.
+  scanEscapeSequence: function(checks) {
+    var allowNewLine = false;
+    var jump = 1;
+    this.skip();
+    var char = this.peek();
+
+    switch (char) {
+    case "'":
+      this.triggerAsync("warning", {
+        code: "W114",
+        line: this.line,
+        character: this.char,
+        data: [ "\\'" ]
+      }, checks, function() {return state.jsonMode; });
+      break;
+    case "b":
+      char = "\\b";
+      break;
+    case "f":
+      char = "\\f";
+      break;
+    case "n":
+      char = "\\n";
+      break;
+    case "r":
+      char = "\\r";
+      break;
+    case "t":
+      char = "\\t";
+      break;
+    case "0":
+      char = "\\0";
+
+      // Octal literals fail in strict mode.
+      // Check if the number is between 00 and 07.
+      var n = parseInt(this.peek(1), 10);
+      this.triggerAsync("warning", {
+        code: "W115",
+        line: this.line,
+        character: this.char
+      }, checks,
+      function() { return n >= 0 && n <= 7 && state.isStrict(); });
+      break;
+    case "1":
+    case "2":
+    case "3":
+    case "4":
+    case "5":
+    case "6":
+    case "7":
+      char = "\\" + char;
+      this.triggerAsync("warning", {
+        code: "W115",
+        line: this.line,
+        character: this.char
+      }, checks,
+      function() { return state.isStrict(); });
+      break;
+    case "u":
+      var sequence = this.input.substr(1, 4);
+      var code = parseInt(sequence, 16);
+      if (!isHex(sequence)) {
+        // This condition unequivocally describes a syntax error.
+        // TODO: Re-factor as an "error" (not a "warning").
+        this.trigger("warning", {
+          code: "W052",
+          line: this.line,
+          character: this.char,
+          data: [ "u" + sequence ]
+        });
+      }
+      char = String.fromCharCode(code);
+      jump = 5;
+      break;
+    case "v":
+      this.triggerAsync("warning", {
+        code: "W114",
+        line: this.line,
+        character: this.char,
+        data: [ "\\v" ]
+      }, checks, function() { return state.jsonMode; });
+
+      char = "\v";
+      break;
+    case "x":
+      var  x = parseInt(this.input.substr(1, 2), 16);
+
+      this.triggerAsync("warning", {
+        code: "W114",
+        line: this.line,
+        character: this.char,
+        data: [ "\\x-" ]
+      }, checks, function() { return state.jsonMode; });
+
+      char = String.fromCharCode(x);
+      jump = 3;
+      break;
+    case "\\":
+      char = "\\\\";
+      break;
+    case "\"":
+      char = "\\\"";
+      break;
+    case "/":
+      break;
+    case "":
+      allowNewLine = true;
+      char = "";
+      break;
+    }
+
+    return { char: char, jump: jump, allowNewLine: allowNewLine };
+  },
+
+  /*
+   * Extract a template literal out of the next sequence of characters
+   * and/or lines or return 'null' if its not possible. Since template
+   * literals can span across multiple lines, this method has to move
+   * the char pointer.
+   */
+  scanTemplateLiteral: function(checks) {
+    var tokenType;
+    var value = "";
+    var ch;
+    var startLine = this.line;
+    var startChar = this.char;
+    var depth = this.templateStarts.length;
+
+    if (this.peek() === "`") {
+      if (!state.inES6(true)) {
+        this.triggerAsync(
+          "warning",
+          {
+            code: "W119",
+            line: this.line,
+            character: this.char,
+            data: ["template literal syntax", "6"]
+          },
+          checks,
+          function() { return true; }
+        );
+      }
+      // Template must start with a backtick.
+      tokenType = Token.TemplateHead;
+      this.templateStarts.push({ line: this.line, char: this.char });
+      depth = this.templateStarts.length;
+      this.skip(1);
+      this.pushContext(Context.Template);
+    } else if (this.inContext(Context.Template) && this.peek() === "}") {
+      // If we're in a template context, and we have a '}', lex a TemplateMiddle.
+      tokenType = Token.TemplateMiddle;
+    } else {
+      // Go lex something else.
+      return null;
+    }
+
+    while (this.peek() !== "`") {
+      while ((ch = this.peek()) === "") {
+        value += "\n";
+        if (!this.nextLine(checks)) {
+          // Unclosed template literal --- point to the starting "`"
+          var startPos = this.templateStarts.pop();
+          this.trigger("error", {
+            code: "E052",
+            line: startPos.line,
+            character: startPos.char
+          });
+          return {
+            type: tokenType,
+            value: value,
+            startLine: startLine,
+            startChar: startChar,
+            isUnclosed: true,
+            depth: depth,
+            context: this.popContext()
+          };
+        }
+      }
+
+      if (ch === '$' && this.peek(1) === '{') {
+        value += '${';
+        this.skip(2);
+        return {
+          type: tokenType,
+          value: value,
+          startLine: startLine,
+          startChar: startChar,
+          isUnclosed: false,
+          depth: depth,
+          context: this.currentContext()
+        };
+      } else if (ch === '\\') {
+        var escape = this.scanEscapeSequence(checks);
+        value += escape.char;
+        this.skip(escape.jump);
+      } else if (ch !== '`') {
+        // Otherwise, append the value and continue.
+        value += ch;
+        this.skip(1);
+      }
+    }
+
+    // Final value is either NoSubstTemplate or TemplateTail
+    tokenType = tokenType === Token.TemplateHead ? Token.NoSubstTemplate : Token.TemplateTail;
+    this.skip(1);
+    this.templateStarts.pop();
+
+    return {
+      type: tokenType,
+      value: value,
+      startLine: startLine,
+      startChar: startChar,
+      isUnclosed: false,
+      depth: depth,
+      context: this.popContext()
+    };
+  },
+
+  /*
+   * Extract a string out of the next sequence of characters and/or
+   * lines or return 'null' if its not possible. Since strings can
+   * span across multiple lines this method has to move the char
+   * pointer.
+   *
+   * This method recognizes pseudo-multiline JavaScript strings:
+   *
+   *   var str = "hello\
+   *   world";
+   */
+  scanStringLiteral: function(checks) {
+    /*jshint loopfunc:true */
+    var quote = this.peek();
+
+    // String must start with a quote.
+    if (quote !== "\"" && quote !== "'") {
+      return null;
+    }
+
+    // In JSON strings must always use double quotes.
+    this.triggerAsync("warning", {
+      code: "W108",
+      line: this.line,
+      character: this.char // +1?
+    }, checks, function() { return state.jsonMode && quote !== "\""; });
+
+    var value = "";
+    var startLine = this.line;
+    var startChar = this.char;
+    var allowNewLine = false;
+
+    this.skip();
+
+    while (this.peek() !== quote) {
+      if (this.peek() === "") { // End Of Line
+
+        // If an EOL is not preceded by a backslash, show a warning
+        // and proceed like it was a legit multi-line string where
+        // author simply forgot to escape the newline symbol.
+        //
+        // Another approach is to implicitly close a string on EOL
+        // but it generates too many false positives.
+
+        if (!allowNewLine) {
+          // This condition unequivocally describes a syntax error.
+          // TODO: Re-factor as an "error" (not a "warning").
+          this.trigger("warning", {
+            code: "W112",
+            line: this.line,
+            character: this.char
+          });
+        } else {
+          allowNewLine = false;
+
+          // Otherwise show a warning if multistr option was not set.
+          // For JSON, show warning no matter what.
+
+          this.triggerAsync("warning", {
+            code: "W043",
+            line: this.line,
+            character: this.char
+          }, checks, function() { return !state.option.multistr; });
+
+          this.triggerAsync("warning", {
+            code: "W042",
+            line: this.line,
+            character: this.char
+          }, checks, function() { return state.jsonMode && state.option.multistr; });
+        }
+
+        // If we get an EOF inside of an unclosed string, show an
+        // error and implicitly close it at the EOF point.
+
+        if (!this.nextLine(checks)) {
+          this.trigger("error", {
+            code: "E029",
+            line: startLine,
+            character: startChar
+          });
+
+          return {
+            type: Token.StringLiteral,
+            value: value,
+            startLine: startLine,
+            startChar: startChar,
+            isUnclosed: true,
+            quote: quote
+          };
+        }
+
+      } else { // Any character other than End Of Line
+
+        allowNewLine = false;
+        var char = this.peek();
+        var jump = 1; // A length of a jump, after we're done
+                      // parsing this character.
+
+        if (char < " ") {
+          // Warn about a control character in a string.
+          this.triggerAsync(
+            "warning",
+            {
+              code: "W113",
+              line: this.line,
+              character: this.char,
+              data: [ "<non-printable>" ]
+            },
+            checks,
+            function() { return true; }
+          );
+        }
+
+        // Special treatment for some escaped characters.
+        if (char === "\\") {
+          var parsed = this.scanEscapeSequence(checks);
+          char = parsed.char;
+          jump = parsed.jump;
+          allowNewLine = parsed.allowNewLine;
+        }
+
+        value += char;
+        this.skip(jump);
+      }
+    }
+
+    this.skip();
+    return {
+      type: Token.StringLiteral,
+      value: value,
+      startLine: startLine,
+      startChar: startChar,
+      isUnclosed: false,
+      quote: quote
+    };
+  },
+
+  /*
+   * Extract a regular expression out of the next sequence of
+   * characters and/or lines or return 'null' if its not possible.
+   *
+   * This method is platform dependent: it accepts almost any
+   * regular expression values but then tries to compile and run
+   * them using system's RegExp object. This means that there are
+   * rare edge cases where one JavaScript engine complains about
+   * your regular expression while others don't.
+   */
+  scanRegExp: function(checks) {
+    var index = 0;
+    var length = this.input.length;
+    var char = this.peek();
+    var value = char;
+    var body = "";
+    var flags = [];
+    var malformed = false;
+    var isCharSet = false;
+    var terminated, malformedDesc;
+
+    var scanUnexpectedChars = function() {
+      // Unexpected control character
+      if (char < " ") {
+        malformed = true;
+        this.triggerAsync(
+          "warning",
+          {
+            code: "W048",
+            line: this.line,
+            character: this.char
+          },
+          checks,
+          function() { return true; }
+        );
+      }
+
+      // Unexpected escaped character
+      if (char === "<") {
+        malformed = true;
+        this.triggerAsync(
+          "warning",
+          {
+            code: "W049",
+            line: this.line,
+            character: this.char,
+            data: [ char ]
+          },
+          checks,
+          function() { return true; }
+        );
+      }
+    }.bind(this);
+
+    // Regular expressions must start with '/'
+    if (!this.prereg || char !== "/") {
+      return null;
+    }
+
+    index += 1;
+    terminated = false;
+
+    // Try to get everything in between slashes. A couple of
+    // cases aside (see scanUnexpectedChars) we don't really
+    // care whether the resulting expression is valid or not.
+    // We will check that later using the RegExp object.
+
+    while (index < length) {
+      char = this.peek(index);
+      value += char;
+      body += char;
+
+      if (isCharSet) {
+        if (char === "]") {
+          if (this.peek(index - 1) !== "\\" || this.peek(index - 2) === "\\") {
+            isCharSet = false;
+          }
+        }
+
+        if (char === "\\") {
+          index += 1;
+          char = this.peek(index);
+          body += char;
+          value += char;
+
+          scanUnexpectedChars();
+        }
+
+        index += 1;
+        continue;
+      }
+
+      if (char === "\\") {
+        index += 1;
+        char = this.peek(index);
+        body += char;
+        value += char;
+
+        scanUnexpectedChars();
+
+        if (char === "/") {
+          index += 1;
+          continue;
+        }
+
+        if (char === "[") {
+          index += 1;
+          continue;
+        }
+      }
+
+      if (char === "[") {
+        isCharSet = true;
+        index += 1;
+        continue;
+      }
+
+      if (char === "/") {
+        body = body.substr(0, body.length - 1);
+        terminated = true;
+        index += 1;
+        break;
+      }
+
+      index += 1;
+    }
+
+    // A regular expression that was never closed is an
+    // error from which we cannot recover.
+
+    if (!terminated) {
+      this.trigger("error", {
+        code: "E015",
+        line: this.line,
+        character: this.from
+      });
+
+      return void this.trigger("fatal", {
+        line: this.line,
+        from: this.from
+      });
+    }
+
+    // Parse flags (if any).
+
+    while (index < length) {
+      char = this.peek(index);
+      if (!/[gimy]/.test(char)) {
+        break;
+      }
+      if (char === "y") {
+        if (!state.inES6(true)) {
+          this.triggerAsync(
+            "warning",
+            {
+              code: "W119",
+              line: this.line,
+              character: this.char,
+              data: [ "Sticky RegExp flag", "6" ]
+            },
+            checks,
+            function() { return true; }
+          );
+        }
+        if (value.indexOf("y") > -1) {
+          malformedDesc = "Duplicate RegExp flag";
+        }
+      } else {
+        flags.push(char);
+      }
+      value += char;
+      index += 1;
+    }
+
+    // Check regular expression for correctness.
+
+    try {
+      new RegExp(body, flags.join(""));
+    } catch (err) {
+      /**
+       * Because JSHint relies on the current engine's RegExp parser to
+       * validate RegExp literals, the description (exposed as the "data"
+       * property on the error object) is platform dependent.
+       */
+      malformedDesc = err.message;
+    }
+
+    if (malformedDesc) {
+      malformed = true;
+      this.trigger("error", {
+        code: "E016",
+        line: this.line,
+        character: this.char,
+        data: [ malformedDesc ]
+      });
+    }
+
+    return {
+      type: Token.RegExp,
+      value: value,
+      flags: flags,
+      isMalformed: malformed
+    };
+  },
+
+  /*
+   * Scan for any occurrence of non-breaking spaces. Non-breaking spaces
+   * can be mistakenly typed on OS X with option-space. Non UTF-8 web
+   * pages with non-breaking pages produce syntax errors.
+   */
+  scanNonBreakingSpaces: function() {
+    return state.option.nonbsp ?
+      this.input.search(/(\u00A0)/) : -1;
+  },
+
+  /*
+   * Scan for characters that get silently deleted by one or more browsers.
+   */
+  scanUnsafeChars: function() {
+    return this.input.search(reg.unsafeChars);
+  },
+
+  /*
+   * Produce the next raw token or return 'null' if no tokens can be matched.
+   * This method skips over all space characters.
+   */
+  next: function(checks) {
+    this.from = this.char;
+
+    // Move to the next non-space character.
+    while (/\s/.test(this.peek())) {
+      this.from += 1;
+      this.skip();
+    }
+
+    // Methods that work with multi-line structures and move the
+    // character pointer.
+
+    var match = this.scanComments(checks) ||
+      this.scanStringLiteral(checks) ||
+      this.scanTemplateLiteral(checks);
+
+    if (match) {
+      return match;
+    }
+
+    // Methods that don't move the character pointer.
+
+    match =
+      this.scanRegExp(checks) ||
+      this.scanPunctuator() ||
+      this.scanKeyword() ||
+      this.scanIdentifier() ||
+      this.scanNumericLiteral(checks);
+
+    if (match) {
+      this.skip(match.tokenLength || match.value.length);
+      return match;
+    }
+
+    // No token could be matched, give up.
+
+    return null;
+  },
+
+  /*
+   * Switch to the next line and reset all char pointers. Once
+   * switched, this method also checks for other minor warnings.
+   */
+  nextLine: function(checks) {
+    var char;
+
+    if (this.line >= this.getLines().length) {
+      return false;
+    }
+
+    this.input = this.getLines()[this.line];
+    this.line += 1;
+    this.char = 1;
+    this.from = 1;
+
+    var inputTrimmed = this.input.trim();
+
+    var startsWith = function() {
+      return _.some(arguments, function(prefix) {
+        return inputTrimmed.indexOf(prefix) === 0;
+      });
+    };
+
+    var endsWith = function() {
+      return _.some(arguments, function(suffix) {
+        return inputTrimmed.indexOf(suffix, inputTrimmed.length - suffix.length) !== -1;
+      });
+    };
+
+    // If we are ignoring linter errors, replace the input with empty string
+    // if it doesn't already at least start or end a multi-line comment
+    if (this.ignoringLinterErrors === true) {
+      if (!startsWith("/*", "//") && !(this.inComment && endsWith("*/"))) {
+        this.input = "";
+      }
+    }
+
+    char = this.scanNonBreakingSpaces();
+    if (char >= 0) {
+      this.triggerAsync(
+        "warning",
+        { code: "W125", line: this.line, character: char + 1 },
+        checks,
+        function() { return true; }
+      );
+    }
+
+    this.input = this.input.replace(/\t/g, state.tab);
+    char = this.scanUnsafeChars();
+
+    if (char >= 0) {
+      this.triggerAsync(
+        "warning",
+        { code: "W100", line: this.line, character: char },
+        checks,
+        function() { return true; }
+      );
+    }
+
+    // If there is a limit on line length, warn when lines get too
+    // long.
+
+    if (!this.ignoringLinterErrors && state.option.maxlen &&
+      state.option.maxlen < this.input.length) {
+      var inComment = this.inComment ||
+        startsWith.call(inputTrimmed, "//") ||
+        startsWith.call(inputTrimmed, "/*");
+
+      var shouldTriggerError = !inComment || !reg.maxlenException.test(inputTrimmed);
+
+      if (shouldTriggerError) {
+        this.triggerAsync(
+          "warning",
+          { code: "W101", line: this.line, character: this.input.length },
+          checks,
+          function() { return true; }
+        );
+      }
+    }
+
+    return true;
+  },
+
+  /*
+   * Produce the next token. This function is called by advance() to get
+   * the next token. It returns a token in a JSLint-compatible format.
+   */
+  token: function() {
+    /*jshint loopfunc:true */
+    var checks = asyncTrigger();
+    var token;
+
+
+    function isReserved(token, isProperty) {
+      if (!token.reserved) {
+        return false;
+      }
+      var meta = token.meta;
+
+      if (meta && meta.isFutureReservedWord && state.inES5()) {
+        // ES3 FutureReservedWord in an ES5 environment.
+        if (!meta.es5) {
+          return false;
+        }
+
+        // Some ES5 FutureReservedWord identifiers are active only
+        // within a strict mode environment.
+        if (meta.strictOnly) {
+          if (!state.option.strict && !state.isStrict()) {
+            return false;
+          }
+        }
+
+        if (isProperty) {
+          return false;
+        }
+      }
+
+      return true;
+    }
+
+    // Produce a token object.
+    var create = function(type, value, isProperty, token) {
+      /*jshint validthis:true */
+      var obj;
+
+      if (type !== "(endline)" && type !== "(end)") {
+        this.prereg = false;
+      }
+
+      if (type === "(punctuator)") {
+        switch (value) {
+        case ".":
+        case ")":
+        case "~":
+        case "#":
+        case "]":
+        case "++":
+        case "--":
+          this.prereg = false;
+          break;
+        default:
+          this.prereg = true;
+        }
+
+        obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
+      }
+
+      if (type === "(identifier)") {
+        if (value === "return" || value === "case" || value === "yield" ||
+            value === "typeof" || value === "instanceof") {
+          this.prereg = true;
+        }
+
+        if (_.has(state.syntax, value)) {
+          obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
+
+          // If this can't be a reserved keyword, reset the object.
+          if (!isReserved(obj, isProperty && type === "(identifier)")) {
+            obj = null;
+          }
+        }
+      }
+
+      if (type === "(template)" || type === "(template middle)") {
+        this.prereg = true;
+      }
+
+      if (!obj) {
+        obj = Object.create(state.syntax[type]);
+      }
+
+      obj.identifier = (type === "(identifier)");
+      obj.type = obj.type || type;
+      obj.value = value;
+      obj.line = this.line;
+      obj.character = this.char;
+      obj.from = this.from;
+      if (obj.identifier && token) obj.raw_text = token.text || token.value;
+      if (token && token.startLine && token.startLine !== this.line) {
+        obj.startLine = token.startLine;
+      }
+      if (token && token.context) {
+        // Context of current token
+        obj.context = token.context;
+      }
+      if (token && token.depth) {
+        // Nested template depth
+        obj.depth = token.depth;
+      }
+      if (token && token.isUnclosed) {
+        // Mark token as unclosed string / template literal
+        obj.isUnclosed = token.isUnclosed;
+      }
+
+      if (isProperty && obj.identifier) {
+        obj.isProperty = isProperty;
+      }
+
+      obj.check = checks.check;
+
+      return obj;
+    }.bind(this);
+
+    for (;;) {
+      if (!this.input.length) {
+        if (this.nextLine(checks)) {
+          return create("(endline)", "");
+        }
+
+        if (this.exhausted) {
+          return null;
+        }
+
+        this.exhausted = true;
+        return create("(end)", "");
+      }
+
+      token = this.next(checks);
+
+      if (!token) {
+        if (this.input.length) {
+          // Unexpected character.
+          this.trigger("error", {
+            code: "E024",
+            line: this.line,
+            character: this.char,
+            data: [ this.peek() ]
+          });
+
+          this.input = "";
+        }
+
+        continue;
+      }
+
+      switch (token.type) {
+      case Token.StringLiteral:
+        this.triggerAsync("String", {
+          line: this.line,
+          char: this.char,
+          from: this.from,
+          startLine: token.startLine,
+          startChar: token.startChar,
+          value: token.value,
+          quote: token.quote
+        }, checks, function() { return true; });
+
+        return create("(string)", token.value, null, token);
+
+      case Token.TemplateHead:
+        this.trigger("TemplateHead", {
+          line: this.line,
+          char: this.char,
+          from: this.from,
+          startLine: token.startLine,
+          startChar: token.startChar,
+          value: token.value
+        });
+        return create("(template)", token.value, null, token);
+
+      case Token.TemplateMiddle:
+        this.trigger("TemplateMiddle", {
+          line: this.line,
+          char: this.char,
+          from: this.from,
+          startLine: token.startLine,
+          startChar: token.startChar,
+          value: token.value
+        });
+        return create("(template middle)", token.value, null, token);
+
+      case Token.TemplateTail:
+        this.trigger("TemplateTail", {
+          line: this.line,
+          char: this.char,
+          from: this.from,
+          startLine: token.startLine,
+          startChar: token.startChar,
+          value: token.value
+        });
+        return create("(template tail)", token.value, null, token);
+
+      case Token.NoSubstTemplate:
+        this.trigger("NoSubstTemplate", {
+          line: this.line,
+          char: this.char,
+          from: this.from,
+          startLine: token.startLine,
+          startChar: token.startChar,
+          value: token.value
+        });
+        return create("(no subst template)", token.value, null, token);
+
+      case Token.Identifier:
+        this.triggerAsync("Identifier", {
+          line: this.line,
+          char: this.char,
+          from: this.from,
+          name: token.value,
+          raw_name: token.text,
+          isProperty: state.tokens.curr.id === "."
+        }, checks, function() { return true; });
+
+        /* falls through */
+      case Token.Keyword:
+      case Token.NullLiteral:
+      case Token.BooleanLiteral:
+        return create("(identifier)", token.value, state.tokens.curr.id === ".", token);
+
+      case Token.NumericLiteral:
+        if (token.isMalformed) {
+          // This condition unequivocally describes a syntax error.
+          // TODO: Re-factor as an "error" (not a "warning").
+          this.trigger("warning", {
+            code: "W045",
+            line: this.line,
+            character: this.char,
+            data: [ token.value ]
+          });
+        }
+
+        this.triggerAsync("warning", {
+          code: "W114",
+          line: this.line,
+          character: this.char,
+          data: [ "0x-" ]
+        }, checks, function() { return token.base === 16 && state.jsonMode; });
+
+        this.triggerAsync("warning", {
+          code: "W115",
+          line: this.line,
+          character: this.char
+        }, checks, function() {
+          return state.isStrict() && token.base === 8 && token.isLegacy;
+        });
+
+        this.trigger("Number", {
+          line: this.line,
+          char: this.char,
+          from: this.from,
+          value: token.value,
+          base: token.base,
+          isMalformed: token.malformed
+        });
+
+        return create("(number)", token.value);
+
+      case Token.RegExp:
+        return create("(regexp)", token.value);
+
+      case Token.Comment:
+        state.tokens.curr.comment = true;
+
+        if (token.isSpecial) {
+          return {
+            id: '(comment)',
+            value: token.value,
+            body: token.body,
+            type: token.commentType,
+            isSpecial: token.isSpecial,
+            line: this.line,
+            character: this.char,
+            from: this.from
+          };
+        }
+
+        break;
+
+      case "":
+        break;
+
+      default:
+        return create("(punctuator)", token.value);
+      }
+    }
+  }
+};
+
+exports.Lexer = Lexer;
+exports.Context = Context;
+
+},{"../data/ascii-identifier-data.js":1,"../data/non-ascii-identifier-part-only.js":2,"../data/non-ascii-identifier-start.js":3,"./reg.js":17,"./state.js":19,"events":5,"lodash":12}],14:[function(require,module,exports){
+"use strict";
+
+var _ = require("lodash");
+
+var errors = {
+  // JSHint options
+  E001: "Bad option: '{a}'.",
+  E002: "Bad option value.",
+
+  // JSHint input
+  E003: "Expected a JSON value.",
+  E004: "Input is neither a string nor an array of strings.",
+  E005: "Input is empty.",
+  E006: "Unexpected early end of program.",
+
+  // Strict mode
+  E007: "Missing \"use strict\" statement.",
+  E008: "Strict violation.",
+  E009: "Option 'validthis' can't be used in a global scope.",
+  E010: "'with' is not allowed in strict mode.",
+
+  // Constants
+  E011: "'{a}' has already been declared.",
+  E012: "const '{a}' is initialized to 'undefined'.",
+  E013: "Attempting to override '{a}' which is a constant.",
+
+  // Regular expressions
+  E014: "A regular expression literal can be confused with '/='.",
+  E015: "Unclosed regular expression.",
+  E016: "Invalid regular expression.",
+
+  // Tokens
+  E017: "Unclosed comment.",
+  E018: "Unbegun comment.",
+  E019: "Unmatched '{a}'.",
+  E020: "Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",
+  E021: "Expected '{a}' and instead saw '{b}'.",
+  E022: "Line breaking error '{a}'.",
+  E023: "Missing '{a}'.",
+  E024: "Unexpected '{a}'.",
+  E025: "Missing ':' on a case clause.",
+  E026: "Missing '}' to match '{' from line {a}.",
+  E027: "Missing ']' to match '[' from line {a}.",
+  E028: "Illegal comma.",
+  E029: "Unclosed string.",
+
+  // Everything else
+  E030: "Expected an identifier and instead saw '{a}'.",
+  E031: "Bad assignment.", // FIXME: Rephrase
+  E032: "Expected a small integer or 'false' and instead saw '{a}'.",
+  E033: "Expected an operator and instead saw '{a}'.",
+  E034: "get/set are ES5 features.",
+  E035: "Missing property name.",
+  E036: "Expected to see a statement and instead saw a block.",
+  E037: null,
+  E038: null,
+  E039: "Function declarations are not invocable. Wrap the whole function invocation in parens.",
+  E040: "Each value should have its own case label.",
+  E041: "Unrecoverable syntax error.",
+  E042: "Stopping.",
+  E043: "Too many errors.",
+  E044: null,
+  E045: "Invalid for each loop.",
+  E046: "Yield expressions may only occur within generator functions.",
+  E047: null,
+  E048: "{a} declaration not directly within block.",
+  E049: "A {a} cannot be named '{b}'.",
+  E050: "Mozilla requires the yield expression to be parenthesized here.",
+  E051: null,
+  E052: "Unclosed template literal.",
+  E053: "{a} declarations are only allowed at the top level of module scope.",
+  E054: "Class properties must be methods. Expected '(' but instead saw '{a}'.",
+  E055: "The '{a}' option cannot be set after any executable code.",
+  E056: "'{a}' was used before it was declared, which is illegal for '{b}' variables.",
+  E057: "Invalid meta property: '{a}.{b}'.",
+  E058: "Missing semicolon.",
+  E059: "Incompatible values for the '{a}' and '{b}' linting options.",
+  E060: "Non-callable values cannot be used as the second operand to instanceof.",
+  E061: "Invalid position for 'yield' expression (consider wrapping in parenthesis)."
+};
+
+var warnings = {
+  W001: "'hasOwnProperty' is a really bad name.",
+  W002: "Value of '{a}' may be overwritten in IE 8 and earlier.",
+  W003: "'{a}' was used before it was defined.",
+  W004: "'{a}' is already defined.",
+  W005: "A dot following a number can be confused with a decimal point.",
+  W006: "Confusing minuses.",
+  W007: "Confusing plusses.",
+  W008: "A leading decimal point can be confused with a dot: '{a}'.",
+  W009: "The array literal notation [] is preferable.",
+  W010: "The object literal notation {} is preferable.",
+  W011: null,
+  W012: null,
+  W013: null,
+  W014: "Misleading line break before '{a}'; readers may interpret this as an expression boundary.",
+  W015: null,
+  W016: "Unexpected use of '{a}'.",
+  W017: "Bad operand.",
+  W018: "Confusing use of '{a}'.",
+  W019: "Use the isNaN function to compare with NaN.",
+  W020: "Read only.",
+  W021: "Reassignment of '{a}', which is is a {b}. " +
+    "Use 'var' or 'let' to declare bindings that may change.",
+  W022: "Do not assign to the exception parameter.",
+  W023: "Expected an identifier in an assignment and instead saw a function invocation.",
+  W024: "Expected an identifier and instead saw '{a}' (a reserved word).",
+  W025: "Missing name in function declaration.",
+  W026: "Inner functions should be listed at the top of the outer function.",
+  W027: "Unreachable '{a}' after '{b}'.",
+  W028: "Label '{a}' on {b} statement.",
+  W030: "Expected an assignment or function call and instead saw an expression.",
+  W031: "Do not use 'new' for side effects.",
+  W032: "Unnecessary semicolon.",
+  W033: "Missing semicolon.",
+  W034: "Unnecessary directive \"{a}\".",
+  W035: "Empty block.",
+  W036: "Unexpected /*member '{a}'.",
+  W037: "'{a}' is a statement label.",
+  W038: "'{a}' used out of scope.",
+  W039: "'{a}' is not allowed.",
+  W040: "If a strict mode function is executed using function invocation, " +
+    "its 'this' value will be undefined.",
+  W041: null,
+  W042: "Avoid EOL escaping.",
+  W043: "Bad escaping of EOL. Use option multistr if needed.",
+  W044: "Bad or unnecessary escaping.", /* TODO(caitp): remove W044 */
+  W045: "Bad number '{a}'.",
+  W046: "Don't use extra leading zeros '{a}'.",
+  W047: "A trailing decimal point can be confused with a dot: '{a}'.",
+  W048: "Unexpected control character in regular expression.",
+  W049: "Unexpected escaped character '{a}' in regular expression.",
+  W050: "JavaScript URL.",
+  W051: "Variables should not be deleted.",
+  W052: "Unexpected '{a}'.",
+  W053: "Do not use {a} as a constructor.",
+  W054: "The Function constructor is a form of eval.",
+  W055: "A constructor name should start with an uppercase letter.",
+  W056: "Bad constructor.",
+  W057: "Weird construction. Is 'new' necessary?",
+  W058: "Missing '()' invoking a constructor.",
+  W059: "Avoid arguments.{a}.",
+  W060: "document.write can be a form of eval.",
+  W061: "eval can be harmful.",
+  W062: "Wrap an immediate function invocation in parens " +
+    "to assist the reader in understanding that the expression " +
+    "is the result of a function, and not the function itself.",
+  W063: "Math is not a function.",
+  W064: "Missing 'new' prefix when invoking a constructor.",
+  W065: "Missing radix parameter.",
+  W066: "Implied eval. Consider passing a function instead of a string.",
+  W067: "Bad invocation.",
+  W068: "Wrapping non-IIFE function literals in parens is unnecessary.",
+  W069: "['{a}'] is better written in dot notation.",
+  W070: "Extra comma. (it breaks older versions of IE)",
+  W071: "This function has too many statements. ({a})",
+  W072: "This function has too many parameters. ({a})",
+  W073: "Blocks are nested too deeply. ({a})",
+  W074: "This function's cyclomatic complexity is too high. ({a})",
+  W075: "Duplicate {a} '{b}'.",
+  W076: "Unexpected parameter '{a}' in get {b} function.",
+  W077: "Expected a single parameter in set {a} function.",
+  W078: "Setter is defined without getter.",
+  W079: "Redefinition of '{a}'.",
+  W080: "It's not necessary to initialize '{a}' to 'undefined'.",
+  W081: null,
+  W082: "Function declarations should not be placed in blocks. " +
+    "Use a function expression or move the statement to the top of " +
+    "the outer function.",
+  W083: "Functions declared within loops referencing an outer scoped " +
+    "variable may lead to confusing semantics.",
+  W084: "Expected a conditional expression and instead saw an assignment.",
+  W085: "Don't use 'with'.",
+  W086: "Expected a 'break' statement before '{a}'.",
+  W087: "Forgotten 'debugger' statement?",
+  W088: "Creating global 'for' variable. Should be 'for (var {a} ...'.",
+  W089: "The body of a for in should be wrapped in an if statement to filter " +
+    "unwanted properties from the prototype.",
+  W090: "'{a}' is not a statement label.",
+  W091: null,
+  W093: "Did you mean to return a conditional instead of an assignment?",
+  W094: "Unexpected comma.",
+  W095: "Expected a string and instead saw {a}.",
+  W096: "The '{a}' key may produce unexpected results.",
+  W097: "Use the function form of \"use strict\".",
+  W098: "'{a}' is defined but never used.",
+  W099: null,
+  W100: "This character may get silently deleted by one or more browsers.",
+  W101: "Line is too long.",
+  W102: null,
+  W103: "The '{a}' property is deprecated.",
+  W104: "'{a}' is available in ES{b} (use 'esversion: {b}') or Mozilla JS extensions (use moz).",
+  W105: "Unexpected {a} in '{b}'.",
+  W106: "Identifier '{a}' is not in camel case.",
+  W107: "Script URL.",
+  W108: "Strings must use doublequote.",
+  W109: "Strings must use singlequote.",
+  W110: "Mixed double and single quotes.",
+  W112: "Unclosed string.",
+  W113: "Control character in string: {a}.",
+  W114: "Avoid {a}.",
+  W115: "Octal literals are not allowed in strict mode.",
+  W116: "Expected '{a}' and instead saw '{b}'.",
+  W117: "'{a}' is not defined.",
+  W118: "'{a}' is only available in Mozilla JavaScript extensions (use moz option).",
+  W119: "'{a}' is only available in ES{b} (use 'esversion: {b}').",
+  W120: "You might be leaking a variable ({a}) here.",
+  W121: "Extending prototype of native object: '{a}'.",
+  W122: "Invalid typeof value '{a}'",
+  W123: "'{a}' is already defined in outer scope.",
+  W124: "A generator function should contain at least one yield expression.",
+  W125: "This line contains non-breaking spaces: http://jshint.com/docs/options/#nonbsp",
+  W126: "Unnecessary grouping operator.",
+  W127: "Unexpected use of a comma operator.",
+  W128: "Empty array elements require elision=true.",
+  W129: "'{a}' is defined in a future version of JavaScript. Use a " +
+    "different variable name to avoid migration issues.",
+  W130: "Invalid element after rest element.",
+  W131: "Invalid parameter after rest parameter.",
+  W132: "`var` declarations are forbidden. Use `let` or `const` instead.",
+  W133: "Invalid for-{a} loop left-hand-side: {b}.",
+  W134: "The '{a}' option is only available when linting ECMAScript {b} code.",
+  W135: "{a} may not be supported by non-browser environments.",
+  W136: "'{a}' must be in function scope.",
+  W137: "Empty destructuring.",
+  W138: "Regular parameters should not come after default parameters.",
+  W139: "Function expressions should not be used as the second operand to instanceof.",
+  W140: "Missing comma."
+};
+
+var info = {
+  I001: "Comma warnings can be turned off with 'laxcomma'.",
+  I002: null,
+  I003: "ES5 option is now set per default"
+};
+
+exports.errors = {};
+exports.warnings = {};
+exports.info = {};
+
+_.each(errors, function(desc, code) {
+  exports.errors[code] = { code: code, desc: desc };
+});
+
+_.each(warnings, function(desc, code) {
+  exports.warnings[code] = { code: code, desc: desc };
+});
+
+_.each(info, function(desc, code) {
+  exports.info[code] = { code: code, desc: desc };
+});
+
+},{"lodash":12}],15:[function(require,module,exports){
+"use strict";
+
+function NameStack() {
+  this._stack = [];
+}
+
+Object.defineProperty(NameStack.prototype, "length", {
+  get: function() {
+    return this._stack.length;
+  }
+});
+
+/**
+ * Create a new entry in the stack. Useful for tracking names across
+ * expressions.
+ */
+NameStack.prototype.push = function() {
+  this._stack.push(null);
+};
+
+/**
+ * Discard the most recently-created name on the stack.
+ */
+NameStack.prototype.pop = function() {
+  this._stack.pop();
+};
+
+/**
+ * Update the most recent name on the top of the stack.
+ *
+ * @param {object} token The token to consider as the source for the most
+ *                       recent name.
+ */
+NameStack.prototype.set = function(token) {
+  this._stack[this.length - 1] = token;
+};
+
+/**
+ * Generate a string representation of the most recent name.
+ *
+ * @returns {string}
+ */
+NameStack.prototype.infer = function() {
+  var nameToken = this._stack[this.length - 1];
+  var prefix = "";
+  var type;
+
+  // During expected operation, the topmost entry on the stack will only
+  // reflect the current function's name when the function is declared without
+  // the `function` keyword (i.e. for in-line accessor methods). In other
+  // cases, the `function` expression itself will introduce an empty entry on
+  // the top of the stack, and this should be ignored.
+  if (!nameToken || nameToken.type === "class") {
+    nameToken = this._stack[this.length - 2];
+  }
+
+  if (!nameToken) {
+    return "(empty)";
+  }
+
+  type = nameToken.type;
+
+  if (type !== "(string)" && type !== "(number)" && type !== "(identifier)" && type !== "default") {
+    return "(expression)";
+  }
+
+  if (nameToken.accessorType) {
+    prefix = nameToken.accessorType + " ";
+  }
+
+  return prefix + nameToken.value;
+};
+
+module.exports = NameStack;
+
+},{}],16:[function(require,module,exports){
+"use strict";
+
+// These are the JSHint boolean options.
+exports.bool = {
+  enforcing: {
+
+    /**
+     * This option prohibits the use of bitwise operators such as `^` (XOR),
+     * `|` (OR) and others. Bitwise operators are very rare in JavaScript
+     * programs and quite often `&` is simply a mistyped `&&`.
+     */
+    bitwise     : true,
+
+    /**
+     *
+     * This options prohibits overwriting prototypes of native objects such as
+     * `Array`, `Date` and so on.
+     *
+     *     // jshint freeze:true
+     *     Array.prototype.count = function (value) { return 4; };
+     *     // -> Warning: Extending prototype of native object: 'Array'.
+     */
+    freeze      : true,
+
+    /**
+     * This option allows you to force all variable names to use either
+     * camelCase style or UPPER_CASE with underscores.
+     *
+     * @deprecated JSHint is limiting its scope to issues of code correctness.
+     *             If you would like to enforce rules relating to code style,
+     *             check out [the JSCS
+     *             project](https://github.com/jscs-dev/node-jscs).
+     */
+    camelcase   : true,
+
+    /**
+     * This option requires you to always put curly braces around blocks in
+     * loops and conditionals. JavaScript allows you to omit curly braces when
+     * the block consists of only one statement, for example:
+     *
+     *     while (day)
+     *       shuffle();
+     *
+     * However, in some circumstances, it can lead to bugs (you'd think that
+     * `sleep()` is a part of the loop while in reality it is not):
+     *
+     *     while (day)
+     *       shuffle();
+     *       sleep();
+     */
+    curly       : true,
+
+    /**
+     * This options prohibits the use of `==` and `!=` in favor of `===` and
+     * `!==`. The former try to coerce values before comparing them which can
+     * lead to some unexpected results. The latter don't do any coercion so
+     * they are generally safer. If you would like to learn more about type
+     * coercion in JavaScript, we recommend [Truth, Equality and
+     * JavaScript](http://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/)
+     * by Angus Croll.
+     */
+    eqeqeq      : true,
+
+    /**
+     * This option enables warnings about the use of identifiers which are
+     * defined in future versions of JavaScript. Although overwriting them has
+     * no effect in contexts where they are not implemented, this practice can
+     * cause issues when migrating codebases to newer versions of the language.
+     */
+    futurehostile: true,
+
+    /**
+     * This option tells JSHint that your code needs to adhere to ECMAScript 3
+     * specification. Use this option if you need your program to be executable
+     * in older browsers—such as Internet Explorer 6/7/8/9—and other legacy
+     * JavaScript environments.
+     *
+     * @deprecated Use `esversion: 3` instead.
+     */
+    es3         : true,
+
+    /**
+     * This option enables syntax first defined in [the ECMAScript 5.1
+     * specification](http://es5.github.io/). This includes allowing reserved
+     * keywords as object properties.
+     *
+     * @deprecated Use `esversion: 5` instead.
+     */
+    es5         : true,
+
+    /**
+     * This option requires all `for in` loops to filter object's items. The
+     * for in statement allows for looping through the names of all of the
+     * properties of an object including those inherited through the prototype
+     * chain. This behavior can lead to unexpected items in your object so it
+     * is generally safer to always filter inherited properties out as shown in
+     * the example:
+     *
+     *     for (key in obj) {
+     *       if (obj.hasOwnProperty(key)) {
+     *         // We are sure that obj[key] belongs to the object and was not inherited.
+     *       }
+     *     }
+     *
+     * For more in-depth understanding of `for in` loops in JavaScript, read
+     * [Exploring JavaScript for-in
+     * loops](http://javascriptweblog.wordpress.com/2011/01/04/exploring-javascript-for-in-loops/)
+     * by Angus Croll.
+     */
+    forin       : true,
+
+    /**
+     * This option prohibits the use of immediate function invocations without
+     * wrapping them in parentheses. Wrapping parentheses assists readers of
+     * your code in understanding that the expression is the result of a
+     * function, and not the function itself.
+     *
+     * @deprecated JSHint is limiting its scope to issues of code correctness.
+     *             If you would like to enforce rules relating to code style,
+     *             check out [the JSCS
+     *             project](https://github.com/jscs-dev/node-jscs).
+     */
+    immed       : true,
+
+    /**
+     * This option requires you to capitalize names of constructor functions.
+     * Capitalizing functions that are intended to be used with `new` operator
+     * is just a convention that helps programmers to visually distinguish
+     * constructor functions from other types of functions to help spot
+     * mistakes when using `this`.
+     *
+     * Not doing so won't break your code in any browsers or environments but
+     * it will be a bit harder to figure out—by reading the code—if the
+     * function was supposed to be used with or without new. And this is
+     * important because when the function that was intended to be used with
+     * `new` is used without it, `this` will point to the global object instead
+     * of a new object.
+     *
+     * @deprecated JSHint is limiting its scope to issues of code correctness.
+     *             If you would like to enforce rules relating to code style,
+     *             check out [the JSCS
+     *             project](https://github.com/jscs-dev/node-jscs).
+     */
+    newcap      : true,
+
+    /**
+     * This option prohibits the use of `arguments.caller` and
+     * `arguments.callee`.  Both `.caller` and `.callee` make quite a few
+     * optimizations impossible so they were deprecated in future versions of
+     * JavaScript. In fact, ECMAScript 5 forbids the use of `arguments.callee`
+     * in strict mode.
+     */
+    noarg       : true,
+
+    /**
+     * This option prohibits the use of the comma operator. When misused, the
+     * comma operator can obscure the value of a statement and promote
+     * incorrect code.
+     */
+    nocomma     : true,
+
+    /**
+     * This option warns when you have an empty block in your code. JSLint was
+     * originally warning for all empty blocks and we simply made it optional.
+     * There were no studies reporting that empty blocks in JavaScript break
+     * your code in any way.
+     *
+     * @deprecated JSHint is limiting its scope to issues of code correctness.
+     *             If you would like to enforce rules relating to code style,
+     *             check out [the JSCS
+     *             project](https://github.com/jscs-dev/node-jscs).
+     */
+    noempty     : true,
+
+    /**
+     * This option warns about "non-breaking whitespace" characters. These
+     * characters can be entered with option-space on Mac computers and have a
+     * potential of breaking non-UTF8 web pages.
+     */
+    nonbsp      : true,
+
+    /**
+     * This option prohibits the use of constructor functions for side-effects.
+     * Some people like to call constructor functions without assigning its
+     * result to any variable:
+     *
+     *     new MyConstructor();
+     *
+     * There is no advantage in this approach over simply calling
+     * `MyConstructor` since the object that the operator `new` creates isn't
+     * used anywhere so you should generally avoid constructors like this one.
+     */
+    nonew       : true,
+
+    /**
+     * This option prohibits the use of explicitly undeclared variables. This
+     * option is very useful for spotting leaking and mistyped variables.
+     *
+     *     // jshint undef:true
+     *
+     *     function test() {
+     *       var myVar = 'Hello, World';
+     *       console.log(myvar); // Oops, typoed here. JSHint with undef will complain
+     *     }
+     *
+     * If your variable is defined in another file, you can use the `global`
+     * directive to tell JSHint about it.
+     */
+    undef       : true,
+
+    /**
+     * This option prohibits the use of the grouping operator when it is not
+     * strictly required. Such usage commonly reflects a misunderstanding of
+     * unary operators, for example:
+     *
+     *     // jshint singleGroups: true
+     *
+     *     delete(obj.attr); // Warning: Unnecessary grouping operator.
+     */
+    singleGroups: false,
+
+    /**
+     * When set to true, the use of VariableStatements are forbidden.
+     * For example:
+     *
+     *     // jshint varstmt: true
+     *
+     *     var a; // Warning: `var` declarations are forbidden. Use `let` or `const` instead.
+     */
+    varstmt: false,
+
+    /**
+     * This option is a short hand for the most strict JSHint configuration as
+     * available in JSHint version 2.6.3. It enables all enforcing options and
+     * disables all relaxing options that were defined in that release.
+     *
+     * @deprecated The option cannot be maintained without automatically opting
+     *             users in to new features. This can lead to unexpected
+     *             warnings/errors in when upgrading between minor versions of
+     *             JSHint.
+     */
+    enforceall : false,
+
+    /**
+     * This option warns when a comma is not placed after the last element in an
+     * array or object literal. Due to bugs in old versions of IE, trailing
+     * commas used to be discouraged, but since ES5 their semantics were
+     * standardized. (See
+     * [#11.1.4](http://www.ecma-international.org/ecma-262/5.1/#sec-11.1.4) and
+     * [#11.1.5](http://www.ecma-international.org/ecma-262/5.1/#sec-11.1.5).)
+     * Now, they help to prevent the same [visual
+     * ambiguities](http://www.ecma-international.org/ecma-262/5.1/#sec-7.9.2)
+     * that the strict usage of semicolons helps prevent.
+     *
+     * For example, this code might have worked last Tuesday:
+     *
+     *     [
+     *         b + c
+     *     ].forEach(print);
+     *
+     * But if one adds an element to the array and forgets to compensate for the
+     * missing comma, no syntax error is thrown, and a linter cannot determine
+     * if this was a mistake or an intentional function invocation.
+     *
+     *     [
+     *         b + c
+     *         (d + e)
+     *     ].forEach(print);
+     *
+     * If one always appends a list item with a comma, this ambiguity cannot
+     * occur:
+     *
+     *     [
+     *         b + c,
+     *     ].forEach(print);
+     *
+     *     [
+     *         b + c,
+     *         (d + e),
+     *     ].forEach(print);
+     */
+    trailingcomma: false
+  },
+  relaxing: {
+
+    /**
+     * This option suppresses warnings about missing semicolons. There is a lot
+     * of FUD about semicolon spread by quite a few people in the community.
+     * The common myths are that semicolons are required all the time (they are
+     * not) and that they are unreliable. JavaScript has rules about semicolons
+     * which are followed by *all* browsers so it is up to you to decide
+     * whether you should or should not use semicolons in your code.
+     *
+     * For more information about semicolons in JavaScript read [An Open Letter
+     * to JavaScript Leaders Regarding
+     * Semicolons](http://blog.izs.me/post/2353458699/an-open-letter-to-javascript-leaders-regarding)
+     * by Isaac Schlueter and [JavaScript Semicolon
+     * Insertion](http://inimino.org/~inimino/blog/javascript_semicolons).
+     */
+    asi         : true,
+
+    /**
+     * This option suppresses warnings about multi-line strings. Multi-line
+     * strings can be dangerous in JavaScript because all hell breaks loose if
+     * you accidentally put a whitespace in between the escape character (`\`)
+     * and a new line.
+     *
+     * Note that even though this option allows correct multi-line strings, it
+     * still warns about multi-line strings without escape characters or with
+     * anything in between the escape character and a whitespace.
+     *
+     *     // jshint multistr:true
+     *
+     *     var text = "Hello\
+     *     World"; // All good.
+     *
+     *     text = "Hello
+     *     World"; // Warning, no escape character.
+     *
+     *     text = "Hello\
+     *     World"; // Warning, there is a space after \
+     *
+     * @deprecated JSHint is limiting its scope to issues of code correctness.
+     *             If you would like to enforce rules relating to code style,
+     *             check out [the JSCS
+     *             project](https://github.com/jscs-dev/node-jscs).
+     */
+    multistr    : true,
+
+    /**
+     * This option suppresses warnings about the `debugger` statements in your
+     * code.
+     */
+    debug       : true,
+
+    /**
+     * This option suppresses warnings about the use of assignments in cases
+     * where comparisons are expected. More often than not, code like `if (a =
+     * 10) {}` is a typo. However, it can be useful in cases like this one:
+     *
+     *     for (var i = 0, person; person = people[i]; i++) {}
+     *
+     * You can silence this error on a per-use basis by surrounding the assignment
+     * with parenthesis, such as:
+     *
+     *     for (var i = 0, person; (person = people[i]); i++) {}
+     */
+    boss        : true,
+
+    /**
+     * This option suppresses warnings about the use of `eval`. The use of
+     * `eval` is discouraged because it can make your code vulnerable to
+     * various injection attacks and it makes it hard for JavaScript
+     * interpreter to do certain optimizations.
+    */
+    evil        : true,
+
+    /**
+     * This option suppresses warnings about declaring variables inside of
+     * control
+     * structures while accessing them later from the outside. Even though
+     * JavaScript has only two real scopes—global and function—such practice
+     * leads to confusion among people new to the language and hard-to-debug
+     * bugs. This is why, by default, JSHint warns about variables that are
+     * used outside of their intended scope.
+     *
+     *     function test() {
+     *       if (true) {
+     *         var x = 0;
+     *       }
+     *
+     *       x += 1; // Default: 'x' used out of scope.
+     *                 // No warning when funcscope:true
+     *     }
+     */
+    funcscope   : true,
+
+    /**
+     * This option suppresses warnings about the use of global strict mode.
+     * Global strict mode can break third-party widgets so it is not
+     * recommended.
+     *
+     * For more info about strict mode see the `strict` option.
+     *
+     * @deprecated Use `strict: "global"`.
+     */
+    globalstrict: true,
+
+    /**
+     * This option suppresses warnings about the `__iterator__` property. This
+     * property is not supported by all browsers so use it carefully.
+     */
+    iterator    : true,
+
+     /**
+     * This option suppresses warnings about invalid `typeof` operator values.
+     * This operator has only [a limited set of possible return
+     * values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof).
+     * By default, JSHint warns when you compare its result with an invalid
+     * value which often can be a typo.
+     *
+     *     // 'fuction' instead of 'function'
+     *     if (typeof a == "fuction") { // Invalid typeof value 'fuction'
+     *       // ...
+     *     }
+     *
+     * Do not use this option unless you're absolutely sure you don't want
+     * these checks.
+     */
+    notypeof    : true,
+
+    /**
+     * This option prohibits the use of unary increment and decrement
+     * operators.  Some people think that `++` and `--` reduces the quality of
+     * their coding styles and there are programming languages—such as
+     * Python—that go completely without these operators.
+     */
+    plusplus    : true,
+
+    /**
+     * This option suppresses warnings about the `__proto__` property.
+     */
+    proto       : true,
+
+    /**
+     * This option suppresses warnings about the use of script-targeted
+     * URLs—such as `javascript:...`.
+     */
+    scripturl   : true,
+
+    /**
+     * This option suppresses warnings about using `[]` notation when it can be
+     * expressed in dot notation: `person['name']` vs. `person.name`.
+     *
+     * @deprecated JSHint is limiting its scope to issues of code correctness.
+     *             If you would like to enforce rules relating to code style,
+     *             check out [the JSCS
+     *             project](https://github.com/jscs-dev/node-jscs).
+     */
+    sub         : true,
+
+    /**
+     * This option suppresses warnings about "weird" constructions like
+     * `new function () { ... }` and `new Object;`. Such constructions are
+     * sometimes used to produce singletons in JavaScript:
+     *
+     *     var singleton = new function() {
+     *       var privateVar;
+     *
+     *       this.publicMethod  = function () {}
+     *       this.publicMethod2 = function () {}
+     *     };
+     */
+    supernew    : true,
+
+    /**
+     * This option suppresses most of the warnings about possibly unsafe line
+     * breakings in your code. It doesn't suppress warnings about comma-first
+     * coding style. To suppress those you have to use `laxcomma` (see below).
+     *
+     * @deprecated JSHint is limiting its scope to issues of code correctness.
+     *             If you would like to enforce rules relating to code style,
+     *             check out [the JSCS
+     *             project](https://github.com/jscs-dev/node-jscs).
+     */
+    laxbreak    : true,
+
+    /**
+     * This option suppresses warnings about comma-first coding style:
+     *
+     *     var obj = {
+     *         name: 'Anton'
+     *       , handle: 'valueof'
+     *       , role: 'SW Engineer'
+     *     };
+     *
+     * @deprecated JSHint is limiting its scope to issues of code correctness.
+     *             If you would like to enforce rules relating to code style,
+     *             check out [the JSCS
+     *             project](https://github.com/jscs-dev/node-jscs).
+     */
+    laxcomma    : true,
+
+    /**
+     * This option suppresses warnings about possible strict violations when
+     * the code is running in strict mode and you use `this` in a
+     * non-constructor function. You should use this option—in a function scope
+     * only—when you are positive that your use of `this` is valid in the
+     * strict mode (for example, if you call your function using
+     * `Function.call`).
+     *
+     * **Note:** This option can be used only inside of a function scope.
+     * JSHint will fail with an error if you will try to set this option
+     * globally.
+     */
+    validthis   : true,
+
+    /**
+     * This option suppresses warnings about the use of the `with` statement.
+     * The semantics of the `with` statement can cause confusion among
+     * developers and accidental definition of global variables.
+     *
+     * More info:
+     *
+     * * [with Statement Considered
+     *   Harmful](http://yuiblog.com/blog/2006/04/11/with-statement-considered-harmful/)
+     */
+    withstmt    : true,
+
+    /**
+     * This options tells JSHint that your code uses Mozilla JavaScript
+     * extensions. Unless you develop specifically for the Firefox web browser
+     * you don't need this option.
+     *
+     * More info:
+     *
+     * * [New in JavaScript
+     *   1.7](https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.7)
+     */
+    moz         : true,
+
+    /**
+     * This option suppresses warnings about generator functions with no
+     * `yield` statement in them.
+     */
+    noyield     : true,
+
+    /**
+     * This option suppresses warnings about `== null` comparisons. Such
+     * comparisons are often useful when you want to check if a variable is
+     * `null` or `undefined`.
+     */
+    eqnull      : true,
+
+    /**
+     * This option suppresses warnings about missing semicolons, but only when
+     * the semicolon is omitted for the last statement in a one-line block:
+     *
+     *     var name = (function() { return 'Anton' }());
+     *
+     * This is a very niche use case that is useful only when you use automatic
+     * JavaScript code generators.
+     */
+    lastsemic   : true,
+
+    /**
+     * This option suppresses warnings about functions inside of loops.
+     * Defining functions inside of loops can lead to bugs such as this one:
+     *
+     *     var nums = [];
+     *
+     *     for (var i = 0; i < 10; i++) {
+     *       nums[i] = function (j) {
+     *         return i + j;
+     *       };
+     *     }
+     *
+     *     nums[0](2); // Prints 12 instead of 2
+     *
+     * To fix the code above you need to copy the value of `i`:
+     *
+     *     var nums = [];
+     *
+     *     for (var i = 0; i < 10; i++) {
+     *       (function (i) {
+     *         nums[i] = function (j) {
+     *             return i + j;
+     *         };
+     *       }(i));
+     *     }
+     */
+    loopfunc    : true,
+
+    /**
+     * This option suppresses warnings about the use of expressions where
+     * normally you would expect to see assignments or function calls. Most of
+     * the time, such code is a typo. However, it is not forbidden by the spec
+     * and that's why this warning is optional.
+     */
+    expr        : true,
+
+    /**
+     * This option tells JSHint that your code uses ECMAScript 6 specific
+     * syntax. Note that not all browsers implement these features.
+     *
+     * More info:
+     *
+     * * [Specification for ECMAScript
+     *   6](http://www.ecma-international.org/ecma-262/6.0/index.html)
+     *
+     * @deprecated Use `esversion: 6` instead.
+     */
+    esnext      : true,
+
+    /**
+     * This option tells JSHint that your code uses ES3 array elision elements,
+     * or empty elements (for example, `[1, , , 4, , , 7]`).
+     */
+    elision     : true,
+  },
+
+  // Third party globals
+  environments: {
+
+    /**
+     * This option defines globals exposed by the
+     * [MooTools](http://mootools.net/) JavaScript framework.
+     */
+    mootools    : true,
+
+    /**
+     * This option defines globals exposed by
+     * [CouchDB](http://couchdb.apache.org/). CouchDB is a document-oriented
+     * database that can be queried and indexed in a MapReduce fashion using
+     * JavaScript.
+     */
+    couch       : true,
+
+    /**
+     * This option defines globals exposed by [the Jasmine unit testing
+     * framework](https://jasmine.github.io/).
+     */
+    jasmine     : true,
+
+    /**
+     * This option defines globals exposed by the [jQuery](http://jquery.com/)
+     * JavaScript library.
+     */
+    jquery      : true,
+
+    /**
+     * This option defines globals available when your code is running inside
+     * of the Node runtime environment. [Node.js](http://nodejs.org/) is a
+     * server-side JavaScript environment that uses an asynchronous
+     * event-driven model. This option also skips some warnings that make sense
+     * in the browser environments but don't make sense in Node such as
+     * file-level `use strict` pragmas and `console.log` statements.
+     */
+    node        : true,
+
+    /**
+     * This option defines globals exposed by [the QUnit unit testing
+     * framework](http://qunitjs.com/).
+     */
+    qunit       : true,
+
+    /**
+     * This option defines globals available when your code is running inside
+     * of the Rhino runtime environment. [Rhino](http://www.mozilla.org/rhino/)
+     * is an open-source implementation of JavaScript written entirely in Java.
+     */
+    rhino       : true,
+
+    /**
+     * This option defines globals exposed by [the ShellJS
+     * library](http://documentup.com/arturadib/shelljs).
+     */
+    shelljs     : true,
+
+    /**
+     * This option defines globals exposed by the
+     * [Prototype](http://www.prototypejs.org/) JavaScript framework.
+     */
+    prototypejs : true,
+
+    /**
+     * This option defines globals exposed by the [YUI](http://yuilibrary.com/)
+     * JavaScript framework.
+     */
+    yui         : true,
+
+    /**
+     * This option defines globals exposed by the "BDD" and "TDD" UIs of the
+     * [Mocha unit testing framework](http://mochajs.org/).
+     */
+    mocha       : true,
+
+    /**
+     * This option informs JSHint that the input code describes an ECMAScript 6
+     * module. All module code is interpreted as strict mode code.
+     */
+    module      : true,
+
+    /**
+     * This option defines globals available when your code is running as a
+     * script for the [Windows Script
+     * Host](http://en.wikipedia.org/wiki/Windows_Script_Host).
+     */
+    wsh         : true,
+
+    /**
+     * This option defines globals available when your code is running inside
+     * of a Web Worker. [Web
+     * Workers](https://developer.mozilla.org/en/Using_web_workers) provide a
+     * simple means for web content to run scripts in background threads.
+     */
+    worker      : true,
+
+    /**
+     * This option defines non-standard but widely adopted globals such as
+     * `escape` and `unescape`.
+     */
+    nonstandard : true,
+
+    /**
+     * This option defines globals exposed by modern browsers: all the way from
+     * good old `document` and `navigator` to the HTML5 `FileReader` and other
+     * new developments in the browser world.
+     *
+     * **Note:** This option doesn't expose variables like `alert` or
+     * `console`. See option `devel` for more information.
+     */
+    browser     : true,
+
+    /**
+     * This option defines globals available when using [the Browserify
+     * tool](http://browserify.org/) to build a project.
+     */
+    browserify  : true,
+
+    /**
+     * This option defines globals that are usually used for logging poor-man's
+     * debugging: `console`, `alert`, etc. It is usually a good idea to not
+     * ship them in production because, for example, `console.log` breaks in
+     * legacy versions of Internet Explorer.
+     */
+    devel       : true,
+
+    /**
+     * This option defines globals exposed by the [Dojo
+     * Toolkit](http://dojotoolkit.org/).
+     */
+    dojo        : true,
+
+    /**
+     * This option defines globals for typed array constructors.
+     *
+     * More info:
+     *
+     * * [JavaScript typed
+     *   arrays](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays)
+     */
+    typed       : true,
+
+    /**
+     * This option defines globals available when your core is running inside
+     * of the PhantomJS runtime environment. [PhantomJS](http://phantomjs.org/)
+     * is a headless WebKit scriptable with a JavaScript API. It has fast and
+     * native support for various web standards: DOM handling, CSS selector,
+     * JSON, Canvas, and SVG.
+     */
+    phantom     : true
+  },
+
+  // Obsolete options
+  obsolete: {
+    onecase     : true, // if one case switch statements should be allowed
+    regexp      : true, // if the . should not be allowed in regexp literals
+    regexdash   : true  // if unescaped first/last dash (-) inside brackets
+                        // should be tolerated
+  }
+};
+
+// These are the JSHint options that can take any value
+// (we use this object to detect invalid options)
+exports.val = {
+
+  /**
+   * This option lets you set the maximum length of a line.
+   *
+   * @deprecated JSHint is limiting its scope to issues of code correctness. If
+   *             you would like to enforce rules relating to code style, check
+   *             out [the JSCS project](https://github.com/jscs-dev/node-jscs).
+   */
+  maxlen       : false,
+
+  /**
+   * This option sets a specific tab width for your code.
+   *
+   * @deprecated JSHint is limiting its scope to issues of code correctness. If
+   *             you would like to enforce rules relating to code style, check
+   *             out [the JSCS project](https://github.com/jscs-dev/node-jscs).
+   */
+  indent       : false,
+
+  /**
+   * This options allows you to set the maximum amount of warnings JSHint will
+   * produce before giving up. Default is 50.
+   */
+  maxerr       : false,
+
+  /**
+   * This option allows you to control which variables JSHint considers to be
+   * implicitly defined in the environment. Configure it with an array of
+   * string values. Prefixing a variable name with a hyphen (-) character will
+   * remove that name from the collection of predefined variables.
+   *
+   * JSHint will consider variables declared in this way to be read-only.
+   *
+   * This option cannot be specified in-line; it may only be used via the
+   * JavaScript API or from an external configuration file.
+   */
+  predef       : false,
+
+  /**
+   * This option can be used to specify a white list of global variables that
+   * are not formally defined in the source code. This is most useful when
+   * combined with the `undef` option in order to suppress warnings for
+   * project-specific global variables.
+   *
+   * Setting an entry to `true` enables reading and writing to that variable.
+   * Setting it to `false` will trigger JSHint to consider that variable
+   * read-only.
+   *
+   * See also the "environment" options: a set of options to be used as short
+   * hand for enabling global variables defined in common JavaScript
+   * environments.
+   *
+   * To configure `globals` within an individual file, see [Inline
+   * Configuration](http://jshint.com/docs/#inline-configuration).
+   */
+  globals      : false,
+
+  /**
+   * This option enforces the consistency of quotation marks used throughout
+   * your code. It accepts three values: `true` if you don't want to enforce
+   * one particular style but want some consistency, `"single"` if you want to
+   * allow only single quotes and `"double"` if you want to allow only double
+   * quotes.
+   *
+   * @deprecated JSHint is limiting its scope to issues of code correctness. If
+   *             you would like to enforce rules relating to code style, check
+   *             out [the JSCS project](https://github.com/jscs-dev/node-jscs).
+   */
+  quotmark     : false,
+
+  scope        : false,
+
+  /**
+   * This option lets you set the max number of statements allowed per function:
+   *
+   *     // jshint maxstatements:4
+   *
+   *     function main() {
+   *       var i = 0;
+   *       var j = 0;
+   *
+   *       // Function declarations count as one statement. Their bodies
+   *       // don't get taken into account for the outer function.
+   *       function inner() {
+   *         var i2 = 1;
+   *         var j2 = 1;
+   *
+   *         return i2 + j2;
+   *       }
+   *
+   *       j = i + j;
+   *       return j; // JSHint: Too many statements per function. (5)
+   *     }
+   */
+  maxstatements: false,
+
+  /**
+   * This option lets you control how nested do you want your blocks to be:
+   *
+   *     // jshint maxdepth:2
+   *
+   *     function main(meaning) {
+   *       var day = true;
+   *
+   *       if (meaning === 42) {
+   *         while (day) {
+   *           shuffle();
+   *
+   *           if (tired) { // JSHint: Blocks are nested too deeply (3).
+   *               sleep();
+   *           }
+   *         }
+   *       }
+   *     }
+   */
+  maxdepth     : false,
+
+  /**
+   * This option lets you set the max number of formal parameters allowed per
+   * function:
+   *
+   *     // jshint maxparams:3
+   *
+   *     function login(request, onSuccess) {
+   *       // ...
+   *     }
+   *
+   *     // JSHint: Too many parameters per function (4).
+   *     function logout(request, isManual, whereAmI, onSuccess) {
+   *       // ...
+   *     }
+   */
+  maxparams    : false,
+
+  /**
+   * This option lets you control cyclomatic complexity throughout your code.
+   * Cyclomatic complexity measures the number of linearly independent paths
+   * through a program's source code. Read more about [cyclomatic complexity on
+   * Wikipedia](http://en.wikipedia.org/wiki/Cyclomatic_complexity).
+   */
+  maxcomplexity: false,
+
+  /**
+   * This option suppresses warnings about variable shadowing i.e. declaring a
+   * variable that had been already declared somewhere in the outer scope.
+   *
+   * - "inner"  - check for variables defined in the same scope only
+   * - "outer"  - check for variables defined in outer scopes as well
+   * - false    - same as inner
+   * - true     - allow variable shadowing
+   */
+  shadow       : false,
+
+  /**
+   * This option requires the code to run in ECMAScript 5's strict mode.
+   * [Strict mode](https://developer.mozilla.org/en/JavaScript/Strict_mode)
+   * is a way to opt in to a restricted variant of JavaScript. Strict mode
+   * eliminates some JavaScript pitfalls that didn't cause errors by changing
+   * them to produce errors.  It also fixes mistakes that made it difficult
+   * for the JavaScript engines to perform certain optimizations.
+   *
+   * - "global"  - there must be a `"use strict";` directive at global level
+   * - "implied" - lint the code as if there is the `"use strict";` directive
+   * - false     - disable warnings about strict mode
+   * - true      - there must be a `"use strict";` directive at function level;
+   *               this is preferable for scripts intended to be loaded in web
+   *               browsers directly because enabling strict mode globally
+   *               could adversely effect other scripts running on the same
+   *               page
+   */
+  strict      : true,
+
+  /**
+   * This option warns when you define and never use your variables. It is very
+   * useful for general code cleanup, especially when used in addition to
+   * `undef`.
+   *
+   *     // jshint unused:true
+   *
+   *     function test(a, b) {
+   *       var c, d = 2;
+   *
+   *       return a + d;
+   *     }
+   *
+   *     test(1, 2);
+   *
+   *     // Line 3: 'b' was defined but never used.
+   *     // Line 4: 'c' was defined but never used.
+   *
+   * In addition to that, this option will warn you about unused global
+   * variables declared via the `global` directive.
+   *
+   * When set to `true`, unused parameters that are followed by a used
+   * parameter will not produce warnings. This option can be set to `vars` to
+   * only check for variables, not function parameters, or `strict` to check
+   * all variables and parameters.
+   */
+  unused       : true,
+
+  /**
+   * This option prohibits the use of a variable before it was defined.
+   * JavaScript has function scope only and, in addition to that, all variables
+   * are always moved—or hoisted— to the top of the function. This behavior can
+   * lead to some very nasty bugs and that's why it is safer to always use
+   * variable only after they have been explicitly defined.
+   *
+   * Setting this option to "nofunc" will allow function declarations to be
+   * ignored.
+   *
+   * For more in-depth understanding of scoping and hoisting in JavaScript,
+   * read [JavaScript Scoping and
+   * Hoisting](http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting)
+   * by Ben Cherry.
+   */
+  latedef      : false,
+
+  ignore       : false, // start/end ignoring lines of code, bypassing the lexer
+                        //   start    - start ignoring lines, including the current line
+                        //   end      - stop ignoring lines, starting on the next line
+                        //   line     - ignore warnings / errors for just a single line
+                        //              (this option does not bypass the lexer)
+
+  ignoreDelimiters: false, // array of start/end delimiters used to ignore
+                           // certain chunks from code
+
+  /**
+   * This option is used to specify the ECMAScript version to which the code
+   * must adhere. It can assume one of the following values:
+   *  - `3` - If you need your program to be executable
+   *    in older browsers—such as Internet Explorer 6/7/8/9—and other legacy
+   *    JavaScript environments
+   *  - `5` - To enable syntax first defined in [the ECMAScript 5.1
+   *    specification](http://www.ecma-international.org/ecma-262/5.1/index.html).
+   *    This includes allowing reserved keywords as object properties.
+   *  - `6` - To tell JSHint that your code uses [ECMAScript
+   *    6](http://www.ecma-international.org/ecma-262/6.0/index.html) specific
+   *    syntax. Note that not all browsers implement them.
+   */
+  esversion: 5
+};
+
+// These are JSHint boolean options which are shared with JSLint
+// where the definition in JSHint is opposite JSLint
+exports.inverted = {
+  bitwise : true,
+  forin   : true,
+  newcap  : true,
+  plusplus: true,
+  regexp  : true,
+  undef   : true,
+
+  // Inverted and renamed, use JSHint name here
+  eqeqeq  : true,
+  strict  : true
+};
+
+exports.validNames = Object.keys(exports.val)
+  .concat(Object.keys(exports.bool.relaxing))
+  .concat(Object.keys(exports.bool.enforcing))
+  .concat(Object.keys(exports.bool.obsolete))
+  .concat(Object.keys(exports.bool.environments));
+
+// These are JSHint boolean options which are shared with JSLint
+// where the name has been changed but the effect is unchanged
+exports.renamed = {
+  eqeq   : "eqeqeq",
+  windows: "wsh",
+  sloppy : "strict"
+};
+
+exports.removed = {
+  nomen: true,
+  onevar: true,
+  passfail: true,
+  white: true,
+  gcl: true,
+  smarttabs: true,
+  trailing: true
+};
+
+// Add options here which should not be automatically enforced by
+// `enforceall`.
+exports.noenforceall = {
+  varstmt: true,
+  strict: true
+};
+
+},{}],17:[function(require,module,exports){
+/*
+ * Regular expressions. Some of these are stupidly long.
+ */
+
+/*jshint maxlen:1000 */
+
+"use strict";
+
+// Unsafe comment or string (ax)
+exports.unsafeString =
+  /@cc|<\/?|script|\]\s*\]|<\s*!|&lt/i;
+
+// Unsafe characters that are silently deleted by one or more browsers (cx)
+exports.unsafeChars =
+  /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
+
+// Characters in strings that need escaping (nx and nxg)
+exports.needEsc =
+  /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
+
+exports.needEscGlobal =
+  /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
+
+// Star slash (lx)
+exports.starSlash = /\*\//;
+
+// Identifier (ix)
+exports.identifier = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
+
+// JavaScript URL (jx)
+exports.javascriptURL = /^(?:javascript|jscript|ecmascript|vbscript|livescript)\s*:/i;
+
+// Catches /* falls through */ comments (ft)
+exports.fallsThrough = /^\s*falls?\sthrough\s*$/;
+
+// very conservative rule (eg: only one space between the start of the comment and the first character)
+// to relax the maxlen option
+exports.maxlenException = /^(?:(?:\/\/|\/\*|\*) ?)?[^ ]+$/;
+
+},{}],18:[function(require,module,exports){
+"use strict";
+
+var _      = require("lodash");
+var events = require("events");
+
+// Used to denote membership in lookup tables (a primitive value such as `true`
+// would be silently rejected for the property name "__proto__" in some
+// environments)
+var marker = {};
+
+/**
+ * Creates a scope manager that handles variables and labels, storing usages
+ * and resolving when variables are used and undefined
+ */
+var scopeManager = function(state, predefined, exported, declared) {
+
+  var _current;
+  var _scopeStack = [];
+
+  function _newScope(type) {
+    _current = {
+      "(labels)": Object.create(null),
+      "(usages)": Object.create(null),
+      "(breakLabels)": Object.create(null),
+      "(parent)": _current,
+      "(type)": type,
+      "(params)": (type === "functionparams" || type === "catchparams") ? [] : null
+    };
+    _scopeStack.push(_current);
+  }
+
+  _newScope("global");
+  _current["(predefined)"] = predefined;
+
+  var _currentFunctBody = _current; // this is the block after the params = function
+
+  var usedPredefinedAndGlobals = Object.create(null);
+  var impliedGlobals = Object.create(null);
+  var unuseds = [];
+  var emitter = new events.EventEmitter();
+
+  function warning(code, token) {
+    emitter.emit("warning", {
+      code: code,
+      token: token,
+      data: _.slice(arguments, 2)
+    });
+  }
+
+  function error(code, token) {
+    emitter.emit("warning", {
+      code: code,
+      token: token,
+      data: _.slice(arguments, 2)
+    });
+  }
+
+  function _setupUsages(labelName) {
+    if (!_current["(usages)"][labelName]) {
+      _current["(usages)"][labelName] = {
+        "(modified)": [],
+        "(reassigned)": [],
+        "(tokens)": []
+      };
+    }
+  }
+
+  var _getUnusedOption = function(unused_opt) {
+    if (unused_opt === undefined) {
+      unused_opt = state.option.unused;
+    }
+
+    if (unused_opt === true) {
+      unused_opt = "last-param";
+    }
+
+    return unused_opt;
+  };
+
+  var _warnUnused = function(name, tkn, type, unused_opt) {
+    var line = tkn.line;
+    var chr  = tkn.from;
+    var raw_name = tkn.raw_text || name;
+
+    unused_opt = _getUnusedOption(unused_opt);
+
+    var warnable_types = {
+      "vars": ["var"],
+      "last-param": ["var", "param"],
+      "strict": ["var", "param", "last-param"]
+    };
+
+    if (unused_opt) {
+      if (warnable_types[unused_opt] && warnable_types[unused_opt].indexOf(type) !== -1) {
+        warning("W098", { line: line, from: chr }, raw_name);
+      }
+    }
+
+    // inconsistent - see gh-1894
+    if (unused_opt || type === "var") {
+      unuseds.push({
+        name: name,
+        line: line,
+        character: chr
+      });
+    }
+  };
+
+  /**
+   * Checks the current scope for unused identifiers
+   */
+  function _checkForUnused() {
+    // function params are handled specially
+    // assume that parameters are the only thing declared in the param scope
+    if (_current["(type)"] === "functionparams") {
+      _checkParams();
+      return;
+    }
+    var curentLabels = _current["(labels)"];
+    for (var labelName in curentLabels) {
+      if (curentLabels[labelName]) {
+        if (curentLabels[labelName]["(type)"] !== "exception" &&
+          curentLabels[labelName]["(unused)"]) {
+          _warnUnused(labelName, curentLabels[labelName]["(token)"], "var");
+        }
+      }
+    }
+  }
+
+  /**
+   * Checks the current scope for unused parameters
+   * Must be called in a function parameter scope
+   */
+  function _checkParams() {
+    var params = _current["(params)"];
+
+    if (!params) {
+      return;
+    }
+
+    var param = params.pop();
+    var unused_opt;
+
+    while (param) {
+      var label = _current["(labels)"][param];
+
+      unused_opt = _getUnusedOption(state.funct["(unusedOption)"]);
+
+      // 'undefined' is a special case for (function(window, undefined) { ... })();
+      // patterns.
+      if (param === "undefined")
+        return;
+
+      if (label["(unused)"]) {
+        _warnUnused(param, label["(token)"], "param", state.funct["(unusedOption)"]);
+      } else if (unused_opt === "last-param") {
+        return;
+      }
+
+      param = params.pop();
+    }
+  }
+
+  /**
+   * Finds the relevant label's scope, searching from nearest outwards
+   * @returns {Object} the scope the label was found in
+   */
+  function _getLabel(labelName) {
+    for (var i = _scopeStack.length - 1 ; i >= 0; --i) {
+      var scopeLabels = _scopeStack[i]["(labels)"];
+      if (scopeLabels[labelName]) {
+        return scopeLabels;
+      }
+    }
+  }
+
+  function usedSoFarInCurrentFunction(labelName) {
+    // used so far in this whole function and any sub functions
+    for (var i = _scopeStack.length - 1; i >= 0; i--) {
+      var current = _scopeStack[i];
+      if (current["(usages)"][labelName]) {
+        return current["(usages)"][labelName];
+      }
+      if (current === _currentFunctBody) {
+        break;
+      }
+    }
+    return false;
+  }
+
+  function _checkOuterShadow(labelName, token) {
+
+    // only check if shadow is outer
+    if (state.option.shadow !== "outer") {
+      return;
+    }
+
+    var isGlobal = _currentFunctBody["(type)"] === "global",
+      isNewFunction = _current["(type)"] === "functionparams";
+
+    var outsideCurrentFunction = !isGlobal;
+    for (var i = 0; i < _scopeStack.length; i++) {
+      var stackItem = _scopeStack[i];
+
+      if (!isNewFunction && _scopeStack[i + 1] === _currentFunctBody) {
+        outsideCurrentFunction = false;
+      }
+      if (outsideCurrentFunction && stackItem["(labels)"][labelName]) {
+        warning("W123", token, labelName);
+      }
+      if (stackItem["(breakLabels)"][labelName]) {
+        warning("W123", token, labelName);
+      }
+    }
+  }
+
+  function _latedefWarning(type, labelName, token) {
+    if (state.option.latedef) {
+      // if either latedef is strict and this is a function
+      //    or this is not a function
+      if ((state.option.latedef === true && type === "function") ||
+        type !== "function") {
+        warning("W003", token, labelName);
+      }
+    }
+  }
+
+  var scopeManagerInst = {
+
+    on: function(names, listener) {
+      names.split(" ").forEach(function(name) {
+        emitter.on(name, listener);
+      });
+    },
+
+    isPredefined: function(labelName) {
+      return !this.has(labelName) && _.has(_scopeStack[0]["(predefined)"], labelName);
+    },
+
+    /**
+     * Tell the manager we are entering a new block of code
+     * @param {string} [type] - The type of the block. Valid values are
+     *                          "functionparams", "catchparams" and
+     *                          "functionouter"
+     */
+    stack: function(type) {
+      var previousScope = _current;
+      _newScope(type);
+
+      if (!type && previousScope["(type)"] === "functionparams") {
+
+        _current["(isFuncBody)"] = true;
+        _current["(context)"] = _currentFunctBody;
+        _currentFunctBody = _current;
+      }
+    },
+
+    unstack: function() {
+      // jshint proto: true
+      var subScope = _scopeStack.length > 1 ? _scopeStack[_scopeStack.length - 2] : null;
+      var isUnstackingFunctionBody = _current === _currentFunctBody,
+        isUnstackingFunctionParams = _current["(type)"] === "functionparams",
+        isUnstackingFunctionOuter = _current["(type)"] === "functionouter";
+
+      var i, j;
+      var currentUsages = _current["(usages)"];
+      var currentLabels = _current["(labels)"];
+      var usedLabelNameList = Object.keys(currentUsages);
+
+      if (currentUsages.__proto__ && usedLabelNameList.indexOf("__proto__") === -1) {
+        usedLabelNameList.push("__proto__");
+      }
+
+      for (i = 0; i < usedLabelNameList.length; i++) {
+        var usedLabelName = usedLabelNameList[i];
+
+        var usage = currentUsages[usedLabelName];
+        var usedLabel = currentLabels[usedLabelName];
+        if (usedLabel) {
+          var usedLabelType = usedLabel["(type)"];
+          var isImmutable = usedLabelType === "const" || usedLabelType === "import";
+
+          if (usedLabel["(useOutsideOfScope)"] && !state.option.funcscope) {
+            var usedTokens = usage["(tokens)"];
+            if (usedTokens) {
+              for (j = 0; j < usedTokens.length; j++) {
+                // Keep the consistency of https://github.com/jshint/jshint/issues/2409
+                if (usedLabel["(function)"] === usedTokens[j]["(function)"]) {
+                  error("W038", usedTokens[j], usedLabelName);
+                }
+              }
+            }
+          }
+
+          // mark the label used
+          _current["(labels)"][usedLabelName]["(unused)"] = false;
+
+          // check for modifying a const
+          if (isImmutable && usage["(modified)"]) {
+            for (j = 0; j < usage["(modified)"].length; j++) {
+              error("E013", usage["(modified)"][j], usedLabelName);
+            }
+          }
+
+          // check for re-assigning a function declaration
+          if ((usedLabelType === "function" || usedLabelType === "class") &&
+              usage["(reassigned)"]) {
+            for (j = 0; j < usage["(reassigned)"].length; j++) {
+              if (!usage["(reassigned)"][j].ignoreW021) {
+                warning("W021", usage["(reassigned)"][j], usedLabelName, usedLabelType);
+              }
+            }
+          }
+          continue;
+        }
+
+        if (isUnstackingFunctionOuter) {
+          state.funct["(isCapturing)"] = true;
+        }
+
+        if (subScope) {
+          // not exiting the global scope, so copy the usage down in case its an out of scope usage
+          if (!subScope["(usages)"][usedLabelName]) {
+            subScope["(usages)"][usedLabelName] = usage;
+            if (isUnstackingFunctionBody) {
+              subScope["(usages)"][usedLabelName]["(onlyUsedSubFunction)"] = true;
+            }
+          } else {
+            var subScopeUsage = subScope["(usages)"][usedLabelName];
+            subScopeUsage["(modified)"] = subScopeUsage["(modified)"].concat(usage["(modified)"]);
+            subScopeUsage["(tokens)"] = subScopeUsage["(tokens)"].concat(usage["(tokens)"]);
+            subScopeUsage["(reassigned)"] =
+              subScopeUsage["(reassigned)"].concat(usage["(reassigned)"]);
+          }
+        } else {
+          // this is exiting global scope, so we finalise everything here - we are at the end of the file
+          if (typeof _current["(predefined)"][usedLabelName] === "boolean") {
+
+            // remove the declared token, so we know it is used
+            delete declared[usedLabelName];
+
+            // note it as used so it can be reported
+            usedPredefinedAndGlobals[usedLabelName] = marker;
+
+            // check for re-assigning a read-only (set to false) predefined
+            if (_current["(predefined)"][usedLabelName] === false && usage["(reassigned)"]) {
+              for (j = 0; j < usage["(reassigned)"].length; j++) {
+                if (!usage["(reassigned)"][j].ignoreW020) {
+                  warning("W020", usage["(reassigned)"][j]);
+                }
+              }
+            }
+          }
+          else {
+            // label usage is not predefined and we have not found a declaration
+            // so report as undeclared
+            if (usage["(tokens)"]) {
+              for (j = 0; j < usage["(tokens)"].length; j++) {
+                var undefinedToken = usage["(tokens)"][j];
+                // if its not a forgiven undefined (e.g. typof x)
+                if (!undefinedToken.forgiveUndef) {
+                  // if undef is on and undef was on when the token was defined
+                  if (state.option.undef && !undefinedToken.ignoreUndef) {
+                    warning("W117", undefinedToken, usedLabelName);
+                  }
+                  if (impliedGlobals[usedLabelName]) {
+                    impliedGlobals[usedLabelName].line.push(undefinedToken.line);
+                  } else {
+                    impliedGlobals[usedLabelName] = {
+                      name: usedLabelName,
+                      line: [undefinedToken.line]
+                    };
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+
+      // if exiting the global scope, we can warn about declared globals that haven't been used yet
+      if (!subScope) {
+        Object.keys(declared)
+          .forEach(function(labelNotUsed) {
+            _warnUnused(labelNotUsed, declared[labelNotUsed], "var");
+          });
+      }
+
+      // If this is not a function boundary, transfer function-scoped labels to
+      // the parent block (a rough simulation of variable hoisting). Previously
+      // existing labels in the parent block should take precedence so that things and stuff.
+      if (subScope && !isUnstackingFunctionBody &&
+        !isUnstackingFunctionParams && !isUnstackingFunctionOuter) {
+        var labelNames = Object.keys(currentLabels);
+        for (i = 0; i < labelNames.length; i++) {
+
+          var defLabelName = labelNames[i];
+          var defLabel = currentLabels[defLabelName];
+
+          if (!defLabel["(blockscoped)"] && defLabel["(type)"] !== "exception") {
+            var shadowed = subScope["(labels)"][defLabelName];
+
+            // Do not overwrite a label if it exists in the parent scope
+            // because it is shared by adjacent blocks. Copy the `unused`
+            // property so that any references found within the current block
+            // are counted toward that higher-level declaration.
+            if (shadowed) {
+              shadowed["(unused)"] &= defLabel["(unused)"];
+
+            // "Hoist" the variable to the parent block, decorating the label
+            // so that future references, though technically valid, can be
+            // reported as "out-of-scope" in the absence of the `funcscope`
+            // option.
+            } else {
+              defLabel["(useOutsideOfScope)"] =
+                // Do not warn about out-of-scope usages in the global scope
+                _currentFunctBody["(type)"] !== "global" &&
+                // When a higher scope contains a binding for the label, the
+                // label is a re-declaration and should not prompt "used
+                // out-of-scope" warnings.
+                !this.funct.has(defLabelName, { excludeCurrent: true });
+
+              subScope["(labels)"][defLabelName] = defLabel;
+            }
+
+            delete currentLabels[defLabelName];
+          }
+        }
+      }
+
+      _checkForUnused();
+
+      _scopeStack.pop();
+      if (isUnstackingFunctionBody) {
+        _currentFunctBody = _scopeStack[_.findLastIndex(_scopeStack, function(scope) {
+          // if function or if global (which is at the bottom so it will only return true if we call back)
+          return scope["(isFuncBody)"] || scope["(type)"] === "global";
+        })];
+      }
+
+      _current = subScope;
+    },
+
+    /**
+     * Add a param to the current scope
+     * @param {string} labelName
+     * @param {Token} token
+     * @param {string} [type="param"] param type
+     */
+    addParam: function(labelName, token, type) {
+      type = type || "param";
+
+      if (type === "exception") {
+        // if defined in the current function
+        var previouslyDefinedLabelType = this.funct.labeltype(labelName);
+        if (previouslyDefinedLabelType && previouslyDefinedLabelType !== "exception") {
+          // and has not been used yet in the current function scope
+          if (!state.option.node) {
+            warning("W002", state.tokens.next, labelName);
+          }
+        }
+      }
+
+      // The variable was declared in the current scope
+      if (_.has(_current["(labels)"], labelName)) {
+        _current["(labels)"][labelName].duplicated = true;
+
+      // The variable was declared in an outer scope
+      } else {
+        // if this scope has the variable defined, it's a re-definition error
+        _checkOuterShadow(labelName, token, type);
+
+        _current["(labels)"][labelName] = {
+          "(type)" : type,
+          "(token)": token,
+          "(unused)": true };
+
+        _current["(params)"].push(labelName);
+      }
+
+      if (_.has(_current["(usages)"], labelName)) {
+        var usage = _current["(usages)"][labelName];
+        // if its in a sub function it is not necessarily an error, just latedef
+        if (usage["(onlyUsedSubFunction)"]) {
+          _latedefWarning(type, labelName, token);
+        } else {
+          // this is a clear illegal usage for block scoped variables
+          warning("E056", token, labelName, type);
+        }
+      }
+    },
+
+    validateParams: function() {
+      // This method only concerns errors for function parameters
+      if (_currentFunctBody["(type)"] === "global") {
+        return;
+      }
+
+      var isStrict = state.isStrict();
+      var currentFunctParamScope = _currentFunctBody["(parent)"];
+
+      if (!currentFunctParamScope["(params)"]) {
+        return;
+      }
+
+      currentFunctParamScope["(params)"].forEach(function(labelName) {
+        var label = currentFunctParamScope["(labels)"][labelName];
+
+        if (label && label.duplicated) {
+          if (isStrict) {
+            warning("E011", label["(token)"], labelName);
+          } else if (state.option.shadow !== true) {
+            warning("W004", label["(token)"], labelName);
+          }
+        }
+      });
+    },
+
+    getUsedOrDefinedGlobals: function() {
+      // jshint proto: true
+      var list = Object.keys(usedPredefinedAndGlobals);
+
+      // If `__proto__` is used as a global variable name, its entry in the
+      // lookup table may not be enumerated by `Object.keys` (depending on the
+      // environment).
+      if (usedPredefinedAndGlobals.__proto__ === marker &&
+        list.indexOf("__proto__") === -1) {
+        list.push("__proto__");
+      }
+
+      return list;
+    },
+
+    /**
+     * Gets an array of implied globals
+     * @returns {Array.<{ name: string, line: Array.<number>}>}
+     */
+    getImpliedGlobals: function() {
+      // jshint proto: true
+      var values = _.values(impliedGlobals);
+      var hasProto = false;
+
+      // If `__proto__` is an implied global variable, its entry in the lookup
+      // table may not be enumerated by `_.values` (depending on the
+      // environment).
+      if (impliedGlobals.__proto__) {
+        hasProto = values.some(function(value) {
+          return value.name === "__proto__";
+        });
+
+        if (!hasProto) {
+          values.push(impliedGlobals.__proto__);
+        }
+      }
+
+      return values;
+    },
+
+    /**
+     * Returns a list of unused variables
+     * @returns {Array}
+     */
+    getUnuseds: function() {
+      return unuseds;
+    },
+
+    has: function(labelName) {
+      return Boolean(_getLabel(labelName));
+    },
+
+    labeltype: function(labelName) {
+      // returns a labels type or null if not present
+      var scopeLabels = _getLabel(labelName);
+      if (scopeLabels) {
+        return scopeLabels[labelName]["(type)"];
+      }
+      return null;
+    },
+
+    /**
+     * for the exported options, indicating a variable is used outside the file
+     */
+    addExported: function(labelName) {
+      var globalLabels = _scopeStack[0]["(labels)"];
+      if (_.has(declared, labelName)) {
+        // remove the declared token, so we know it is used
+        delete declared[labelName];
+      } else if (_.has(globalLabels, labelName)) {
+        globalLabels[labelName]["(unused)"] = false;
+      } else {
+        for (var i = 1; i < _scopeStack.length; i++) {
+          var scope = _scopeStack[i];
+          // if `scope.(type)` is not defined, it is a block scope
+          if (!scope["(type)"]) {
+            if (_.has(scope["(labels)"], labelName) &&
+                !scope["(labels)"][labelName]["(blockscoped)"]) {
+              scope["(labels)"][labelName]["(unused)"] = false;
+              return;
+            }
+          } else {
+            break;
+          }
+        }
+        exported[labelName] = true;
+      }
+    },
+
+    /**
+     * Mark an indentifier as es6 module exported
+     */
+    setExported: function(labelName, token) {
+      this.block.use(labelName, token);
+    },
+
+    initialize: function(labelName) {
+      if (_current["(labels)"][labelName]) {
+        _current["(labels)"][labelName]["(initialized)"] = true;
+      }
+    },
+
+    /**
+     * adds an indentifier to the relevant current scope and creates warnings/errors as necessary
+     * @param {string} labelName
+     * @param {Object} opts
+     * @param {String} opts.type - the type of the label e.g. "param", "var", "let, "const", "import", "function"
+     * @param {Token} opts.token - the token pointing at the declaration
+     * @param {boolean} opts.initialized - whether the binding should be created in an "initialized" state.
+     */
+    addlabel: function(labelName, opts) {
+
+      var type  = opts.type;
+      var token = opts.token;
+      var isblockscoped = type === "let" || type === "const" ||
+        type === "class" || type === "import";
+      var ishoisted = type === "function" || type === "import";
+      var isexported    = (isblockscoped ? _current : _currentFunctBody)["(type)"] === "global" &&
+                          _.has(exported, labelName);
+
+      // outer shadow check (inner is only on non-block scoped)
+      _checkOuterShadow(labelName, token, type);
+
+      if (isblockscoped) {
+
+        var declaredInCurrentScope = _current["(labels)"][labelName];
+        // for block scoped variables, params are seen in the current scope as the root function
+        // scope, so check these too.
+        if (!declaredInCurrentScope && _current === _currentFunctBody &&
+          _current["(type)"] !== "global") {
+          declaredInCurrentScope = !!_currentFunctBody["(parent)"]["(labels)"][labelName];
+        }
+
+        // if its not already defined (which is an error, so ignore) and is used in TDZ
+        if (!declaredInCurrentScope && _current["(usages)"][labelName]) {
+          var usage = _current["(usages)"][labelName];
+          // if its in a sub function it is not necessarily an error, just latedef
+          if (usage["(onlyUsedSubFunction)"] || ishoisted) {
+            _latedefWarning(type, labelName, token);
+          } else if (!ishoisted) {
+            // this is a clear illegal usage for block scoped variables
+            warning("E056", token, labelName, type);
+          }
+        }
+
+        // if this scope has the variable defined, its a re-definition error
+        if (declaredInCurrentScope) {
+          warning("E011", token, labelName);
+        }
+        else if (state.option.shadow === "outer") {
+
+          // if shadow is outer, for block scope we want to detect any shadowing within this function
+          if (scopeManagerInst.funct.has(labelName)) {
+            warning("W004", token, labelName);
+          }
+        }
+
+        scopeManagerInst.block.add(
+          labelName, type, token, !isexported, opts.initialized
+        );
+
+      } else {
+
+        var declaredInCurrentFunctionScope = scopeManagerInst.funct.has(labelName);
+
+        // check for late definition, ignore if already declared
+        if (!declaredInCurrentFunctionScope && usedSoFarInCurrentFunction(labelName)) {
+          _latedefWarning(type, labelName, token);
+        }
+
+        // defining with a var or a function when a block scope variable of the same name
+        // is in scope is an error
+        if (scopeManagerInst.funct.has(labelName, { onlyBlockscoped: true })) {
+          warning("E011", token, labelName);
+        } else if (state.option.shadow !== true) {
+          // now since we didn't get any block scope variables, test for var/function
+          // shadowing
+          if (declaredInCurrentFunctionScope && labelName !== "__proto__") {
+
+            // see https://github.com/jshint/jshint/issues/2400
+            if (_currentFunctBody["(type)"] !== "global") {
+              warning("W004", token, labelName);
+            }
+          }
+        }
+
+        scopeManagerInst.funct.add(labelName, type, token, !isexported);
+
+        if (_currentFunctBody["(type)"] === "global" && !state.impliedClosure()) {
+          usedPredefinedAndGlobals[labelName] = marker;
+        }
+      }
+    },
+
+    funct: {
+      /**
+       * Returns the label type given certain options
+       * @param labelName
+       * @param {Object=} options
+       * @param {Boolean=} options.onlyBlockscoped - only include block scoped labels
+       * @param {Boolean=} options.excludeParams - exclude the param scope
+       * @param {Boolean=} options.excludeCurrent - exclude the current scope
+       * @returns {String}
+       */
+      labeltype: function(labelName, options) {
+        var onlyBlockscoped = options && options.onlyBlockscoped;
+        var excludeParams = options && options.excludeParams;
+        var currentScopeIndex = _scopeStack.length - (options && options.excludeCurrent ? 2 : 1);
+        for (var i = currentScopeIndex; i >= 0; i--) {
+          var current = _scopeStack[i];
+          if (current["(labels)"][labelName] &&
+            (!onlyBlockscoped || current["(labels)"][labelName]["(blockscoped)"])) {
+            return current["(labels)"][labelName]["(type)"];
+          }
+          var scopeCheck = excludeParams ? _scopeStack[ i - 1 ] : current;
+          if (scopeCheck && scopeCheck["(type)"] === "functionparams") {
+            return null;
+          }
+        }
+        return null;
+      },
+      /**
+       * Returns if a break label exists in the function scope
+       * @param {string} labelName
+       * @returns {boolean}
+       */
+      hasBreakLabel: function(labelName) {
+        for (var i = _scopeStack.length - 1; i >= 0; i--) {
+          var current = _scopeStack[i];
+
+          if (current["(breakLabels)"][labelName]) {
+            return true;
+          }
+          if (current["(type)"] === "functionparams") {
+            return false;
+          }
+        }
+        return false;
+      },
+      /**
+       * Returns if the label is in the current function scope
+       * See scopeManager.funct.labelType for options
+       */
+      has: function(labelName, options) {
+        return Boolean(this.labeltype(labelName, options));
+      },
+
+      /**
+       * Adds a new function scoped variable
+       * see block.add for block scoped
+       */
+      add: function(labelName, type, tok, unused) {
+        _current["(labels)"][labelName] = {
+          "(type)" : type,
+          "(token)": tok,
+          "(blockscoped)": false,
+          "(function)": _currentFunctBody,
+          "(unused)": unused };
+      }
+    },
+
+    block: {
+
+      /**
+       * is the current block global?
+       * @returns Boolean
+       */
+      isGlobal: function() {
+        return _current["(type)"] === "global";
+      },
+
+      use: function(labelName, token) {
+
+        // if resolves to current function params, then do not store usage just resolve
+        // this is because function(a) { var a; a = a; } will resolve to the param, not
+        // to the unset var
+        // first check the param is used
+        var paramScope = _currentFunctBody["(parent)"];
+        if (paramScope && paramScope["(labels)"][labelName] &&
+          paramScope["(labels)"][labelName]["(type)"] === "param") {
+
+          // then check its not declared by a block scope variable
+          if (!scopeManagerInst.funct.has(labelName,
+                { excludeParams: true, onlyBlockscoped: true })) {
+            paramScope["(labels)"][labelName]["(unused)"] = false;
+          }
+        }
+
+        if (token && (state.ignored.W117 || state.option.undef === false)) {
+          token.ignoreUndef = true;
+        }
+
+        _setupUsages(labelName);
+
+        _current["(usages)"][labelName]["(onlyUsedSubFunction)"] = false;
+
+        if (token) {
+          token["(function)"] = _currentFunctBody;
+          _current["(usages)"][labelName]["(tokens)"].push(token);
+        }
+
+        // blockscoped vars can't be used within their initializer (TDZ)
+        var label = _current["(labels)"][labelName];
+        if (label && label["(blockscoped)"] && !label["(initialized)"]) {
+          error("E056", token, labelName, label["(type)"]);
+        }
+      },
+
+      reassign: function(labelName, token) {
+        token.ignoreW020 = state.ignored.W020;
+        token.ignoreW021 = state.ignored.W021;
+
+        this.modify(labelName, token);
+
+        _current["(usages)"][labelName]["(reassigned)"].push(token);
+      },
+
+      modify: function(labelName, token) {
+
+        _setupUsages(labelName);
+
+        _current["(usages)"][labelName]["(onlyUsedSubFunction)"] = false;
+        _current["(usages)"][labelName]["(modified)"].push(token);
+      },
+
+      /**
+       * Adds a new variable
+       */
+      add: function(labelName, type, tok, unused, initialized) {
+        _current["(labels)"][labelName] = {
+          "(type)" : type,
+          "(token)": tok,
+          "(initialized)": !!initialized,
+          "(blockscoped)": true,
+          "(unused)": unused };
+      },
+
+      addBreakLabel: function(labelName, opts) {
+        var token = opts.token;
+        if (scopeManagerInst.funct.hasBreakLabel(labelName)) {
+          warning("E011", token, labelName);
+        }
+        else if (state.option.shadow === "outer") {
+          if (scopeManagerInst.funct.has(labelName)) {
+            warning("W004", token, labelName);
+          } else {
+            _checkOuterShadow(labelName, token);
+          }
+        }
+        _current["(breakLabels)"][labelName] = token;
+      }
+    }
+  };
+  return scopeManagerInst;
+};
+
+module.exports = scopeManager;
+
+},{"events":5,"lodash":12}],19:[function(require,module,exports){
+"use strict";
+var NameStack = require("./name-stack.js");
+
+var state = {
+  syntax: {},
+
+  /**
+   * Determine if the code currently being linted is strict mode code.
+   *
+   * @returns {boolean}
+   */
+  isStrict: function() {
+    return this.directive["use strict"] || this.inClassBody ||
+      this.option.module || this.option.strict === "implied";
+  },
+
+  /**
+   * Determine if the current state warrants a warning for statements outside
+   * of strict mode code.
+   *
+   * While emitting warnings based on function scope would be more intuitive
+   * (and less noisy), JSHint observes statement-based semantics in order to
+   * preserve legacy behavior.
+   *
+   * This method does not take the state of the parser into account, making no
+   * distinction between global code and function code. Because the "missing
+   * 'use strict'" warning is *also* reported at function boundaries, this
+   * function interprets `strict` option values `true` and `undefined` as
+   * equivalent.
+   */
+  stmtMissingStrict: function() {
+    if (this.option.strict === "global") {
+      return true;
+    }
+
+    if (this.option.strict === false) {
+      return false;
+    }
+
+    if (this.option.globalstrict) {
+      return true;
+    }
+
+    return false;
+  },
+
+  allowsGlobalUsd: function() {
+    return this.option.strict === "global" || this.option.globalstrict ||
+      this.option.module || this.impliedClosure();
+  },
+
+  /**
+   * Determine if the current configuration describes an environment that is
+   * wrapped in an immediately-invoked function expression prior to evaluation.
+   *
+   * @returns {boolean}
+   */
+  impliedClosure: function() {
+    return this.option.node || this.option.phantom || this.option.browserify;
+  },
+
+  // Assumption: chronologically ES3 < ES5 < ES6 < Moz
+
+  inMoz: function() {
+    return this.option.moz;
+  },
+
+  /**
+   * @param {boolean} strict - When `true`, only consider ES6 when in
+   *                           "esversion: 6" code.
+   */
+  inES6: function(strict) {
+    if (strict) {
+      return this.esVersion === 6;
+    }
+    return this.option.moz || this.esVersion >= 6;
+  },
+
+  /**
+   * @param {boolean} strict - When `true`, return `true` only when
+   *                           esVersion is exactly 5
+   */
+  inES5: function(strict) {
+    if (strict) {
+      return (!this.esVersion || this.esVersion === 5) && !this.option.moz;
+    }
+    return !this.esVersion || this.esVersion >= 5 || this.option.moz;
+  },
+
+  /**
+   * Determine the current version of the input language by inspecting the
+   * value of all ECMAScript-version-related options. This logic is necessary
+   * to ensure compatibility with deprecated options `es3`, `es5`, and
+   * `esnext`, and it may be drastically simplified when those options are
+   * removed.
+   *
+   * @returns {string|null} - the name of any incompatible option detected,
+   *                          `null` otherwise
+   */
+  inferEsVersion: function() {
+    var badOpt = null;
+
+    if (this.option.esversion) {
+      if (this.option.es3) {
+        badOpt = "es3";
+      } else if (this.option.es5) {
+        badOpt = "es5";
+      } else if (this.option.esnext) {
+        badOpt = "esnext";
+      }
+
+      if (badOpt) {
+        return badOpt;
+      }
+
+      if (this.option.esversion === 2015) {
+        this.esVersion = 6;
+      } else {
+        this.esVersion = this.option.esversion;
+      }
+    } else if (this.option.es3) {
+      this.esVersion = 3;
+    } else if (this.option.esnext) {
+      this.esVersion = 6;
+    }
+
+    return null;
+  },
+
+  reset: function() {
+    this.tokens = {
+      prev: null,
+      next: null,
+      curr: null
+    };
+
+    this.option = {};
+    this.esVersion = 5;
+    this.funct = null;
+    this.ignored = {};
+    this.directive = {};
+    this.jsonMode = false;
+    this.jsonWarnings = [];
+    this.lines = [];
+    this.tab = "";
+    this.cache = {}; // Node.JS doesn't have Map. Sniff.
+    this.ignoredLines = {};
+    this.forinifcheckneeded = false;
+    this.nameStack = new NameStack();
+    this.inClassBody = false;
+  }
+};
+
+exports.state = state;
+
+},{"./name-stack.js":15}],20:[function(require,module,exports){
+"use strict";
+
+exports.register = function(linter) {
+  // Check for properties named __proto__. This special property was
+  // deprecated and then re-introduced for ES6.
+
+  linter.on("Identifier", function style_scanProto(data) {
+    if (linter.getOption("proto")) {
+      return;
+    }
+
+    if (data.name === "__proto__") {
+      linter.warn("W103", {
+        line: data.line,
+        char: data.char,
+        data: [ data.name, "6" ]
+      });
+    }
+  });
+
+  // Check for properties named __iterator__. This is a special property
+  // available only in browsers with JavaScript 1.7 implementation, but
+  // it is deprecated for ES6
+
+  linter.on("Identifier", function style_scanIterator(data) {
+    if (linter.getOption("iterator")) {
+      return;
+    }
+
+    if (data.name === "__iterator__") {
+      linter.warn("W103", {
+        line: data.line,
+        char: data.char,
+        data: [ data.name ]
+      });
+    }
+  });
+
+  // Check that all identifiers are using camelCase notation.
+  // Exceptions: names like MY_VAR and _myVar.
+
+  linter.on("Identifier", function style_scanCamelCase(data) {
+    if (!linter.getOption("camelcase")) {
+      return;
+    }
+
+    if (data.name.replace(/^_+|_+$/g, "").indexOf("_") > -1 && !data.name.match(/^[A-Z0-9_]*$/)) {
+      linter.warn("W106", {
+        line: data.line,
+        char: data.char,
+        data: [ data.name ]
+      });
+    }
+  });
+
+  // Enforce consistency in style of quoting.
+
+  linter.on("String", function style_scanQuotes(data) {
+    var quotmark = linter.getOption("quotmark");
+    var code;
+
+    if (!quotmark) {
+      return;
+    }
+
+    // If quotmark is set to 'single' warn about all double-quotes.
+
+    if (quotmark === "single" && data.quote !== "'") {
+      code = "W109";
+    }
+
+    // If quotmark is set to 'double' warn about all single-quotes.
+
+    if (quotmark === "double" && data.quote !== "\"") {
+      code = "W108";
+    }
+
+    // If quotmark is set to true, remember the first quotation style
+    // and then warn about all others.
+
+    if (quotmark === true) {
+      if (!linter.getCache("quotmark")) {
+        linter.setCache("quotmark", data.quote);
+      }
+
+      if (linter.getCache("quotmark") !== data.quote) {
+        code = "W110";
+      }
+    }
+
+    if (code) {
+      linter.warn(code, {
+        line: data.line,
+        char: data.char,
+      });
+    }
+  });
+
+  linter.on("Number", function style_scanNumbers(data) {
+    if (data.value.charAt(0) === ".") {
+      // Warn about a leading decimal point.
+      linter.warn("W008", {
+        line: data.line,
+        char: data.char,
+        data: [ data.value ]
+      });
+    }
+
+    if (data.value.substr(data.value.length - 1) === ".") {
+      // Warn about a trailing decimal point.
+      linter.warn("W047", {
+        line: data.line,
+        char: data.char,
+        data: [ data.value ]
+      });
+    }
+
+    if (/^00+/.test(data.value)) {
+      // Multiple leading zeroes.
+      linter.warn("W046", {
+        line: data.line,
+        char: data.char,
+        data: [ data.value ]
+      });
+    }
+  });
+
+  // Warn about script URLs.
+
+  linter.on("String", function style_scanJavaScriptURLs(data) {
+    var re = /^(?:javascript|jscript|ecmascript|vbscript|livescript)\s*:/i;
+
+    if (linter.getOption("scripturl")) {
+      return;
+    }
+
+    if (re.test(data.value)) {
+      linter.warn("W107", {
+        line: data.line,
+        char: data.char
+      });
+    }
+  });
+};
+
+},{}],21:[function(require,module,exports){
+// jshint -W001
+
+"use strict";
+
+// Identifiers provided by the ECMAScript standard.
+
+exports.reservedVars = {
+  arguments : false,
+  NaN       : false
+};
+
+exports.ecmaIdentifiers = {
+  3: {
+    Array              : false,
+    Boolean            : false,
+    Date               : false,
+    decodeURI          : false,
+    decodeURIComponent : false,
+    encodeURI          : false,
+    encodeURIComponent : false,
+    Error              : false,
+    "eval"             : false,
+    EvalError          : false,
+    Function           : false,
+    hasOwnProperty     : false,
+    isFinite           : false,
+    isNaN              : false,
+    Math               : false,
+    Number             : false,
+    Object             : false,
+    parseInt           : false,
+    parseFloat         : false,
+    RangeError         : false,
+    ReferenceError     : false,
+    RegExp             : false,
+    String             : false,
+    SyntaxError        : false,
+    TypeError          : false,
+    URIError           : false
+  },
+  5: {
+    JSON               : false
+  },
+  6: {
+    ArrayBuffer        : false,
+    DataView           : false,
+    Float32Array       : false,
+    Float64Array       : false,
+    Int8Array          : false,
+    Int16Array         : false,
+    Int32Array         : false,
+    Map                : false,
+    Promise            : false,
+    Proxy              : false,
+    Reflect            : false,
+    Set                : false,
+    Symbol             : false,
+    Uint8Array         : false,
+    Uint16Array        : false,
+    Uint32Array        : false,
+    Uint8ClampledArray : false,
+    WeakMap            : false,
+    WeakSet            : false
+  }
+};
+
+// Global variables commonly provided by a web browser environment.
+
+exports.browser = {
+  Audio                : false,
+  Blob                 : false,
+  addEventListener     : false,
+  applicationCache     : false,
+  atob                 : false,
+  blur                 : false,
+  btoa                 : false,
+  cancelAnimationFrame : false,
+  CanvasGradient       : false,
+  CanvasPattern        : false,
+  CanvasRenderingContext2D: false,
+  CSS                  : false,
+  clearInterval        : false,
+  clearTimeout         : false,
+  close                : false,
+  closed               : false,
+  Comment              : false,
+  CompositionEvent     : false,
+  CustomEvent          : false,
+  DOMParser            : false,
+  defaultStatus        : false,
+  Document             : false,
+  document             : false,
+  DocumentFragment     : false,
+  Element              : false,
+  ElementTimeControl   : false,
+  Event                : false,
+  event                : false,
+  fetch                : false,
+  File                 : false,
+  FileList             : false,
+  FileReader           : false,
+  FormData             : false,
+  focus                : false,
+  frames               : false,
+  getComputedStyle     : false,
+  HTMLElement          : false,
+  HTMLAnchorElement    : false,
+  HTMLBaseElement      : false,
+  HTMLBlockquoteElement: false,
+  HTMLBodyElement      : false,
+  HTMLBRElement        : false,
+  HTMLButtonElement    : false,
+  HTMLCanvasElement    : false,
+  HTMLCollection       : false,
+  HTMLDirectoryElement : false,
+  HTMLDivElement       : false,
+  HTMLDListElement     : false,
+  HTMLFieldSetElement  : false,
+  HTMLFontElement      : false,
+  HTMLFormElement      : false,
+  HTMLFrameElement     : false,
+  HTMLFrameSetElement  : false,
+  HTMLHeadElement      : false,
+  HTMLHeadingElement   : false,
+  HTMLHRElement        : false,
+  HTMLHtmlElement      : false,
+  HTMLIFrameElement    : false,
+  HTMLImageElement     : false,
+  HTMLInputElement     : false,
+  HTMLIsIndexElement   : false,
+  HTMLLabelElement     : false,
+  HTMLLayerElement     : false,
+  HTMLLegendElement    : false,
+  HTMLLIElement        : false,
+  HTMLLinkElement      : false,
+  HTMLMapElement       : false,
+  HTMLMenuElement      : false,
+  HTMLMetaElement      : false,
+  HTMLModElement       : false,
+  HTMLObjectElement    : false,
+  HTMLOListElement     : false,
+  HTMLOptGroupElement  : false,
+  HTMLOptionElement    : false,
+  HTMLParagraphElement : false,
+  HTMLParamElement     : false,
+  HTMLPreElement       : false,
+  HTMLQuoteElement     : false,
+  HTMLScriptElement    : false,
+  HTMLSelectElement    : false,
+  HTMLStyleElement     : false,
+  HTMLTableCaptionElement: false,
+  HTMLTableCellElement : false,
+  HTMLTableColElement  : false,
+  HTMLTableElement     : false,
+  HTMLTableRowElement  : false,
+  HTMLTableSectionElement: false,
+  HTMLTemplateElement  : false,
+  HTMLTextAreaElement  : false,
+  HTMLTitleElement     : false,
+  HTMLUListElement     : false,
+  HTMLVideoElement     : false,
+  history              : false,
+  Image                : false,
+  Intl                 : false,
+  length               : false,
+  localStorage         : false,
+  location             : false,
+  matchMedia           : false,
+  MediaRecorder        : false,
+  MessageChannel       : false,
+  MessageEvent         : false,
+  MessagePort          : false,
+  MouseEvent           : false,
+  moveBy               : false,
+  moveTo               : false,
+  MutationObserver     : false,
+  name                 : false,
+  Node                 : false,
+  NodeFilter           : false,
+  NodeList             : false,
+  Notification         : false,
+  navigator            : false,
+  onbeforeunload       : true,
+  onblur               : true,
+  onerror              : true,
+  onfocus              : true,
+  onload               : true,
+  onresize             : true,
+  onunload             : true,
+  open                 : false,
+  openDatabase         : false,
+  opener               : false,
+  Option               : false,
+  parent               : false,
+  performance          : false,
+  print                : false,
+  Range                : false,
+  requestAnimationFrame : false,
+  removeEventListener  : false,
+  resizeBy             : false,
+  resizeTo             : false,
+  screen               : false,
+  scroll               : false,
+  scrollBy             : false,
+  scrollTo             : false,
+  sessionStorage       : false,
+  setInterval          : false,
+  setTimeout           : false,
+  SharedWorker         : false,
+  status               : false,
+  Storage              : false,
+  SVGAElement          : false,
+  SVGAltGlyphDefElement: false,
+  SVGAltGlyphElement   : false,
+  SVGAltGlyphItemElement: false,
+  SVGAngle             : false,
+  SVGAnimateColorElement: false,
+  SVGAnimateElement    : false,
+  SVGAnimateMotionElement: false,
+  SVGAnimateTransformElement: false,
+  SVGAnimatedAngle     : false,
+  SVGAnimatedBoolean   : false,
+  SVGAnimatedEnumeration: false,
+  SVGAnimatedInteger   : false,
+  SVGAnimatedLength    : false,
+  SVGAnimatedLengthList: false,
+  SVGAnimatedNumber    : false,
+  SVGAnimatedNumberList: false,
+  SVGAnimatedPathData  : false,
+  SVGAnimatedPoints    : false,
+  SVGAnimatedPreserveAspectRatio: false,
+  SVGAnimatedRect      : false,
+  SVGAnimatedString    : false,
+  SVGAnimatedTransformList: false,
+  SVGAnimationElement  : false,
+  SVGCSSRule           : false,
+  SVGCircleElement     : false,
+  SVGClipPathElement   : false,
+  SVGColor             : false,
+  SVGColorProfileElement: false,
+  SVGColorProfileRule  : false,
+  SVGComponentTransferFunctionElement: false,
+  SVGCursorElement     : false,
+  SVGDefsElement       : false,
+  SVGDescElement       : false,
+  SVGDocument          : false,
+  SVGElement           : false,
+  SVGElementInstance   : false,
+  SVGElementInstanceList: false,
+  SVGEllipseElement    : false,
+  SVGExternalResourcesRequired: false,
+  SVGFEBlendElement    : false,
+  SVGFEColorMatrixElement: false,
+  SVGFEComponentTransferElement: false,
+  SVGFECompositeElement: false,
+  SVGFEConvolveMatrixElement: false,
+  SVGFEDiffuseLightingElement: false,
+  SVGFEDisplacementMapElement: false,
+  SVGFEDistantLightElement: false,
+  SVGFEFloodElement    : false,
+  SVGFEFuncAElement    : false,
+  SVGFEFuncBElement    : false,
+  SVGFEFuncGElement    : false,
+  SVGFEFuncRElement    : false,
+  SVGFEGaussianBlurElement: false,
+  SVGFEImageElement    : false,
+  SVGFEMergeElement    : false,
+  SVGFEMergeNodeElement: false,
+  SVGFEMorphologyElement: false,
+  SVGFEOffsetElement   : false,
+  SVGFEPointLightElement: false,
+  SVGFESpecularLightingElement: false,
+  SVGFESpotLightElement: false,
+  SVGFETileElement     : false,
+  SVGFETurbulenceElement: false,
+  SVGFilterElement     : false,
+  SVGFilterPrimitiveStandardAttributes: false,
+  SVGFitToViewBox      : false,
+  SVGFontElement       : false,
+  SVGFontFaceElement   : false,
+  SVGFontFaceFormatElement: false,
+  SVGFontFaceNameElement: false,
+  SVGFontFaceSrcElement: false,
+  SVGFontFaceUriElement: false,
+  SVGForeignObjectElement: false,
+  SVGGElement          : false,
+  SVGGlyphElement      : false,
+  SVGGlyphRefElement   : false,
+  SVGGradientElement   : false,
+  SVGHKernElement      : false,
+  SVGICCColor          : false,
+  SVGImageElement      : false,
+  SVGLangSpace         : false,
+  SVGLength            : false,
+  SVGLengthList        : false,
+  SVGLineElement       : false,
+  SVGLinearGradientElement: false,
+  SVGLocatable         : false,
+  SVGMPathElement      : false,
+  SVGMarkerElement     : false,
+  SVGMaskElement       : false,
+  SVGMatrix            : false,
+  SVGMetadataElement   : false,
+  SVGMissingGlyphElement: false,
+  SVGNumber            : false,
+  SVGNumberList        : false,
+  SVGPaint             : false,
+  SVGPathElement       : false,
+  SVGPathSeg           : false,
+  SVGPathSegArcAbs     : false,
+  SVGPathSegArcRel     : false,
+  SVGPathSegClosePath  : false,
+  SVGPathSegCurvetoCubicAbs: false,
+  SVGPathSegCurvetoCubicRel: false,
+  SVGPathSegCurvetoCubicSmoothAbs: false,
+  SVGPathSegCurvetoCubicSmoothRel: false,
+  SVGPathSegCurvetoQuadraticAbs: false,
+  SVGPathSegCurvetoQuadraticRel: false,
+  SVGPathSegCurvetoQuadraticSmoothAbs: false,
+  SVGPathSegCurvetoQuadraticSmoothRel: false,
+  SVGPathSegLinetoAbs  : false,
+  SVGPathSegLinetoHorizontalAbs: false,
+  SVGPathSegLinetoHorizontalRel: false,
+  SVGPathSegLinetoRel  : false,
+  SVGPathSegLinetoVerticalAbs: false,
+  SVGPathSegLinetoVerticalRel: false,
+  SVGPathSegList       : false,
+  SVGPathSegMovetoAbs  : false,
+  SVGPathSegMovetoRel  : false,
+  SVGPatternElement    : false,
+  SVGPoint             : false,
+  SVGPointList         : false,
+  SVGPolygonElement    : false,
+  SVGPolylineElement   : false,
+  SVGPreserveAspectRatio: false,
+  SVGRadialGradientElement: false,
+  SVGRect              : false,
+  SVGRectElement       : false,
+  SVGRenderingIntent   : false,
+  SVGSVGElement        : false,
+  SVGScriptElement     : false,
+  SVGSetElement        : false,
+  SVGStopElement       : false,
+  SVGStringList        : false,
+  SVGStylable          : false,
+  SVGStyleElement      : false,
+  SVGSwitchElement     : false,
+  SVGSymbolElement     : false,
+  SVGTRefElement       : false,
+  SVGTSpanElement      : false,
+  SVGTests             : false,
+  SVGTextContentElement: false,
+  SVGTextElement       : false,
+  SVGTextPathElement   : false,
+  SVGTextPositioningElement: false,
+  SVGTitleElement      : false,
+  SVGTransform         : false,
+  SVGTransformList     : false,
+  SVGTransformable     : false,
+  SVGURIReference      : false,
+  SVGUnitTypes         : false,
+  SVGUseElement        : false,
+  SVGVKernElement      : false,
+  SVGViewElement       : false,
+  SVGViewSpec          : false,
+  SVGZoomAndPan        : false,
+  Text                 : false,
+  TextDecoder          : false,
+  TextEncoder          : false,
+  TimeEvent            : false,
+  top                  : false,
+  URL                  : false,
+  WebGLActiveInfo      : false,
+  WebGLBuffer          : false,
+  WebGLContextEvent    : false,
+  WebGLFramebuffer     : false,
+  WebGLProgram         : false,
+  WebGLRenderbuffer    : false,
+  WebGLRenderingContext: false,
+  WebGLShader          : false,
+  WebGLShaderPrecisionFormat: false,
+  WebGLTexture         : false,
+  WebGLUniformLocation : false,
+  WebSocket            : false,
+  window               : false,
+  Window               : false,
+  Worker               : false,
+  XDomainRequest       : false,
+  XMLHttpRequest       : false,
+  XMLSerializer        : false,
+  XPathEvaluator       : false,
+  XPathException       : false,
+  XPathExpression      : false,
+  XPathNamespace       : false,
+  XPathNSResolver      : false,
+  XPathResult          : false
+};
+
+exports.devel = {
+  alert  : false,
+  confirm: false,
+  console: false,
+  Debug  : false,
+  opera  : false,
+  prompt : false
+};
+
+exports.worker = {
+  importScripts  : true,
+  onmessage      : true,
+  postMessage    : true,
+  self           : true,
+  FileReaderSync : true
+};
+
+// Widely adopted global names that are not part of ECMAScript standard
+exports.nonstandard = {
+  escape  : false,
+  unescape: false
+};
+
+// Globals provided by popular JavaScript environments.
+
+exports.couch = {
+  "require" : false,
+  respond   : false,
+  getRow    : false,
+  emit      : false,
+  send      : false,
+  start     : false,
+  sum       : false,
+  log       : false,
+  exports   : false,
+  module    : false,
+  provides  : false
+};
+
+exports.node = {
+  __filename    : false,
+  __dirname     : false,
+  GLOBAL        : false,
+  global        : false,
+  module        : false,
+  require       : false,
+
+  // These globals are writeable because Node allows the following
+  // usage pattern: var Buffer = require("buffer").Buffer;
+
+  Buffer        : true,
+  console       : true,
+  exports       : true,
+  process       : true,
+  setTimeout    : true,
+  clearTimeout  : true,
+  setInterval   : true,
+  clearInterval : true,
+  setImmediate  : true, // v0.9.1+
+  clearImmediate: true  // v0.9.1+
+};
+
+exports.browserify = {
+  __filename    : false,
+  __dirname     : false,
+  global        : false,
+  module        : false,
+  require       : false,
+  Buffer        : true,
+  exports       : true,
+  process       : true
+};
+
+exports.phantom = {
+  phantom      : true,
+  require      : true,
+  WebPage      : true,
+  console      : true, // in examples, but undocumented
+  exports      : true  // v1.7+
+};
+
+exports.qunit = {
+  asyncTest      : false,
+  deepEqual      : false,
+  equal          : false,
+  expect         : false,
+  module         : false,
+  notDeepEqual   : false,
+  notEqual       : false,
+  notOk          : false,
+  notPropEqual   : false,
+  notStrictEqual : false,
+  ok             : false,
+  propEqual      : false,
+  QUnit          : false,
+  raises         : false,
+  start          : false,
+  stop           : false,
+  strictEqual    : false,
+  test           : false,
+  "throws"       : false
+};
+
+exports.rhino = {
+  defineClass  : false,
+  deserialize  : false,
+  gc           : false,
+  help         : false,
+  importClass  : false,
+  importPackage: false,
+  "java"       : false,
+  load         : false,
+  loadClass    : false,
+  Packages     : false,
+  print        : false,
+  quit         : false,
+  readFile     : false,
+  readUrl      : false,
+  runCommand   : false,
+  seal         : false,
+  serialize    : false,
+  spawn        : false,
+  sync         : false,
+  toint32      : false,
+  version      : false
+};
+
+exports.shelljs = {
+  target       : false,
+  echo         : false,
+  exit         : false,
+  cd           : false,
+  pwd          : false,
+  ls           : false,
+  find         : false,
+  cp           : false,
+  rm           : false,
+  mv           : false,
+  mkdir        : false,
+  test         : false,
+  cat          : false,
+  sed          : false,
+  grep         : false,
+  which        : false,
+  dirs         : false,
+  pushd        : false,
+  popd         : false,
+  env          : false,
+  exec         : false,
+  chmod        : false,
+  config       : false,
+  error        : false,
+  tempdir      : false
+};
+
+exports.typed = {
+  ArrayBuffer         : false,
+  ArrayBufferView     : false,
+  DataView            : false,
+  Float32Array        : false,
+  Float64Array        : false,
+  Int16Array          : false,
+  Int32Array          : false,
+  Int8Array           : false,
+  Uint16Array         : false,
+  Uint32Array         : false,
+  Uint8Array          : false,
+  Uint8ClampedArray   : false
+};
+
+exports.wsh = {
+  ActiveXObject            : true,
+  Enumerator               : true,
+  GetObject                : true,
+  ScriptEngine             : true,
+  ScriptEngineBuildVersion : true,
+  ScriptEngineMajorVersion : true,
+  ScriptEngineMinorVersion : true,
+  VBArray                  : true,
+  WSH                      : true,
+  WScript                  : true,
+  XDomainRequest           : true
+};
+
+// Globals provided by popular JavaScript libraries.
+
+exports.dojo = {
+  dojo     : false,
+  dijit    : false,
+  dojox    : false,
+  define   : false,
+  "require": false
+};
+
+exports.jquery = {
+  "$"    : false,
+  jQuery : false
+};
+
+exports.mootools = {
+  "$"           : false,
+  "$$"          : false,
+  Asset         : false,
+  Browser       : false,
+  Chain         : false,
+  Class         : false,
+  Color         : false,
+  Cookie        : false,
+  Core          : false,
+  Document      : false,
+  DomReady      : false,
+  DOMEvent      : false,
+  DOMReady      : false,
+  Drag          : false,
+  Element       : false,
+  Elements      : false,
+  Event         : false,
+  Events        : false,
+  Fx            : false,
+  Group         : false,
+  Hash          : false,
+  HtmlTable     : false,
+  IFrame        : false,
+  IframeShim    : false,
+  InputValidator: false,
+  instanceOf    : false,
+  Keyboard      : false,
+  Locale        : false,
+  Mask          : false,
+  MooTools      : false,
+  Native        : false,
+  Options       : false,
+  OverText      : false,
+  Request       : false,
+  Scroller      : false,
+  Slick         : false,
+  Slider        : false,
+  Sortables     : false,
+  Spinner       : false,
+  Swiff         : false,
+  Tips          : false,
+  Type          : false,
+  typeOf        : false,
+  URI           : false,
+  Window        : false
+};
+
+exports.prototypejs = {
+  "$"               : false,
+  "$$"              : false,
+  "$A"              : false,
+  "$F"              : false,
+  "$H"              : false,
+  "$R"              : false,
+  "$break"          : false,
+  "$continue"       : false,
+  "$w"              : false,
+  Abstract          : false,
+  Ajax              : false,
+  Class             : false,
+  Enumerable        : false,
+  Element           : false,
+  Event             : false,
+  Field             : false,
+  Form              : false,
+  Hash              : false,
+  Insertion         : false,
+  ObjectRange       : false,
+  PeriodicalExecuter: false,
+  Position          : false,
+  Prototype         : false,
+  Selector          : false,
+  Template          : false,
+  Toggle            : false,
+  Try               : false,
+  Autocompleter     : false,
+  Builder           : false,
+  Control           : false,
+  Draggable         : false,
+  Draggables        : false,
+  Droppables        : false,
+  Effect            : false,
+  Sortable          : false,
+  SortableObserver  : false,
+  Sound             : false,
+  Scriptaculous     : false
+};
+
+exports.yui = {
+  YUI       : false,
+  Y         : false,
+  YUI_config: false
+};
+
+exports.mocha = {
+  // Global (for config etc.)
+  mocha       : false,
+  // BDD
+  describe    : false,
+  xdescribe   : false,
+  it          : false,
+  xit         : false,
+  context     : false,
+  xcontext    : false,
+  before      : false,
+  after       : false,
+  beforeEach  : false,
+  afterEach   : false,
+  // TDD
+  suite         : false,
+  test          : false,
+  setup         : false,
+  teardown      : false,
+  suiteSetup    : false,
+  suiteTeardown : false
+};
+
+exports.jasmine = {
+  jasmine     : false,
+  describe    : false,
+  xdescribe   : false,
+  it          : false,
+  xit         : false,
+  beforeEach  : false,
+  afterEach   : false,
+  setFixtures : false,
+  loadFixtures: false,
+  spyOn       : false,
+  expect      : false,
+  // Jasmine 1.3
+  runs        : false,
+  waitsFor    : false,
+  waits       : false,
+  // Jasmine 2.1
+  beforeAll   : false,
+  afterAll    : false,
+  fail        : false,
+  fdescribe   : false,
+  fit         : false,
+  pending     : false
+};
+
+},{}],"jshint":[function(require,module,exports){
+/*!
+ * JSHint, by JSHint Community.
+ *
+ * This file (and this file only) is licensed under the same slightly modified
+ * MIT license that JSLint is. It stops evil-doers everywhere:
+ *
+ *   Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)
+ *
+ *   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 shall be used for Good, not Evil.
+ *
+ *   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.
+ *
+ */
+
+/*jshint quotmark:double */
+/*exported console */
+
+var _            = require("lodash");
+var events       = require("events");
+var vars         = require("./vars.js");
+var messages     = require("./messages.js");
+var Lexer        = require("./lex.js").Lexer;
+var reg          = require("./reg.js");
+var state        = require("./state.js").state;
+var style        = require("./style.js");
+var options      = require("./options.js");
+var scopeManager = require("./scope-manager.js");
+
+// We need this module here because environments such as IE and Rhino
+// don't necessarilly expose the 'console' API and browserify uses
+// it to log things. It's a sad state of affair, really.
+var console = require("console-browserify");
+
+// We build the application inside a function so that we produce only a singleton
+// variable. That function will be invoked immediately, and its return value is
+// the JSHINT function itself.
+
+var JSHINT = (function() {
+  "use strict";
+
+  var api, // Extension API
+
+    // These are operators that should not be used with the ! operator.
+    bang = {
+      "<"  : true,
+      "<=" : true,
+      "==" : true,
+      "===": true,
+      "!==": true,
+      "!=" : true,
+      ">"  : true,
+      ">=" : true,
+      "+"  : true,
+      "-"  : true,
+      "*"  : true,
+      "/"  : true,
+      "%"  : true
+    },
+
+    declared, // Globals that were declared using /*global ... */ syntax.
+
+    functionicity = [
+      "closure", "exception", "global", "label",
+      "outer", "unused", "var"
+    ],
+
+    functions, // All of the functions
+
+    inblock,
+    indent,
+    lookahead,
+    lex,
+    member,
+    membersOnly,
+    predefined,    // Global variables defined by option
+
+    stack,
+    urls,
+
+    extraModules = [],
+    emitter = new events.EventEmitter();
+
+  function checkOption(name, t) {
+    name = name.trim();
+
+    if (/^[+-]W\d{3}$/g.test(name)) {
+      return true;
+    }
+
+    if (options.validNames.indexOf(name) === -1) {
+      if (t.type !== "jslint" && !_.has(options.removed, name)) {
+        error("E001", t, name);
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  function isString(obj) {
+    return Object.prototype.toString.call(obj) === "[object String]";
+  }
+
+  function isIdentifier(tkn, value) {
+    if (!tkn)
+      return false;
+
+    if (!tkn.identifier || tkn.value !== value)
+      return false;
+
+    return true;
+  }
+
+  function isReserved(token) {
+    if (!token.reserved) {
+      return false;
+    }
+    var meta = token.meta;
+
+    if (meta && meta.isFutureReservedWord) {
+      if (meta.moduleOnly && !state.option.module) {
+        return false;
+      }
+
+      if (state.inES5()) {
+        // ES3 FutureReservedWord in an ES5 environment.
+        if (!meta.es5) {
+          return false;
+        }
+
+        // Some ES5 FutureReservedWord identifiers are active only
+        // within a strict mode environment.
+        if (meta.strictOnly) {
+          if (!state.option.strict && !state.isStrict()) {
+            return false;
+          }
+        }
+
+        if (token.isProperty) {
+          return false;
+        }
+      }
+    }
+
+    return true;
+  }
+
+  function supplant(str, data) {
+    return str.replace(/\{([^{}]*)\}/g, function(a, b) {
+      var r = data[b];
+      return typeof r === "string" || typeof r === "number" ? r : a;
+    });
+  }
+
+  function combine(dest, src) {
+    Object.keys(src).forEach(function(name) {
+      if (_.has(JSHINT.blacklist, name)) return;
+      dest[name] = src[name];
+    });
+  }
+
+  function processenforceall() {
+    if (state.option.enforceall) {
+      for (var enforceopt in options.bool.enforcing) {
+        if (state.option[enforceopt] === undefined &&
+            !options.noenforceall[enforceopt]) {
+          state.option[enforceopt] = true;
+        }
+      }
+      for (var relaxopt in options.bool.relaxing) {
+        if (state.option[relaxopt] === undefined) {
+          state.option[relaxopt] = false;
+        }
+      }
+    }
+  }
+
+  /**
+   * Apply all linting options according to the status of the `state` object.
+   */
+  function applyOptions() {
+    var badESOpt = null;
+    processenforceall();
+
+    /**
+     * TODO: Remove in JSHint 3
+     */
+    badESOpt = state.inferEsVersion();
+    if (badESOpt) {
+      quit("E059", state.tokens.next, "esversion", badESOpt);
+    }
+
+    if (state.inES5()) {
+      combine(predefined, vars.ecmaIdentifiers[5]);
+    }
+
+    if (state.inES6()) {
+      combine(predefined, vars.ecmaIdentifiers[6]);
+    }
+
+    /**
+     * Use `in` to check for the presence of any explicitly-specified value for
+     * `globalstrict` because both `true` and `false` should trigger an error.
+     */
+    if (state.option.strict === "global" && "globalstrict" in state.option) {
+      quit("E059", state.tokens.next, "strict", "globalstrict");
+    }
+
+    if (state.option.module) {
+      /**
+       * TODO: Extend this restriction to *all* ES6-specific options.
+       */
+      if (!state.inES6()) {
+        warning("W134", state.tokens.next, "module", 6);
+      }
+    }
+
+    if (state.option.couch) {
+      combine(predefined, vars.couch);
+    }
+
+    if (state.option.qunit) {
+      combine(predefined, vars.qunit);
+    }
+
+    if (state.option.rhino) {
+      combine(predefined, vars.rhino);
+    }
+
+    if (state.option.shelljs) {
+      combine(predefined, vars.shelljs);
+      combine(predefined, vars.node);
+    }
+    if (state.option.typed) {
+      combine(predefined, vars.typed);
+    }
+
+    if (state.option.phantom) {
+      combine(predefined, vars.phantom);
+    }
+
+    if (state.option.prototypejs) {
+      combine(predefined, vars.prototypejs);
+    }
+
+    if (state.option.node) {
+      combine(predefined, vars.node);
+      combine(predefined, vars.typed);
+    }
+
+    if (state.option.devel) {
+      combine(predefined, vars.devel);
+    }
+
+    if (state.option.dojo) {
+      combine(predefined, vars.dojo);
+    }
+
+    if (state.option.browser) {
+      combine(predefined, vars.browser);
+      combine(predefined, vars.typed);
+    }
+
+    if (state.option.browserify) {
+      combine(predefined, vars.browser);
+      combine(predefined, vars.typed);
+      combine(predefined, vars.browserify);
+    }
+
+    if (state.option.nonstandard) {
+      combine(predefined, vars.nonstandard);
+    }
+
+    if (state.option.jasmine) {
+      combine(predefined, vars.jasmine);
+    }
+
+    if (state.option.jquery) {
+      combine(predefined, vars.jquery);
+    }
+
+    if (state.option.mootools) {
+      combine(predefined, vars.mootools);
+    }
+
+    if (state.option.worker) {
+      combine(predefined, vars.worker);
+    }
+
+    if (state.option.wsh) {
+      combine(predefined, vars.wsh);
+    }
+
+    if (state.option.yui) {
+      combine(predefined, vars.yui);
+    }
+
+    if (state.option.mocha) {
+      combine(predefined, vars.mocha);
+    }
+  }
+
+  // Produce an error warning.
+  function quit(code, token, a, b) {
+    var percentage = Math.floor((token.line / state.lines.length) * 100);
+    var message = messages.errors[code].desc;
+
+    var exception = {
+      name: "JSHintError",
+      line: token.line,
+      character: token.from,
+      message: message + " (" + percentage + "% scanned).",
+      raw: message,
+      code: code,
+      a: a,
+      b: b
+    };
+
+    exception.reason = supplant(message, exception) + " (" + percentage +
+      "% scanned).";
+
+    throw exception;
+  }
+
+  function removeIgnoredMessages() {
+    var ignored = state.ignoredLines;
+
+    if (_.isEmpty(ignored)) return;
+    JSHINT.errors = _.reject(JSHINT.errors, function(err) { return ignored[err.line] });
+  }
+
+  function warning(code, t, a, b, c, d) {
+    var ch, l, w, msg;
+
+    if (/^W\d{3}$/.test(code)) {
+      if (state.ignored[code])
+        return;
+
+      msg = messages.warnings[code];
+    } else if (/E\d{3}/.test(code)) {
+      msg = messages.errors[code];
+    } else if (/I\d{3}/.test(code)) {
+      msg = messages.info[code];
+    }
+
+    t = t || state.tokens.next || {};
+    if (t.id === "(end)") {  // `~
+      t = state.tokens.curr;
+    }
+
+    l = t.line;
+    ch = t.from;
+
+    w = {
+      id: "(error)",
+      raw: msg.desc,
+      code: msg.code,
+      evidence: state.lines[l - 1] || "",
+      line: l,
+      character: ch,
+      scope: JSHINT.scope,
+      a: a,
+      b: b,
+      c: c,
+      d: d
+    };
+
+    w.reason = supplant(msg.desc, w);
+    JSHINT.errors.push(w);
+
+    removeIgnoredMessages();
+
+    if (JSHINT.errors.length >= state.option.maxerr)
+      quit("E043", t);
+
+    return w;
+  }
+
+  function warningAt(m, l, ch, a, b, c, d) {
+    return warning(m, {
+      line: l,
+      from: ch
+    }, a, b, c, d);
+  }
+
+  function error(m, t, a, b, c, d) {
+    warning(m, t, a, b, c, d);
+  }
+
+  function errorAt(m, l, ch, a, b, c, d) {
+    return error(m, {
+      line: l,
+      from: ch
+    }, a, b, c, d);
+  }
+
+  // Tracking of "internal" scripts, like eval containing a static string
+  function addEvalCode(elem, token) {
+    JSHINT.internals.push({
+      id: "(internal)",
+      elem: elem,
+      token: token,
+      code: token.value.replace(/([^\\])(\\*)\2\\n/g, "$1\n")
+    });
+  }
+
+  /**
+   * Process an inline linting directive
+   *
+   * @param {Token} directiveToken - the directive-bearing comment token
+   * @param {Token} previous - the token that preceeds the directive
+   */
+  function lintingDirective(directiveToken, previous) {
+    var body = directiveToken.body.split(",")
+      .map(function(s) { return s.trim(); });
+    var predef = {};
+
+    if (directiveToken.type === "falls through") {
+      previous.caseFallsThrough = true;
+      return;
+    }
+
+    if (directiveToken.type === "globals") {
+      body.forEach(function(g, idx) {
+        g = g.split(":");
+        var key = (g[0] || "").trim();
+        var val = (g[1] || "").trim();
+
+        if (key === "-" || !key.length) {
+          // Ignore trailing comma
+          if (idx > 0 && idx === body.length - 1) {
+            return;
+          }
+          error("E002", directiveToken);
+          return;
+        }
+
+        if (key.charAt(0) === "-") {
+          key = key.slice(1);
+          val = false;
+
+          JSHINT.blacklist[key] = key;
+          delete predefined[key];
+        } else {
+          predef[key] = (val === "true");
+        }
+      });
+
+      combine(predefined, predef);
+
+      for (var key in predef) {
+        if (_.has(predef, key)) {
+          declared[key] = directiveToken;
+        }
+      }
+    }
+
+    if (directiveToken.type === "exported") {
+      body.forEach(function(e, idx) {
+        if (!e.length) {
+          // Ignore trailing comma
+          if (idx > 0 && idx === body.length - 1) {
+            return;
+          }
+          error("E002", directiveToken);
+          return;
+        }
+
+        state.funct["(scope)"].addExported(e);
+      });
+    }
+
+    if (directiveToken.type === "members") {
+      membersOnly = membersOnly || {};
+
+      body.forEach(function(m) {
+        var ch1 = m.charAt(0);
+        var ch2 = m.charAt(m.length - 1);
+
+        if (ch1 === ch2 && (ch1 === "\"" || ch1 === "'")) {
+          m = m
+            .substr(1, m.length - 2)
+            .replace("\\\"", "\"");
+        }
+
+        membersOnly[m] = false;
+      });
+    }
+
+    var numvals = [
+      "maxstatements",
+      "maxparams",
+      "maxdepth",
+      "maxcomplexity",
+      "maxerr",
+      "maxlen",
+      "indent"
+    ];
+
+    if (directiveToken.type === "jshint" || directiveToken.type === "jslint") {
+      body.forEach(function(g) {
+        g = g.split(":");
+        var key = (g[0] || "").trim();
+        var val = (g[1] || "").trim();
+
+        if (!checkOption(key, directiveToken)) {
+          return;
+        }
+
+        if (numvals.indexOf(key) >= 0) {
+          // GH988 - numeric options can be disabled by setting them to `false`
+          if (val !== "false") {
+            val = +val;
+
+            if (typeof val !== "number" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) {
+              error("E032", directiveToken, g[1].trim());
+              return;
+            }
+
+            state.option[key] = val;
+          } else {
+            state.option[key] = key === "indent" ? 4 : false;
+          }
+
+          return;
+        }
+
+        if (key === "validthis") {
+          // `validthis` is valid only within a function scope.
+
+          if (state.funct["(global)"])
+            return void error("E009");
+
+          if (val !== "true" && val !== "false")
+            return void error("E002", directiveToken);
+
+          state.option.validthis = (val === "true");
+          return;
+        }
+
+        if (key === "quotmark") {
+          switch (val) {
+          case "true":
+          case "false":
+            state.option.quotmark = (val === "true");
+            break;
+          case "double":
+          case "single":
+            state.option.quotmark = val;
+            break;
+          default:
+            error("E002", directiveToken);
+          }
+          return;
+        }
+
+        if (key === "shadow") {
+          switch (val) {
+          case "true":
+            state.option.shadow = true;
+            break;
+          case "outer":
+            state.option.shadow = "outer";
+            break;
+          case "false":
+          case "inner":
+            state.option.shadow = "inner";
+            break;
+          default:
+            error("E002", directiveToken);
+          }
+          return;
+        }
+
+        if (key === "unused") {
+          switch (val) {
+          case "true":
+            state.option.unused = true;
+            break;
+          case "false":
+            state.option.unused = false;
+            break;
+          case "vars":
+          case "strict":
+            state.option.unused = val;
+            break;
+          default:
+            error("E002", directiveToken);
+          }
+          return;
+        }
+
+        if (key === "latedef") {
+          switch (val) {
+          case "true":
+            state.option.latedef = true;
+            break;
+          case "false":
+            state.option.latedef = false;
+            break;
+          case "nofunc":
+            state.option.latedef = "nofunc";
+            break;
+          default:
+            error("E002", directiveToken);
+          }
+          return;
+        }
+
+        if (key === "ignore") {
+          switch (val) {
+          case "line":
+            state.ignoredLines[directiveToken.line] = true;
+            removeIgnoredMessages();
+            break;
+          default:
+            error("E002", directiveToken);
+          }
+          return;
+        }
+
+        if (key === "strict") {
+          switch (val) {
+          case "true":
+            state.option.strict = true;
+            break;
+          case "false":
+            state.option.strict = false;
+            break;
+          case "global":
+          case "implied":
+            state.option.strict = val;
+            break;
+          default:
+            error("E002", directiveToken);
+          }
+          return;
+        }
+
+        if (key === "module") {
+          /**
+           * TODO: Extend this restriction to *all* "environmental" options.
+           */
+          if (!hasParsedCode(state.funct)) {
+            error("E055", directiveToken, "module");
+          }
+        }
+
+        if (key === "esversion") {
+          switch (val) {
+          case "3":
+          case "5":
+          case "6":
+          case "2015":
+            state.option.moz = false;
+            state.option.esversion = +val;
+            break;
+          default:
+            error("E002", directiveToken);
+          }
+          if (!hasParsedCode(state.funct)) {
+            error("E055", directiveToken, "esversion");
+          }
+          return;
+        }
+
+        var match = /^([+-])(W\d{3})$/g.exec(key);
+        if (match) {
+          // ignore for -W..., unignore for +W...
+          state.ignored[match[2]] = (match[1] === "-");
+          return;
+        }
+
+        var tn;
+        if (val === "true" || val === "false") {
+          if (directiveToken.type === "jslint") {
+            tn = options.renamed[key] || key;
+            state.option[tn] = (val === "true");
+
+            if (options.inverted[tn] !== undefined) {
+              state.option[tn] = !state.option[tn];
+            }
+          } else {
+            state.option[key] = (val === "true");
+          }
+
+          return;
+        }
+
+        error("E002", directiveToken);
+      });
+
+      applyOptions();
+    }
+  }
+
+  /**
+   * Return a token beyond the token available in `state.tokens.next`. If no
+   * such token exists, return the "(end)" token. This function is used to
+   * determine parsing strategies in cases where the value of the next token
+   * does not provide sufficient information, as is the case with `for` loops,
+   * e.g.:
+   *
+   *     for ( var i in ...
+   *
+   * versus:
+   *
+   *     for ( var i = ...
+   *
+   * @param {number} [p] - offset of desired token; defaults to 0
+   *
+   * @returns {token}
+   */
+  function peek(p) {
+    var i = p || 0, j = lookahead.length, t;
+
+    if (i < j) {
+      return lookahead[i];
+    }
+
+    while (j <= i) {
+      t = lex.token();
+
+      // When the lexer is exhausted, this function should produce the "(end)"
+      // token, even in cases where the requested token is beyond the end of
+      // the input stream.
+      if (!t) {
+        // If the lookahead buffer is empty, the expected "(end)" token was
+        // already emitted by the most recent invocation of `advance` and is
+        // available as the next token.
+        if (!lookahead.length) {
+          return state.tokens.next;
+        }
+
+        return lookahead[j - 1];
+      }
+
+      lookahead[j] = t;
+      j += 1;
+    }
+
+    return t;
+  }
+
+  function peekIgnoreEOL() {
+    var i = 0;
+    var t;
+    do {
+      t = peek(i++);
+    } while (t.id === "(endline)");
+    return t;
+  }
+
+  // Produce the next token. It looks for programming errors.
+
+  function advance(id, t) {
+
+    switch (state.tokens.curr.id) {
+    case "(number)":
+      if (state.tokens.next.id === ".") {
+        warning("W005", state.tokens.curr);
+      }
+      break;
+    case "-":
+      if (state.tokens.next.id === "-" || state.tokens.next.id === "--") {
+        warning("W006");
+      }
+      break;
+    case "+":
+      if (state.tokens.next.id === "+" || state.tokens.next.id === "++") {
+        warning("W007");
+      }
+      break;
+    }
+
+    if (id && state.tokens.next.id !== id) {
+      if (t) {
+        if (state.tokens.next.id === "(end)") {
+          error("E019", t, t.id);
+        } else {
+          error("E020", state.tokens.next, id, t.id, t.line, state.tokens.next.value);
+        }
+      } else if (state.tokens.next.type !== "(identifier)" || state.tokens.next.value !== id) {
+        warning("W116", state.tokens.next, id, state.tokens.next.value);
+      }
+    }
+
+    state.tokens.prev = state.tokens.curr;
+    state.tokens.curr = state.tokens.next;
+    for (;;) {
+      state.tokens.next = lookahead.shift() || lex.token();
+
+      if (!state.tokens.next) { // No more tokens left, give up
+        quit("E041", state.tokens.curr);
+      }
+
+      if (state.tokens.next.id === "(end)" || state.tokens.next.id === "(error)") {
+        return;
+      }
+
+      if (state.tokens.next.check) {
+        state.tokens.next.check();
+      }
+
+      if (state.tokens.next.isSpecial) {
+        lintingDirective(state.tokens.next, state.tokens.curr);
+      } else {
+        if (state.tokens.next.id !== "(endline)") {
+          break;
+        }
+      }
+    }
+  }
+
+  /**
+   * Determine whether a given token is an operator.
+   *
+   * @param {token} token
+   *
+   * @returns {boolean}
+   */
+  function isOperator(token) {
+    return token.first || token.right || token.left || token.id === "yield";
+  }
+
+  function isEndOfExpr(curr, next) {
+    if (arguments.length === 0) {
+      curr = state.tokens.curr;
+      next = state.tokens.next;
+    }
+
+    if (next.id === ";" || next.id === "}" || next.id === ":") {
+      return true;
+    }
+    if (next.infix === curr.infix || curr.ltBoundary === "after" ||
+      next.ltBoundary === "before") {
+      return curr.line !== startLine(next);
+    }
+    return false;
+  }
+
+  // This is the heart of JSHINT, the Pratt parser. In addition to parsing, it
+  // is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is
+  // like .nud except that it is only used on the first token of a statement.
+  // Having .fud makes it much easier to define statement-oriented languages like
+  // JavaScript. I retained Pratt's nomenclature.
+
+  // .nud  Null denotation
+  // .fud  First null denotation
+  // .led  Left denotation
+  //  lbp  Left binding power
+  //  rbp  Right binding power
+
+  // They are elements of the parsing method called Top Down Operator Precedence.
+
+  function expression(rbp, initial) {
+    var left, isArray = false, isObject = false, isLetExpr = false;
+
+    state.nameStack.push();
+
+    // if current expression is a let expression
+    if (!initial && state.tokens.next.value === "let" && peek(0).value === "(") {
+      if (!state.inMoz()) {
+        warning("W118", state.tokens.next, "let expressions");
+      }
+      isLetExpr = true;
+      // create a new block scope we use only for the current expression
+      state.funct["(scope)"].stack();
+      advance("let");
+      advance("(");
+      state.tokens.prev.fud();
+      advance(")");
+    }
+
+    if (state.tokens.next.id === "(end)")
+      error("E006", state.tokens.curr);
+
+    var isDangerous =
+      state.option.asi &&
+      state.tokens.prev.line !== startLine(state.tokens.curr) &&
+      _.contains(["]", ")"], state.tokens.prev.id) &&
+      _.contains(["[", "("], state.tokens.curr.id);
+
+    if (isDangerous)
+      warning("W014", state.tokens.curr, state.tokens.curr.id);
+
+    advance();
+
+    if (initial) {
+      state.funct["(verb)"] = state.tokens.curr.value;
+      state.tokens.curr.beginsStmt = true;
+    }
+
+    if (initial === true && state.tokens.curr.fud) {
+      left = state.tokens.curr.fud();
+    } else {
+      if (state.tokens.curr.nud) {
+        left = state.tokens.curr.nud(rbp);
+      } else {
+        error("E030", state.tokens.curr, state.tokens.curr.id);
+      }
+
+      while (rbp < state.tokens.next.lbp && !isEndOfExpr()) {
+        isArray = state.tokens.curr.value === "Array";
+        isObject = state.tokens.curr.value === "Object";
+
+        // #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object()
+        // Line breaks in IfStatement heads exist to satisfy the checkJSHint
+        // "Line too long." error.
+        if (left && (left.value || (left.first && left.first.value))) {
+          // If the left.value is not "new", or the left.first.value is a "."
+          // then safely assume that this is not "new Array()" and possibly
+          // not "new Object()"...
+          if (left.value !== "new" ||
+            (left.first && left.first.value && left.first.value === ".")) {
+            isArray = false;
+            // ...In the case of Object, if the left.value and state.tokens.curr.value
+            // are not equal, then safely assume that this not "new Object()"
+            if (left.value !== state.tokens.curr.value) {
+              isObject = false;
+            }
+          }
+        }
+
+        advance();
+
+        if (isArray && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
+          warning("W009", state.tokens.curr);
+        }
+
+        if (isObject && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
+          warning("W010", state.tokens.curr);
+        }
+
+        if (left && state.tokens.curr.led) {
+          left = state.tokens.curr.led(left);
+        } else {
+          error("E033", state.tokens.curr, state.tokens.curr.id);
+        }
+      }
+    }
+    if (isLetExpr) {
+      state.funct["(scope)"].unstack();
+    }
+
+    state.nameStack.pop();
+
+    return left;
+  }
+
+
+  // Functions for conformance of style.
+
+  function startLine(token) {
+    return token.startLine || token.line;
+  }
+
+  function nobreaknonadjacent(left, right) {
+    left = left || state.tokens.curr;
+    right = right || state.tokens.next;
+    if (!state.option.laxbreak && left.line !== startLine(right)) {
+      warning("W014", right, right.value);
+    }
+  }
+
+  function nolinebreak(t) {
+    t = t || state.tokens.curr;
+    if (t.line !== startLine(state.tokens.next)) {
+      warning("E022", t, t.value);
+    }
+  }
+
+  function nobreakcomma(left, right) {
+    if (left.line !== startLine(right)) {
+      if (!state.option.laxcomma) {
+        if (parseComma.first) {
+          warning("I001");
+          parseComma.first = false;
+        }
+        warning("W014", left, right.value);
+      }
+    }
+  }
+
+  function parseComma(opts) {
+    opts = opts || {};
+
+    if (!opts.peek) {
+      nobreakcomma(state.tokens.curr, state.tokens.next);
+      advance(",");
+    } else {
+      nobreakcomma(state.tokens.prev, state.tokens.curr);
+    }
+
+    if (state.tokens.next.identifier && !(opts.property && state.inES5())) {
+      // Keywords that cannot follow a comma operator.
+      switch (state.tokens.next.value) {
+      case "break":
+      case "case":
+      case "catch":
+      case "continue":
+      case "default":
+      case "do":
+      case "else":
+      case "finally":
+      case "for":
+      case "if":
+      case "in":
+      case "instanceof":
+      case "return":
+      case "switch":
+      case "throw":
+      case "try":
+      case "var":
+      case "let":
+      case "while":
+      case "with":
+        error("E024", state.tokens.next, state.tokens.next.value);
+        return false;
+      }
+    }
+
+    if (state.tokens.next.type === "(punctuator)") {
+      switch (state.tokens.next.value) {
+      case "}":
+      case "]":
+      case ",":
+        if (opts.allowTrailing) {
+          return true;
+        }
+
+        /* falls through */
+      case ")":
+        error("E024", state.tokens.next, state.tokens.next.value);
+        return false;
+      }
+    }
+    return true;
+  }
+
+  // Functional constructors for making the symbols that will be inherited by
+  // tokens.
+
+  function symbol(s, p) {
+    var x = state.syntax[s];
+    if (!x || typeof x !== "object") {
+      state.syntax[s] = x = {
+        id: s,
+        lbp: p,
+        value: s
+      };
+    }
+    return x;
+  }
+
+  function delim(s) {
+    var x = symbol(s, 0);
+    x.delim = true;
+    return x;
+  }
+
+  function stmt(s, f) {
+    var x = delim(s);
+    x.identifier = x.reserved = true;
+    x.fud = f;
+    return x;
+  }
+
+  function blockstmt(s, f) {
+    var x = stmt(s, f);
+    x.block = true;
+    return x;
+  }
+
+  function reserveName(x) {
+    var c = x.id.charAt(0);
+    if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) {
+      x.identifier = x.reserved = true;
+    }
+    return x;
+  }
+
+  function prefix(s, f) {
+    var x = symbol(s, 150);
+    reserveName(x);
+
+    x.nud = (typeof f === "function") ? f : function() {
+      this.arity = "unary";
+      this.right = expression(150);
+
+      if (this.id === "++" || this.id === "--") {
+        if (state.option.plusplus) {
+          warning("W016", this, this.id);
+        } else if (this.right && (!this.right.identifier || isReserved(this.right)) &&
+            this.right.id !== "." && this.right.id !== "[") {
+          warning("W017", this);
+        }
+
+        if (this.right && this.right.isMetaProperty) {
+          error("E031", this);
+        // detect increment/decrement of a const
+        // in the case of a.b, right will be the "." punctuator
+        } else if (this.right && this.right.identifier) {
+          state.funct["(scope)"].block.modify(this.right.value, this);
+        }
+      }
+
+      return this;
+    };
+
+    return x;
+  }
+
+  function type(s, f) {
+    var x = delim(s);
+    x.type = s;
+    x.nud = f;
+    return x;
+  }
+
+  function reserve(name, func) {
+    var x = type(name, func);
+    x.identifier = true;
+    x.reserved = true;
+    return x;
+  }
+
+  function FutureReservedWord(name, meta) {
+    var x = type(name, (meta && meta.nud) || function() {
+      return this;
+    });
+
+    meta = meta || {};
+    meta.isFutureReservedWord = true;
+
+    x.value = name;
+    x.identifier = true;
+    x.reserved = true;
+    x.meta = meta;
+
+    return x;
+  }
+
+  function reservevar(s, v) {
+    return reserve(s, function() {
+      if (typeof v === "function") {
+        v(this);
+      }
+      return this;
+    });
+  }
+
+  function infix(s, f, p, w) {
+    var x = symbol(s, p);
+    reserveName(x);
+    x.infix = true;
+    x.led = function(left) {
+      if (!w) {
+        nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
+      }
+      if ((s === "in" || s === "instanceof") && left.id === "!") {
+        warning("W018", left, "!");
+      }
+      if (typeof f === "function") {
+        return f(left, this);
+      } else {
+        this.left = left;
+        this.right = expression(p);
+        return this;
+      }
+    };
+    return x;
+  }
+
+  function application(s) {
+    var x = symbol(s, 42);
+
+    x.infix = true;
+    x.led = function(left) {
+      nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
+
+      this.left = left;
+      this.right = doFunction({ type: "arrow", loneArg: left });
+      return this;
+    };
+    return x;
+  }
+
+  function relation(s, f) {
+    var x = symbol(s, 100);
+
+    x.infix = true;
+    x.led = function(left) {
+      nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
+      this.left = left;
+      var right = this.right = expression(100);
+
+      if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) {
+        warning("W019", this);
+      } else if (f) {
+        f.apply(this, [left, right]);
+      }
+
+      if (!left || !right) {
+        quit("E041", state.tokens.curr);
+      }
+
+      if (left.id === "!") {
+        warning("W018", left, "!");
+      }
+
+      if (right.id === "!") {
+        warning("W018", right, "!");
+      }
+
+      return this;
+    };
+    return x;
+  }
+
+  var typeofValues = {};
+  typeofValues.legacy = [
+    // E4X extended the `typeof` operator to return "xml" for the XML and
+    // XMLList types it introduced.
+    // Ref: 11.3.2 The typeof Operator
+    // http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-357.pdf
+    "xml",
+    // IE<9 reports "unknown" when the `typeof` operator is applied to an
+    // object existing across a COM+ bridge. In lieu of official documentation
+    // (which does not exist), see:
+    // http://robertnyman.com/2005/12/21/what-is-typeof-unknown/
+    "unknown"
+  ];
+  typeofValues.es3 = [
+    "undefined", "boolean", "number", "string", "function", "object",
+  ];
+  typeofValues.es3 = typeofValues.es3.concat(typeofValues.legacy);
+  typeofValues.es6 = typeofValues.es3.concat("symbol");
+
+  // Checks whether the 'typeof' operator is used with the correct
+  // value. For docs on 'typeof' see:
+  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
+  function isTypoTypeof(left, right, state) {
+    var values;
+
+    if (state.option.notypeof)
+      return false;
+
+    if (!left || !right)
+      return false;
+
+    values = state.inES6() ? typeofValues.es6 : typeofValues.es3;
+
+    if (right.type === "(identifier)" && right.value === "typeof" && left.type === "(string)")
+      return !_.contains(values, left.value);
+
+    return false;
+  }
+
+  function isGlobalEval(left, state) {
+    var isGlobal = false;
+
+    // permit methods to refer to an "eval" key in their own context
+    if (left.type === "this" && state.funct["(context)"] === null) {
+      isGlobal = true;
+    }
+    // permit use of "eval" members of objects
+    else if (left.type === "(identifier)") {
+      if (state.option.node && left.value === "global") {
+        isGlobal = true;
+      }
+
+      else if (state.option.browser && (left.value === "window" || left.value === "document")) {
+        isGlobal = true;
+      }
+    }
+
+    return isGlobal;
+  }
+
+  function findNativePrototype(left) {
+    var natives = [
+      "Array", "ArrayBuffer", "Boolean", "Collator", "DataView", "Date",
+      "DateTimeFormat", "Error", "EvalError", "Float32Array", "Float64Array",
+      "Function", "Infinity", "Intl", "Int16Array", "Int32Array", "Int8Array",
+      "Iterator", "Number", "NumberFormat", "Object", "RangeError",
+      "ReferenceError", "RegExp", "StopIteration", "String", "SyntaxError",
+      "TypeError", "Uint16Array", "Uint32Array", "Uint8Array", "Uint8ClampedArray",
+      "URIError"
+    ];
+
+    function walkPrototype(obj) {
+      if (typeof obj !== "object") return;
+      return obj.right === "prototype" ? obj : walkPrototype(obj.left);
+    }
+
+    function walkNative(obj) {
+      while (!obj.identifier && typeof obj.left === "object")
+        obj = obj.left;
+
+      if (obj.identifier && natives.indexOf(obj.value) >= 0 &&
+          state.funct["(scope)"].isPredefined(obj.value)) {
+        return obj.value;
+      }
+    }
+
+    var prototype = walkPrototype(left);
+    if (prototype) return walkNative(prototype);
+  }
+
+  /**
+   * Checks the left hand side of an assignment for issues, returns if ok
+   * @param {token} left - the left hand side of the assignment
+   * @param {token=} assignToken - the token for the assignment, used for reporting
+   * @param {object=} options - optional object
+   * @param {boolean} options.allowDestructuring - whether to allow destructuting binding
+   * @returns {boolean} Whether the left hand side is OK
+   */
+  function checkLeftSideAssign(left, assignToken, options) {
+
+    var allowDestructuring = options && options.allowDestructuring;
+
+    assignToken = assignToken || left;
+
+    if (state.option.freeze) {
+      var nativeObject = findNativePrototype(left);
+      if (nativeObject)
+        warning("W121", left, nativeObject);
+    }
+    if (checkPunctuator(left, "...")) {
+      left = left.right;
+    }
+
+    if (left.identifier && !left.isMetaProperty) {
+      // reassign also calls modify
+      // but we are specific in order to catch function re-assignment
+      // and globals re-assignment
+      state.funct["(scope)"].block.reassign(left.value, left);
+    }
+
+    if (left.id === ".") {
+      if (!left.left || left.left.value === "arguments" && !state.isStrict()) {
+        warning("E031", assignToken);
+      }
+
+      state.nameStack.set(state.tokens.prev);
+      return true;
+    } else if (left.id === "{" || left.id === "[") {
+      if (!allowDestructuring || !left.destructAssign) {
+        if (left.id === "{" || !left.left) {
+          warning("E031", assignToken);
+        } else if (left.left.value === "arguments" && !state.isStrict()) {
+          warning("E031", assignToken);
+        }
+      }
+
+      if (left.id === "[") {
+        state.nameStack.set(left.right);
+      }
+
+      return true;
+    } else if (left.identifier && !isReserved(left) && !left.isMetaProperty) {
+      if (state.funct["(scope)"].labeltype(left.value) === "exception") {
+        warning("W022", left);
+      }
+      state.nameStack.set(left);
+      return true;
+    }
+
+    if (left === state.syntax["function"]) {
+      warning("W023", state.tokens.curr);
+    } else {
+      error("E031", assignToken);
+    }
+
+    return false;
+  }
+
+  function assignop(s, f, p) {
+    var x = infix(s, typeof f === "function" ? f : function(left, that) {
+      that.left = left;
+
+      checkLeftSideAssign(left, that, { allowDestructuring: true });
+
+      that.right = expression(10);
+
+      return that;
+    }, p);
+
+    x.exps = true;
+    x.assign = true;
+    return x;
+  }
+
+
+  function bitwise(s, f, p) {
+    var x = symbol(s, p);
+    reserveName(x);
+    x.infix = true;
+    x.led = (typeof f === "function") ? f : function(left) {
+      if (state.option.bitwise) {
+        warning("W016", this, this.id);
+      }
+      this.left = left;
+      this.right = expression(p);
+      return this;
+    };
+    return x;
+  }
+
+  function bitwiseassignop(s) {
+    return assignop(s, function(left, that) {
+      if (state.option.bitwise) {
+        warning("W016", that, that.id);
+      }
+
+      checkLeftSideAssign(left, that);
+
+      that.right = expression(10);
+
+      return that;
+    }, 20);
+  }
+
+  function suffix(s) {
+    var x = symbol(s, 150);
+
+    x.led = function(left) {
+      // this = suffix e.g. "++" punctuator
+      // left = symbol operated e.g. "a" identifier or "a.b" punctuator
+      if (state.option.plusplus) {
+        warning("W016", this, this.id);
+      } else if ((!left.identifier || isReserved(left)) && left.id !== "." && left.id !== "[") {
+        warning("W017", this);
+      }
+
+      if (left.isMetaProperty) {
+        error("E031", this);
+      // detect increment/decrement of a const
+      // in the case of a.b, left will be the "." punctuator
+      } else if (left && left.identifier) {
+        state.funct["(scope)"].block.modify(left.value, left);
+      }
+
+      this.left = left;
+      return this;
+    };
+    return x;
+  }
+
+  // fnparam means that this identifier is being defined as a function
+  // argument (see identifier())
+  // prop means that this identifier is that of an object property
+
+  function optionalidentifier(fnparam, prop, preserve) {
+    if (!state.tokens.next.identifier) {
+      return;
+    }
+
+    if (!preserve) {
+      advance();
+    }
+
+    var curr = state.tokens.curr;
+    var val  = state.tokens.curr.value;
+
+    if (!isReserved(curr)) {
+      return val;
+    }
+
+    if (prop) {
+      if (state.inES5()) {
+        return val;
+      }
+    }
+
+    if (fnparam && val === "undefined") {
+      return val;
+    }
+
+    warning("W024", state.tokens.curr, state.tokens.curr.id);
+    return val;
+  }
+
+  // fnparam means that this identifier is being defined as a function
+  // argument
+  // prop means that this identifier is that of an object property
+  function identifier(fnparam, prop) {
+    var i = optionalidentifier(fnparam, prop, false);
+    if (i) {
+      return i;
+    }
+
+    // parameter destructuring with rest operator
+    if (state.tokens.next.value === "...") {
+      if (!state.inES6(true)) {
+        warning("W119", state.tokens.next, "spread/rest operator", "6");
+      }
+      advance();
+
+      if (checkPunctuator(state.tokens.next, "...")) {
+        warning("E024", state.tokens.next, "...");
+        while (checkPunctuator(state.tokens.next, "...")) {
+          advance();
+        }
+      }
+
+      if (!state.tokens.next.identifier) {
+        warning("E024", state.tokens.curr, state.tokens.next.id);
+        return;
+      }
+
+      return identifier(fnparam, prop);
+    } else {
+      error("E030", state.tokens.next, state.tokens.next.value);
+
+      // The token should be consumed after a warning is issued so the parser
+      // can continue as though an identifier were found. The semicolon token
+      // should not be consumed in this way so that the parser interprets it as
+      // a statement delimeter;
+      if (state.tokens.next.id !== ";") {
+        advance();
+      }
+    }
+  }
+
+
+  function reachable(controlToken) {
+    var i = 0, t;
+    if (state.tokens.next.id !== ";" || controlToken.inBracelessBlock) {
+      return;
+    }
+    for (;;) {
+      do {
+        t = peek(i);
+        i += 1;
+      } while (t.id !== "(end)" && t.id === "(comment)");
+
+      if (t.reach) {
+        return;
+      }
+      if (t.id !== "(endline)") {
+        if (t.id === "function") {
+          if (state.option.latedef === true) {
+            warning("W026", t);
+          }
+          break;
+        }
+
+        warning("W027", t, t.value, controlToken.value);
+        break;
+      }
+    }
+  }
+
+  /**
+   * Consume the semicolon that delimits the statement currently being parsed,
+   * emitting relevant warnings/errors as appropriate.
+   *
+   * @param {token} stmt - token describing the statement under consideration
+   */
+  function parseFinalSemicolon(stmt) {
+    if (state.tokens.next.id !== ";") {
+      // don't complain about unclosed templates / strings
+      if (state.tokens.next.isUnclosed) return advance();
+
+      var sameLine = startLine(state.tokens.next) === state.tokens.curr.line &&
+                     state.tokens.next.id !== "(end)";
+      var blockEnd = checkPunctuator(state.tokens.next, "}");
+
+      if (sameLine && !blockEnd && !(stmt.id === "do" && state.inES6(true))) {
+        errorAt("E058", state.tokens.curr.line, state.tokens.curr.character);
+      } else if (!state.option.asi) {
+        // If this is the last statement in a block that ends on
+        // the same line *and* option lastsemic is on, ignore the warning.
+        // Otherwise, complain about missing semicolon.
+        if (!(blockEnd && sameLine && state.option.lastsemic)) {
+          warningAt("W033", state.tokens.curr.line, state.tokens.curr.character);
+        }
+      }
+    } else {
+      advance(";");
+    }
+  }
+
+  function statement() {
+    var i = indent, r, t = state.tokens.next, hasOwnScope = false;
+
+    if (t.id === ";") {
+      advance(";");
+      return;
+    }
+
+    // Is this a labelled statement?
+    var res = isReserved(t);
+
+    // We're being more tolerant here: if someone uses
+    // a FutureReservedWord as a label, we warn but proceed
+    // anyway.
+
+    if (res && t.meta && t.meta.isFutureReservedWord && peek().id === ":") {
+      warning("W024", t, t.id);
+      res = false;
+    }
+
+    if (t.identifier && !res && peek().id === ":") {
+      advance();
+      advance(":");
+
+      hasOwnScope = true;
+      state.funct["(scope)"].stack();
+      state.funct["(scope)"].block.addBreakLabel(t.value, { token: state.tokens.curr });
+
+      if (!state.tokens.next.labelled && state.tokens.next.value !== "{") {
+        warning("W028", state.tokens.next, t.value, state.tokens.next.value);
+      }
+
+      state.tokens.next.label = t.value;
+      t = state.tokens.next;
+    }
+
+    // Is it a lonely block?
+
+    if (t.id === "{") {
+      // Is it a switch case block?
+      //
+      //  switch (foo) {
+      //    case bar: { <= here.
+      //      ...
+      //    }
+      //  }
+      var iscase = (state.funct["(verb)"] === "case" && state.tokens.curr.value === ":");
+      block(true, true, false, false, iscase);
+
+      if (hasOwnScope) {
+        state.funct["(scope)"].unstack();
+      }
+
+      return;
+    }
+
+    // Parse the statement.
+
+    r = expression(0, true);
+
+    if (r && !(r.identifier && r.value === "function") &&
+        !(r.type === "(punctuator)" && r.left &&
+          r.left.identifier && r.left.value === "function")) {
+      if (!state.isStrict() && state.stmtMissingStrict()) {
+        warning("E007");
+      }
+    }
+
+    // Look for the final semicolon.
+
+    if (!t.block) {
+      if (!state.option.expr && (!r || !r.exps)) {
+        warning("W030", state.tokens.curr);
+      } else if (state.option.nonew && r && r.left && r.id === "(" && r.left.id === "new") {
+        warning("W031", t);
+      }
+      parseFinalSemicolon(t);
+    }
+
+
+    // Restore the indentation.
+
+    indent = i;
+    if (hasOwnScope) {
+      state.funct["(scope)"].unstack();
+    }
+    return r;
+  }
+
+
+  function statements() {
+    var a = [], p;
+
+    while (!state.tokens.next.reach && state.tokens.next.id !== "(end)") {
+      if (state.tokens.next.id === ";") {
+        p = peek();
+
+        if (!p || (p.id !== "(" && p.id !== "[")) {
+          warning("W032");
+        }
+
+        advance(";");
+      } else {
+        a.push(statement());
+      }
+    }
+    return a;
+  }
+
+
+  /*
+   * read all directives
+   */
+  function directives() {
+    var current = state.tokens.next;
+    while (state.tokens.next.id === "(string)") {
+      var next = peekIgnoreEOL();
+      if (!isEndOfExpr(current, next)) {
+        break;
+      }
+      current = next;
+
+      advance();
+      var directive = state.tokens.curr.value;
+      if (state.directive[directive] ||
+          (directive === "use strict" && state.option.strict === "implied")) {
+        warning("W034", state.tokens.curr, directive);
+      }
+
+      // there's no directive negation, so always set to true
+      state.directive[directive] = true;
+
+      parseFinalSemicolon(current);
+    }
+
+    if (state.isStrict()) {
+      state.option.undef = true;
+    }
+  }
+
+
+  /*
+   * Parses a single block. A block is a sequence of statements wrapped in
+   * braces.
+   *
+   * ordinary   - true for everything but function bodies and try blocks.
+   * stmt       - true if block can be a single statement (e.g. in if/for/while).
+   * isfunc     - true if block is a function body
+   * isfatarrow - true if its a body of a fat arrow function
+   * iscase      - true if block is a switch case block
+   */
+  function block(ordinary, stmt, isfunc, isfatarrow, iscase) {
+    var a,
+      b = inblock,
+      old_indent = indent,
+      m,
+      t,
+      line,
+      d;
+
+    inblock = ordinary;
+
+    t = state.tokens.next;
+
+    var metrics = state.funct["(metrics)"];
+    metrics.nestedBlockDepth += 1;
+    metrics.verifyMaxNestedBlockDepthPerFunction();
+
+    if (state.tokens.next.id === "{") {
+      advance("{");
+
+      // create a new block scope
+      state.funct["(scope)"].stack();
+      state.funct["(noblockscopedvar)"] = false;
+
+      line = state.tokens.curr.line;
+      if (state.tokens.next.id !== "}") {
+        indent += state.option.indent;
+        while (!ordinary && state.tokens.next.from > indent) {
+          indent += state.option.indent;
+        }
+
+        if (isfunc) {
+          m = {};
+          for (d in state.directive) {
+            if (_.has(state.directive, d)) {
+              m[d] = state.directive[d];
+            }
+          }
+          directives();
+
+          if (state.option.strict && state.funct["(context)"]["(global)"]) {
+            if (!m["use strict"] && !state.isStrict()) {
+              warning("E007");
+            }
+          }
+        }
+
+        a = statements();
+
+        metrics.statementCount += a.length;
+
+        indent -= state.option.indent;
+      }
+
+      advance("}", t);
+
+      if (isfunc) {
+        state.funct["(scope)"].validateParams();
+        if (m) {
+          state.directive = m;
+        }
+      }
+
+      state.funct["(scope)"].unstack();
+
+      indent = old_indent;
+    } else if (!ordinary) {
+      if (isfunc) {
+        state.funct["(scope)"].stack();
+
+        m = {};
+        if (stmt && !isfatarrow && !state.inMoz()) {
+          error("W118", state.tokens.curr, "function closure expressions");
+        }
+
+        if (!stmt) {
+          for (d in state.directive) {
+            if (_.has(state.directive, d)) {
+              m[d] = state.directive[d];
+            }
+          }
+        }
+        expression(10);
+
+        if (state.option.strict && state.funct["(context)"]["(global)"]) {
+          if (!m["use strict"] && !state.isStrict()) {
+            warning("E007");
+          }
+        }
+
+        state.funct["(scope)"].unstack();
+      } else {
+        error("E021", state.tokens.next, "{", state.tokens.next.value);
+      }
+    } else {
+
+      // check to avoid let declaration not within a block
+      // though is fine inside for loop initializer section
+      state.funct["(noblockscopedvar)"] = state.tokens.next.id !== "for";
+      state.funct["(scope)"].stack();
+
+      if (!stmt || state.option.curly) {
+        warning("W116", state.tokens.next, "{", state.tokens.next.value);
+      }
+
+      state.tokens.next.inBracelessBlock = true;
+      indent += state.option.indent;
+      // test indentation only if statement is in new line
+      a = [statement()];
+      indent -= state.option.indent;
+
+      state.funct["(scope)"].unstack();
+      delete state.funct["(noblockscopedvar)"];
+    }
+
+    // Don't clear and let it propagate out if it is "break", "return" or similar in switch case
+    switch (state.funct["(verb)"]) {
+    case "break":
+    case "continue":
+    case "return":
+    case "throw":
+      if (iscase) {
+        break;
+      }
+
+      /* falls through */
+    default:
+      state.funct["(verb)"] = null;
+    }
+
+    inblock = b;
+    if (ordinary && state.option.noempty && (!a || a.length === 0)) {
+      warning("W035", state.tokens.prev);
+    }
+    metrics.nestedBlockDepth -= 1;
+    return a;
+  }
+
+
+  function countMember(m) {
+    if (membersOnly && typeof membersOnly[m] !== "boolean") {
+      warning("W036", state.tokens.curr, m);
+    }
+    if (typeof member[m] === "number") {
+      member[m] += 1;
+    } else {
+      member[m] = 1;
+    }
+  }
+
+  // Build the syntax table by declaring the syntactic elements of the language.
+
+  type("(number)", function() {
+    return this;
+  });
+
+  type("(string)", function() {
+    return this;
+  });
+
+  state.syntax["(identifier)"] = {
+    type: "(identifier)",
+    lbp: 0,
+    identifier: true,
+
+    nud: function() {
+      var v = this.value;
+
+      // If this identifier is the lone parameter to a shorthand "fat arrow"
+      // function definition, i.e.
+      //
+      //     x => x;
+      //
+      // ...it should not be considered as a variable in the current scope. It
+      // will be added to the scope of the new function when the next token is
+      // parsed, so it can be safely ignored for now.
+      if (state.tokens.next.id === "=>") {
+        return this;
+      }
+
+      if (!state.funct["(comparray)"].check(v)) {
+        state.funct["(scope)"].block.use(v, state.tokens.curr);
+      }
+      return this;
+    },
+
+    led: function() {
+      error("E033", state.tokens.next, state.tokens.next.value);
+    }
+  };
+
+  var baseTemplateSyntax = {
+    identifier: false,
+    template: true,
+  };
+  state.syntax["(template)"] = _.extend({
+    lbp: 155,
+    type: "(template)",
+    nud: doTemplateLiteral,
+    led: doTemplateLiteral,
+    noSubst: false
+  }, baseTemplateSyntax);
+
+  state.syntax["(template middle)"] = _.extend({
+    lbp: 0,
+    type: "(template middle)",
+    middle: true,
+    noSubst: false
+  }, baseTemplateSyntax);
+
+  state.syntax["(template tail)"] = _.extend({
+    lbp: 0,
+    type: "(template tail)",
+    tail: true,
+    noSubst: false
+  }, baseTemplateSyntax);
+
+  state.syntax["(no subst template)"] = _.extend({
+    lbp: 155,
+    type: "(template)",
+    nud: doTemplateLiteral,
+    led: doTemplateLiteral,
+    noSubst: true,
+    tail: true // mark as tail, since it's always the last component
+  }, baseTemplateSyntax);
+
+  type("(regexp)", function() {
+    return this;
+  });
+
+  // ECMAScript parser
+
+  delim("(endline)");
+  (function(x) {
+    x.line = x.from = 0;
+  })(delim("(begin)"));
+  delim("(end)").reach = true;
+  delim("(error)").reach = true;
+  delim("}").reach = true;
+  delim(")");
+  delim("]");
+  delim("\"").reach = true;
+  delim("'").reach = true;
+  delim(";");
+  delim(":").reach = true;
+  delim("#");
+
+  reserve("else");
+  reserve("case").reach = true;
+  reserve("catch");
+  reserve("default").reach = true;
+  reserve("finally");
+  reservevar("arguments", function(x) {
+    if (state.isStrict() && state.funct["(global)"]) {
+      warning("E008", x);
+    }
+  });
+  reservevar("eval");
+  reservevar("false");
+  reservevar("Infinity");
+  reservevar("null");
+  reservevar("this", function(x) {
+    if (state.isStrict() && !isMethod() &&
+        !state.option.validthis && ((state.funct["(statement)"] &&
+        state.funct["(name)"].charAt(0) > "Z") || state.funct["(global)"])) {
+      warning("W040", x);
+    }
+  });
+  reservevar("true");
+  reservevar("undefined");
+
+  assignop("=", "assign", 20);
+  assignop("+=", "assignadd", 20);
+  assignop("-=", "assignsub", 20);
+  assignop("*=", "assignmult", 20);
+  assignop("/=", "assigndiv", 20).nud = function() {
+    error("E014");
+  };
+  assignop("%=", "assignmod", 20);
+
+  bitwiseassignop("&=");
+  bitwiseassignop("|=");
+  bitwiseassignop("^=");
+  bitwiseassignop("<<=");
+  bitwiseassignop(">>=");
+  bitwiseassignop(">>>=");
+  infix(",", function(left, that) {
+    var expr;
+    that.exprs = [left];
+
+    if (state.option.nocomma) {
+      warning("W127");
+    }
+
+    if (!parseComma({ peek: true })) {
+      return that;
+    }
+    while (true) {
+      if (!(expr = expression(10))) {
+        break;
+      }
+      that.exprs.push(expr);
+      if (state.tokens.next.value !== "," || !parseComma()) {
+        break;
+      }
+    }
+    return that;
+  }, 10, true);
+
+  infix("?", function(left, that) {
+    increaseComplexityCount();
+    that.left = left;
+    that.right = expression(10);
+    advance(":");
+    that["else"] = expression(10);
+    return that;
+  }, 30);
+
+  var orPrecendence = 40;
+  infix("||", function(left, that) {
+    increaseComplexityCount();
+    that.left = left;
+    that.right = expression(orPrecendence);
+    return that;
+  }, orPrecendence);
+  infix("&&", "and", 50);
+  bitwise("|", "bitor", 70);
+  bitwise("^", "bitxor", 80);
+  bitwise("&", "bitand", 90);
+  relation("==", function(left, right) {
+    var eqnull = state.option.eqnull &&
+      ((left && left.value) === "null" || (right && right.value) === "null");
+
+    switch (true) {
+      case !eqnull && state.option.eqeqeq:
+        this.from = this.character;
+        warning("W116", this, "===", "==");
+        break;
+      case isTypoTypeof(right, left, state):
+        warning("W122", this, right.value);
+        break;
+      case isTypoTypeof(left, right, state):
+        warning("W122", this, left.value);
+        break;
+    }
+
+    return this;
+  });
+  relation("===", function(left, right) {
+    if (isTypoTypeof(right, left, state)) {
+      warning("W122", this, right.value);
+    } else if (isTypoTypeof(left, right, state)) {
+      warning("W122", this, left.value);
+    }
+    return this;
+  });
+  relation("!=", function(left, right) {
+    var eqnull = state.option.eqnull &&
+        ((left && left.value) === "null" || (right && right.value) === "null");
+
+    if (!eqnull && state.option.eqeqeq) {
+      this.from = this.character;
+      warning("W116", this, "!==", "!=");
+    } else if (isTypoTypeof(right, left, state)) {
+      warning("W122", this, right.value);
+    } else if (isTypoTypeof(left, right, state)) {
+      warning("W122", this, left.value);
+    }
+    return this;
+  });
+  relation("!==", function(left, right) {
+    if (isTypoTypeof(right, left, state)) {
+      warning("W122", this, right.value);
+    } else if (isTypoTypeof(left, right, state)) {
+      warning("W122", this, left.value);
+    }
+    return this;
+  });
+  relation("<");
+  relation(">");
+  relation("<=");
+  relation(">=");
+  bitwise("<<", "shiftleft", 120);
+  bitwise(">>", "shiftright", 120);
+  bitwise(">>>", "shiftrightunsigned", 120);
+  infix("in", "in", 120);
+  infix("instanceof", function(left, token) {
+    var right;
+    var scope = state.funct["(scope)"];
+    token.left = left;
+    token.right = right = expression(120);
+
+    // This condition reflects a syntax error which will be reported by the
+    // `expression` function.
+    if (!right) {
+      return token;
+    }
+
+    if (right.id === "(number)" ||
+        right.id === "(string)" ||
+        right.value === "null" ||
+        (right.value === "undefined" && !scope.has("undefined")) ||
+        right.arity === "unary" ||
+        right.id === "{" ||
+        (right.id === "[" && !right.right) ||
+        right.id === "(regexp)" ||
+        (right.id === "(template)" && !right.tag)) {
+      error("E060");
+    }
+
+    if (right.id === "function") {
+      warning("W139");
+    }
+
+    return token;
+  }, 120);
+  infix("+", function(left, that) {
+    var right;
+    that.left = left;
+    that.right = right = expression(130);
+
+    if (left && right && left.id === "(string)" && right.id === "(string)") {
+      left.value += right.value;
+      left.character = right.character;
+      if (!state.option.scripturl && reg.javascriptURL.test(left.value)) {
+        warning("W050", left);
+      }
+      return left;
+    }
+
+    return that;
+  }, 130);
+  prefix("+", "num");
+  prefix("+++", function() {
+    warning("W007");
+    this.arity = "unary";
+    this.right = expression(150);
+    return this;
+  });
+  infix("+++", function(left) {
+    warning("W007");
+    this.left = left;
+    this.right = expression(130);
+    return this;
+  }, 130);
+  infix("-", "sub", 130);
+  prefix("-", "neg");
+  prefix("---", function() {
+    warning("W006");
+    this.arity = "unary";
+    this.right = expression(150);
+    return this;
+  });
+  infix("---", function(left) {
+    warning("W006");
+    this.left = left;
+    this.right = expression(130);
+    return this;
+  }, 130);
+  infix("*", "mult", 140);
+  infix("/", "div", 140);
+  infix("%", "mod", 140);
+
+  suffix("++");
+  prefix("++", "preinc");
+  state.syntax["++"].exps = true;
+  state.syntax["++"].ltBoundary = "before";
+
+  suffix("--");
+  prefix("--", "predec");
+  state.syntax["--"].exps = true;
+  state.syntax["--"].ltBoundary = "before";
+
+  prefix("delete", function() {
+    var p = expression(10);
+    if (!p) {
+      return this;
+    }
+
+    if (p.id !== "." && p.id !== "[") {
+      warning("W051");
+    }
+    this.first = p;
+
+    // The `delete` operator accepts unresolvable references when not in strict
+    // mode, so the operand may be undefined.
+    if (p.identifier && !state.isStrict()) {
+      p.forgiveUndef = true;
+    }
+    return this;
+  }).exps = true;
+
+  prefix("~", function() {
+    if (state.option.bitwise) {
+      warning("W016", this, "~");
+    }
+    this.arity = "unary";
+    this.right = expression(150);
+    return this;
+  });
+
+  prefix("...", function() {
+    if (!state.inES6(true)) {
+      warning("W119", this, "spread/rest operator", "6");
+    }
+
+    // TODO: Allow all AssignmentExpression
+    // once parsing permits.
+    //
+    // How to handle eg. number, boolean when the built-in
+    // prototype of may have an @@iterator definition?
+    //
+    // Number.prototype[Symbol.iterator] = function * () {
+    //   yield this.valueOf();
+    // };
+    //
+    // var a = [ ...1 ];
+    // console.log(a); // [1];
+    //
+    // for (let n of [...10]) {
+    //    console.log(n);
+    // }
+    // // 10
+    //
+    //
+    // Boolean.prototype[Symbol.iterator] = function * () {
+    //   yield this.valueOf();
+    // };
+    //
+    // var a = [ ...true ];
+    // console.log(a); // [true];
+    //
+    // for (let n of [...false]) {
+    //    console.log(n);
+    // }
+    // // false
+    //
+    if (!state.tokens.next.identifier &&
+        state.tokens.next.type !== "(string)" &&
+          !checkPunctuators(state.tokens.next, ["[", "("])) {
+
+      error("E030", state.tokens.next, state.tokens.next.value);
+    }
+    this.right = expression(150);
+    return this;
+  });
+
+  prefix("!", function() {
+    this.arity = "unary";
+    this.right = expression(150);
+
+    if (!this.right) { // '!' followed by nothing? Give up.
+      quit("E041", this);
+    }
+
+    if (bang[this.right.id] === true) {
+      warning("W018", this, "!");
+    }
+    return this;
+  });
+
+  prefix("typeof", (function() {
+    var p = expression(150);
+    this.first = this.right = p;
+
+    if (!p) { // 'typeof' followed by nothing? Give up.
+      quit("E041", this);
+    }
+
+    // The `typeof` operator accepts unresolvable references, so the operand
+    // may be undefined.
+    if (p.identifier) {
+      p.forgiveUndef = true;
+    }
+    return this;
+  }));
+  prefix("new", function() {
+    var mp = metaProperty("target", function() {
+      if (!state.inES6(true)) {
+        warning("W119", state.tokens.prev, "new.target", "6");
+      }
+      var inFunction, c = state.funct;
+      while (c) {
+        inFunction = !c["(global)"];
+        if (!c["(arrow)"]) { break; }
+        c = c["(context)"];
+      }
+      if (!inFunction) {
+        warning("W136", state.tokens.prev, "new.target");
+      }
+    });
+    if (mp) { return mp; }
+
+    var c = expression(155), i;
+    if (c && c.id !== "function") {
+      if (c.identifier) {
+        c["new"] = true;
+        switch (c.value) {
+        case "Number":
+        case "String":
+        case "Boolean":
+        case "Math":
+        case "JSON":
+          warning("W053", state.tokens.prev, c.value);
+          break;
+        case "Symbol":
+          if (state.inES6()) {
+            warning("W053", state.tokens.prev, c.value);
+          }
+          break;
+        case "Function":
+          if (!state.option.evil) {
+            warning("W054");
+          }
+          break;
+        case "Date":
+        case "RegExp":
+        case "this":
+          break;
+        default:
+          if (c.id !== "function") {
+            i = c.value.substr(0, 1);
+            if (state.option.newcap && (i < "A" || i > "Z") &&
+              !state.funct["(scope)"].isPredefined(c.value)) {
+              warning("W055", state.tokens.curr);
+            }
+          }
+        }
+      } else {
+        if (c.id !== "." && c.id !== "[" && c.id !== "(") {
+          warning("W056", state.tokens.curr);
+        }
+      }
+    } else {
+      if (!state.option.supernew)
+        warning("W057", this);
+    }
+    if (state.tokens.next.id !== "(" && !state.option.supernew) {
+      warning("W058", state.tokens.curr, state.tokens.curr.value);
+    }
+    this.first = this.right = c;
+    return this;
+  });
+  state.syntax["new"].exps = true;
+
+  prefix("void").exps = true;
+
+  infix(".", function(left, that) {
+    var m = identifier(false, true);
+
+    if (typeof m === "string") {
+      countMember(m);
+    }
+
+    that.left = left;
+    that.right = m;
+
+    if (m && m === "hasOwnProperty" && state.tokens.next.value === "=") {
+      warning("W001");
+    }
+
+    if (left && left.value === "arguments" && (m === "callee" || m === "caller")) {
+      if (state.option.noarg)
+        warning("W059", left, m);
+      else if (state.isStrict())
+        error("E008");
+    } else if (!state.option.evil && left && left.value === "document" &&
+        (m === "write" || m === "writeln")) {
+      warning("W060", left);
+    }
+
+    if (!state.option.evil && (m === "eval" || m === "execScript")) {
+      if (isGlobalEval(left, state)) {
+        warning("W061");
+      }
+    }
+
+    return that;
+  }, 160, true);
+
+  infix("(", function(left, that) {
+    if (state.option.immed && left && !left.immed && left.id === "function") {
+      warning("W062");
+    }
+
+    var n = 0;
+    var p = [];
+
+    if (left) {
+      if (left.type === "(identifier)") {
+        if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {
+          if ("Array Number String Boolean Date Object Error Symbol".indexOf(left.value) === -1) {
+            if (left.value === "Math") {
+              warning("W063", left);
+            } else if (state.option.newcap) {
+              warning("W064", left);
+            }
+          }
+        }
+      }
+    }
+
+    if (state.tokens.next.id !== ")") {
+      for (;;) {
+        p[p.length] = expression(10);
+        n += 1;
+        if (state.tokens.next.id !== ",") {
+          break;
+        }
+        parseComma();
+      }
+    }
+
+    advance(")");
+
+    if (typeof left === "object") {
+      if (!state.inES5() && left.value === "parseInt" && n === 1) {
+        warning("W065", state.tokens.curr);
+      }
+      if (!state.option.evil) {
+        if (left.value === "eval" || left.value === "Function" ||
+            left.value === "execScript") {
+          warning("W061", left);
+
+          // This conditional expression was initially implemented with a typo
+          // which prevented the branch's execution in all cases. While
+          // enabling the code will produce behavior that is consistent with
+          // the other forms of code evaluation that follow, such a change is
+          // also technically incompatable with prior versions of JSHint (due
+          // to the fact that the behavior was never formally documented). This
+          // branch should be enabled as part of a major release.
+          //if (p[0] && p[0].id === "(string)") {
+          //  addEvalCode(left, p[0]);
+          //}
+        } else if (p[0] && p[0].id === "(string)" &&
+             (left.value === "setTimeout" ||
+            left.value === "setInterval")) {
+          warning("W066", left);
+          addEvalCode(left, p[0]);
+
+        // window.setTimeout/setInterval
+        } else if (p[0] && p[0].id === "(string)" &&
+             left.value === "." &&
+             left.left.value === "window" &&
+             (left.right === "setTimeout" ||
+            left.right === "setInterval")) {
+          warning("W066", left);
+          addEvalCode(left, p[0]);
+        }
+      }
+      if (!left.identifier && left.id !== "." && left.id !== "[" && left.id !== "=>" &&
+          left.id !== "(" && left.id !== "&&" && left.id !== "||" && left.id !== "?" &&
+          !(state.inES6() && left["(name)"])) {
+        warning("W067", that);
+      }
+    }
+
+    that.left = left;
+    return that;
+  }, 155, true).exps = true;
+
+  prefix("(", function(rbp) {
+    var pn = state.tokens.next, pn1, i = -1;
+    var ret, triggerFnExpr, first, last;
+    var parens = 1;
+    var opening = state.tokens.curr;
+    var preceeding = state.tokens.prev;
+    var isNecessary = !state.option.singleGroups;
+
+    do {
+      if (pn.value === "(") {
+        parens += 1;
+      } else if (pn.value === ")") {
+        parens -= 1;
+      }
+
+      i += 1;
+      pn1 = pn;
+      pn = peek(i);
+    } while (!(parens === 0 && pn1.value === ")") && pn.type !== "(end)");
+
+    if (state.tokens.next.id === "function") {
+      triggerFnExpr = state.tokens.next.immed = true;
+    }
+
+    // If the balanced grouping operator is followed by a "fat arrow", the
+    // current token marks the beginning of a "fat arrow" function and parsing
+    // should proceed accordingly.
+    if (pn.value === "=>") {
+      return doFunction({ type: "arrow", parsedOpening: true });
+    }
+
+    var exprs = [];
+
+    if (state.tokens.next.id !== ")") {
+      for (;;) {
+        exprs.push(expression(10));
+
+        if (state.tokens.next.id !== ",") {
+          break;
+        }
+
+        if (state.option.nocomma) {
+          warning("W127");
+        }
+
+        parseComma();
+      }
+    }
+
+    advance(")", this);
+    if (state.option.immed && exprs[0] && exprs[0].id === "function") {
+      if (state.tokens.next.id !== "(" &&
+        state.tokens.next.id !== "." && state.tokens.next.id !== "[") {
+        warning("W068", this);
+      }
+    }
+
+    if (!exprs.length) {
+      return;
+    }
+    if (exprs.length > 1) {
+      ret = Object.create(state.syntax[","]);
+      ret.exprs = exprs;
+
+      first = exprs[0];
+      last = exprs[exprs.length - 1];
+    } else {
+      ret = first = last = exprs[0];
+
+      if (!isNecessary) {
+        isNecessary =
+          // Used to distinguish from an ExpressionStatement which may not
+          // begin with the `{` and `function` tokens
+          (opening.beginsStmt && (ret.id === "{" || triggerFnExpr || isFunctor(ret))) ||
+          // Used to signal that a function expression is being supplied to
+          // some other operator.
+          (triggerFnExpr &&
+            // For parenthesis wrapping a function expression to be considered
+            // necessary, the grouping operator should be the left-hand-side of
+            // some other operator--either within the parenthesis or directly
+            // following them.
+            (!isEndOfExpr() || state.tokens.prev.id !== "}")) ||
+          // Used to demarcate an arrow function as the left-hand side of some
+          // operator.
+          (isFunctor(ret) && !isEndOfExpr()) ||
+          // Used as the return value of a single-statement arrow function
+          (ret.id === "{" && preceeding.id === "=>") ||
+          // Used to delineate an integer number literal from a dereferencing
+          // punctuator (otherwise interpreted as a decimal point)
+          (ret.type === "(number)" &&
+            checkPunctuator(pn, ".") && /^\d+$/.test(ret.value)) ||
+          // Used to wrap object destructuring assignment
+          (opening.beginsStmt && ret.id === "=" && ret.left.id === "{");
+      }
+    }
+
+    if (ret) {
+      // The operator may be necessary to override the default binding power of
+      // neighboring operators (whenever there is an operator in use within the
+      // first expression *or* the current group contains multiple expressions)
+      if (!isNecessary && (isOperator(first) || ret.exprs)) {
+        isNecessary =
+          (rbp > first.lbp) ||
+          (rbp > 0 && rbp === first.lbp) ||
+          (!isEndOfExpr() && last.lbp < state.tokens.next.lbp);
+      }
+
+      if (!isNecessary) {
+        warning("W126", opening);
+      }
+
+      ret.paren = true;
+    }
+
+    return ret;
+  });
+
+  application("=>");
+
+  infix("[", function(left, that) {
+    var e = expression(10), s;
+    if (e && e.type === "(string)") {
+      if (!state.option.evil && (e.value === "eval" || e.value === "execScript")) {
+        if (isGlobalEval(left, state)) {
+          warning("W061");
+        }
+      }
+
+      countMember(e.value);
+      if (!state.option.sub && reg.identifier.test(e.value)) {
+        s = state.syntax[e.value];
+        if (!s || !isReserved(s)) {
+          warning("W069", state.tokens.prev, e.value);
+        }
+      }
+    }
+    advance("]", that);
+
+    if (e && e.value === "hasOwnProperty" && state.tokens.next.value === "=") {
+      warning("W001");
+    }
+
+    that.left = left;
+    that.right = e;
+    return that;
+  }, 160, true);
+
+  function comprehensiveArrayExpression() {
+    var res = {};
+    res.exps = true;
+    state.funct["(comparray)"].stack();
+
+    // Handle reversed for expressions, used in spidermonkey
+    var reversed = false;
+    if (state.tokens.next.value !== "for") {
+      reversed = true;
+      if (!state.inMoz()) {
+        warning("W116", state.tokens.next, "for", state.tokens.next.value);
+      }
+      state.funct["(comparray)"].setState("use");
+      res.right = expression(10);
+    }
+
+    advance("for");
+    if (state.tokens.next.value === "each") {
+      advance("each");
+      if (!state.inMoz()) {
+        warning("W118", state.tokens.curr, "for each");
+      }
+    }
+    advance("(");
+    state.funct["(comparray)"].setState("define");
+    res.left = expression(130);
+    if (_.contains(["in", "of"], state.tokens.next.value)) {
+      advance();
+    } else {
+      error("E045", state.tokens.curr);
+    }
+    state.funct["(comparray)"].setState("generate");
+    expression(10);
+
+    advance(")");
+    if (state.tokens.next.value === "if") {
+      advance("if");
+      advance("(");
+      state.funct["(comparray)"].setState("filter");
+      res.filter = expression(10);
+      advance(")");
+    }
+
+    if (!reversed) {
+      state.funct["(comparray)"].setState("use");
+      res.right = expression(10);
+    }
+
+    advance("]");
+    state.funct["(comparray)"].unstack();
+    return res;
+  }
+
+  prefix("[", function() {
+    var blocktype = lookupBlockType();
+    if (blocktype.isCompArray) {
+      if (!state.option.esnext && !state.inMoz()) {
+        warning("W118", state.tokens.curr, "array comprehension");
+      }
+      return comprehensiveArrayExpression();
+    } else if (blocktype.isDestAssign) {
+      this.destructAssign = destructuringPattern({ openingParsed: true, assignment: true });
+      return this;
+    }
+    var b = state.tokens.curr.line !== startLine(state.tokens.next);
+    this.first = [];
+    if (b) {
+      indent += state.option.indent;
+      if (state.tokens.next.from === indent + state.option.indent) {
+        indent += state.option.indent;
+      }
+    }
+    while (state.tokens.next.id !== "(end)") {
+      while (state.tokens.next.id === ",") {
+        if (!state.option.elision) {
+          if (!state.inES5()) {
+            // Maintain compat with old options --- ES5 mode without
+            // elision=true will warn once per comma
+            warning("W070");
+          } else {
+            warning("W128");
+            do {
+              advance(",");
+            } while (state.tokens.next.id === ",");
+            continue;
+          }
+        }
+        advance(",");
+      }
+
+      if (state.tokens.next.id === "]") {
+        break;
+      }
+
+      this.first.push(expression(10));
+      if (state.tokens.next.id === ",") {
+        parseComma({ allowTrailing: true });
+        if (state.tokens.next.id === "]" && !state.inES5()) {
+          warning("W070", state.tokens.curr);
+          break;
+        }
+      } else {
+        if (state.option.trailingcomma && state.inES5()) {
+          warningAt("W140", state.tokens.curr.line, state.tokens.curr.character);
+        }
+        break;
+      }
+    }
+    if (b) {
+      indent -= state.option.indent;
+    }
+    advance("]", this);
+    return this;
+  });
+
+
+  function isMethod() {
+    return state.funct["(statement)"] && state.funct["(statement)"].type === "class" ||
+           state.funct["(context)"] && state.funct["(context)"]["(verb)"] === "class";
+  }
+
+
+  function isPropertyName(token) {
+    return token.identifier || token.id === "(string)" || token.id === "(number)";
+  }
+
+
+  function propertyName(preserveOrToken) {
+    var id;
+    var preserve = true;
+    if (typeof preserveOrToken === "object") {
+      id = preserveOrToken;
+    } else {
+      preserve = preserveOrToken;
+      id = optionalidentifier(false, true, preserve);
+    }
+
+    if (!id) {
+      if (state.tokens.next.id === "(string)") {
+        id = state.tokens.next.value;
+        if (!preserve) {
+          advance();
+        }
+      } else if (state.tokens.next.id === "(number)") {
+        id = state.tokens.next.value.toString();
+        if (!preserve) {
+          advance();
+        }
+      }
+    } else if (typeof id === "object") {
+      if (id.id === "(string)" || id.id === "(identifier)") id = id.value;
+      else if (id.id === "(number)") id = id.value.toString();
+    }
+
+    if (id === "hasOwnProperty") {
+      warning("W001");
+    }
+
+    return id;
+  }
+
+  /**
+   * @param {Object} [options]
+   * @param {token} [options.loneArg] The argument to the function in cases
+   *                                  where it was defined using the
+   *                                  single-argument shorthand.
+   * @param {bool} [options.parsedOpening] Whether the opening parenthesis has
+   *                                       already been parsed.
+   * @returns {{ arity: number, params: Array.<string>}}
+   */
+  function functionparams(options) {
+    var next;
+    var paramsIds = [];
+    var ident;
+    var tokens = [];
+    var t;
+    var pastDefault = false;
+    var pastRest = false;
+    var arity = 0;
+    var loneArg = options && options.loneArg;
+
+    if (loneArg && loneArg.identifier === true) {
+      state.funct["(scope)"].addParam(loneArg.value, loneArg);
+      return { arity: 1, params: [ loneArg.value ] };
+    }
+
+    next = state.tokens.next;
+
+    if (!options || !options.parsedOpening) {
+      advance("(");
+    }
+
+    if (state.tokens.next.id === ")") {
+      advance(")");
+      return;
+    }
+
+    function addParam(addParamArgs) {
+      state.funct["(scope)"].addParam.apply(state.funct["(scope)"], addParamArgs);
+    }
+
+    for (;;) {
+      arity++;
+      // are added to the param scope
+      var currentParams = [];
+
+      if (_.contains(["{", "["], state.tokens.next.id)) {
+        tokens = destructuringPattern();
+        for (t in tokens) {
+          t = tokens[t];
+          if (t.id) {
+            paramsIds.push(t.id);
+            currentParams.push([t.id, t.token]);
+          }
+        }
+      } else {
+        if (checkPunctuator(state.tokens.next, "...")) pastRest = true;
+        ident = identifier(true);
+        if (ident) {
+          paramsIds.push(ident);
+          currentParams.push([ident, state.tokens.curr]);
+        } else {
+          // Skip invalid parameter.
+          while (!checkPunctuators(state.tokens.next, [",", ")"])) advance();
+        }
+      }
+
+      // It is valid to have a regular argument after a default argument
+      // since undefined can be used for missing parameters. Still warn as it is
+      // a possible code smell.
+      if (pastDefault) {
+        if (state.tokens.next.id !== "=") {
+          error("W138", state.tokens.current);
+        }
+      }
+      if (state.tokens.next.id === "=") {
+        if (!state.inES6()) {
+          warning("W119", state.tokens.next, "default parameters", "6");
+        }
+        advance("=");
+        pastDefault = true;
+        expression(10);
+      }
+
+      // now we have evaluated the default expression, add the variable to the param scope
+      currentParams.forEach(addParam);
+
+      if (state.tokens.next.id === ",") {
+        if (pastRest) {
+          warning("W131", state.tokens.next);
+        }
+        parseComma();
+      } else {
+        advance(")", next);
+        return { arity: arity, params: paramsIds };
+      }
+    }
+  }
+
+  function functor(name, token, overwrites) {
+    var funct = {
+      "(name)"      : name,
+      "(breakage)"  : 0,
+      "(loopage)"   : 0,
+      "(tokens)"    : {},
+      "(properties)": {},
+
+      "(catch)"     : false,
+      "(global)"    : false,
+
+      "(line)"      : null,
+      "(character)" : null,
+      "(metrics)"   : null,
+      "(statement)" : null,
+      "(context)"   : null,
+      "(scope)"     : null,
+      "(comparray)" : null,
+      "(generator)" : null,
+      "(arrow)"     : null,
+      "(params)"    : null
+    };
+
+    if (token) {
+      _.extend(funct, {
+        "(line)"     : token.line,
+        "(character)": token.character,
+        "(metrics)"  : createMetrics(token)
+      });
+    }
+
+    _.extend(funct, overwrites);
+
+    if (funct["(context)"]) {
+      funct["(scope)"] = funct["(context)"]["(scope)"];
+      funct["(comparray)"]  = funct["(context)"]["(comparray)"];
+    }
+
+    return funct;
+  }
+
+  function isFunctor(token) {
+    return "(scope)" in token;
+  }
+
+  /**
+   * Determine if the parser has begun parsing executable code.
+   *
+   * @param {Token} funct - The current "functor" token
+   *
+   * @returns {boolean}
+   */
+  function hasParsedCode(funct) {
+    return funct["(global)"] && !funct["(verb)"];
+  }
+
+  /**
+   * This function is used as both a null-denotation method *and* a
+   * left-denotation method, meaning the first parameter is overloaded.
+   */
+  function doTemplateLiteral(leftOrRbp) {
+    // ASSERT: this.type === "(template)"
+    // jshint validthis: true
+    var ctx = this.context;
+    var noSubst = this.noSubst;
+    var depth = this.depth;
+    var left = typeof leftOrRbp === "number" ? null : leftOrRbp;
+
+    if (!noSubst) {
+      while (!end()) {
+        if (!state.tokens.next.template || state.tokens.next.depth > depth) {
+          expression(0); // should probably have different rbp?
+        } else {
+          // skip template start / middle
+          advance();
+        }
+      }
+    }
+
+    return {
+      id: "(template)",
+      type: "(template)",
+      tag: left
+    };
+
+    function end() {
+      if (state.tokens.curr.template && state.tokens.curr.tail &&
+          state.tokens.curr.context === ctx) return true;
+      var complete = (state.tokens.next.template && state.tokens.next.tail &&
+                      state.tokens.next.context === ctx);
+      if (complete) advance();
+      return complete || state.tokens.next.isUnclosed;
+    }
+  }
+
+  /**
+   * @param {Object} [options]
+   * @param {token} [options.name] The identifier belonging to the function (if
+   *                               any)
+   * @param {boolean} [options.statement] The statement that triggered creation
+   *                                      of the current function.
+   * @param {string} [options.type] If specified, either "generator" or "arrow"
+   * @param {token} [options.loneArg] The argument to the function in cases
+   *                                  where it was defined using the
+   *                                  single-argument shorthand
+   * @param {bool} [options.parsedOpening] Whether the opening parenthesis has
+   *                                       already been parsed
+   * @param {token} [options.classExprBinding] Define a function with this
+   *                                           identifier in the new function's
+   *                                           scope, mimicking the bahavior of
+   *                                           class expression names within
+   *                                           the body of member functions.
+   */
+  function doFunction(options) {
+    var f, token, name, statement, classExprBinding, isGenerator, isArrow, ignoreLoopFunc;
+    var oldOption = state.option;
+    var oldIgnored = state.ignored;
+
+    if (options) {
+      name = options.name;
+      statement = options.statement;
+      classExprBinding = options.classExprBinding;
+      isGenerator = options.type === "generator";
+      isArrow = options.type === "arrow";
+      ignoreLoopFunc = options.ignoreLoopFunc;
+    }
+
+    state.option = Object.create(state.option);
+    state.ignored = Object.create(state.ignored);
+
+    state.funct = functor(name || state.nameStack.infer(), state.tokens.next, {
+      "(statement)": statement,
+      "(context)":   state.funct,
+      "(arrow)":     isArrow,
+      "(generator)": isGenerator
+    });
+
+    f = state.funct;
+    token = state.tokens.curr;
+    token.funct = state.funct;
+
+    functions.push(state.funct);
+
+    // So that the function is available to itself and referencing itself is not
+    // seen as a closure, add the function name to a new scope, but do not
+    // test for unused (unused: false)
+    // it is a new block scope so that params can override it, it can be block scoped
+    // but declarations inside the function don't cause already declared error
+    state.funct["(scope)"].stack("functionouter");
+    var internallyAccessibleName = name || classExprBinding;
+    if (internallyAccessibleName) {
+      state.funct["(scope)"].block.add(internallyAccessibleName,
+        classExprBinding ? "class" : "function", state.tokens.curr, false);
+    }
+
+    // create the param scope (params added in functionparams)
+    state.funct["(scope)"].stack("functionparams");
+
+    var paramsInfo = functionparams(options);
+
+    if (paramsInfo) {
+      state.funct["(params)"] = paramsInfo.params;
+      state.funct["(metrics)"].arity = paramsInfo.arity;
+      state.funct["(metrics)"].verifyMaxParametersPerFunction();
+    } else {
+      state.funct["(metrics)"].arity = 0;
+    }
+
+    if (isArrow) {
+      if (!state.inES6(true)) {
+        warning("W119", state.tokens.curr, "arrow function syntax (=>)", "6");
+      }
+
+      if (!options.loneArg) {
+        advance("=>");
+      }
+    }
+
+    block(false, true, true, isArrow);
+
+    if (!state.option.noyield && isGenerator &&
+        state.funct["(generator)"] !== "yielded") {
+      warning("W124", state.tokens.curr);
+    }
+
+    state.funct["(metrics)"].verifyMaxStatementsPerFunction();
+    state.funct["(metrics)"].verifyMaxComplexityPerFunction();
+    state.funct["(unusedOption)"] = state.option.unused;
+    state.option = oldOption;
+    state.ignored = oldIgnored;
+    state.funct["(last)"] = state.tokens.curr.line;
+    state.funct["(lastcharacter)"] = state.tokens.curr.character;
+
+    // unstack the params scope
+    state.funct["(scope)"].unstack(); // also does usage and label checks
+
+    // unstack the function outer stack
+    state.funct["(scope)"].unstack();
+
+    state.funct = state.funct["(context)"];
+
+    if (!ignoreLoopFunc && !state.option.loopfunc && state.funct["(loopage)"]) {
+      // If the function we just parsed accesses any non-local variables
+      // trigger a warning. Otherwise, the function is safe even within
+      // a loop.
+      if (f["(isCapturing)"]) {
+        warning("W083", token);
+      }
+    }
+
+    return f;
+  }
+
+  function createMetrics(functionStartToken) {
+    return {
+      statementCount: 0,
+      nestedBlockDepth: -1,
+      ComplexityCount: 1,
+      arity: 0,
+
+      verifyMaxStatementsPerFunction: function() {
+        if (state.option.maxstatements &&
+          this.statementCount > state.option.maxstatements) {
+          warning("W071", functionStartToken, this.statementCount);
+        }
+      },
+
+      verifyMaxParametersPerFunction: function() {
+        if (_.isNumber(state.option.maxparams) &&
+          this.arity > state.option.maxparams) {
+          warning("W072", functionStartToken, this.arity);
+        }
+      },
+
+      verifyMaxNestedBlockDepthPerFunction: function() {
+        if (state.option.maxdepth &&
+          this.nestedBlockDepth > 0 &&
+          this.nestedBlockDepth === state.option.maxdepth + 1) {
+          warning("W073", null, this.nestedBlockDepth);
+        }
+      },
+
+      verifyMaxComplexityPerFunction: function() {
+        var max = state.option.maxcomplexity;
+        var cc = this.ComplexityCount;
+        if (max && cc > max) {
+          warning("W074", functionStartToken, cc);
+        }
+      }
+    };
+  }
+
+  function increaseComplexityCount() {
+    state.funct["(metrics)"].ComplexityCount += 1;
+  }
+
+  // Parse assignments that were found instead of conditionals.
+  // For example: if (a = 1) { ... }
+
+  function checkCondAssignment(expr) {
+    var id, paren;
+    if (expr) {
+      id = expr.id;
+      paren = expr.paren;
+      if (id === "," && (expr = expr.exprs[expr.exprs.length - 1])) {
+        id = expr.id;
+        paren = paren || expr.paren;
+      }
+    }
+    switch (id) {
+    case "=":
+    case "+=":
+    case "-=":
+    case "*=":
+    case "%=":
+    case "&=":
+    case "|=":
+    case "^=":
+    case "/=":
+      if (!paren && !state.option.boss) {
+        warning("W084");
+      }
+    }
+  }
+
+  /**
+   * @param {object} props Collection of property descriptors for a given
+   *                       object.
+   */
+  function checkProperties(props) {
+    // Check for lonely setters if in the ES5 mode.
+    if (state.inES5()) {
+      for (var name in props) {
+        if (props[name] && props[name].setterToken && !props[name].getterToken) {
+          warning("W078", props[name].setterToken);
+        }
+      }
+    }
+  }
+
+  function metaProperty(name, c) {
+    if (checkPunctuator(state.tokens.next, ".")) {
+      var left = state.tokens.curr.id;
+      advance(".");
+      var id = identifier();
+      state.tokens.curr.isMetaProperty = true;
+      if (name !== id) {
+        error("E057", state.tokens.prev, left, id);
+      } else {
+        c();
+      }
+      return state.tokens.curr;
+    }
+  }
+
+  (function(x) {
+    x.nud = function() {
+      var b, f, i, p, t, isGeneratorMethod = false, nextVal;
+      var props = Object.create(null); // All properties, including accessors
+
+      b = state.tokens.curr.line !== startLine(state.tokens.next);
+      if (b) {
+        indent += state.option.indent;
+        if (state.tokens.next.from === indent + state.option.indent) {
+          indent += state.option.indent;
+        }
+      }
+
+      var blocktype = lookupBlockType();
+      if (blocktype.isDestAssign) {
+        this.destructAssign = destructuringPattern({ openingParsed: true, assignment: true });
+        return this;
+      }
+
+      for (;;) {
+        if (state.tokens.next.id === "}") {
+          break;
+        }
+
+        nextVal = state.tokens.next.value;
+        if (state.tokens.next.identifier &&
+            (peekIgnoreEOL().id === "," || peekIgnoreEOL().id === "}")) {
+          if (!state.inES6()) {
+            warning("W104", state.tokens.next, "object short notation", "6");
+          }
+          i = propertyName(true);
+          saveProperty(props, i, state.tokens.next);
+
+          expression(10);
+
+        } else if (peek().id !== ":" && (nextVal === "get" || nextVal === "set")) {
+          advance(nextVal);
+
+          if (!state.inES5()) {
+            error("E034");
+          }
+
+          i = propertyName();
+
+          // ES6 allows for get() {...} and set() {...} method
+          // definition shorthand syntax, so we don't produce an error
+          // if linting ECMAScript 6 code.
+          if (!i && !state.inES6()) {
+            error("E035");
+          }
+
+          // We don't want to save this getter unless it's an actual getter
+          // and not an ES6 concise method
+          if (i) {
+            saveAccessor(nextVal, props, i, state.tokens.curr);
+          }
+
+          t = state.tokens.next;
+          f = doFunction();
+          p = f["(params)"];
+
+          // Don't warn about getter/setter pairs if this is an ES6 concise method
+          if (nextVal === "get" && i && p) {
+            warning("W076", t, p[0], i);
+          } else if (nextVal === "set" && i && f["(metrics)"].arity !== 1) {
+            warning("W077", t, i);
+          }
+        } else {
+          if (state.tokens.next.value === "*" && state.tokens.next.type === "(punctuator)") {
+            if (!state.inES6()) {
+              warning("W104", state.tokens.next, "generator functions", "6");
+            }
+            advance("*");
+            isGeneratorMethod = true;
+          } else {
+            isGeneratorMethod = false;
+          }
+
+          if (state.tokens.next.id === "[") {
+            i = computedPropertyName();
+            state.nameStack.set(i);
+          } else {
+            state.nameStack.set(state.tokens.next);
+            i = propertyName();
+            saveProperty(props, i, state.tokens.next);
+
+            if (typeof i !== "string") {
+              break;
+            }
+          }
+
+          if (state.tokens.next.value === "(") {
+            if (!state.inES6()) {
+              warning("W104", state.tokens.curr, "concise methods", "6");
+            }
+            doFunction({ type: isGeneratorMethod ? "generator" : null });
+          } else {
+            advance(":");
+            expression(10);
+          }
+        }
+
+        countMember(i);
+
+        if (state.tokens.next.id === ",") {
+          parseComma({ allowTrailing: true, property: true });
+          if (state.tokens.next.id === ",") {
+            warning("W070", state.tokens.curr);
+          } else if (state.tokens.next.id === "}" && !state.inES5()) {
+            warning("W070", state.tokens.curr);
+          }
+        } else {
+          if (state.option.trailingcomma && state.inES5()) {
+            warningAt("W140", state.tokens.curr.line, state.tokens.curr.character);
+          }
+          break;
+        }
+      }
+      if (b) {
+        indent -= state.option.indent;
+      }
+      advance("}", this);
+
+      checkProperties(props);
+
+      return this;
+    };
+    x.fud = function() {
+      error("E036", state.tokens.curr);
+    };
+  }(delim("{")));
+
+  function destructuringPattern(options) {
+    var isAssignment = options && options.assignment;
+
+    if (!state.inES6()) {
+      warning("W104", state.tokens.curr,
+        isAssignment ? "destructuring assignment" : "destructuring binding", "6");
+    }
+
+    return destructuringPatternRecursive(options);
+  }
+
+  function destructuringPatternRecursive(options) {
+    var ids;
+    var identifiers = [];
+    var openingParsed = options && options.openingParsed;
+    var isAssignment = options && options.assignment;
+    var recursiveOptions = isAssignment ? { assignment: isAssignment } : null;
+    var firstToken = openingParsed ? state.tokens.curr : state.tokens.next;
+
+    var nextInnerDE = function() {
+      var ident;
+      if (checkPunctuators(state.tokens.next, ["[", "{"])) {
+        ids = destructuringPatternRecursive(recursiveOptions);
+        for (var id in ids) {
+          id = ids[id];
+          identifiers.push({ id: id.id, token: id.token });
+        }
+      } else if (checkPunctuator(state.tokens.next, ",")) {
+        identifiers.push({ id: null, token: state.tokens.curr });
+      } else if (checkPunctuator(state.tokens.next, "(")) {
+        advance("(");
+        nextInnerDE();
+        advance(")");
+      } else {
+        var is_rest = checkPunctuator(state.tokens.next, "...");
+
+        if (isAssignment) {
+          var assignTarget = expression(20);
+          if (assignTarget) {
+            checkLeftSideAssign(assignTarget);
+
+            // if the target was a simple identifier, add it to the list to return
+            if (assignTarget.identifier) {
+              ident = assignTarget.value;
+            }
+          }
+        } else {
+          ident = identifier();
+        }
+        if (ident) {
+          identifiers.push({ id: ident, token: state.tokens.curr });
+        }
+        return is_rest;
+      }
+      return false;
+    };
+    var assignmentProperty = function() {
+      var id;
+      if (checkPunctuator(state.tokens.next, "[")) {
+        advance("[");
+        expression(10);
+        advance("]");
+        advance(":");
+        nextInnerDE();
+      } else if (state.tokens.next.id === "(string)" ||
+                 state.tokens.next.id === "(number)") {
+        advance();
+        advance(":");
+        nextInnerDE();
+      } else {
+        // this id will either be the property name or the property name and the assigning identifier
+        id = identifier();
+        if (checkPunctuator(state.tokens.next, ":")) {
+          advance(":");
+          nextInnerDE();
+        } else if (id) {
+          // in this case we are assigning (not declaring), so check assignment
+          if (isAssignment) {
+            checkLeftSideAssign(state.tokens.curr);
+          }
+          identifiers.push({ id: id, token: state.tokens.curr });
+        }
+      }
+    };
+
+    var id, value;
+    if (checkPunctuator(firstToken, "[")) {
+      if (!openingParsed) {
+        advance("[");
+      }
+      if (checkPunctuator(state.tokens.next, "]")) {
+        warning("W137", state.tokens.curr);
+      }
+      var element_after_rest = false;
+      while (!checkPunctuator(state.tokens.next, "]")) {
+        if (nextInnerDE() && !element_after_rest &&
+            checkPunctuator(state.tokens.next, ",")) {
+          warning("W130", state.tokens.next);
+          element_after_rest = true;
+        }
+        if (checkPunctuator(state.tokens.next, "=")) {
+          if (checkPunctuator(state.tokens.prev, "...")) {
+            advance("]");
+          } else {
+            advance("=");
+          }
+          id = state.tokens.prev;
+          value = expression(10);
+          if (value && value.type === "undefined") {
+            warning("W080", id, id.value);
+          }
+        }
+        if (!checkPunctuator(state.tokens.next, "]")) {
+          advance(",");
+        }
+      }
+      advance("]");
+    } else if (checkPunctuator(firstToken, "{")) {
+
+      if (!openingParsed) {
+        advance("{");
+      }
+      if (checkPunctuator(state.tokens.next, "}")) {
+        warning("W137", state.tokens.curr);
+      }
+      while (!checkPunctuator(state.tokens.next, "}")) {
+        assignmentProperty();
+        if (checkPunctuator(state.tokens.next, "=")) {
+          advance("=");
+          id = state.tokens.prev;
+          value = expression(10);
+          if (value && value.type === "undefined") {
+            warning("W080", id, id.value);
+          }
+        }
+        if (!checkPunctuator(state.tokens.next, "}")) {
+          advance(",");
+          if (checkPunctuator(state.tokens.next, "}")) {
+            // Trailing comma
+            // ObjectBindingPattern: { BindingPropertyList , }
+            break;
+          }
+        }
+      }
+      advance("}");
+    }
+    return identifiers;
+  }
+
+  function destructuringPatternMatch(tokens, value) {
+    var first = value.first;
+
+    if (!first)
+      return;
+
+    _.zip(tokens, Array.isArray(first) ? first : [ first ]).forEach(function(val) {
+      var token = val[0];
+      var value = val[1];
+
+      if (token && value)
+        token.first = value;
+      else if (token && token.first && !value)
+        warning("W080", token.first, token.first.value);
+    });
+  }
+
+  function blockVariableStatement(type, statement, context) {
+    // used for both let and const statements
+
+    var prefix = context && context.prefix;
+    var inexport = context && context.inexport;
+    var isLet = type === "let";
+    var isConst = type === "const";
+    var tokens, lone, value, letblock;
+
+    if (!state.inES6()) {
+      warning("W104", state.tokens.curr, type, "6");
+    }
+
+    if (isLet && state.tokens.next.value === "(") {
+      if (!state.inMoz()) {
+        warning("W118", state.tokens.next, "let block");
+      }
+      advance("(");
+      state.funct["(scope)"].stack();
+      letblock = true;
+    } else if (state.funct["(noblockscopedvar)"]) {
+      error("E048", state.tokens.curr, isConst ? "Const" : "Let");
+    }
+
+    statement.first = [];
+    for (;;) {
+      var names = [];
+      if (_.contains(["{", "["], state.tokens.next.value)) {
+        tokens = destructuringPattern();
+        lone = false;
+      } else {
+        tokens = [ { id: identifier(), token: state.tokens.curr } ];
+        lone = true;
+      }
+
+      if (!prefix && isConst && state.tokens.next.id !== "=") {
+        warning("E012", state.tokens.curr, state.tokens.curr.value);
+      }
+
+      for (var t in tokens) {
+        if (tokens.hasOwnProperty(t)) {
+          t = tokens[t];
+          if (state.funct["(scope)"].block.isGlobal()) {
+            if (predefined[t.id] === false) {
+              warning("W079", t.token, t.id);
+            }
+          }
+          if (t.id && !state.funct["(noblockscopedvar)"]) {
+            state.funct["(scope)"].addlabel(t.id, {
+              type: type,
+              token: t.token });
+            names.push(t.token);
+          }
+        }
+      }
+
+      if (state.tokens.next.id === "=") {
+        advance("=");
+        if (!prefix && peek(0).id === "=" && state.tokens.next.identifier) {
+          warning("W120", state.tokens.next, state.tokens.next.value);
+        }
+        var id = state.tokens.prev;
+        // don't accept `in` in expression if prefix is used for ForIn/Of loop.
+        value = expression(prefix ? 120 : 10);
+        if (!prefix && value && value.type === "undefined") {
+          warning("W080", id, id.value);
+        }
+        if (lone) {
+          tokens[0].first = value;
+        } else {
+          destructuringPatternMatch(names, value);
+        }
+      }
+
+      if (!prefix) {
+        for (t in tokens) {
+          if (tokens.hasOwnProperty(t)) {
+            t = tokens[t];
+            state.funct["(scope)"].initialize(t.id);
+
+            if (lone && inexport) {
+              state.funct["(scope)"].setExported(t.token.value, t.token);
+            }
+          }
+        }
+      }
+
+      statement.first = statement.first.concat(names);
+
+      if (state.tokens.next.id !== ",") {
+        break;
+      }
+      parseComma();
+    }
+    if (letblock) {
+      advance(")");
+      block(true, true);
+      statement.block = true;
+      state.funct["(scope)"].unstack();
+    }
+
+    return statement;
+  }
+
+  var conststatement = stmt("const", function(context) {
+    return blockVariableStatement("const", this, context);
+  });
+  conststatement.exps = true;
+
+  var letstatement = stmt("let", function(context) {
+    return blockVariableStatement("let", this, context);
+  });
+  letstatement.exps = true;
+
+  var varstatement = stmt("var", function(context) {
+    var prefix = context && context.prefix;
+    var inexport = context && context.inexport;
+    var tokens, lone, value;
+
+    this.first = [];
+    for (;;) {
+      var names = [];
+      if (_.contains(["{", "["], state.tokens.next.value)) {
+        tokens = destructuringPattern();
+        lone = false;
+      } else {
+        tokens = [ { id: identifier(), token: state.tokens.curr } ];
+        lone = true;
+      }
+
+      if (state.option.varstmt) {
+        warning("W132", this);
+      }
+
+      this.first = this.first.concat(names);
+
+      for (var t in tokens) {
+        if (tokens.hasOwnProperty(t)) {
+          t = tokens[t];
+          if (state.funct["(global)"] && !state.impliedClosure()) {
+            if (predefined[t.id] === false) {
+              warning("W079", t.token, t.id);
+            } else if (state.option.futurehostile === false) {
+              if ((!state.inES5() && vars.ecmaIdentifiers[5][t.id] === false) ||
+                (!state.inES6() && vars.ecmaIdentifiers[6][t.id] === false)) {
+                warning("W129", t.token, t.id);
+              }
+            }
+          }
+          if (t.id) {
+            state.funct["(scope)"].addlabel(t.id, {
+              type: "var",
+              token: t.token });
+
+            if (lone && inexport) {
+              state.funct["(scope)"].setExported(t.id, t.token);
+            }
+            names.push(t.token);
+          }
+        }
+      }
+
+      if (state.tokens.next.id === "=") {
+        state.nameStack.set(state.tokens.curr);
+
+        advance("=");
+        if (peek(0).id === "=" && state.tokens.next.identifier) {
+          if (!prefix &&
+              !state.funct["(params)"] ||
+              state.funct["(params)"].indexOf(state.tokens.next.value) === -1) {
+            warning("W120", state.tokens.next, state.tokens.next.value);
+          }
+        }
+        var id = state.tokens.prev;
+        // don't accept `in` in expression if prefix is used for ForIn/Of loop.
+        value = expression(prefix ? 120 : 10);
+        if (value && !prefix && !state.funct["(loopage)"] && value.type === "undefined") {
+          warning("W080", id, id.value);
+        }
+        if (lone) {
+          tokens[0].first = value;
+        } else {
+          destructuringPatternMatch(names, value);
+        }
+      }
+
+      if (state.tokens.next.id !== ",") {
+        break;
+      }
+      parseComma();
+    }
+
+    return this;
+  });
+  varstatement.exps = true;
+
+  blockstmt("class", function(rbp) {
+    return classdef.call(this, rbp, true);
+  });
+
+  function classdef(rbp, isStatement) {
+
+    /*jshint validthis:true */
+    if (!state.inES6()) {
+      warning("W104", state.tokens.curr, "class", "6");
+    }
+    if (isStatement) {
+      // BindingIdentifier
+      this.name = identifier();
+
+      state.funct["(scope)"].addlabel(this.name, {
+        type: "class",
+        token: state.tokens.curr });
+
+    } else if (state.tokens.next.identifier && state.tokens.next.value !== "extends") {
+      // BindingIdentifier(opt)
+      this.name = identifier();
+      this.namedExpr = true;
+    } else {
+      this.name = state.nameStack.infer();
+    }
+
+    classtail(this);
+
+    if (isStatement) {
+      state.funct["(scope)"].initialize(this.name);
+    }
+
+    return this;
+  }
+
+  function classtail(c) {
+    var wasInClassBody = state.inClassBody;
+    // ClassHeritage(opt)
+    if (state.tokens.next.value === "extends") {
+      advance("extends");
+      c.heritage = expression(10);
+    }
+
+    state.inClassBody = true;
+    advance("{");
+    // ClassBody(opt)
+    c.body = classbody(c);
+    advance("}");
+    state.inClassBody = wasInClassBody;
+  }
+
+  function classbody(c) {
+    var name;
+    var isStatic;
+    var isGenerator;
+    var getset;
+    var props = Object.create(null);
+    var staticProps = Object.create(null);
+    var computed;
+    for (var i = 0; state.tokens.next.id !== "}"; ++i) {
+      name = state.tokens.next;
+      isStatic = false;
+      isGenerator = false;
+      getset = null;
+
+      // The ES6 grammar for ClassElement includes the `;` token, but it is
+      // defined only as a placeholder to facilitate future language
+      // extensions. In ES6 code, it serves no purpose.
+      if (name.id === ";") {
+        warning("W032");
+        advance(";");
+        continue;
+      }
+
+      if (name.id === "*") {
+        isGenerator = true;
+        advance("*");
+        name = state.tokens.next;
+      }
+      if (name.id === "[") {
+        name = computedPropertyName();
+        computed = true;
+      } else if (isPropertyName(name)) {
+        // Non-Computed PropertyName
+        advance();
+        computed = false;
+        if (name.identifier && name.value === "static") {
+          if (checkPunctuator(state.tokens.next, "*")) {
+            isGenerator = true;
+            advance("*");
+          }
+          if (isPropertyName(state.tokens.next) || state.tokens.next.id === "[") {
+            computed = state.tokens.next.id === "[";
+            isStatic = true;
+            name = state.tokens.next;
+            if (state.tokens.next.id === "[") {
+              name = computedPropertyName();
+            } else advance();
+          }
+        }
+
+        if (name.identifier && (name.value === "get" || name.value === "set")) {
+          if (isPropertyName(state.tokens.next) || state.tokens.next.id === "[") {
+            computed = state.tokens.next.id === "[";
+            getset = name;
+            name = state.tokens.next;
+            if (state.tokens.next.id === "[") {
+              name = computedPropertyName();
+            } else advance();
+          }
+        }
+      } else {
+        warning("W052", state.tokens.next, state.tokens.next.value || state.tokens.next.type);
+        advance();
+        continue;
+      }
+
+      if (!checkPunctuator(state.tokens.next, "(")) {
+        // error --- class properties must be methods
+        error("E054", state.tokens.next, state.tokens.next.value);
+        while (state.tokens.next.id !== "}" &&
+               !checkPunctuator(state.tokens.next, "(")) {
+          advance();
+        }
+        if (state.tokens.next.value !== "(") {
+          doFunction({ statement: c });
+        }
+      }
+
+      if (!computed) {
+        // We don't know how to determine if we have duplicate computed property names :(
+        if (getset) {
+          saveAccessor(
+            getset.value, isStatic ? staticProps : props, name.value, name, true, isStatic);
+        } else {
+          if (name.value === "constructor") {
+            state.nameStack.set(c);
+          } else {
+            state.nameStack.set(name);
+          }
+          saveProperty(isStatic ? staticProps : props, name.value, name, true, isStatic);
+        }
+      }
+
+      if (getset && name.value === "constructor") {
+        var propDesc = getset.value === "get" ? "class getter method" : "class setter method";
+        error("E049", name, propDesc, "constructor");
+      } else if (name.value === "prototype") {
+        error("E049", name, "class method", "prototype");
+      }
+
+      propertyName(name);
+
+      doFunction({
+        statement: c,
+        type: isGenerator ? "generator" : null,
+        classExprBinding: c.namedExpr ? c.name : null
+      });
+    }
+
+    checkProperties(props);
+  }
+
+  blockstmt("function", function(context) {
+    var inexport = context && context.inexport;
+    var generator = false;
+    if (state.tokens.next.value === "*") {
+      advance("*");
+      if (state.inES6(true)) {
+        generator = true;
+      } else {
+        warning("W119", state.tokens.curr, "function*", "6");
+      }
+    }
+    if (inblock) {
+      warning("W082", state.tokens.curr);
+    }
+    var i = optionalidentifier();
+
+    state.funct["(scope)"].addlabel(i, {
+      type: "function",
+      token: state.tokens.curr });
+
+    if (i === undefined) {
+      warning("W025");
+    } else if (inexport) {
+      state.funct["(scope)"].setExported(i, state.tokens.prev);
+    }
+
+    doFunction({
+      name: i,
+      statement: this,
+      type: generator ? "generator" : null,
+      ignoreLoopFunc: inblock // a declaration may already have warned
+    });
+    if (state.tokens.next.id === "(" && state.tokens.next.line === state.tokens.curr.line) {
+      error("E039");
+    }
+    return this;
+  });
+
+  prefix("function", function() {
+    var generator = false;
+
+    if (state.tokens.next.value === "*") {
+      if (!state.inES6()) {
+        warning("W119", state.tokens.curr, "function*", "6");
+      }
+      advance("*");
+      generator = true;
+    }
+
+    var i = optionalidentifier();
+    doFunction({ name: i, type: generator ? "generator" : null });
+    return this;
+  });
+
+  blockstmt("if", function() {
+    var t = state.tokens.next;
+    increaseComplexityCount();
+    state.condition = true;
+    advance("(");
+    var expr = expression(0);
+
+    if (!expr) {
+      quit("E041", this);
+    }
+
+    checkCondAssignment(expr);
+
+    // When the if is within a for-in loop, check if the condition
+    // starts with a negation operator
+    var forinifcheck = null;
+    if (state.option.forin && state.forinifcheckneeded) {
+      state.forinifcheckneeded = false; // We only need to analyze the first if inside the loop
+      forinifcheck = state.forinifchecks[state.forinifchecks.length - 1];
+      if (expr.type === "(punctuator)" && expr.value === "!") {
+        forinifcheck.type = "(negative)";
+      } else {
+        forinifcheck.type = "(positive)";
+      }
+    }
+
+    advance(")", t);
+    state.condition = false;
+    var s = block(true, true);
+
+    // When the if is within a for-in loop and the condition has a negative form,
+    // check if the body contains nothing but a continue statement
+    if (forinifcheck && forinifcheck.type === "(negative)") {
+      if (s && s[0] && s[0].type === "(identifier)" && s[0].value === "continue") {
+        forinifcheck.type = "(negative-with-continue)";
+      }
+    }
+
+    if (state.tokens.next.id === "else") {
+      advance("else");
+      if (state.tokens.next.id === "if" || state.tokens.next.id === "switch") {
+        statement();
+      } else {
+        block(true, true);
+      }
+    }
+    return this;
+  });
+
+  blockstmt("try", function() {
+    var b;
+
+    function doCatch() {
+      advance("catch");
+      advance("(");
+
+      state.funct["(scope)"].stack("catchparams");
+
+      if (checkPunctuators(state.tokens.next, ["[", "{"])) {
+        var tokens = destructuringPattern();
+        _.each(tokens, function(token) {
+          if (token.id) {
+            state.funct["(scope)"].addParam(token.id, token, "exception");
+          }
+        });
+      } else if (state.tokens.next.type !== "(identifier)") {
+        warning("E030", state.tokens.next, state.tokens.next.value);
+      } else {
+        // only advance if we have an identifier so we can continue parsing in the most common error - that no param is given.
+        state.funct["(scope)"].addParam(identifier(), state.tokens.curr, "exception");
+      }
+
+      if (state.tokens.next.value === "if") {
+        if (!state.inMoz()) {
+          warning("W118", state.tokens.curr, "catch filter");
+        }
+        advance("if");
+        expression(0);
+      }
+
+      advance(")");
+
+      block(false);
+
+      state.funct["(scope)"].unstack();
+    }
+
+    block(true);
+
+    while (state.tokens.next.id === "catch") {
+      increaseComplexityCount();
+      if (b && (!state.inMoz())) {
+        warning("W118", state.tokens.next, "multiple catch blocks");
+      }
+      doCatch();
+      b = true;
+    }
+
+    if (state.tokens.next.id === "finally") {
+      advance("finally");
+      block(true);
+      return;
+    }
+
+    if (!b) {
+      error("E021", state.tokens.next, "catch", state.tokens.next.value);
+    }
+
+    return this;
+  });
+
+  blockstmt("while", function() {
+    var t = state.tokens.next;
+    state.funct["(breakage)"] += 1;
+    state.funct["(loopage)"] += 1;
+    increaseComplexityCount();
+    advance("(");
+    checkCondAssignment(expression(0));
+    advance(")", t);
+    block(true, true);
+    state.funct["(breakage)"] -= 1;
+    state.funct["(loopage)"] -= 1;
+    return this;
+  }).labelled = true;
+
+  blockstmt("with", function() {
+    var t = state.tokens.next;
+    if (state.isStrict()) {
+      error("E010", state.tokens.curr);
+    } else if (!state.option.withstmt) {
+      warning("W085", state.tokens.curr);
+    }
+
+    advance("(");
+    expression(0);
+    advance(")", t);
+    block(true, true);
+
+    return this;
+  });
+
+  blockstmt("switch", function() {
+    var t = state.tokens.next;
+    var g = false;
+    var noindent = false;
+
+    state.funct["(breakage)"] += 1;
+    advance("(");
+    checkCondAssignment(expression(0));
+    advance(")", t);
+    t = state.tokens.next;
+    advance("{");
+
+    if (state.tokens.next.from === indent)
+      noindent = true;
+
+    if (!noindent)
+      indent += state.option.indent;
+
+    this.cases = [];
+
+    for (;;) {
+      switch (state.tokens.next.id) {
+      case "case":
+        switch (state.funct["(verb)"]) {
+        case "yield":
+        case "break":
+        case "case":
+        case "continue":
+        case "return":
+        case "switch":
+        case "throw":
+          break;
+        default:
+          // You can tell JSHint that you don't use break intentionally by
+          // adding a comment /* falls through */ on a line just before
+          // the next `case`.
+          if (!state.tokens.curr.caseFallsThrough) {
+            warning("W086", state.tokens.curr, "case");
+          }
+        }
+
+        advance("case");
+        this.cases.push(expression(0));
+        increaseComplexityCount();
+        g = true;
+        advance(":");
+        state.funct["(verb)"] = "case";
+        break;
+      case "default":
+        switch (state.funct["(verb)"]) {
+        case "yield":
+        case "break":
+        case "continue":
+        case "return":
+        case "throw":
+          break;
+        default:
+          // Do not display a warning if 'default' is the first statement or if
+          // there is a special /* falls through */ comment.
+          if (this.cases.length) {
+            if (!state.tokens.curr.caseFallsThrough) {
+              warning("W086", state.tokens.curr, "default");
+            }
+          }
+        }
+
+        advance("default");
+        g = true;
+        advance(":");
+        break;
+      case "}":
+        if (!noindent)
+          indent -= state.option.indent;
+
+        advance("}", t);
+        state.funct["(breakage)"] -= 1;
+        state.funct["(verb)"] = undefined;
+        return;
+      case "(end)":
+        error("E023", state.tokens.next, "}");
+        return;
+      default:
+        indent += state.option.indent;
+        if (g) {
+          switch (state.tokens.curr.id) {
+          case ",":
+            error("E040");
+            return;
+          case ":":
+            g = false;
+            statements();
+            break;
+          default:
+            error("E025", state.tokens.curr);
+            return;
+          }
+        } else {
+          if (state.tokens.curr.id === ":") {
+            advance(":");
+            error("E024", state.tokens.curr, ":");
+            statements();
+          } else {
+            error("E021", state.tokens.next, "case", state.tokens.next.value);
+            return;
+          }
+        }
+        indent -= state.option.indent;
+      }
+    }
+    return this;
+  }).labelled = true;
+
+  stmt("debugger", function() {
+    if (!state.option.debug) {
+      warning("W087", this);
+    }
+    return this;
+  }).exps = true;
+
+  (function() {
+    var x = stmt("do", function() {
+      state.funct["(breakage)"] += 1;
+      state.funct["(loopage)"] += 1;
+      increaseComplexityCount();
+
+      this.first = block(true, true);
+      advance("while");
+      var t = state.tokens.next;
+      advance("(");
+      checkCondAssignment(expression(0));
+      advance(")", t);
+      state.funct["(breakage)"] -= 1;
+      state.funct["(loopage)"] -= 1;
+      return this;
+    });
+    x.labelled = true;
+    x.exps = true;
+  }());
+
+  blockstmt("for", function() {
+    var s, t = state.tokens.next;
+    var letscope = false;
+    var foreachtok = null;
+
+    if (t.value === "each") {
+      foreachtok = t;
+      advance("each");
+      if (!state.inMoz()) {
+        warning("W118", state.tokens.curr, "for each");
+      }
+    }
+
+    increaseComplexityCount();
+    advance("(");
+
+    // what kind of for(…) statement it is? for(…of…)? for(…in…)? for(…;…;…)?
+    var nextop; // contains the token of the "in" or "of" operator
+    var i = 0;
+    var inof = ["in", "of"];
+    var level = 0; // BindingPattern "level" --- level 0 === no BindingPattern
+    var comma; // First comma punctuator at level 0
+    var initializer; // First initializer at level 0
+    var bindingPower;
+    var targets;
+    var target;
+
+    // If initial token is a BindingPattern, count it as such.
+    if (checkPunctuators(state.tokens.next, ["{", "["])) ++level;
+    do {
+      nextop = peek(i);
+      ++i;
+      if (checkPunctuators(nextop, ["{", "["])) ++level;
+      else if (checkPunctuators(nextop, ["}", "]"])) --level;
+      if (level < 0) break;
+      if (level === 0) {
+        if (!comma && checkPunctuator(nextop, ",")) comma = nextop;
+        else if (!initializer && checkPunctuator(nextop, "=")) initializer = nextop;
+      }
+    } while (level > 0 || !_.contains(inof, nextop.value) && nextop.value !== ";" &&
+    nextop.type !== "(end)"); // Is this a JSCS bug? This looks really weird.
+
+    // if we're in a for (… in|of â€¦) statement
+    if (_.contains(inof, nextop.value)) {
+      if (nextop.value === "of") {
+        bindingPower = 20;
+        if (!state.inES6()) {
+          warning("W104", nextop, "for of", "6");
+        }
+      } else {
+        bindingPower = 0;
+      }
+
+      if (initializer) {
+        error("W133", comma, nextop.value, "initializer is forbidden");
+      }
+
+      if (comma) {
+        error("W133", comma, nextop.value, "more than one ForBinding");
+      }
+
+      if (state.tokens.next.id === "var") {
+        advance("var");
+        state.tokens.curr.fud({ prefix: true });
+      } else if (state.tokens.next.id === "let" || state.tokens.next.id === "const") {
+        advance(state.tokens.next.id);
+        // create a new block scope
+        letscope = true;
+        state.funct["(scope)"].stack();
+        state.tokens.curr.fud({ prefix: true });
+      } else {
+        targets = [];
+
+        // The following parsing logic recognizes initializers and the comma
+        // operator despite the fact that they are not supported by the
+        // grammar. Doing so allows JSHint to emit more a meaningful error
+        // message (i.e. W133) in response to a common programming mistake.
+        do {
+          if (checkPunctuators(state.tokens.next, ["{", "["])) {
+            destructuringPattern({ assignment: true }).forEach(function(elem) {
+              this.push(elem.token);
+            }, targets);
+          } else {
+            target = expression(120);
+
+            if (target.type === "(identifier)") {
+              targets.push(target);
+            }
+
+            checkLeftSideAssign(target, nextop);
+          }
+
+          if (checkPunctuator(state.tokens.next, "=")) {
+            advance("=");
+            expression(120);
+          }
+
+          if (checkPunctuator(state.tokens.next, ",")) {
+            advance(",");
+          }
+        } while (state.tokens.next !== nextop);
+
+        // In the event of a syntax error, do no issue warnings regarding the
+        // implicit creation of bindings.
+        if (!initializer && !comma) {
+          targets.forEach(function(token) {
+            if (!state.funct["(scope)"].has(token.value)) {
+              warning("W088", token, token.value);
+            }
+          });
+        }
+      }
+
+      advance(nextop.value);
+      // The binding power is variable because for-in statements accept any
+      // Expression in this position, while for-of statements are limited to
+      // AssignmentExpressions. For example:
+      //
+      //     for ( LeftHandSideExpression in Expression ) Statement
+      //     for ( LeftHandSideExpression of AssignmentExpression ) Statement
+      expression(bindingPower);
+      advance(")", t);
+
+      if (nextop.value === "in" && state.option.forin) {
+        state.forinifcheckneeded = true;
+
+        if (state.forinifchecks === undefined) {
+          state.forinifchecks = [];
+        }
+
+        // Push a new for-in-if check onto the stack. The type will be modified
+        // when the loop's body is parsed and a suitable if statement exists.
+        state.forinifchecks.push({
+          type: "(none)"
+        });
+      }
+
+      state.funct["(breakage)"] += 1;
+      state.funct["(loopage)"] += 1;
+
+      s = block(true, true);
+
+      if (nextop.value === "in" && state.option.forin) {
+        if (state.forinifchecks && state.forinifchecks.length > 0) {
+          var check = state.forinifchecks.pop();
+
+          if (// No if statement or not the first statement in loop body
+              s && s.length > 0 && (typeof s[0] !== "object" || s[0].value !== "if") ||
+              // Positive if statement is not the only one in loop body
+              check.type === "(positive)" && s.length > 1 ||
+              // Negative if statement but no continue
+              check.type === "(negative)") {
+            warning("W089", this);
+          }
+        }
+
+        // Reset the flag in case no if statement was contained in the loop body
+        state.forinifcheckneeded = false;
+      }
+
+      state.funct["(breakage)"] -= 1;
+      state.funct["(loopage)"] -= 1;
+    } else {
+      if (foreachtok) {
+        error("E045", foreachtok);
+      }
+      if (state.tokens.next.id !== ";") {
+        if (state.tokens.next.id === "var") {
+          advance("var");
+          state.tokens.curr.fud();
+        } else if (state.tokens.next.id === "let") {
+          advance("let");
+          // create a new block scope
+          letscope = true;
+          state.funct["(scope)"].stack();
+          state.tokens.curr.fud();
+        } else {
+          for (;;) {
+            expression(0, "for");
+            if (state.tokens.next.id !== ",") {
+              break;
+            }
+            parseComma();
+          }
+        }
+      }
+      nolinebreak(state.tokens.curr);
+      advance(";");
+
+      // start loopage after the first ; as the next two expressions are executed
+      // on every loop
+      state.funct["(loopage)"] += 1;
+      if (state.tokens.next.id !== ";") {
+        checkCondAssignment(expression(0));
+      }
+      nolinebreak(state.tokens.curr);
+      advance(";");
+      if (state.tokens.next.id === ";") {
+        error("E021", state.tokens.next, ")", ";");
+      }
+      if (state.tokens.next.id !== ")") {
+        for (;;) {
+          expression(0, "for");
+          if (state.tokens.next.id !== ",") {
+            break;
+          }
+          parseComma();
+        }
+      }
+      advance(")", t);
+      state.funct["(breakage)"] += 1;
+      block(true, true);
+      state.funct["(breakage)"] -= 1;
+      state.funct["(loopage)"] -= 1;
+
+    }
+    // unstack loop blockscope
+    if (letscope) {
+      state.funct["(scope)"].unstack();
+    }
+    return this;
+  }).labelled = true;
+
+
+  stmt("break", function() {
+    var v = state.tokens.next.value;
+
+    if (!state.option.asi)
+      nolinebreak(this);
+
+    if (state.tokens.next.id !== ";" && !state.tokens.next.reach &&
+        state.tokens.curr.line === startLine(state.tokens.next)) {
+      if (!state.funct["(scope)"].funct.hasBreakLabel(v)) {
+        warning("W090", state.tokens.next, v);
+      }
+      this.first = state.tokens.next;
+      advance();
+    } else {
+      if (state.funct["(breakage)"] === 0)
+        warning("W052", state.tokens.next, this.value);
+    }
+
+    reachable(this);
+
+    return this;
+  }).exps = true;
+
+
+  stmt("continue", function() {
+    var v = state.tokens.next.value;
+
+    if (state.funct["(breakage)"] === 0 || !state.funct["(loopage)"]) {
+      warning("W052", state.tokens.next, this.value);
+    }
+
+    if (!state.option.asi)
+      nolinebreak(this);
+
+    if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
+      if (state.tokens.curr.line === startLine(state.tokens.next)) {
+        if (!state.funct["(scope)"].funct.hasBreakLabel(v)) {
+          warning("W090", state.tokens.next, v);
+        }
+        this.first = state.tokens.next;
+        advance();
+      }
+    }
+
+    reachable(this);
+
+    return this;
+  }).exps = true;
+
+
+  stmt("return", function() {
+    if (this.line === startLine(state.tokens.next)) {
+      if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
+        this.first = expression(0);
+
+        if (this.first &&
+            this.first.type === "(punctuator)" && this.first.value === "=" &&
+            !this.first.paren && !state.option.boss) {
+          warningAt("W093", this.first.line, this.first.character);
+        }
+      }
+    } else {
+      if (state.tokens.next.type === "(punctuator)" &&
+        ["[", "{", "+", "-"].indexOf(state.tokens.next.value) > -1) {
+        nolinebreak(this); // always warn (Line breaking error)
+      }
+    }
+
+    reachable(this);
+
+    return this;
+  }).exps = true;
+
+  (function(x) {
+    x.exps = true;
+    x.lbp = 25;
+    x.ltBoundary = "after";
+  }(prefix("yield", function() {
+    if (state.inMoz()) {
+      return mozYield.call(this);
+    }
+    var prev = state.tokens.prev;
+
+    if (!this.beginsStmt && prev.lbp > 30 && !checkPunctuators(prev, ["("])) {
+      error("E061", this);
+    }
+
+    if (state.inES6(true) && !state.funct["(generator)"]) {
+      // If it's a yield within a catch clause inside a generator then that's ok
+      if (!("(catch)" === state.funct["(name)"] && state.funct["(context)"]["(generator)"])) {
+        error("E046", state.tokens.curr, "yield");
+      }
+    } else if (!state.inES6()) {
+      warning("W104", state.tokens.curr, "yield", "6");
+    }
+    state.funct["(generator)"] = "yielded";
+    var delegatingYield = false;
+
+    if (state.tokens.next.value === "*") {
+      delegatingYield = true;
+      advance("*");
+    }
+
+    // Parse operand
+    if (!isEndOfExpr() && state.tokens.next.id !== ",") {
+      if (state.tokens.next.nud) {
+
+        nobreaknonadjacent(state.tokens.curr, state.tokens.next);
+        this.first = expression(10);
+
+        if (this.first.type === "(punctuator)" && this.first.value === "=" &&
+            !this.first.paren && !state.option.boss) {
+          warningAt("W093", this.first.line, this.first.character);
+        }
+      } else if (state.tokens.next.led) {
+        if (state.tokens.next.id !== ",") {
+          error("W017", state.tokens.next);
+        }
+      }
+    }
+
+    return this;
+  })));
+
+  /**
+   * Parsing logic for non-standard Mozilla implementation of `yield`
+   * expressions.
+   */
+  var mozYield = function() {
+    var prev = state.tokens.prev;
+    if (state.inES6(true) && !state.funct["(generator)"]) {
+      // If it's a yield within a catch clause inside a generator then that's ok
+      if (!("(catch)" === state.funct["(name)"] && state.funct["(context)"]["(generator)"])) {
+        error("E046", state.tokens.curr, "yield");
+      }
+    }
+    state.funct["(generator)"] = "yielded";
+    var delegatingYield = false;
+
+    if (state.tokens.next.value === "*") {
+      delegatingYield = true;
+      advance("*");
+    }
+
+    if (this.line === startLine(state.tokens.next)) {
+      if (delegatingYield ||
+          (state.tokens.next.id !== ";" && !state.option.asi &&
+           !state.tokens.next.reach && state.tokens.next.nud)) {
+
+        nobreaknonadjacent(state.tokens.curr, state.tokens.next);
+        this.first = expression(10);
+
+        if (this.first.type === "(punctuator)" && this.first.value === "=" &&
+            !this.first.paren && !state.option.boss) {
+          warningAt("W093", this.first.line, this.first.character);
+        }
+      }
+
+      if (state.tokens.next.id !== ")" &&
+          (prev.lbp > 30 || (!prev.assign && !isEndOfExpr()) || prev.id === "yield")) {
+        error("E050", this);
+      }
+    } else if (!state.option.asi) {
+      nolinebreak(this); // always warn (Line breaking error)
+    }
+    return this;
+  };
+
+  stmt("throw", function() {
+    nolinebreak(this);
+    this.first = expression(20);
+
+    reachable(this);
+
+    return this;
+  }).exps = true;
+
+  stmt("import", function() {
+    if (!state.funct["(scope)"].block.isGlobal()) {
+      error("E053", state.tokens.curr, "Import");
+    }
+
+    if (!state.inES6()) {
+      warning("W119", state.tokens.curr, "import", "6");
+    }
+
+    if (state.tokens.next.type === "(string)") {
+      // ModuleSpecifier :: StringLiteral
+      advance("(string)");
+      return this;
+    }
+
+    if (state.tokens.next.identifier) {
+      // ImportClause :: ImportedDefaultBinding
+      this.name = identifier();
+      // Import bindings are immutable (see ES6 8.1.1.5.5)
+      state.funct["(scope)"].addlabel(this.name, {
+        type: "import",
+        initialized: true,
+        token: state.tokens.curr });
+
+      if (state.tokens.next.value === ",") {
+        // ImportClause :: ImportedDefaultBinding , NameSpaceImport
+        // ImportClause :: ImportedDefaultBinding , NamedImports
+        advance(",");
+        // At this point, we intentionally fall through to continue matching
+        // either NameSpaceImport or NamedImports.
+        // Discussion:
+        // https://github.com/jshint/jshint/pull/2144#discussion_r23978406
+      } else {
+        advance("from");
+        advance("(string)");
+        return this;
+      }
+    }
+
+    if (state.tokens.next.id === "*") {
+      // ImportClause :: NameSpaceImport
+      advance("*");
+      advance("as");
+      if (state.tokens.next.identifier) {
+        this.name = identifier();
+        // Import bindings are immutable (see ES6 8.1.1.5.5)
+        state.funct["(scope)"].addlabel(this.name, {
+          type: "import",
+          initialized: true,
+          token: state.tokens.curr });
+      }
+    } else {
+      // ImportClause :: NamedImports
+      advance("{");
+      for (;;) {
+        if (state.tokens.next.value === "}") {
+          advance("}");
+          break;
+        }
+        var importName;
+        if (state.tokens.next.type === "default") {
+          importName = "default";
+          advance("default");
+        } else {
+          importName = identifier();
+        }
+        if (state.tokens.next.value === "as") {
+          advance("as");
+          importName = identifier();
+        }
+
+        // Import bindings are immutable (see ES6 8.1.1.5.5)
+        state.funct["(scope)"].addlabel(importName, {
+          type: "import",
+          initialized: true,
+          token: state.tokens.curr });
+
+        if (state.tokens.next.value === ",") {
+          advance(",");
+        } else if (state.tokens.next.value === "}") {
+          advance("}");
+          break;
+        } else {
+          error("E024", state.tokens.next, state.tokens.next.value);
+          break;
+        }
+      }
+    }
+
+    // FromClause
+    advance("from");
+    advance("(string)");
+    return this;
+  }).exps = true;
+
+  stmt("export", function() {
+    var ok = true;
+    var token;
+    var identifier;
+
+    if (!state.inES6()) {
+      warning("W119", state.tokens.curr, "export", "6");
+      ok = false;
+    }
+
+    if (!state.funct["(scope)"].block.isGlobal()) {
+      error("E053", state.tokens.curr, "Export");
+      ok = false;
+    }
+
+    if (state.tokens.next.value === "*") {
+      // ExportDeclaration :: export * FromClause
+      advance("*");
+      advance("from");
+      advance("(string)");
+      return this;
+    }
+
+    if (state.tokens.next.type === "default") {
+      // ExportDeclaration ::
+      //      export default [lookahead âˆ‰ { function, class }] AssignmentExpression[In] ;
+      //      export default HoistableDeclaration
+      //      export default ClassDeclaration
+      state.nameStack.set(state.tokens.next);
+      advance("default");
+      var exportType = state.tokens.next.id;
+      if (exportType === "function" || exportType === "class") {
+        this.block = true;
+      }
+
+      token = peek();
+
+      expression(10);
+
+      identifier = token.value;
+
+      if (this.block) {
+        state.funct["(scope)"].addlabel(identifier, {
+          type: exportType,
+          initialized: true,
+          token: token });
+
+        state.funct["(scope)"].setExported(identifier, token);
+      }
+
+      return this;
+    }
+
+    if (state.tokens.next.value === "{") {
+      // ExportDeclaration :: export ExportClause
+      advance("{");
+      var exportedTokens = [];
+      for (;;) {
+        if (!state.tokens.next.identifier) {
+          error("E030", state.tokens.next, state.tokens.next.value);
+        }
+        advance();
+
+        exportedTokens.push(state.tokens.curr);
+
+        if (state.tokens.next.value === "as") {
+          advance("as");
+          if (!state.tokens.next.identifier) {
+            error("E030", state.tokens.next, state.tokens.next.value);
+          }
+          advance();
+        }
+
+        if (state.tokens.next.value === ",") {
+          advance(",");
+        } else if (state.tokens.next.value === "}") {
+          advance("}");
+          break;
+        } else {
+          error("E024", state.tokens.next, state.tokens.next.value);
+          break;
+        }
+      }
+      if (state.tokens.next.value === "from") {
+        // ExportDeclaration :: export ExportClause FromClause
+        advance("from");
+        advance("(string)");
+      } else if (ok) {
+        exportedTokens.forEach(function(token) {
+          state.funct["(scope)"].setExported(token.value, token);
+        });
+      }
+      return this;
+    }
+
+    if (state.tokens.next.id === "var") {
+      // ExportDeclaration :: export VariableStatement
+      advance("var");
+      state.tokens.curr.fud({ inexport:true });
+    } else if (state.tokens.next.id === "let") {
+      // ExportDeclaration :: export VariableStatement
+      advance("let");
+      state.tokens.curr.fud({ inexport:true });
+    } else if (state.tokens.next.id === "const") {
+      // ExportDeclaration :: export VariableStatement
+      advance("const");
+      state.tokens.curr.fud({ inexport:true });
+    } else if (state.tokens.next.id === "function") {
+      // ExportDeclaration :: export Declaration
+      this.block = true;
+      advance("function");
+      state.syntax["function"].fud({ inexport:true });
+    } else if (state.tokens.next.id === "class") {
+      // ExportDeclaration :: export Declaration
+      this.block = true;
+      advance("class");
+      var classNameToken = state.tokens.next;
+      state.syntax["class"].fud();
+      state.funct["(scope)"].setExported(classNameToken.value, classNameToken);
+    } else {
+      error("E024", state.tokens.next, state.tokens.next.value);
+    }
+
+    return this;
+  }).exps = true;
+
+  // Future Reserved Words
+
+  FutureReservedWord("abstract");
+  FutureReservedWord("await", { es5: true, moduleOnly: true });
+  FutureReservedWord("boolean");
+  FutureReservedWord("byte");
+  FutureReservedWord("char");
+  FutureReservedWord("class", { es5: true, nud: classdef });
+  FutureReservedWord("double");
+  FutureReservedWord("enum", { es5: true });
+  FutureReservedWord("export", { es5: true });
+  FutureReservedWord("extends", { es5: true });
+  FutureReservedWord("final");
+  FutureReservedWord("float");
+  FutureReservedWord("goto");
+  FutureReservedWord("implements", { es5: true, strictOnly: true });
+  FutureReservedWord("import", { es5: true });
+  FutureReservedWord("int");
+  FutureReservedWord("interface", { es5: true, strictOnly: true });
+  FutureReservedWord("long");
+  FutureReservedWord("native");
+  FutureReservedWord("package", { es5: true, strictOnly: true });
+  FutureReservedWord("private", { es5: true, strictOnly: true });
+  FutureReservedWord("protected", { es5: true, strictOnly: true });
+  FutureReservedWord("public", { es5: true, strictOnly: true });
+  FutureReservedWord("short");
+  FutureReservedWord("static", { es5: true, strictOnly: true });
+  FutureReservedWord("super", { es5: true });
+  FutureReservedWord("synchronized");
+  FutureReservedWord("transient");
+  FutureReservedWord("volatile");
+
+  // this function is used to determine whether a squarebracket or a curlybracket
+  // expression is a comprehension array, destructuring assignment or a json value.
+
+  var lookupBlockType = function() {
+    var pn, pn1, prev;
+    var i = -1;
+    var bracketStack = 0;
+    var ret = {};
+    if (checkPunctuators(state.tokens.curr, ["[", "{"])) {
+      bracketStack += 1;
+    }
+    do {
+      prev = i === -1 ? state.tokens.curr : pn;
+      pn = i === -1 ? state.tokens.next : peek(i);
+      pn1 = peek(i + 1);
+      i = i + 1;
+      if (checkPunctuators(pn, ["[", "{"])) {
+        bracketStack += 1;
+      } else if (checkPunctuators(pn, ["]", "}"])) {
+        bracketStack -= 1;
+      }
+      if (bracketStack === 1 && pn.identifier && pn.value === "for" &&
+          !checkPunctuator(prev, ".")) {
+        ret.isCompArray = true;
+        ret.notJson = true;
+        break;
+      }
+      if (bracketStack === 0 && checkPunctuators(pn, ["}", "]"])) {
+        if (pn1.value === "=") {
+          ret.isDestAssign = true;
+          ret.notJson = true;
+          break;
+        } else if (pn1.value === ".") {
+          ret.notJson = true;
+          break;
+        }
+      }
+      if (checkPunctuator(pn, ";")) {
+        ret.isBlock = true;
+        ret.notJson = true;
+      }
+    } while (bracketStack > 0 && pn.id !== "(end)");
+    return ret;
+  };
+
+  function saveProperty(props, name, tkn, isClass, isStatic) {
+    var msg = ["key", "class method", "static class method"];
+    msg = msg[(isClass || false) + (isStatic || false)];
+    if (tkn.identifier) {
+      name = tkn.value;
+    }
+
+    if (props[name] && name !== "__proto__") {
+      warning("W075", state.tokens.next, msg, name);
+    } else {
+      props[name] = Object.create(null);
+    }
+
+    props[name].basic = true;
+    props[name].basictkn = tkn;
+  }
+
+  /**
+   * @param {string} accessorType - Either "get" or "set"
+   * @param {object} props - a collection of all properties of the object to
+   *                         which the current accessor is being assigned
+   * @param {object} tkn - the identifier token representing the accessor name
+   * @param {boolean} isClass - whether the accessor is part of an ES6 Class
+   *                            definition
+   * @param {boolean} isStatic - whether the accessor is a static method
+   */
+  function saveAccessor(accessorType, props, name, tkn, isClass, isStatic) {
+    var flagName = accessorType === "get" ? "getterToken" : "setterToken";
+    var msg = "";
+
+    if (isClass) {
+      if (isStatic) {
+        msg += "static ";
+      }
+      msg += accessorType + "ter method";
+    } else {
+      msg = "key";
+    }
+
+    state.tokens.curr.accessorType = accessorType;
+    state.nameStack.set(tkn);
+
+    if (props[name]) {
+      if ((props[name].basic || props[name][flagName]) && name !== "__proto__") {
+        warning("W075", state.tokens.next, msg, name);
+      }
+    } else {
+      props[name] = Object.create(null);
+    }
+
+    props[name][flagName] = tkn;
+  }
+
+  function computedPropertyName() {
+    advance("[");
+    if (!state.inES6()) {
+      warning("W119", state.tokens.curr, "computed property names", "6");
+    }
+    var value = expression(10);
+    advance("]");
+    return value;
+  }
+
+  /**
+   * Test whether a given token is a punctuator matching one of the specified values
+   * @param {Token} token
+   * @param {Array.<string>} values
+   * @returns {boolean}
+   */
+  function checkPunctuators(token, values) {
+    if (token.type === "(punctuator)") {
+      return _.contains(values, token.value);
+    }
+    return false;
+  }
+
+  /**
+   * Test whether a given token is a punctuator matching the specified value
+   * @param {Token} token
+   * @param {string} value
+   * @returns {boolean}
+   */
+  function checkPunctuator(token, value) {
+    return token.type === "(punctuator)" && token.value === value;
+  }
+
+  // Check whether this function has been reached for a destructuring assign with undeclared values
+  function destructuringAssignOrJsonValue() {
+    // lookup for the assignment (ECMAScript 6 only)
+    // if it has semicolons, it is a block, so go parse it as a block
+    // or it's not a block, but there are assignments, check for undeclared variables
+
+    var block = lookupBlockType();
+    if (block.notJson) {
+      if (!state.inES6() && block.isDestAssign) {
+        warning("W104", state.tokens.curr, "destructuring assignment", "6");
+      }
+      statements();
+    // otherwise parse json value
+    } else {
+      state.option.laxbreak = true;
+      state.jsonMode = true;
+      jsonValue();
+    }
+  }
+
+  // array comprehension parsing function
+  // parses and defines the three states of the list comprehension in order
+  // to avoid defining global variables, but keeping them to the list comprehension scope
+  // only. The order of the states are as follows:
+  //  * "use" which will be the returned iterative part of the list comprehension
+  //  * "define" which will define the variables local to the list comprehension
+  //  * "filter" which will help filter out values
+
+  var arrayComprehension = function() {
+    var CompArray = function() {
+      this.mode = "use";
+      this.variables = [];
+    };
+    var _carrays = [];
+    var _current;
+    function declare(v) {
+      var l = _current.variables.filter(function(elt) {
+        // if it has, change its undef state
+        if (elt.value === v) {
+          elt.undef = false;
+          return v;
+        }
+      }).length;
+      return l !== 0;
+    }
+    function use(v) {
+      var l = _current.variables.filter(function(elt) {
+        // and if it has been defined
+        if (elt.value === v && !elt.undef) {
+          if (elt.unused === true) {
+            elt.unused = false;
+          }
+          return v;
+        }
+      }).length;
+      // otherwise we warn about it
+      return (l === 0);
+    }
+    return { stack: function() {
+          _current = new CompArray();
+          _carrays.push(_current);
+        },
+        unstack: function() {
+          _current.variables.filter(function(v) {
+            if (v.unused)
+              warning("W098", v.token, v.raw_text || v.value);
+            if (v.undef)
+              state.funct["(scope)"].block.use(v.value, v.token);
+          });
+          _carrays.splice(-1, 1);
+          _current = _carrays[_carrays.length - 1];
+        },
+        setState: function(s) {
+          if (_.contains(["use", "define", "generate", "filter"], s))
+            _current.mode = s;
+        },
+        check: function(v) {
+          if (!_current) {
+            return;
+          }
+          // When we are in "use" state of the list comp, we enqueue that var
+          if (_current && _current.mode === "use") {
+            if (use(v)) {
+              _current.variables.push({
+                funct: state.funct,
+                token: state.tokens.curr,
+                value: v,
+                undef: true,
+                unused: false
+              });
+            }
+            return true;
+          // When we are in "define" state of the list comp,
+          } else if (_current && _current.mode === "define") {
+            // check if the variable has been used previously
+            if (!declare(v)) {
+              _current.variables.push({
+                funct: state.funct,
+                token: state.tokens.curr,
+                value: v,
+                undef: false,
+                unused: true
+              });
+            }
+            return true;
+          // When we are in the "generate" state of the list comp,
+          } else if (_current && _current.mode === "generate") {
+            state.funct["(scope)"].block.use(v, state.tokens.curr);
+            return true;
+          // When we are in "filter" state,
+          } else if (_current && _current.mode === "filter") {
+            // we check whether current variable has been declared
+            if (use(v)) {
+              // if not we warn about it
+              state.funct["(scope)"].block.use(v, state.tokens.curr);
+            }
+            return true;
+          }
+          return false;
+        }
+        };
+  };
+
+
+  // Parse JSON
+
+  function jsonValue() {
+    function jsonObject() {
+      var o = {}, t = state.tokens.next;
+      advance("{");
+      if (state.tokens.next.id !== "}") {
+        for (;;) {
+          if (state.tokens.next.id === "(end)") {
+            error("E026", state.tokens.next, t.line);
+          } else if (state.tokens.next.id === "}") {
+            warning("W094", state.tokens.curr);
+            break;
+          } else if (state.tokens.next.id === ",") {
+            error("E028", state.tokens.next);
+          } else if (state.tokens.next.id !== "(string)") {
+            warning("W095", state.tokens.next, state.tokens.next.value);
+          }
+          if (o[state.tokens.next.value] === true) {
+            warning("W075", state.tokens.next, "key", state.tokens.next.value);
+          } else if ((state.tokens.next.value === "__proto__" &&
+            !state.option.proto) || (state.tokens.next.value === "__iterator__" &&
+            !state.option.iterator)) {
+            warning("W096", state.tokens.next, state.tokens.next.value);
+          } else {
+            o[state.tokens.next.value] = true;
+          }
+          advance();
+          advance(":");
+          jsonValue();
+          if (state.tokens.next.id !== ",") {
+            break;
+          }
+          advance(",");
+        }
+      }
+      advance("}");
+    }
+
+    function jsonArray() {
+      var t = state.tokens.next;
+      advance("[");
+      if (state.tokens.next.id !== "]") {
+        for (;;) {
+          if (state.tokens.next.id === "(end)") {
+            error("E027", state.tokens.next, t.line);
+          } else if (state.tokens.next.id === "]") {
+            warning("W094", state.tokens.curr);
+            break;
+          } else if (state.tokens.next.id === ",") {
+            error("E028", state.tokens.next);
+          }
+          jsonValue();
+          if (state.tokens.next.id !== ",") {
+            break;
+          }
+          advance(",");
+        }
+      }
+      advance("]");
+    }
+
+    switch (state.tokens.next.id) {
+    case "{":
+      jsonObject();
+      break;
+    case "[":
+      jsonArray();
+      break;
+    case "true":
+    case "false":
+    case "null":
+    case "(number)":
+    case "(string)":
+      advance();
+      break;
+    case "-":
+      advance("-");
+      advance("(number)");
+      break;
+    default:
+      error("E003", state.tokens.next);
+    }
+  }
+
+  /**
+   * Lint dynamically-evaluated code, appending any resulting errors/warnings
+   * into the global `errors` array.
+   *
+   * @param {array} internals - collection of "internals" objects describing
+   *                            string tokens that contain evaluated code
+   * @param {object} options - linting options to apply
+   * @param {object} globals - globally-defined bindings for the evaluated code
+   */
+  function lintEvalCode(internals, options, globals) {
+    var priorErrorCount, idx, jdx, internal;
+
+    for (idx = 0; idx < internals.length; idx += 1) {
+      internal = internals[idx];
+      options.scope = internal.elem;
+      priorErrorCount = JSHINT.errors.length;
+
+      itself(internal.code, options, globals);
+
+      for (jdx = priorErrorCount; jdx < JSHINT.errors.length; jdx += 1) {
+        JSHINT.errors[jdx].line += internal.token.line - 1;
+      }
+    }
+  }
+
+  var escapeRegex = function(str) {
+    return str.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&");
+  };
+
+  // The actual JSHINT function itself.
+  var itself = function(s, o, g) {
+    var x, reIgnoreStr, reIgnore;
+    var optionKeys;
+    var newOptionObj = {};
+    var newIgnoredObj = {};
+
+    o = _.clone(o);
+    state.reset();
+
+    if (o && o.scope) {
+      JSHINT.scope = o.scope;
+    } else {
+      JSHINT.errors = [];
+      JSHINT.undefs = [];
+      JSHINT.internals = [];
+      JSHINT.blacklist = {};
+      JSHINT.scope = "(main)";
+    }
+
+    predefined = Object.create(null);
+    combine(predefined, vars.ecmaIdentifiers[3]);
+    combine(predefined, vars.reservedVars);
+
+    combine(predefined, g || {});
+
+    declared = Object.create(null);
+    var exported = Object.create(null); // Variables that live outside the current file
+
+    function each(obj, cb) {
+      if (!obj)
+        return;
+
+      if (!Array.isArray(obj) && typeof obj === "object")
+        obj = Object.keys(obj);
+
+      obj.forEach(cb);
+    }
+
+    if (o) {
+      each(o.predef || null, function(item) {
+        var slice, prop;
+
+        if (item[0] === "-") {
+          slice = item.slice(1);
+          JSHINT.blacklist[slice] = slice;
+          // remove from predefined if there
+          delete predefined[slice];
+        } else {
+          prop = Object.getOwnPropertyDescriptor(o.predef, item);
+          predefined[item] = prop ? prop.value : false;
+        }
+      });
+
+      each(o.exported || null, function(item) {
+        exported[item] = true;
+      });
+
+      delete o.predef;
+      delete o.exported;
+
+      optionKeys = Object.keys(o);
+      for (x = 0; x < optionKeys.length; x++) {
+        if (/^-W\d{3}$/g.test(optionKeys[x])) {
+          newIgnoredObj[optionKeys[x].slice(1)] = true;
+        } else {
+          var optionKey = optionKeys[x];
+          newOptionObj[optionKey] = o[optionKey];
+        }
+      }
+    }
+
+    state.option = newOptionObj;
+    state.ignored = newIgnoredObj;
+
+    state.option.indent = state.option.indent || 4;
+    state.option.maxerr = state.option.maxerr || 50;
+
+    indent = 1;
+
+    var scopeManagerInst = scopeManager(state, predefined, exported, declared);
+    scopeManagerInst.on("warning", function(ev) {
+      warning.apply(null, [ ev.code, ev.token].concat(ev.data));
+    });
+
+    scopeManagerInst.on("error", function(ev) {
+      error.apply(null, [ ev.code, ev.token ].concat(ev.data));
+    });
+
+    state.funct = functor("(global)", null, {
+      "(global)"    : true,
+      "(scope)"     : scopeManagerInst,
+      "(comparray)" : arrayComprehension(),
+      "(metrics)"   : createMetrics(state.tokens.next)
+    });
+
+    functions = [state.funct];
+    urls = [];
+    stack = null;
+    member = {};
+    membersOnly = null;
+    inblock = false;
+    lookahead = [];
+
+    if (!isString(s) && !Array.isArray(s)) {
+      errorAt("E004", 0);
+      return false;
+    }
+
+    api = {
+      get isJSON() {
+        return state.jsonMode;
+      },
+
+      getOption: function(name) {
+        return state.option[name] || null;
+      },
+
+      getCache: function(name) {
+        return state.cache[name];
+      },
+
+      setCache: function(name, value) {
+        state.cache[name] = value;
+      },
+
+      warn: function(code, data) {
+        warningAt.apply(null, [ code, data.line, data.char ].concat(data.data));
+      },
+
+      on: function(names, listener) {
+        names.split(" ").forEach(function(name) {
+          emitter.on(name, listener);
+        }.bind(this));
+      }
+    };
+
+    emitter.removeAllListeners();
+    (extraModules || []).forEach(function(func) {
+      func(api);
+    });
+
+    state.tokens.prev = state.tokens.curr = state.tokens.next = state.syntax["(begin)"];
+
+    if (o && o.ignoreDelimiters) {
+
+      if (!Array.isArray(o.ignoreDelimiters)) {
+        o.ignoreDelimiters = [o.ignoreDelimiters];
+      }
+
+      o.ignoreDelimiters.forEach(function(delimiterPair) {
+        if (!delimiterPair.start || !delimiterPair.end)
+            return;
+
+        reIgnoreStr = escapeRegex(delimiterPair.start) +
+                      "[\\s\\S]*?" +
+                      escapeRegex(delimiterPair.end);
+
+        reIgnore = new RegExp(reIgnoreStr, "ig");
+
+        s = s.replace(reIgnore, function(match) {
+          return match.replace(/./g, " ");
+        });
+      });
+    }
+
+    lex = new Lexer(s);
+
+    lex.on("warning", function(ev) {
+      warningAt.apply(null, [ ev.code, ev.line, ev.character].concat(ev.data));
+    });
+
+    lex.on("error", function(ev) {
+      errorAt.apply(null, [ ev.code, ev.line, ev.character ].concat(ev.data));
+    });
+
+    lex.on("fatal", function(ev) {
+      quit("E041", ev);
+    });
+
+    lex.on("Identifier", function(ev) {
+      emitter.emit("Identifier", ev);
+    });
+
+    lex.on("String", function(ev) {
+      emitter.emit("String", ev);
+    });
+
+    lex.on("Number", function(ev) {
+      emitter.emit("Number", ev);
+    });
+
+    // Check options
+    for (var name in o) {
+      if (_.has(o, name)) {
+        checkOption(name, state.tokens.curr);
+      }
+    }
+
+    try {
+      applyOptions();
+
+      // combine the passed globals after we've assumed all our options
+      combine(predefined, g || {});
+
+      //reset values
+      parseComma.first = true;
+
+      advance();
+      switch (state.tokens.next.id) {
+      case "{":
+      case "[":
+        destructuringAssignOrJsonValue();
+        break;
+      default:
+        directives();
+
+        if (state.directive["use strict"]) {
+          if (!state.allowsGlobalUsd()) {
+            warning("W097", state.tokens.prev);
+          }
+        }
+
+        statements();
+      }
+
+      if (state.tokens.next.id !== "(end)") {
+        quit("E041", state.tokens.curr);
+      }
+
+      state.funct["(scope)"].unstack();
+
+    } catch (err) {
+      if (err && err.name === "JSHintError") {
+        var nt = state.tokens.next || {};
+        JSHINT.errors.push({
+          scope     : "(main)",
+          raw       : err.raw,
+          code      : err.code,
+          reason    : err.reason,
+          line      : err.line || nt.line,
+          character : err.character || nt.from
+        });
+      } else {
+        throw err;
+      }
+    }
+
+    // Loop over the listed "internals", and check them as well.
+    if (JSHINT.scope === "(main)") {
+      lintEvalCode(JSHINT.internals, o || {}, g);
+    }
+
+    return JSHINT.errors.length === 0;
+  };
+
+  // Modules.
+  itself.addModule = function(func) {
+    extraModules.push(func);
+  };
+
+  itself.addModule(style.register);
+
+  // Data summary.
+  itself.data = function() {
+    var data = {
+      functions: [],
+      options: state.option
+    };
+
+    var fu, f, i, j, n, globals;
+
+    if (itself.errors.length) {
+      data.errors = itself.errors;
+    }
+
+    if (state.jsonMode) {
+      data.json = true;
+    }
+
+    var impliedGlobals = state.funct["(scope)"].getImpliedGlobals();
+    if (impliedGlobals.length > 0) {
+      data.implieds = impliedGlobals;
+    }
+
+    if (urls.length > 0) {
+      data.urls = urls;
+    }
+
+    globals = state.funct["(scope)"].getUsedOrDefinedGlobals();
+    if (globals.length > 0) {
+      data.globals = globals;
+    }
+
+    for (i = 1; i < functions.length; i += 1) {
+      f = functions[i];
+      fu = {};
+
+      for (j = 0; j < functionicity.length; j += 1) {
+        fu[functionicity[j]] = [];
+      }
+
+      for (j = 0; j < functionicity.length; j += 1) {
+        if (fu[functionicity[j]].length === 0) {
+          delete fu[functionicity[j]];
+        }
+      }
+
+      fu.name = f["(name)"];
+      fu.param = f["(params)"];
+      fu.line = f["(line)"];
+      fu.character = f["(character)"];
+      fu.last = f["(last)"];
+      fu.lastcharacter = f["(lastcharacter)"];
+
+      fu.metrics = {
+        complexity: f["(metrics)"].ComplexityCount,
+        parameters: f["(metrics)"].arity,
+        statements: f["(metrics)"].statementCount
+      };
+
+      data.functions.push(fu);
+    }
+
+    var unuseds = state.funct["(scope)"].getUnuseds();
+    if (unuseds.length > 0) {
+      data.unused = unuseds;
+    }
+
+    for (n in member) {
+      if (typeof member[n] === "number") {
+        data.member = member;
+        break;
+      }
+    }
+
+    return data;
+  };
+
+  itself.jshint = itself;
+
+  return itself;
+}());
+
+// Make JSHINT a Node module, if possible.
+if (typeof exports === "object" && exports) {
+  exports.JSHINT = JSHINT;
+}
+
+},{"./lex.js":13,"./messages.js":14,"./options.js":16,"./reg.js":17,"./scope-manager.js":18,"./state.js":19,"./style.js":20,"./vars.js":21,"console-browserify":10,"events":5,"lodash":12}]},{},[]);
+
+JSHINT = require('jshint').JSHINT;
+if (typeof exports === 'object' && exports) exports.JSHINT = JSHINT;
+}());
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesjscodemirrorjsonlintjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/src/wp-includes/js/codemirror/jsonlint.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/js/codemirror/jsonlint.js                           (rev 0)
+++ trunk/src/wp-includes/js/codemirror/jsonlint.js     2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,432 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/* Jison generated parser */
+var jsonlint = (function(){
+var parser = {trace: function trace() { },
+yy: {},
+symbols_: {"error":2,"JSONString":3,"STRING":4,"JSONNumber":5,"NUMBER":6,"JSONNullLiteral":7,"NULL":8,"JSONBooleanLiteral":9,"TRUE":10,"FALSE":11,"JSONText":12,"JSONValue":13,"EOF":14,"JSONObject":15,"JSONArray":16,"{":17,"}":18,"JSONMemberList":19,"JSONMember":20,":":21,",":22,"[":23,"]":24,"JSONElementList":25,"$accept":0,"$end":1},
+terminals_: {2:"error",4:"STRING",6:"NUMBER",8:"NULL",10:"TRUE",11:"FALSE",14:"EOF",17:"{",18:"}",21:":",22:",",23:"[",24:"]"},
+productions_: [0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]],
+performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
+
+var $0 = $$.length - 1;
+switch (yystate) {
+case 1: // replace escaped characters with actual character
+          this.$ = yytext.replace(/\\(\\|")/g, "$"+"1")
+                     .replace(/\\n/g,'\n')
+                     .replace(/\\r/g,'\r')
+                     .replace(/\\t/g,'\t')
+                     .replace(/\\v/g,'\v')
+                     .replace(/\\f/g,'\f')
+                     .replace(/\\b/g,'\b');
+        
+break;
+case 2:this.$ = Number(yytext);
+break;
+case 3:this.$ = null;
+break;
+case 4:this.$ = true;
+break;
+case 5:this.$ = false;
+break;
+case 6:return this.$ = $$[$0-1];
+break;
+case 13:this.$ = {};
+break;
+case 14:this.$ = $$[$0-1];
+break;
+case 15:this.$ = [$$[$0-2], $$[$0]];
+break;
+case 16:this.$ = {}; this.$[$$[$0][0]] = $$[$0][1];
+break;
+case 17:this.$ = $$[$0-2]; $$[$0-2][$$[$0][0]] = $$[$0][1];
+break;
+case 18:this.$ = [];
+break;
+case 19:this.$ = $$[$0-1];
+break;
+case 20:this.$ = [$$[$0]];
+break;
+case 21:this.$ = $$[$0-2]; $$[$0-2].push($$[$0]);
+break;
+}
+},
+table: [{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],12:1,13:2,15:7,16:8,17:[1,14],23:[1,15]},{1:[3]},{14:[1,16]},{14:[2,7],18:[2,7],22:[2,7],24:[2,7]},{14:[2,8],18:[2,8],22:[2,8],24:[2,8]},{14:[2,9],18:[2,9],22:[2,9],24:[2,9]},{14:[2,10],18:[2,10],22:[2,10],24:[2,10]},{14:[2,11],18:[2,11],22:[2,11],24:[2,11]},{14:[2,12],18:[2,12],22:[2,12],24:[2,12]},{14:[2,3],18:[2,3],22:[2,3],24:[2,3]},{14:[2,4],18:[2,4],22:[2,4],24:[2,4]},{14:[2,5],18:[2,5],22:[2,5],24:[2,5]},{14:[2,1],18:[2,1],21:[2,1],22:[2,1],24:[2,1]},{14:[2,2],18:[2,2],22:[2,2],24:[2,2]},{3:20,4:[1,12],18:[1,17],19:18,20:19},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:23,15:7,16:8,17:[1,14],23:[1,15],24:[1,21],25:22},{1:[2,6]},{14:[2,13],18:[2,13],22:[2,13],24:[2,13]},{18:[1,24],22:[1,25]},{18:[2,16],22:[2,16]},{21:[1,26]},{14:[2,18],18:[2,18],22:[2,18],24:[2,18]},{22:[1,28],24:[1,27]},{22:[2,20],24:[2,20]},{14:[2,14],18:[2,14],22:[2,14],24:[2,14]},{3:20,4:[1,12],20:29},{3:5,4:[1,12],
 5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:30,15:7,16:8,17:[1,14],23:[1,15]},{14:[2,19],18:[2,19],22:[2,19],24:[2,19]},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:31,15:7,16:8,17:[1,14],23:[1,15]},{18:[2,17],22:[2,17]},{18:[2,15],22:[2,15]},{22:[2,21],24:[2,21]}],
+defaultActions: {16:[2,6]},
+parseError: function parseError(str, hash) {
+    throw new Error(str);
+},
+parse: function parse(input) {
+    var self = this,
+        stack = [0],
+        vstack = [null], // semantic value stack
+        lstack = [], // location stack
+        table = this.table,
+        yytext = '',
+        yylineno = 0,
+        yyleng = 0,
+        recovering = 0,
+        TERROR = 2,
+        EOF = 1;
+
+    //this.reductionCount = this.shiftCount = 0;
+
+    this.lexer.setInput(input);
+    this.lexer.yy = this.yy;
+    this.yy.lexer = this.lexer;
+    if (typeof this.lexer.yylloc == 'undefined')
+        this.lexer.yylloc = {};
+    var yyloc = this.lexer.yylloc;
+    lstack.push(yyloc);
+
+    if (typeof this.yy.parseError === 'function')
+        this.parseError = this.yy.parseError;
+
+    function popStack (n) {
+        stack.length = stack.length - 2*n;
+        vstack.length = vstack.length - n;
+        lstack.length = lstack.length - n;
+    }
+
+    function lex() {
+        var token;
+        token = self.lexer.lex() || 1; // $end = 1
+        // if token isn't its numeric value, convert
+        if (typeof token !== 'number') {
+            token = self.symbols_[token] || token;
+        }
+        return token;
+    }
+
+    var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected;
+    while (true) {
+        // retreive state number from top of stack
+        state = stack[stack.length-1];
+
+        // use default actions if available
+        if (this.defaultActions[state]) {
+            action = this.defaultActions[state];
+        } else {
+            if (symbol == null)
+                symbol = lex();
+            // read action for current state and first input
+            action = table[state] && table[state][symbol];
+        }
+
+        // handle parse error
+        _handle_error:
+        if (typeof action === 'undefined' || !action.length || !action[0]) {
+
+            if (!recovering) {
+                // Report error
+                expected = [];
+                for (p in table[state]) if (this.terminals_[p] && p > 2) {
+                    expected.push("'"+this.terminals_[p]+"'");
+                }
+                var errStr = '';
+                if (this.lexer.showPosition) {
+                    errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'";
+                } else {
+                    errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
+                                  (symbol == 1 /*EOF*/ ? "end of input" :
+                                              ("'"+(this.terminals_[symbol] || symbol)+"'"));
+                }
+                this.parseError(errStr,
+                    {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
+            }
+
+            // just recovered from another error
+            if (recovering == 3) {
+                if (symbol == EOF) {
+                    throw new Error(errStr || 'Parsing halted.');
+                }
+
+                // discard current lookahead and grab another
+                yyleng = this.lexer.yyleng;
+                yytext = this.lexer.yytext;
+                yylineno = this.lexer.yylineno;
+                yyloc = this.lexer.yylloc;
+                symbol = lex();
+            }
+
+            // try to recover from error
+            while (1) {
+                // check for error recovery rule in this state
+                if ((TERROR.toString()) in table[state]) {
+                    break;
+                }
+                if (state == 0) {
+                    throw new Error(errStr || 'Parsing halted.');
+                }
+                popStack(1);
+                state = stack[stack.length-1];
+            }
+
+            preErrorSymbol = symbol; // save the lookahead token
+            symbol = TERROR;         // insert generic error symbol as new lookahead
+            state = stack[stack.length-1];
+            action = table[state] && table[state][TERROR];
+            recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
+        }
+
+        // this shouldn't happen, unless resolve defaults are off
+        if (action[0] instanceof Array && action.length > 1) {
+            throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
+        }
+
+        switch (action[0]) {
+
+            case 1: // shift
+                //this.shiftCount++;
+
+                stack.push(symbol);
+                vstack.push(this.lexer.yytext);
+                lstack.push(this.lexer.yylloc);
+                stack.push(action[1]); // push state
+                symbol = null;
+                if (!preErrorSymbol) { // normal execution/no error
+                    yyleng = this.lexer.yyleng;
+                    yytext = this.lexer.yytext;
+                    yylineno = this.lexer.yylineno;
+                    yyloc = this.lexer.yylloc;
+                    if (recovering > 0)
+                        recovering--;
+                } else { // error just occurred, resume old lookahead f/ before error
+                    symbol = preErrorSymbol;
+                    preErrorSymbol = null;
+                }
+                break;
+
+            case 2: // reduce
+                //this.reductionCount++;
+
+                len = this.productions_[action[1]][1];
+
+                // perform semantic action
+                yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
+                // default location, uses first token for firsts, last for lasts
+                yyval._$ = {
+                    first_line: lstack[lstack.length-(len||1)].first_line,
+                    last_line: lstack[lstack.length-1].last_line,
+                    first_column: lstack[lstack.length-(len||1)].first_column,
+                    last_column: lstack[lstack.length-1].last_column
+                };
+                r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
+
+                if (typeof r !== 'undefined') {
+                    return r;
+                }
+
+                // pop off stack
+                if (len) {
+                    stack = stack.slice(0,-1*len*2);
+                    vstack = vstack.slice(0, -1*len);
+                    lstack = lstack.slice(0, -1*len);
+                }
+
+                stack.push(this.productions_[action[1]][0]);    // push nonterminal (reduce)
+                vstack.push(yyval.$);
+                lstack.push(yyval._$);
+                // goto new state = table[STATE][NONTERMINAL]
+                newState = table[stack[stack.length-2]][stack[stack.length-1]];
+                stack.push(newState);
+                break;
+
+            case 3: // accept
+                return true;
+        }
+
+    }
+
+    return true;
+}};
+/* Jison generated lexer */
+var lexer = (function(){
+var lexer = ({EOF:1,
+parseError:function parseError(str, hash) {
+        if (this.yy.parseError) {
+            this.yy.parseError(str, hash);
+        } else {
+            throw new Error(str);
+        }
+    },
+setInput:function (input) {
+        this._input = input;
+        this._more = this._less = this.done = false;
+        this.yylineno = this.yyleng = 0;
+        this.yytext = this.matched = this.match = '';
+        this.conditionStack = ['INITIAL'];
+        this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
+        return this;
+    },
+input:function () {
+        var ch = this._input[0];
+        this.yytext+=ch;
+        this.yyleng++;
+        this.match+=ch;
+        this.matched+=ch;
+        var lines = ch.match(/\n/);
+        if (lines) this.yylineno++;
+        this._input = this._input.slice(1);
+        return ch;
+    },
+unput:function (ch) {
+        this._input = ch + this._input;
+        return this;
+    },
+more:function () {
+        this._more = true;
+        return this;
+    },
+less:function (n) {
+        this._input = this.match.slice(n) + this._input;
+    },
+pastInput:function () {
+        var past = this.matched.substr(0, this.matched.length - this.match.length);
+        return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
+    },
+upcomingInput:function () {
+        var next = this.match;
+        if (next.length < 20) {
+            next += this._input.substr(0, 20-next.length);
+        }
+        return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
+    },
+showPosition:function () {
+        var pre = this.pastInput();
+        var c = new Array(pre.length + 1).join("-");
+        return pre + this.upcomingInput() + "\n" + c+"^";
+    },
+next:function () {
+        if (this.done) {
+            return this.EOF;
+        }
+        if (!this._input) this.done = true;
+
+        var token,
+            match,
+            tempMatch,
+            index,
+            col,
+            lines;
+        if (!this._more) {
+            this.yytext = '';
+            this.match = '';
+        }
+        var rules = this._currentRules();
+        for (var i=0;i < rules.length; i++) {
+            tempMatch = this._input.match(this.rules[rules[i]]);
+            if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
+                match = tempMatch;
+                index = i;
+                if (!this.options.flex) break;
+            }
+        }
+        if (match) {
+            lines = match[0].match(/\n.*/g);
+            if (lines) this.yylineno += lines.length;
+            this.yylloc = {first_line: this.yylloc.last_line,
+                           last_line: this.yylineno+1,
+                           first_column: this.yylloc.last_column,
+                           last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length}
+            this.yytext += match[0];
+            this.match += match[0];
+            this.yyleng = this.yytext.length;
+            this._more = false;
+            this._input = this._input.slice(match[0].length);
+            this.matched += match[0];
+            token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]);
+            if (this.done && this._input) this.done = false;
+            if (token) return token;
+            else return;
+        }
+        if (this._input === "") {
+            return this.EOF;
+        } else {
+            this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), 
+                    {text: "", token: null, line: this.yylineno});
+        }
+    },
+lex:function lex() {
+        var r = this.next();
+        if (typeof r !== 'undefined') {
+            return r;
+        } else {
+            return this.lex();
+        }
+    },
+begin:function begin(condition) {
+        this.conditionStack.push(condition);
+    },
+popState:function popState() {
+        return this.conditionStack.pop();
+    },
+_currentRules:function _currentRules() {
+        return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
+    },
+topState:function () {
+        return this.conditionStack[this.conditionStack.length-2];
+    },
+pushState:function begin(condition) {
+        this.begin(condition);
+    }});
+lexer.options = {};
+lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
+
+var YYSTATE=YY_START
+switch($avoiding_name_collisions) {
+case 0:/* skip whitespace */
+break;
+case 1:return 6
+break;
+case 2:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 4
+break;
+case 3:return 17
+break;
+case 4:return 18
+break;
+case 5:return 23
+break;
+case 6:return 24
+break;
+case 7:return 22
+break;
+case 8:return 21
+break;
+case 9:return 10
+break;
+case 10:return 11
+break;
+case 11:return 8
+break;
+case 12:return 14
+break;
+case 13:return 'INVALID'
+break;
+}
+};
+lexer.rules = [/^(?:\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\.[0-9]+)?([eE][-+]?[0-9]+)?\b)/,/^(?:"(?:\\[\\"bfnrt/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*")/,/^(?:\{)/,/^(?:\})/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?::)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:$)/,/^(?:.)/];
+lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"inclusive":true}};
+
+
+;
+return lexer;})()
+parser.lexer = lexer;
+return parser;
+})();
+if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
+exports.parser = jsonlint;
+exports.parse = function () { return jsonlint.parse.apply(jsonlint, arguments); }
+exports.main = function commonjsMain(args) {
+    if (!args[1])
+        throw new Error('Usage: '+args[0]+' FILE');
+    if (typeof process !== 'undefined') {
+        var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8");
+    } else {
+        var cwd = require("file").path(require("file").cwd());
+        var source = cwd.join(args[1]).read({charset: "utf-8"});
+    }
+    return exports.parser.parse(source);
+}
+if (typeof module !== 'undefined' && require.main === module) {
+  exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args);
+}
+}
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span></span></pre></div>
<a id="trunksrcwpincludesscriptloaderphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/script-loader.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/script-loader.php   2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/src/wp-includes/script-loader.php     2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -466,6 +466,20 @@
</span><span class="cx" style="display: block; padding: 0 10px">                apply_filters( 'mejs_settings', $mejs_settings )
</span><span class="cx" style="display: block; padding: 0 10px">        );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        $scripts->add( 'codemirror', '/wp-includes/js/codemirror/codemirror.min.js', array(), '5.29.1-alpha-ee20357' );
+       $scripts->add( 'csslint', '/wp-includes/js/codemirror/csslint.js', array(), '1.0.5' );
+       $scripts->add( 'jshint', '/wp-includes/js/codemirror/jshint.js', array(), '2.9.5' );
+       $scripts->add( 'jsonlint', '/wp-includes/js/codemirror/jsonlint.js', array(), '1.6.2' );
+       $scripts->add( 'htmlhint', '/wp-includes/js/codemirror/htmlhint.js', array(), '0.9.14-xwp' );
+       $scripts->add( 'htmlhint-kses', '/wp-includes/js/codemirror/htmlhint-kses.js', array( 'htmlhint' ) );
+       $scripts->add( 'code-editor', "/wp-admin/js/code-editor$suffix.js", array( 'jquery', 'codemirror' ) );
+       $scripts->add( 'wp-theme-plugin-editor', "/wp-admin/js/theme-plugin-editor$suffix.js", array( 'code-editor', 'jquery', 'jquery-ui-core', 'wp-a11y', 'underscore' ) );
+       did_action( 'init' ) && $scripts->add_inline_script( 'wp-theme-plugin-editor', sprintf( 'wp.themePluginEditor.l10n = %s;', wp_json_encode( wp_array_slice_assoc(
+               /* translators: placeholder is error count */
+               _n_noop( 'There is %d error which must be fixed before you can save.', 'There are %d errors which must be fixed before you can save.' ),
+               array( 'singular', 'plural' )
+       ) ) ) );
+
</ins><span class="cx" style="display: block; padding: 0 10px">         $scripts->add( 'wp-playlist', "/wp-includes/js/mediaelement/wp-playlist$suffix.js", array( 'wp-util', 'backbone', 'mediaelement' ), false, 1 );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        $scripts->add( 'zxcvbn-async', "/wp-includes/js/zxcvbn-async$suffix.js", array(), '1.0' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -551,6 +565,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">                'serverSaveError'    => __( 'Failed connecting to the server. Please try saving again.' ),
</span><span class="cx" style="display: block; padding: 0 10px">                // Used for overriding the file types allowed in plupload.
</span><span class="cx" style="display: block; padding: 0 10px">                'allowedFiles'       => __( 'Allowed Files' ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                'customCssError'     => wp_array_slice_assoc(
+                       /* translators: placeholder is error count */
+                       _n_noop( 'There is %d error which must be fixed before you can save.', 'There are %d errors which must be fixed before you can save.' ),
+                       array( 'singular', 'plural' )
+               ),
</ins><span class="cx" style="display: block; padding: 0 10px">         ) );
</span><span class="cx" style="display: block; padding: 0 10px">        $scripts->add( 'customize-selective-refresh', "/wp-includes/js/customize-selective-refresh$suffix.js", array( 'jquery', 'wp-util', 'customize-preview' ), false, 1 );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -688,7 +707,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $scripts->add( 'media-image-widget', "/wp-admin/js/widgets/media-image-widget$suffix.js", array( 'media-widgets' ) );
</span><span class="cx" style="display: block; padding: 0 10px">                $scripts->add( 'media-video-widget', "/wp-admin/js/widgets/media-video-widget$suffix.js", array( 'media-widgets', 'media-audiovideo', 'wp-api-request' ) );
</span><span class="cx" style="display: block; padding: 0 10px">                $scripts->add( 'text-widgets', "/wp-admin/js/widgets/text-widgets$suffix.js", array( 'jquery', 'backbone', 'editor', 'wp-util', 'wp-a11y' ) );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $scripts->add_inline_script( 'text-widgets', 'wp.textWidgets.init();', 'after' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $scripts->add( 'custom-html-widgets', "/wp-admin/js/widgets/custom-html-widgets$suffix.js", array( 'code-editor', 'jquery', 'backbone', 'wp-util', 'jquery-ui-core', 'wp-a11y' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $scripts->add( 'theme', "/wp-admin/js/theme$suffix.js", array( 'wp-backbone', 'wp-a11y' ), false, 1 );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -929,6 +948,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">        $styles->add( 'widgets',             "/wp-admin/css/widgets$suffix.css", array( 'wp-pointer' ) );
</span><span class="cx" style="display: block; padding: 0 10px">        $styles->add( 'site-icon',           "/wp-admin/css/site-icon$suffix.css" );
</span><span class="cx" style="display: block; padding: 0 10px">        $styles->add( 'l10n',                "/wp-admin/css/l10n$suffix.css" );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        $styles->add( 'code-editor',         "/wp-admin/css/code-editor$suffix.css", array( 'codemirror' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        $styles->add( 'wp-admin', false, array( 'dashicons', 'common', 'forms', 'admin-menu', 'dashboard', 'list-tables', 'edit', 'revisions', 'media', 'themes', 'about', 'nav-menus', 'widgets', 'site-icon', 'l10n' ) );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -963,6 +983,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">        $styles->add( 'mediaelement',        "/wp-includes/js/mediaelement/mediaelementplayer-legacy.min.css", array(), '4.2.5-74e01a40' );
</span><span class="cx" style="display: block; padding: 0 10px">        $styles->add( 'wp-mediaelement',     "/wp-includes/js/mediaelement/wp-mediaelement$suffix.css", array( 'mediaelement' ) );
</span><span class="cx" style="display: block; padding: 0 10px">        $styles->add( 'thickbox',            '/wp-includes/js/thickbox/thickbox.css', array( 'dashicons' ) );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        $styles->add( 'codemirror',          '/wp-includes/js/codemirror/codemirror.min.css', array(), '5.29.1-alpha-ee20357' );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        // Deprecated CSS
</span><span class="cx" style="display: block; padding: 0 10px">        $styles->add( 'deprecated-media', "/wp-admin/css/deprecated-media$suffix.css" );
</span></span></pre></div>
<a id="trunksrcwpincludesuserphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/user.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/user.php    2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/src/wp-includes/user.php      2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1376,7 +1376,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">  * Insert a user into the database.
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * Most of the `$userdata` array fields have filters associated with the values. Exceptions are
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * 'ID', 'rich_editing', 'comment_shortcuts', 'admin_color', 'use_ssl',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * 'ID', 'rich_editing', 'syntax_highlighting', 'comment_shortcuts', 'admin_color', 'use_ssl',
</ins><span class="cx" style="display: block; padding: 0 10px">  * 'user_registered', and 'role'. The filters have the prefix 'pre_user_' followed by the field
</span><span class="cx" style="display: block; padding: 0 10px">  * name. An example using 'description' would have the filter called, 'pre_user_description' that
</span><span class="cx" style="display: block; padding: 0 10px">  * can be hooked into.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1410,6 +1410,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">  *     @type string      $description          The user's biographical description.
</span><span class="cx" style="display: block; padding: 0 10px">  *     @type string|bool $rich_editing         Whether to enable the rich-editor for the user.
</span><span class="cx" style="display: block; padding: 0 10px">  *                                             False if not empty.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *     @type string|bool $syntax_highlighting  Whether to enable the rich code editor for the user.
+ *                                             False if not empty.
</ins><span class="cx" style="display: block; padding: 0 10px">  *     @type string|bool $comment_shortcuts    Whether to enable comment moderation keyboard
</span><span class="cx" style="display: block; padding: 0 10px">  *                                             shortcuts for the user. Default false.
</span><span class="cx" style="display: block; padding: 0 10px">  *     @type string      $admin_color          Admin color scheme for the user. Default 'fresh'.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1623,6 +1625,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        $meta['rich_editing'] = empty( $userdata['rich_editing'] ) ? 'true' : $userdata['rich_editing'];
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        $meta['syntax_highlighting'] = empty( $userdata['syntax_highlighting'] ) ? 'true' : $userdata['syntax_highlighting'];
+
</ins><span class="cx" style="display: block; padding: 0 10px">         $meta['comment_shortcuts'] = empty( $userdata['comment_shortcuts'] ) || 'false' === $userdata['comment_shortcuts'] ? 'false' : 'true';
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        $admin_color = empty( $userdata['admin_color'] ) ? 'fresh' : $userdata['admin_color'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1709,6 +1713,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">         *     @type string   $last_name            The user's last name.
</span><span class="cx" style="display: block; padding: 0 10px">         *     @type string   $description          The user's description.
</span><span class="cx" style="display: block; padding: 0 10px">         *     @type bool     $rich_editing         Whether to enable the rich-editor for the user. False if not empty.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         *     @type bool     $syntax_highlighting  Whether to enable the rich code editor for the user. False if not empty.
</ins><span class="cx" style="display: block; padding: 0 10px">          *     @type bool     $comment_shortcuts    Whether to enable keyboard shortcuts for the user. Default false.
</span><span class="cx" style="display: block; padding: 0 10px">         *     @type string   $admin_color          The color scheme for a user's admin screen. Default 'fresh'.
</span><span class="cx" style="display: block; padding: 0 10px">         *     @type int|bool $use_ssl              Whether to force SSL on the user's admin area. 0|false if SSL is
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2035,7 +2040,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">  * @return array List of user keys to be populated in wp_update_user().
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><span class="cx" style="display: block; padding: 0 10px"> function _get_additional_user_keys( $user ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        $keys = array( 'first_name', 'last_name', 'nickname', 'description', 'rich_editing', 'comment_shortcuts', 'admin_color', 'use_ssl', 'show_admin_bar_front', 'locale' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $keys = array( 'first_name', 'last_name', 'nickname', 'description', 'rich_editing', 'syntax_highlighting', 'comment_shortcuts', 'admin_color', 'use_ssl', 'show_admin_bar_front', 'locale' );
</ins><span class="cx" style="display: block; padding: 0 10px">         return array_merge( $keys, array_keys( wp_get_user_contact_methods( $user ) ) );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span></span></pre></div>
<a id="trunksrcwpincludeswidgetsclasswpwidgetcustomhtmlphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/widgets/class-wp-widget-custom-html.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/widgets/class-wp-widget-custom-html.php     2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/src/wp-includes/widgets/class-wp-widget-custom-html.php       2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -17,6 +17,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> class WP_Widget_Custom_HTML extends WP_Widget {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Whether or not the widget has been registered yet.
+        *
+        * @since 4.9.0
+        * @var bool
+        */
+       protected $registered = false;
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Default instance.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 4.8.1
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -46,6 +54,33 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Add hooks for enqueueing assets when registering all widget instances of this widget class.
+        *
+        * @since 4.9.0
+        *
+        * @param integer $number Optional. The unique order number of this widget instance
+        *                        compared to other instances of the same class. Default -1.
+        */
+       public function _register_one( $number = -1 ) {
+               parent::_register_one( $number );
+               if ( $this->registered ) {
+                       return;
+               }
+               $this->registered = true;
+
+               wp_add_inline_script( 'custom-html-widgets', sprintf( 'wp.customHtmlWidgets.idBases.push( %s );', wp_json_encode( $this->id_base ) ) );
+
+               // Note that the widgets component in the customizer will also do the 'admin_print_scripts-widgets.php' action in WP_Customize_Widgets::print_scripts().
+               add_action( 'admin_print_scripts-widgets.php', array( $this, 'enqueue_admin_scripts' ) );
+
+               // Note that the widgets component in the customizer will also do the 'admin_footer-widgets.php' action in WP_Customize_Widgets::print_footer_scripts().
+               add_action( 'admin_footer-widgets.php', array( 'WP_Widget_Custom_HTML', 'render_control_template_scripts' ) );
+
+               // Note this action is used to ensure the help text is added to the end.
+               add_action( 'admin_head-widgets.php', array( 'WP_Widget_Custom_HTML', 'add_help_text' ) );
+       }
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Outputs the content for the current Custom HTML widget instance.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 4.8.1
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -118,39 +153,127 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Loads the required scripts and styles for the widget control.
+        *
+        * @since 4.9.0
+        */
+       public function enqueue_admin_scripts() {
+               $settings = wp_enqueue_code_editor( array(
+                       'type' => 'text/html',
+               ) );
+
+               wp_enqueue_script( 'custom-html-widgets' );
+               if ( empty( $settings ) ) {
+                       $settings = array(
+                               'disabled' => true,
+                       );
+               }
+               wp_add_inline_script( 'custom-html-widgets', sprintf( 'wp.customHtmlWidgets.init( %s );', wp_json_encode( $settings ) ), 'after' );
+
+               $l10n = array(
+                       'errorNotice' => wp_array_slice_assoc(
+                               /* translators: placeholder is error count */
+                               _n_noop( 'There is %d error which must be fixed before you can save.', 'There are %d errors which must be fixed before you can save.' ),
+                               array( 'singular', 'plural' )
+                       ),
+               );
+               wp_add_inline_script( 'custom-html-widgets', sprintf( 'jQuery.extend( wp.customHtmlWidgets.l10n, %s );', wp_json_encode( $l10n ) ), 'after' );
+       }
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Outputs the Custom HTML widget settings form.
</span><span class="cx" style="display: block; padding: 0 10px">         *
</span><span class="cx" style="display: block; padding: 0 10px">         * @since 4.8.1
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @since 4.9.0 The form contains only hidden sync inputs. For the control UI, see `WP_Widget_Custom_HTML::render_control_template_scripts()`.
</ins><span class="cx" style="display: block; padding: 0 10px">          *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * @see WP_Widget_Custom_HTML::render_control_template_scripts()
</ins><span class="cx" style="display: block; padding: 0 10px">          * @param array $instance Current instance.
</span><span class="cx" style="display: block; padding: 0 10px">         * @returns void
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        public function form( $instance ) {
</span><span class="cx" style="display: block; padding: 0 10px">                $instance = wp_parse_args( (array) $instance, $this->default_instance );
</span><span class="cx" style="display: block; padding: 0 10px">                ?>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                <p>
-                       <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
-                       <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $instance['title'] ); ?>"/>
-               </p>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         <input id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" class="title sync-input" type="hidden" value="<?php echo esc_attr( $instance['title'] ); ?>"/>
+               <textarea id="<?php echo $this->get_field_id( 'content' ); ?>" name="<?php echo $this->get_field_name( 'content' ); ?>" class="content sync-input" hidden><?php echo esc_textarea( $instance['content'] ); ?></textarea>
+               <?php
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                <p>
-                       <label for="<?php echo $this->get_field_id( 'content' ); ?>"><?php _e( 'Content:' ); ?></label>
-                       <textarea class="widefat code" rows="16" cols="20" id="<?php echo $this->get_field_id( 'content' ); ?>" name="<?php echo $this->get_field_name( 'content' ); ?>"><?php echo esc_textarea( $instance['content'] ); ?></textarea>
-               </p>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+        * Render form template scripts.
+        *
+        * @since 4.9.0
+        */
+       public static function render_control_template_scripts() {
+               ?>
+               <script type="text/html" id="tmpl-widget-custom-html-control-fields">
+                       <# var elementIdPrefix = 'el' + String( Math.random() ).replace( /\D/g, '' ) + '_' #>
+                       <p>
+                               <label for="{{ elementIdPrefix }}title"><?php esc_html_e( 'Title:', 'default' ); ?></label>
+                               <input id="{{ elementIdPrefix }}title" type="text" class="widefat title">
+                       </p>
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                <?php if ( ! current_user_can( 'unfiltered_html' ) ) : ?>
-                       <?php
-                       $probably_unsafe_html = array( 'script', 'iframe', 'form', 'input', 'style' );
-                       $allowed_html = wp_kses_allowed_html( 'post' );
-                       $disallowed_html = array_diff( $probably_unsafe_html, array_keys( $allowed_html ) );
-                       ?>
-                       <?php if ( ! empty( $disallowed_html ) ) : ?>
-                               <p>
-                                       <?php _e( 'Some HTML tags are not permitted, including:' ); ?>
-                                       <code><?php echo join( '</code>, <code>', $disallowed_html ); ?></code>
-                               </p>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 <p>
+                               <label for="{{ elementIdPrefix }}content" class="screen-reader-text"><?php esc_html_e( 'Content:', 'default' ); ?></label>
+                               <textarea id="{{ elementIdPrefix }}content" class="widefat code content" rows="16" cols="20"></textarea>
+                       </p>
+
+                       <?php if ( ! current_user_can( 'unfiltered_html' ) ) : ?>
+                               <?php
+                               $probably_unsafe_html = array( 'script', 'iframe', 'form', 'input', 'style' );
+                               $allowed_html = wp_kses_allowed_html( 'post' );
+                               $disallowed_html = array_diff( $probably_unsafe_html, array_keys( $allowed_html ) );
+                               ?>
+                               <?php if ( ! empty( $disallowed_html ) ) : ?>
+                                       <# if ( data.codeEditorDisabled ) { #>
+                                               <p>
+                                                       <?php _e( 'Some HTML tags are not permitted, including:', 'default' ); ?>
+                                                       <code><?php echo join( '</code>, <code>', $disallowed_html ); ?></code>
+                                               </p>
+                                       <# } #>
+                               <?php endif; ?>
</ins><span class="cx" style="display: block; padding: 0 10px">                         <?php endif; ?>
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                <?php endif; ?>
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+                       <div class="code-editor-error-container"></div>
+               </script>
</ins><span class="cx" style="display: block; padding: 0 10px">                 <?php
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       /**
+        * Add help text to widgets admin screen.
+        *
+        * @since 4.9.0
+        */
+       public static function add_help_text() {
+               $screen = get_current_screen();
+
+               $content = '<p>';
+               $content .= __( 'Use the Custom HTML widget to add arbitrary HTML code to your widget areas.' );
+               $content .= '</p>';
+
+               $content .= '<p>' . __( 'When using a keyboard to navigate:' ) . '</p>';
+               $content .= '<ul>';
+               $content .= '<li>' . __( 'In the HTML edit field, Tab enters a tab character.' ) . '</li>';
+               $content .= '<li>' . __( 'To move keyboard focus, press Esc then Tab for the next element, or Esc then Shift+Tab for the previous element.' ) . '</li>';
+               $content .= '</ul>';
+
+               $content .= '<p>';
+               $content .= sprintf(
+                       /* translators: placeholder is link to user profile */
+                       __( 'The edit field automatically highlights code syntax. You can disable this in your %s to work in plan text mode.' ),
+                       sprintf(
+                               ' <a href="%1$s" class="external-link" target="_blank">%2$s<span class="screen-reader-text">%3$s</span></a>',
+                               esc_url( get_edit_profile_url() . '#syntax_highlighting' ),
+                               __( 'user profile' ),
+                               /* translators: accessibility text */
+                               __( '(opens in a new window)', 'default' )
+                       )
+               );
+               $content .= '</p>';
+
+               $screen->add_help_tab( array(
+                       'id' => 'custom_html_widget',
+                       'title' => __( 'Custom HTML Widget' ),
+                       'content' => $content,
+               ) );
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunksrcwpincludeswidgetsclasswpwidgettextphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/widgets/class-wp-widget-text.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/widgets/class-wp-widget-text.php    2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/src/wp-includes/widgets/class-wp-widget-text.php      2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -353,6 +353,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">        public function enqueue_admin_scripts() {
</span><span class="cx" style="display: block; padding: 0 10px">                wp_enqueue_editor();
</span><span class="cx" style="display: block; padding: 0 10px">                wp_enqueue_script( 'text-widgets' );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                wp_add_inline_script( 'text-widgets', 'wp.textWidgets.init();', 'after' );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span></span></pre></div>
<a id="trunktestsphpunittestscustomizecustomcsssettingphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/customize/custom-css-setting.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/customize/custom-css-setting.php        2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/tests/phpunit/tests/customize/custom-css-setting.php  2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -355,82 +355,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $result = $this->setting->validate( $basic_css );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertTrue( $result );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                // Check for Unclosed Comment.
-               $unclosed_comment = $basic_css . ' /* This is a comment. ';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         // Check for markup.
+               $unclosed_comment = $basic_css . '</style>';
</ins><span class="cx" style="display: block; padding: 0 10px">                 $result = $this->setting->validate( $unclosed_comment );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->assertTrue( array_key_exists( 'unclosed_comment', $result->errors ) );
-
-               // Check for Unopened Comment.
-               $unclosed_comment = $basic_css . ' This is a comment.*/';
-               $result = $this->setting->validate( $unclosed_comment );
-               $this->assertTrue( array_key_exists( 'imbalanced_comments', $result->errors ) );
-
-               // Check for Unclosed Curly Brackets.
-               $unclosed_curly_bracket = $basic_css . '  a.link { text-decoration: none;';
-               $result = $this->setting->validate( $unclosed_curly_bracket );
-               $this->assertTrue( array_key_exists( 'imbalanced_curly_brackets', $result->errors ) );
-
-               // Check for Unopened Curly Brackets.
-               $unopened_curly_bracket = $basic_css . '  a.link text-decoration: none; }';
-               $result = $this->setting->validate( $unopened_curly_bracket );
-               $this->assertTrue( array_key_exists( 'imbalanced_curly_brackets', $result->errors ) );
-
-               // Check for Unclosed Braces.
-               $unclosed_brace = $basic_css . '  input[type="text" { color: #f00; } ';
-               $result = $this->setting->validate( $unclosed_brace );
-               $this->assertTrue( array_key_exists( 'imbalanced_braces', $result->errors ) );
-
-               // Check for Unopened Braces.
-               $unopened_brace = $basic_css . ' inputtype="text"] { color: #f00; } ';
-               $result = $this->setting->validate( $unopened_brace );
-               $this->assertTrue( array_key_exists( 'imbalanced_braces', $result->errors ) );
-
-               // Check for Imbalanced Double Quotes.
-               $imbalanced_double_quotes = $basic_css . ' div.background-image { background-image: url( "image.jpg ); } ';
-               $result = $this->setting->validate( $imbalanced_double_quotes );
-               $this->assertTrue( array_key_exists( 'unequal_double_quotes', $result->errors ) );
-
-               // Check for Unclosed Parentheses.
-               $unclosed_parentheses = $basic_css . ' div.background-image { background-image: url( "image.jpg" ; } ';
-               $result = $this->setting->validate( $unclosed_parentheses );
-               $this->assertTrue( array_key_exists( 'imbalanced_parentheses', $result->errors ) );
-
-               // Check for Unopened Parentheses.
-               $unopened_parentheses = $basic_css . ' div.background-image { background-image: url "image.jpg" ); } ';
-               $result = $this->setting->validate( $unopened_parentheses );
-               $this->assertTrue( array_key_exists( 'imbalanced_parentheses', $result->errors ) );
-
-               // A basic Content declaration with no other errors should not throw an error.
-               $content_declaration = $basic_css . ' a:before { content: ""; display: block; }';
-               $result = $this->setting->validate( $content_declaration );
-               $this->assertTrue( $result );
-
-               // An error, along with a Content declaration will throw two errors.
-               // In this case, we're using an extra opening brace.
-               $content_declaration = $basic_css . ' a:before { content: "["; display: block; }';
-               $result = $this->setting->validate( $content_declaration );
-               $this->assertTrue( array_key_exists( 'imbalanced_braces', $result->errors ) );
-               $this->assertTrue( array_key_exists( 'possible_false_positive', $result->errors ) );
-
-               $css = 'body { background: #f00; } h1.site-title { font-size: 36px; } a:hover { text-decoration: none; } input[type="text"] { padding: 1em; } /* This is a comment */';
-               $this->assertTrue( $this->setting->validate( $css ) );
-
-               $validity = $this->setting->validate( $css . ' /* This is another comment.' );
-               $this->assertInstanceOf( 'WP_Error', $validity );
-               $this->assertContains( 'unclosed code comment', join( ' ', $validity->get_error_messages() ) );
-
-               $css = '/* This is comment one. */  /* This is comment two. */';
-               $this->assertTrue( $this->setting->validate( $css ) );
-
-               $basic_css = 'body { background: #f00; } h1.site-title { font-size: 36px; } a:hover { text-decoration: none; } input[type="text"] { padding: 1em; }';
-               $this->assertTrue( $this->setting->validate( $basic_css ) );
-
-               $css = $basic_css . ' .link:before { content: "*"; display: block; }';
-               $this->assertTrue( $this->setting->validate( $css ) );
-
-               $css .= ' ( trailing';
-               $validity = $this->setting->validate( $css );
-               $this->assertWPError( $validity );
-               $this->assertNotEmpty( $result->get_error_message( 'possible_false_positive' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->assertTrue( array_key_exists( 'illegal_markup', $result->errors ) );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestsphpunittestscustomizemanagerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/customize/manager.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/customize/manager.php   2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/tests/phpunit/tests/customize/manager.php     2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -2351,7 +2351,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $data = json_decode( $json, true );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertNotEmpty( $data );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $this->assertEqualSets( array( 'theme', 'url', 'browser', 'panels', 'sections', 'nonce', 'autofocus', 'documentTitleTmpl', 'previewableDevices', 'changeset', 'timeouts' ), array_keys( $data ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $this->assertEqualSets( array( 'theme', 'url', 'browser', 'panels', 'sections', 'nonce', 'autofocus', 'documentTitleTmpl', 'previewableDevices', 'customCss', 'changeset', 'timeouts' ), array_keys( $data ) );
</ins><span class="cx" style="display: block; padding: 0 10px">                 $this->assertEquals( $autofocus, $data['autofocus'] );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertArrayHasKey( 'save', $data['nonce'] );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertArrayHasKey( 'preview', $data['nonce'] );
</span></span></pre></div>
<a id="trunktestsphpunittestsuserphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/user.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/user.php        2017-09-12 12:53:21 UTC (rev 41375)
+++ trunk/tests/phpunit/tests/user.php  2017-09-13 06:07:48 UTC (rev 41376)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -358,7 +358,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                // Test update of fields in _get_additional_user_keys()
</span><span class="cx" style="display: block; padding: 0 10px">                $user_data = array(
</span><span class="cx" style="display: block; padding: 0 10px">                        'ID' => self::$author_id, 'use_ssl' => 1, 'show_admin_bar_front' => 1,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                        'rich_editing' => 1, 'first_name' => 'first', 'last_name' => 'last',
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                 'rich_editing' => 1, 'syntax_highlighting' => 1, 'first_name' => 'first', 'last_name' => 'last',
</ins><span class="cx" style="display: block; padding: 0 10px">                         'nickname' => 'nick', 'comment_shortcuts' => 'true', 'admin_color' => 'classic',
</span><span class="cx" style="display: block; padding: 0 10px">                        'description' => 'describe'
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span></span></pre>
</div>
</div>

</body>
</html>