Update CodeMirror to 5.57.0

This required updating the FormatterWorker.js to use the proper version
of the StringStream constructor. Otherwise, pretty-printing files would
throw an error, as the first argument wasn't a string but an array.

R=bmeurer@chromium.org

Fixed: 1109347
Change-Id: I56524a92227eaf73cc3dc40d9fe8638b792fafb0
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2398824
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Tim van der Lippe <tvanderlippe@chromium.org>
diff --git a/front_end/externs.js b/front_end/externs.js
index 359bf7f..a9c9fef 100644
--- a/front_end/externs.js
+++ b/front_end/externs.js
@@ -550,7 +550,7 @@
 
 /**
  * @constructor
- * @param {(!Array<string>|string)} line
+ * @param {string} line
  * @param {number=} index
  */
 CodeMirror.StringStream = function(line, index) {
diff --git a/front_end/formatter_worker/FormatterWorker.js b/front_end/formatter_worker/FormatterWorker.js
index 4a89ab5..7d9f9f4 100644
--- a/front_end/formatter_worker/FormatterWorker.js
+++ b/front_end/formatter_worker/FormatterWorker.js
@@ -63,8 +63,7 @@
    * @param {function(string, ?string, number, number):?} callback
    */
   return (line, callback) => {
-    // @ts-expect-error Broken in @types/codemirror
-    const stream = new CodeMirror.StringStream([line], 0);
+    const stream = new CodeMirror.StringStream(line);
     while (!stream.eol()) {
       // @ts-expect-error TypeScript can't determine that `mode.token` is defined based on lines above
       const style = mode.token(stream, state);
diff --git a/front_end/third_party/codemirror/README.chromium b/front_end/third_party/codemirror/README.chromium
index cef05b0..d55bb15 100644
--- a/front_end/third_party/codemirror/README.chromium
+++ b/front_end/third_party/codemirror/README.chromium
@@ -1,7 +1,7 @@
 Name: CodeMirror is a versatile text editor implemented in JavaScript for the browser.
 Short Name: CodeMirror
 URL: https://github.com/codemirror/CodeMirror/
-Version: 5.53.2
+Version: 5.57.0
 License: MIT
 License File: LICENSE
 Security Critical: no
@@ -14,7 +14,7 @@
 To update this package, run the following command (replace version number with updated version number):
 
 ```bash
-wget -qO- https://registry.npmjs.org/codemirror/-/codemirror-5.53.2.tgz | tar xzf -
+wget -qO- https://registry.npmjs.org/codemirror/-/codemirror-5.57.0.tgz | tar xzf -
 ```
 
 Local changes applied:
diff --git a/front_end/third_party/codemirror/package/AUTHORS b/front_end/third_party/codemirror/package/AUTHORS
index f5b5d7a..3fa6199 100644
--- a/front_end/third_party/codemirror/package/AUTHORS
+++ b/front_end/third_party/codemirror/package/AUTHORS
@@ -113,6 +113,7 @@
 Bharad
 BigBlueHat
 Billy Moon
+Bin Ni
 binny
 Bjorn Hansen
 B Krishna Chaitanya
@@ -235,6 +236,7 @@
 Duncan Lilley
 duralog
 dwelle
+Ealton
 eborden
 edoroshenko
 edsharp
@@ -312,6 +314,7 @@
 Hanno Fellmann
 Hans Engel
 Hanzhao Deng
+Haoran Yu
 Harald Schilly
 Hardest
 Harshvardhan Gupta
@@ -328,6 +331,7 @@
 Hiroyuki Makino
 hitsthings
 Hocdoc
+Howard
 Hugues Malphettes
 Ian Beck
 Ian Davies
@@ -347,6 +351,7 @@
 Irakli Gozalishvili
 Ivan Kurnosov
 Ivoah
+Jack Douglas
 Jacob Lee
 Jaimin
 Jake Peyser
@@ -439,6 +444,7 @@
 kaniga
 karevn
 Karol
+Kaushik Kulkarni
 Kayur Patel
 Kazuhito Hokamura
 kcwiakala
@@ -489,6 +495,7 @@
 Lorenzo Stoakes
 Louis Mauchet
 Luca Fabbri
+Lucas Buchala
 Luciano Longo
 Luciano Santana
 Lu Fangjian
@@ -634,6 +641,7 @@
 Opender Singh
 opl-
 Oreoluwa Onatemowo
+orionlee
 oscar.lofwenhamn
 Oskar Segersvärd
 ossdev
@@ -655,6 +663,7 @@
 Paul Garvin
 Paul Ivanov
 Paul Masson
+Paul Schmidt
 Pavel
 Pavel Feldman
 Pavel Petržela
@@ -756,6 +765,7 @@
 Shmuel Englard
 Shubham Jain
 Siamak Mokhtari
+Siddhartha Gunti
 silverwind
 Simon Edwards
 sinkuu
@@ -816,6 +826,7 @@
 TobiasBg
 Todd Berman
 Todd Kennedy
+tokafew420
 Tomas-A
 Tomas Varaneckas
 Tom Erik Støwer
@@ -870,6 +881,7 @@
 Yvonnick Esnault
 Zac Anger
 Zachary Dremann
+ZeeshanNoor
 Zeno Rocha
 Zhang Hao
 Ziv
diff --git a/front_end/third_party/codemirror/package/CHANGELOG.md b/front_end/third_party/codemirror/package/CHANGELOG.md
index a445dd9..8e651ec 100644
--- a/front_end/third_party/codemirror/package/CHANGELOG.md
+++ b/front_end/third_party/codemirror/package/CHANGELOG.md
@@ -1,3 +1,57 @@
+## 5.57.0 (2020-08-20)
+
+### Bug fixes
+
+Fix issue that broke binding the macOS Command key.
+
+[comment addon](https://codemirror.net/doc/manual.html#addon_comment): Keep selection in front of inserted markers when adding a block comment.
+
+[css mode](https://codemirror.net/mode/css/): Recognize more properties and value names.
+
+[annotatescrollbar addon](https://codemirror.net/doc/manual.html#addon_annotatescrollbar): Don't hide matches in collapsed content.
+
+### New features
+
+[vim bindings](https://codemirror.net/demo/vim.html): Support tag text objects in xml and html modes.
+
+## 5.56.0 (2020-07-20)
+
+### Bug fixes
+
+Line-wise pasting was fixed on Chrome Windows.
+
+[wast mode](https://codemirror.net/mode/wast/): Follow standard changes.
+
+[soy mode](https://codemirror.net/mode/soy/): Support import expressions, template type, and loop indices.
+
+[sql-hint addon](https://codemirror.net/doc/manual.html#addon_sql-hint): Improve handling of double quotes.
+
+### New features
+
+[show-hint addon](https://codemirror.net/doc/manual.html#addon_show-hint): New option `scrollMargin` to control how many options are visible beyond the selected one.
+
+[hardwrap addon](https://codemirror.net/doc/manual.html#addon_hardwrap): New option `forceBreak` to disable breaking of words that are longer than a line.
+
+## 5.55.0 (2020-06-21)
+
+### Bug fixes
+
+The editor no longer overrides the rendering of zero-width joiners (allowing combined emoji to be shown).
+
+[vim bindings](https://codemirror.net/demo/vim.html): Fix an issue where the `vim-mode-change` event was fired twice.
+
+[javascript mode](https://codemirror.net/mode/javascript/): Only allow `-->`-style comments at the start of a line.
+
+[julia mode](https://codemirror.net/mode/julia/): Improve indentation.
+
+[pascal mode](https://codemirror.net/mode/pascal/index.html): Recognize curly bracket comments.
+
+[runmode addon](https://codemirror.net/doc/manual.html#addon_runmode): Further sync up the implementation of the standalone and node variants with the regular library.
+
+### New features
+
+[loadmode addon](https://codemirror.net/doc/manual.html#addon_loadmode): Allow overriding the way the addon constructs filenames and loads modules.
+
 ## 5.54.0 (2020-05-20)
 
 ### Bug fixes
diff --git a/front_end/third_party/codemirror/package/addon/comment/comment.js b/front_end/third_party/codemirror/package/addon/comment/comment.js
index 8394e85..dac48d0 100644
--- a/front_end/third_party/codemirror/package/addon/comment/comment.js
+++ b/front_end/third_party/codemirror/package/addon/comment/comment.js
@@ -13,7 +13,7 @@
 
   var noOptions = {};
   var nonWS = /[^\s\u00a0]/;
-  var Pos = CodeMirror.Pos;
+  var Pos = CodeMirror.Pos, cmp = CodeMirror.cmpPos;
 
   function firstNonWS(str) {
     var found = str.search(nonWS);
@@ -126,7 +126,9 @@
           if (i != end || lastLineHasText)
             self.replaceRange(lead + pad, Pos(i, 0));
       } else {
+        var atCursor = cmp(self.getCursor("to"), to) == 0, empty = !self.somethingSelected()
         self.replaceRange(endString, to);
+        if (atCursor) self.setSelection(empty ? to : self.getCursor("from"), to)
         self.replaceRange(startString, from);
       }
     });
diff --git a/front_end/third_party/codemirror/package/addon/edit/closetag.js b/front_end/third_party/codemirror/package/addon/edit/closetag.js
index b8cbf95..8689765 100644
--- a/front_end/third_party/codemirror/package/addon/edit/closetag.js
+++ b/front_end/third_party/codemirror/package/addon/edit/closetag.js
@@ -40,9 +40,9 @@
       cm.removeKeyMap("autoCloseTags");
     if (!val) return;
     var map = {name: "autoCloseTags"};
-    if (typeof val != "object" || val.whenClosing)
+    if (typeof val != "object" || val.whenClosing !== false)
       map["'/'"] = function(cm) { return autoCloseSlash(cm); };
-    if (typeof val != "object" || val.whenOpening)
+    if (typeof val != "object" || val.whenOpening !== false)
       map["'>'"] = function(cm) { return autoCloseGT(cm); };
     cm.addKeyMap(map);
   });
diff --git a/front_end/third_party/codemirror/package/addon/hint/show-hint.js b/front_end/third_party/codemirror/package/addon/hint/show-hint.js
index c55deab..cd0d6a7 100644
--- a/front_end/third_party/codemirror/package/addon/hint/show-hint.js
+++ b/front_end/third_party/codemirror/package/addon/hint/show-hint.js
@@ -379,12 +379,14 @@
     },
 
     scrollToActive: function() {
-      var node = this.hints.childNodes[this.selectedHint]
+      var margin = this.completion.options.scrollMargin || 0;
+      var node1 = this.hints.childNodes[Math.max(0, this.selectedHint - margin)];
+      var node2 = this.hints.childNodes[Math.min(this.data.list.length - 1, this.selectedHint + margin)];
       var firstNode = this.hints.firstChild;
-      if (node.offsetTop < this.hints.scrollTop)
-        this.hints.scrollTop = node.offsetTop - firstNode.offsetTop;
-      else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
-        this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + firstNode.offsetTop;
+      if (node1.offsetTop < this.hints.scrollTop)
+        this.hints.scrollTop = node1.offsetTop - firstNode.offsetTop;
+      else if (node2.offsetTop + node2.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
+        this.hints.scrollTop = node2.offsetTop + node2.offsetHeight - this.hints.clientHeight + firstNode.offsetTop;
     },
 
     screenAmount: function() {
diff --git a/front_end/third_party/codemirror/package/addon/hint/sql-hint.js b/front_end/third_party/codemirror/package/addon/hint/sql-hint.js
index 444eba8..de84707 100644
--- a/front_end/third_party/codemirror/package/addon/hint/sql-hint.js
+++ b/front_end/third_party/codemirror/package/addon/hint/sql-hint.js
@@ -264,7 +264,7 @@
       token.string = token.string.slice(0, cur.ch - token.start);
     }
 
-    if (token.string.match(/^[.`"\w@]\w*$/)) {
+    if (token.string.match(/^[.`"'\w@][\w$#]*$/g)) {
       search = token.string;
       start = token.start;
       end = token.end;
diff --git a/front_end/third_party/codemirror/package/addon/hint/xml-hint.js b/front_end/third_party/codemirror/package/addon/hint/xml-hint.js
index 7575b37..543d19b 100644
--- a/front_end/third_party/codemirror/package/addon/hint/xml-hint.js
+++ b/front_end/third_party/codemirror/package/addon/hint/xml-hint.js
@@ -101,8 +101,14 @@
           }
           replaceToken = true;
         }
-        for (var i = 0; i < atValues.length; ++i) if (!prefix || matches(atValues[i], prefix, matchInMiddle))
-          result.push(quote + atValues[i] + quote);
+        function returnHintsFromAtValues(atValues) {
+          if (atValues)
+            for (var i = 0; i < atValues.length; ++i) if (!prefix || matches(atValues[i], prefix, matchInMiddle))
+              result.push(quote + atValues[i] + quote);
+          return returnHints();
+        }
+        if (atValues && atValues.then) return atValues.then(returnHintsFromAtValues);
+        return returnHintsFromAtValues(atValues);
       } else { // An attribute name
         if (token.type == "attribute") {
           prefix = token.string;
@@ -112,11 +118,14 @@
           result.push(attr);
       }
     }
-    return {
-      list: result,
-      from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
-      to: replaceToken ? Pos(cur.line, token.end) : cur
-    };
+    function returnHints() {
+      return {
+        list: result,
+        from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
+        to: replaceToken ? Pos(cur.line, token.end) : cur
+      };
+    }
+    return returnHints();
   }
 
   CodeMirror.registerHelper("hint", "xml", getHints);
diff --git a/front_end/third_party/codemirror/package/addon/mode/loadmode.js b/front_end/third_party/codemirror/package/addon/mode/loadmode.js
index 4ce716a..fc695d0 100644
--- a/front_end/third_party/codemirror/package/addon/mode/loadmode.js
+++ b/front_end/third_party/codemirror/package/addon/mode/loadmode.js
@@ -16,8 +16,8 @@
     var countDown = n;
     return function() { if (--countDown == 0) cont(); };
   }
-  function ensureDeps(mode, cont) {
-    var deps = CodeMirror.modes[mode].dependencies;
+  function ensureDeps(mode, cont, options) {
+    var modeObj = CodeMirror.modes[mode], deps = modeObj && modeObj.dependencies;
     if (!deps) return cont();
     var missing = [];
     for (var i = 0; i < deps.length; ++i) {
@@ -27,16 +27,18 @@
     if (!missing.length) return cont();
     var split = splitCallback(cont, missing.length);
     for (var i = 0; i < missing.length; ++i)
-      CodeMirror.requireMode(missing[i], split);
+      CodeMirror.requireMode(missing[i], split, options);
   }
 
-  CodeMirror.requireMode = function(mode, cont) {
+  CodeMirror.requireMode = function(mode, cont, options) {
     if (typeof mode != "string") mode = mode.name;
-    if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);
+    if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont, options);
     if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
 
-    var file = CodeMirror.modeURL.replace(/%N/g, mode);
-    if (env == "plain") {
+    var file = options && options.path ? options.path(mode) : CodeMirror.modeURL.replace(/%N/g, mode);
+    if (options && options.loadMode) {
+      options.loadMode(file, function() { ensureDeps(mode, cont, options) })
+    } else if (env == "plain") {
       var script = document.createElement("script");
       script.src = file;
       var others = document.getElementsByTagName("script")[0];
@@ -44,7 +46,7 @@
       CodeMirror.on(script, "load", function() {
         ensureDeps(mode, function() {
           for (var i = 0; i < list.length; ++i) list[i]();
-        });
+        }, options);
       });
       others.parentNode.insertBefore(script, others);
     } else if (env == "cjs") {
@@ -55,10 +57,10 @@
     }
   };
 
-  CodeMirror.autoLoadMode = function(instance, mode) {
+  CodeMirror.autoLoadMode = function(instance, mode, options) {
     if (!CodeMirror.modes.hasOwnProperty(mode))
       CodeMirror.requireMode(mode, function() {
         instance.setOption("mode", instance.getOption("mode"));
-      });
+      }, options);
   };
 });
diff --git a/front_end/third_party/codemirror/package/addon/runmode/runmode-standalone.js b/front_end/third_party/codemirror/package/addon/runmode/runmode-standalone.js
index f47af3f..02e41fe 100644
--- a/front_end/third_party/codemirror/package/addon/runmode/runmode-standalone.js
+++ b/front_end/third_party/codemirror/package/addon/runmode/runmode-standalone.js
@@ -1,165 +1,333 @@
-// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+(function () {
+  'use strict';
 
-var root = typeof globalThis !== 'undefined' ? globalThis : window;
-root.CodeMirror = {};
+  function copyObj(obj, target, overwrite) {
+    if (!target) { target = {}; }
+    for (var prop in obj)
+      { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
+        { target[prop] = obj[prop]; } }
+    return target
+  }
 
-(function() {
-"use strict";
+  // Counts the column offset in a string, taking tabs into account.
+  // Used mostly to find indentation.
+  function countColumn(string, end, tabSize, startIndex, startValue) {
+    if (end == null) {
+      end = string.search(/[^\s\u00a0]/);
+      if (end == -1) { end = string.length; }
+    }
+    for (var i = startIndex || 0, n = startValue || 0;;) {
+      var nextTab = string.indexOf("\t", i);
+      if (nextTab < 0 || nextTab >= end)
+        { return n + (end - i) }
+      n += nextTab - i;
+      n += tabSize - (n % tabSize);
+      i = nextTab + 1;
+    }
+  }
 
-function splitLines(string){ return string.split(/\r?\n|\r/); };
+  function nothing() {}
 
-function StringStream(strings, i) {
-  this.pos = this.start = 0;
-  this.string = strings[i];
-  this.strings = strings
-  this.i = i
-  this.lineStart = 0;
-}
-StringStream.prototype = {
-  eol: function() {return this.pos >= this.string.length;},
-  sol: function() {return this.pos == 0;},
-  peek: function() {return this.string.charAt(this.pos) || null;},
-  next: function() {
+  function createObj(base, props) {
+    var inst;
+    if (Object.create) {
+      inst = Object.create(base);
+    } else {
+      nothing.prototype = base;
+      inst = new nothing();
+    }
+    if (props) { copyObj(props, inst); }
+    return inst
+  }
+
+  // STRING STREAM
+
+  // Fed to the mode parsers, provides helper functions to make
+  // parsers more succinct.
+
+  var StringStream = function(string, tabSize, lineOracle) {
+    this.pos = this.start = 0;
+    this.string = string;
+    this.tabSize = tabSize || 8;
+    this.lastColumnPos = this.lastColumnValue = 0;
+    this.lineStart = 0;
+    this.lineOracle = lineOracle;
+  };
+
+  StringStream.prototype.eol = function () {return this.pos >= this.string.length};
+  StringStream.prototype.sol = function () {return this.pos == this.lineStart};
+  StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined};
+  StringStream.prototype.next = function () {
     if (this.pos < this.string.length)
-      return this.string.charAt(this.pos++);
-  },
-  eat: function(match) {
+      { return this.string.charAt(this.pos++) }
+  };
+  StringStream.prototype.eat = function (match) {
     var ch = this.string.charAt(this.pos);
-    if (typeof match == "string") var ok = ch == match;
-    else var ok = ch && (match.test ? match.test(ch) : match(ch));
-    if (ok) {++this.pos; return ch;}
-  },
-  eatWhile: function(match) {
+    var ok;
+    if (typeof match == "string") { ok = ch == match; }
+    else { ok = ch && (match.test ? match.test(ch) : match(ch)); }
+    if (ok) {++this.pos; return ch}
+  };
+  StringStream.prototype.eatWhile = function (match) {
     var start = this.pos;
     while (this.eat(match)){}
-    return this.pos > start;
-  },
-  eatSpace: function() {
+    return this.pos > start
+  };
+  StringStream.prototype.eatSpace = function () {
     var start = this.pos;
-    while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
-    return this.pos > start;
-  },
-  skipToEnd: function() {this.pos = this.string.length;},
-  skipTo: function(ch) {
+    while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this.pos; }
+    return this.pos > start
+  };
+  StringStream.prototype.skipToEnd = function () {this.pos = this.string.length;};
+  StringStream.prototype.skipTo = function (ch) {
     var found = this.string.indexOf(ch, this.pos);
-    if (found > -1) {this.pos = found; return true;}
-  },
-  backUp: function(n) {this.pos -= n;},
-  column: function() {return this.start - this.lineStart;},
-  indentation: function() {return 0;},
-  match: function(pattern, consume, caseInsensitive) {
+    if (found > -1) {this.pos = found; return true}
+  };
+  StringStream.prototype.backUp = function (n) {this.pos -= n;};
+  StringStream.prototype.column = function () {
+    if (this.lastColumnPos < this.start) {
+      this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
+      this.lastColumnPos = this.start;
+    }
+    return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
+  };
+  StringStream.prototype.indentation = function () {
+    return countColumn(this.string, null, this.tabSize) -
+      (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
+  };
+  StringStream.prototype.match = function (pattern, consume, caseInsensitive) {
     if (typeof pattern == "string") {
-      var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
+      var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; };
       var substr = this.string.substr(this.pos, pattern.length);
       if (cased(substr) == cased(pattern)) {
-        if (consume !== false) this.pos += pattern.length;
-        return true;
+        if (consume !== false) { this.pos += pattern.length; }
+        return true
       }
     } else {
       var match = this.string.slice(this.pos).match(pattern);
-      if (match && match.index > 0) return null;
-      if (match && consume !== false) this.pos += match[0].length;
-      return match;
+      if (match && match.index > 0) { return null }
+      if (match && consume !== false) { this.pos += match[0].length; }
+      return match
     }
-  },
-  current: function(){return this.string.slice(this.start, this.pos);},
-  hideFirstChars: function(n, inner) {
+  };
+  StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)};
+  StringStream.prototype.hideFirstChars = function (n, inner) {
     this.lineStart += n;
-    try { return inner(); }
+    try { return inner() }
     finally { this.lineStart -= n; }
-  },
-  lookAhead: function(n) { return this.strings[this.i + n] }
-};
-CodeMirror.StringStream = StringStream;
+  };
+  StringStream.prototype.lookAhead = function (n) {
+    var oracle = this.lineOracle;
+    return oracle && oracle.lookAhead(n)
+  };
+  StringStream.prototype.baseToken = function () {
+    var oracle = this.lineOracle;
+    return oracle && oracle.baseToken(this.pos)
+  };
 
-CodeMirror.startState = function (mode, a1, a2) {
-  return mode.startState ? mode.startState(a1, a2) : true;
-};
+  // Known modes, by name and by MIME
+  var modes = {}, mimeModes = {};
 
-var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
-CodeMirror.defineMode = function (name, mode) {
-  if (arguments.length > 2)
-    mode.dependencies = Array.prototype.slice.call(arguments, 2);
-  modes[name] = mode;
-};
-CodeMirror.defineMIME = function (mime, spec) { mimeModes[mime] = spec; };
-CodeMirror.resolveMode = function(spec) {
-  if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
-    spec = mimeModes[spec];
-  } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
-    spec = mimeModes[spec.name];
-  }
-  if (typeof spec == "string") return {name: spec};
-  else return spec || {name: "null"};
-};
-CodeMirror.getMode = function (options, spec) {
-  spec = CodeMirror.resolveMode(spec);
-  var mfactory = modes[spec.name];
-  if (!mfactory) throw new Error("Unknown mode: " + spec);
-  return mfactory(options, spec);
-};
-CodeMirror.registerHelper = CodeMirror.registerGlobalHelper = Math.min;
-CodeMirror.defineMode("null", function() {
-  return {token: function(stream) {stream.skipToEnd();}};
-});
-CodeMirror.defineMIME("text/plain", "null");
-
-CodeMirror.runMode = function (string, modespec, callback, options) {
-  var mode = CodeMirror.getMode({ indentUnit: 2 }, modespec);
-  var ie = /MSIE \d/.test(navigator.userAgent);
-  var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
-
-  if (callback.appendChild) {
-    var tabSize = (options && options.tabSize) || 4;
-    var node = callback, col = 0;
-    node.innerHTML = "";
-    callback = function (text, style) {
-      if (text == "\n") {
-        // Emitting LF or CRLF on IE8 or earlier results in an incorrect display.
-        // Emitting a carriage return makes everything ok.
-        node.appendChild(document.createTextNode(ie_lt9 ? '\r' : text));
-        col = 0;
-        return;
-      }
-      var content = "";
-      // replace tabs
-      for (var pos = 0; ;) {
-        var idx = text.indexOf("\t", pos);
-        if (idx == -1) {
-          content += text.slice(pos);
-          col += text.length - pos;
-          break;
-        } else {
-          col += idx - pos;
-          content += text.slice(pos, idx);
-          var size = tabSize - col % tabSize;
-          col += size;
-          for (var i = 0; i < size; ++i) content += " ";
-          pos = idx + 1;
-        }
-      }
-
-      if (style) {
-        var sp = node.appendChild(document.createElement("span"));
-        sp.className = "cm-" + style.replace(/ +/g, " cm-");
-        sp.appendChild(document.createTextNode(content));
-      } else {
-        node.appendChild(document.createTextNode(content));
-      }
-    };
+  // Extra arguments are stored as the mode's dependencies, which is
+  // used by (legacy) mechanisms like loadmode.js to automatically
+  // load a mode. (Preferred mechanism is the require/define calls.)
+  function defineMode(name, mode) {
+    if (arguments.length > 2)
+      { mode.dependencies = Array.prototype.slice.call(arguments, 2); }
+    modes[name] = mode;
   }
 
-  var lines = splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
-  for (var i = 0, e = lines.length; i < e; ++i) {
-    if (i) callback("\n");
-    var stream = new CodeMirror.StringStream(lines, i);
-    if (!stream.string && mode.blankLine) mode.blankLine(state);
-    while (!stream.eol()) {
-      var style = mode.token(stream, state);
-      callback(stream.current(), style, i, stream.start, state);
-      stream.start = stream.pos;
+  function defineMIME(mime, spec) {
+    mimeModes[mime] = spec;
+  }
+
+  // Given a MIME type, a {name, ...options} config object, or a name
+  // string, return a mode config object.
+  function resolveMode(spec) {
+    if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
+      spec = mimeModes[spec];
+    } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
+      var found = mimeModes[spec.name];
+      if (typeof found == "string") { found = {name: found}; }
+      spec = createObj(found, spec);
+      spec.name = found.name;
+    } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
+      return resolveMode("application/xml")
+    } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) {
+      return resolveMode("application/json")
     }
+    if (typeof spec == "string") { return {name: spec} }
+    else { return spec || {name: "null"} }
   }
-};
-})();
+
+  // Given a mode spec (anything that resolveMode accepts), find and
+  // initialize an actual mode object.
+  function getMode(options, spec) {
+    spec = resolveMode(spec);
+    var mfactory = modes[spec.name];
+    if (!mfactory) { return getMode(options, "text/plain") }
+    var modeObj = mfactory(options, spec);
+    if (modeExtensions.hasOwnProperty(spec.name)) {
+      var exts = modeExtensions[spec.name];
+      for (var prop in exts) {
+        if (!exts.hasOwnProperty(prop)) { continue }
+        if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop]; }
+        modeObj[prop] = exts[prop];
+      }
+    }
+    modeObj.name = spec.name;
+    if (spec.helperType) { modeObj.helperType = spec.helperType; }
+    if (spec.modeProps) { for (var prop$1 in spec.modeProps)
+      { modeObj[prop$1] = spec.modeProps[prop$1]; } }
+
+    return modeObj
+  }
+
+  // This can be used to attach properties to mode objects from
+  // outside the actual mode definition.
+  var modeExtensions = {};
+  function extendMode(mode, properties) {
+    var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
+    copyObj(properties, exts);
+  }
+
+  function copyState(mode, state) {
+    if (state === true) { return state }
+    if (mode.copyState) { return mode.copyState(state) }
+    var nstate = {};
+    for (var n in state) {
+      var val = state[n];
+      if (val instanceof Array) { val = val.concat([]); }
+      nstate[n] = val;
+    }
+    return nstate
+  }
+
+  // Given a mode and a state (for that mode), find the inner mode and
+  // state at the position that the state refers to.
+  function innerMode(mode, state) {
+    var info;
+    while (mode.innerMode) {
+      info = mode.innerMode(state);
+      if (!info || info.mode == mode) { break }
+      state = info.state;
+      mode = info.mode;
+    }
+    return info || {mode: mode, state: state}
+  }
+
+  function startState(mode, a1, a2) {
+    return mode.startState ? mode.startState(a1, a2) : true
+  }
+
+  var modeMethods = ({
+    __proto__: null,
+    modes: modes,
+    mimeModes: mimeModes,
+    defineMode: defineMode,
+    defineMIME: defineMIME,
+    resolveMode: resolveMode,
+    getMode: getMode,
+    modeExtensions: modeExtensions,
+    extendMode: extendMode,
+    copyState: copyState,
+    innerMode: innerMode,
+    startState: startState
+  });
+
+  // declare global: globalThis, CodeMirror
+
+  // Create a minimal CodeMirror needed to use runMode, and assign to root.
+  var root = typeof globalThis !== 'undefined' ? globalThis : window;
+  root.CodeMirror = {};
+
+  // Copy StringStream and mode methods into CodeMirror object.
+  CodeMirror.StringStream = StringStream;
+  for (var exported in modeMethods) { CodeMirror[exported] = modeMethods[exported]; }
+
+  // Minimal default mode.
+  CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); });
+  CodeMirror.defineMIME("text/plain", "null");
+
+  CodeMirror.registerHelper = CodeMirror.registerGlobalHelper = Math.min;
+  CodeMirror.splitLines = function(string) { return string.split(/\r?\n|\r/) };
+
+  CodeMirror.defaults = { indentUnit: 2 };
+
+  // CodeMirror, copyright (c) by Marijn Haverbeke and others
+  // Distributed under an MIT license: https://codemirror.net/LICENSE
+
+  (function(mod) {
+    if (typeof exports == "object" && typeof module == "object") // CommonJS
+      { mod(require("../../lib/codemirror")); }
+    else if (typeof define == "function" && define.amd) // AMD
+      { define(["../../lib/codemirror"], mod); }
+    else // Plain browser env
+      { mod(CodeMirror); }
+  })(function(CodeMirror) {
+
+  CodeMirror.runMode = function(string, modespec, callback, options) {
+    var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
+    var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
+
+    // Create a tokenizing callback function if passed-in callback is a DOM element.
+    if (callback.appendChild) {
+      var ie = /MSIE \d/.test(navigator.userAgent);
+      var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
+      var node = callback, col = 0;
+      node.innerHTML = "";
+      callback = function(text, style) {
+        if (text == "\n") {
+          // Emitting LF or CRLF on IE8 or earlier results in an incorrect display.
+          // Emitting a carriage return makes everything ok.
+          node.appendChild(document.createTextNode(ie_lt9 ? '\r' : text));
+          col = 0;
+          return;
+        }
+        var content = "";
+        // replace tabs
+        for (var pos = 0;;) {
+          var idx = text.indexOf("\t", pos);
+          if (idx == -1) {
+            content += text.slice(pos);
+            col += text.length - pos;
+            break;
+          } else {
+            col += idx - pos;
+            content += text.slice(pos, idx);
+            var size = tabSize - col % tabSize;
+            col += size;
+            for (var i = 0; i < size; ++i) { content += " "; }
+            pos = idx + 1;
+          }
+        }
+        // Create a node with token style and append it to the callback DOM element.
+        if (style) {
+          var sp = node.appendChild(document.createElement("span"));
+          sp.className = "cm-" + style.replace(/ +/g, " cm-");
+          sp.appendChild(document.createTextNode(content));
+        } else {
+          node.appendChild(document.createTextNode(content));
+        }
+      };
+    }
+
+    var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
+    for (var i = 0, e = lines.length; i < e; ++i) {
+      if (i) { callback("\n"); }
+      var stream = new CodeMirror.StringStream(lines[i], null, {
+        lookAhead: function(n) { return lines[i + n] },
+        baseToken: function() {}
+      });
+      if (!stream.string && mode.blankLine) { mode.blankLine(state); }
+      while (!stream.eol()) {
+        var style = mode.token(stream, state);
+        callback(stream.current(), style, i, stream.start, state);
+        stream.start = stream.pos;
+      }
+    }
+  };
+
+  });
+
+}());
diff --git a/front_end/third_party/codemirror/package/addon/runmode/runmode.js b/front_end/third_party/codemirror/package/addon/runmode/runmode.js
index ca8d9a9..2cae686 100644
--- a/front_end/third_party/codemirror/package/addon/runmode/runmode.js
+++ b/front_end/third_party/codemirror/package/addon/runmode/runmode.js
@@ -13,11 +13,12 @@
 
 CodeMirror.runMode = function(string, modespec, callback, options) {
   var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
-  var ie = /MSIE \d/.test(navigator.userAgent);
-  var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
+  var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
 
+  // Create a tokenizing callback function if passed-in callback is a DOM element.
   if (callback.appendChild) {
-    var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
+    var ie = /MSIE \d/.test(navigator.userAgent);
+    var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
     var node = callback, col = 0;
     node.innerHTML = "";
     callback = function(text, style) {
@@ -45,7 +46,7 @@
           pos = idx + 1;
         }
       }
-
+      // Create a node with token style and append it to the callback DOM element.
       if (style) {
         var sp = node.appendChild(document.createElement("span"));
         sp.className = "cm-" + style.replace(/ +/g, " cm-");
diff --git a/front_end/third_party/codemirror/package/addon/runmode/runmode.node.js b/front_end/third_party/codemirror/package/addon/runmode/runmode.node.js
index 53b6994..fcb62c6 100644
--- a/front_end/third_party/codemirror/package/addon/runmode/runmode.node.js
+++ b/front_end/third_party/codemirror/package/addon/runmode/runmode.node.js
@@ -1,190 +1,323 @@
-// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+'use strict';
 
-/* Just enough of CodeMirror to run runMode under node.js */
-
-function splitLines(string){return string.split(/\r\n?|\n/);};
+function copyObj(obj, target, overwrite) {
+  if (!target) { target = {}; }
+  for (var prop in obj)
+    { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
+      { target[prop] = obj[prop]; } }
+  return target
+}
 
 // Counts the column offset in a string, taking tabs into account.
 // Used mostly to find indentation.
-var countColumn = exports.countColumn = function(string, end, tabSize, startIndex, startValue) {
+function countColumn(string, end, tabSize, startIndex, startValue) {
   if (end == null) {
     end = string.search(/[^\s\u00a0]/);
-    if (end == -1) end = string.length;
+    if (end == -1) { end = string.length; }
   }
   for (var i = startIndex || 0, n = startValue || 0;;) {
     var nextTab = string.indexOf("\t", i);
     if (nextTab < 0 || nextTab >= end)
-      return n + (end - i);
+      { return n + (end - i) }
     n += nextTab - i;
     n += tabSize - (n % tabSize);
     i = nextTab + 1;
   }
-};
+}
 
-function StringStream(string, tabSize, context) {
+function nothing() {}
+
+function createObj(base, props) {
+  var inst;
+  if (Object.create) {
+    inst = Object.create(base);
+  } else {
+    nothing.prototype = base;
+    inst = new nothing();
+  }
+  if (props) { copyObj(props, inst); }
+  return inst
+}
+
+// STRING STREAM
+
+// Fed to the mode parsers, provides helper functions to make
+// parsers more succinct.
+
+var StringStream = function(string, tabSize, lineOracle) {
   this.pos = this.start = 0;
   this.string = string;
   this.tabSize = tabSize || 8;
   this.lastColumnPos = this.lastColumnValue = 0;
   this.lineStart = 0;
-  this.context = context
+  this.lineOracle = lineOracle;
 };
 
-StringStream.prototype = {
-  eol: function() {return this.pos >= this.string.length;},
-  sol: function() {return this.pos == this.lineStart;},
-  peek: function() {return this.string.charAt(this.pos) || undefined;},
-  next: function() {
-    if (this.pos < this.string.length)
-      return this.string.charAt(this.pos++);
-  },
-  eat: function(match) {
-    var ch = this.string.charAt(this.pos);
-    if (typeof match == "string") var ok = ch == match;
-    else var ok = ch && (match.test ? match.test(ch) : match(ch));
-    if (ok) {++this.pos; return ch;}
-  },
-  eatWhile: function(match) {
-    var start = this.pos;
-    while (this.eat(match)){}
-    return this.pos > start;
-  },
-  eatSpace: function() {
-    var start = this.pos;
-    while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
-    return this.pos > start;
-  },
-  skipToEnd: function() {this.pos = this.string.length;},
-  skipTo: function(ch) {
-    var found = this.string.indexOf(ch, this.pos);
-    if (found > -1) {this.pos = found; return true;}
-  },
-  backUp: function(n) {this.pos -= n;},
-  column: function() {
-    if (this.lastColumnPos < this.start) {
-      this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
-      this.lastColumnPos = this.start;
+StringStream.prototype.eol = function () {return this.pos >= this.string.length};
+StringStream.prototype.sol = function () {return this.pos == this.lineStart};
+StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined};
+StringStream.prototype.next = function () {
+  if (this.pos < this.string.length)
+    { return this.string.charAt(this.pos++) }
+};
+StringStream.prototype.eat = function (match) {
+  var ch = this.string.charAt(this.pos);
+  var ok;
+  if (typeof match == "string") { ok = ch == match; }
+  else { ok = ch && (match.test ? match.test(ch) : match(ch)); }
+  if (ok) {++this.pos; return ch}
+};
+StringStream.prototype.eatWhile = function (match) {
+  var start = this.pos;
+  while (this.eat(match)){}
+  return this.pos > start
+};
+StringStream.prototype.eatSpace = function () {
+  var start = this.pos;
+  while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this.pos; }
+  return this.pos > start
+};
+StringStream.prototype.skipToEnd = function () {this.pos = this.string.length;};
+StringStream.prototype.skipTo = function (ch) {
+  var found = this.string.indexOf(ch, this.pos);
+  if (found > -1) {this.pos = found; return true}
+};
+StringStream.prototype.backUp = function (n) {this.pos -= n;};
+StringStream.prototype.column = function () {
+  if (this.lastColumnPos < this.start) {
+    this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
+    this.lastColumnPos = this.start;
+  }
+  return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
+};
+StringStream.prototype.indentation = function () {
+  return countColumn(this.string, null, this.tabSize) -
+    (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
+};
+StringStream.prototype.match = function (pattern, consume, caseInsensitive) {
+  if (typeof pattern == "string") {
+    var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; };
+    var substr = this.string.substr(this.pos, pattern.length);
+    if (cased(substr) == cased(pattern)) {
+      if (consume !== false) { this.pos += pattern.length; }
+      return true
     }
-    return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
-  },
-  indentation: function() {
-    return countColumn(this.string, null, this.tabSize) -
-      (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
-  },
-  match: function(pattern, consume, caseInsensitive) {
-    if (typeof pattern == "string") {
-      var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
-      var substr = this.string.substr(this.pos, pattern.length);
-      if (cased(substr) == cased(pattern)) {
-        if (consume !== false) this.pos += pattern.length;
-        return true;
-      }
-    } else {
-      var match = this.string.slice(this.pos).match(pattern);
-      if (match && match.index > 0) return null;
-      if (match && consume !== false) this.pos += match[0].length;
-      return match;
-    }
-  },
-  current: function(){return this.string.slice(this.start, this.pos);},
-  hideFirstChars: function(n, inner) {
-    this.lineStart += n;
-    try { return inner(); }
-    finally { this.lineStart -= n; }
-  },
-  lookAhead: function(n) {
-    var line = this.context.line + n
-    return line >= this.context.lines.length ? null : this.context.lines[line]
+  } else {
+    var match = this.string.slice(this.pos).match(pattern);
+    if (match && match.index > 0) { return null }
+    if (match && consume !== false) { this.pos += match[0].length; }
+    return match
   }
 };
-exports.StringStream = StringStream;
-
-exports.startState = function(mode, a1, a2) {
-  return mode.startState ? mode.startState(a1, a2) : true;
+StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)};
+StringStream.prototype.hideFirstChars = function (n, inner) {
+  this.lineStart += n;
+  try { return inner() }
+  finally { this.lineStart -= n; }
+};
+StringStream.prototype.lookAhead = function (n) {
+  var oracle = this.lineOracle;
+  return oracle && oracle.lookAhead(n)
+};
+StringStream.prototype.baseToken = function () {
+  var oracle = this.lineOracle;
+  return oracle && oracle.baseToken(this.pos)
 };
 
-var modes = exports.modes = {}, mimeModes = exports.mimeModes = {};
-exports.defineMode = function(name, mode) {
+// Known modes, by name and by MIME
+var modes = {}, mimeModes = {};
+
+// Extra arguments are stored as the mode's dependencies, which is
+// used by (legacy) mechanisms like loadmode.js to automatically
+// load a mode. (Preferred mechanism is the require/define calls.)
+function defineMode(name, mode) {
   if (arguments.length > 2)
-    mode.dependencies = Array.prototype.slice.call(arguments, 2);
+    { mode.dependencies = Array.prototype.slice.call(arguments, 2); }
   modes[name] = mode;
-};
-exports.defineMIME = function(mime, spec) { mimeModes[mime] = spec; };
+}
 
-exports.defineMode("null", function() {
-  return {token: function(stream) {stream.skipToEnd();}};
-});
-exports.defineMIME("text/plain", "null");
+function defineMIME(mime, spec) {
+  mimeModes[mime] = spec;
+}
 
-exports.resolveMode = function(spec) {
+// Given a MIME type, a {name, ...options} config object, or a name
+// string, return a mode config object.
+function resolveMode(spec) {
   if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
     spec = mimeModes[spec];
   } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
-    spec = mimeModes[spec.name];
+    var found = mimeModes[spec.name];
+    if (typeof found == "string") { found = {name: found}; }
+    spec = createObj(found, spec);
+    spec.name = found.name;
+  } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
+    return resolveMode("application/xml")
+  } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) {
+    return resolveMode("application/json")
   }
-  if (typeof spec == "string") return {name: spec};
-  else return spec || {name: "null"};
-};
-
-function copyObj(obj, target, overwrite) {
-  if (!target) target = {};
-  for (var prop in obj)
-    if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
-      target[prop] = obj[prop];
-  return target;
+  if (typeof spec == "string") { return {name: spec} }
+  else { return spec || {name: "null"} }
 }
 
-// This can be used to attach properties to mode objects from
-// outside the actual mode definition.
-var modeExtensions = exports.modeExtensions = {};
-exports.extendMode = function(mode, properties) {
-  var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
-  copyObj(properties, exts);
-};
-
-exports.getMode = function(options, spec) {
-  var spec = exports.resolveMode(spec);
+// Given a mode spec (anything that resolveMode accepts), find and
+// initialize an actual mode object.
+function getMode(options, spec) {
+  spec = resolveMode(spec);
   var mfactory = modes[spec.name];
-  if (!mfactory) return exports.getMode(options, "text/plain");
+  if (!mfactory) { return getMode(options, "text/plain") }
   var modeObj = mfactory(options, spec);
   if (modeExtensions.hasOwnProperty(spec.name)) {
     var exts = modeExtensions[spec.name];
     for (var prop in exts) {
-      if (!exts.hasOwnProperty(prop)) continue;
-      if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop];
+      if (!exts.hasOwnProperty(prop)) { continue }
+      if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop]; }
       modeObj[prop] = exts[prop];
     }
   }
   modeObj.name = spec.name;
-  if (spec.helperType) modeObj.helperType = spec.helperType;
-  if (spec.modeProps) for (var prop in spec.modeProps)
-    modeObj[prop] = spec.modeProps[prop];
+  if (spec.helperType) { modeObj.helperType = spec.helperType; }
+  if (spec.modeProps) { for (var prop$1 in spec.modeProps)
+    { modeObj[prop$1] = spec.modeProps[prop$1]; } }
 
-  return modeObj;
-};
+  return modeObj
+}
 
-exports.innerMode = function(mode, state) {
+// This can be used to attach properties to mode objects from
+// outside the actual mode definition.
+var modeExtensions = {};
+function extendMode(mode, properties) {
+  var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
+  copyObj(properties, exts);
+}
+
+function copyState(mode, state) {
+  if (state === true) { return state }
+  if (mode.copyState) { return mode.copyState(state) }
+  var nstate = {};
+  for (var n in state) {
+    var val = state[n];
+    if (val instanceof Array) { val = val.concat([]); }
+    nstate[n] = val;
+  }
+  return nstate
+}
+
+// Given a mode and a state (for that mode), find the inner mode and
+// state at the position that the state refers to.
+function innerMode(mode, state) {
   var info;
   while (mode.innerMode) {
     info = mode.innerMode(state);
-    if (!info || info.mode == mode) break;
+    if (!info || info.mode == mode) { break }
     state = info.state;
     mode = info.mode;
   }
-  return info || {mode: mode, state: state};
+  return info || {mode: mode, state: state}
 }
 
-exports.registerHelper = exports.registerGlobalHelper = Math.min;
+function startState(mode, a1, a2) {
+  return mode.startState ? mode.startState(a1, a2) : true
+}
 
-exports.runMode = function(string, modespec, callback, options) {
-  var mode = exports.getMode({indentUnit: 2}, modespec);
-  var lines = splitLines(string), state = (options && options.state) || exports.startState(mode);
-  var context = {lines: lines, line: 0}
-  for (var i = 0, e = lines.length; i < e; ++i, ++context.line) {
-    if (i) callback("\n");
-    var stream = new exports.StringStream(lines[i], 4, context);
-    if (!stream.string && mode.blankLine) mode.blankLine(state);
+var modeMethods = ({
+  __proto__: null,
+  modes: modes,
+  mimeModes: mimeModes,
+  defineMode: defineMode,
+  defineMIME: defineMIME,
+  resolveMode: resolveMode,
+  getMode: getMode,
+  modeExtensions: modeExtensions,
+  extendMode: extendMode,
+  copyState: copyState,
+  innerMode: innerMode,
+  startState: startState
+});
+
+// Copy StringStream and mode methods into exports (CodeMirror) object.
+exports.StringStream = StringStream;
+exports.countColumn = countColumn;
+for (var exported in modeMethods) { exports[exported] = modeMethods[exported]; }
+
+// Shim library CodeMirror with the minimal CodeMirror defined above.
+require.cache[require.resolve("../../lib/codemirror")] = require.cache[require.resolve("./runmode.node")];
+require.cache[require.resolve("../../addon/runmode/runmode")] = require.cache[require.resolve("./runmode.node")];
+
+// Minimal default mode.
+exports.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); });
+exports.defineMIME("text/plain", "null");
+
+exports.registerHelper = exports.registerGlobalHelper = Math.min;
+exports.splitLines = function(string) { return string.split(/\r?\n|\r/) };
+
+exports.defaults = { indentUnit: 2 };
+
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/LICENSE
+
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    { mod(require("../../lib/codemirror")); }
+  else if (typeof define == "function" && define.amd) // AMD
+    { define(["../../lib/codemirror"], mod); }
+  else // Plain browser env
+    { mod(CodeMirror); }
+})(function(CodeMirror) {
+
+CodeMirror.runMode = function(string, modespec, callback, options) {
+  var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
+  var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
+
+  // Create a tokenizing callback function if passed-in callback is a DOM element.
+  if (callback.appendChild) {
+    var ie = /MSIE \d/.test(navigator.userAgent);
+    var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
+    var node = callback, col = 0;
+    node.innerHTML = "";
+    callback = function(text, style) {
+      if (text == "\n") {
+        // Emitting LF or CRLF on IE8 or earlier results in an incorrect display.
+        // Emitting a carriage return makes everything ok.
+        node.appendChild(document.createTextNode(ie_lt9 ? '\r' : text));
+        col = 0;
+        return;
+      }
+      var content = "";
+      // replace tabs
+      for (var pos = 0;;) {
+        var idx = text.indexOf("\t", pos);
+        if (idx == -1) {
+          content += text.slice(pos);
+          col += text.length - pos;
+          break;
+        } else {
+          col += idx - pos;
+          content += text.slice(pos, idx);
+          var size = tabSize - col % tabSize;
+          col += size;
+          for (var i = 0; i < size; ++i) { content += " "; }
+          pos = idx + 1;
+        }
+      }
+      // Create a node with token style and append it to the callback DOM element.
+      if (style) {
+        var sp = node.appendChild(document.createElement("span"));
+        sp.className = "cm-" + style.replace(/ +/g, " cm-");
+        sp.appendChild(document.createTextNode(content));
+      } else {
+        node.appendChild(document.createTextNode(content));
+      }
+    };
+  }
+
+  var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
+  for (var i = 0, e = lines.length; i < e; ++i) {
+    if (i) { callback("\n"); }
+    var stream = new CodeMirror.StringStream(lines[i], null, {
+      lookAhead: function(n) { return lines[i + n] },
+      baseToken: function() {}
+    });
+    if (!stream.string && mode.blankLine) { mode.blankLine(state); }
     while (!stream.eol()) {
       var style = mode.token(stream, state);
       callback(stream.current(), style, i, stream.start, state);
@@ -193,5 +326,4 @@
   }
 };
 
-require.cache[require.resolve("../../lib/codemirror")] = require.cache[require.resolve("./runmode.node")];
-require.cache[require.resolve("../../addon/runmode/runmode")] = require.cache[require.resolve("./runmode.node")];
+});
diff --git a/front_end/third_party/codemirror/package/addon/scroll/annotatescrollbar.js b/front_end/third_party/codemirror/package/addon/scroll/annotatescrollbar.js
index 9fe61ec..c12e44c 100644
--- a/front_end/third_party/codemirror/package/addon/scroll/annotatescrollbar.js
+++ b/front_end/third_party/codemirror/package/addon/scroll/annotatescrollbar.js
@@ -72,10 +72,16 @@
     var wrapping = cm.getOption("lineWrapping");
     var singleLineH = wrapping && cm.defaultTextHeight() * 1.5;
     var curLine = null, curLineObj = null;
+
     function getY(pos, top) {
       if (curLine != pos.line) {
-        curLine = pos.line;
-        curLineObj = cm.getLineHandle(curLine);
+        curLine = pos.line
+        curLineObj = cm.getLineHandle(pos.line)
+        var visual = cm.getLineHandleVisualStart(curLineObj)
+        if (visual != curLineObj) {
+          curLine = cm.getLineNumber(visual)
+          curLineObj = visual
+        }
       }
       if ((curLineObj.widgets && curLineObj.widgets.length) ||
           (wrapping && curLineObj.height > singleLineH))
diff --git a/front_end/third_party/codemirror/package/addon/wrap/hardwrap.js b/front_end/third_party/codemirror/package/addon/wrap/hardwrap.js
index 29cc15f..f194946 100644
--- a/front_end/third_party/codemirror/package/addon/wrap/hardwrap.js
+++ b/front_end/third_party/codemirror/package/addon/wrap/hardwrap.js
@@ -29,11 +29,20 @@
     return {from: start, to: end};
   }
 
-  function findBreakPoint(text, column, wrapOn, killTrailingSpace) {
+  function findBreakPoint(text, column, wrapOn, killTrailingSpace, forceBreak) {
     var at = column
     while (at < text.length && text.charAt(at) == " ") at++
     for (; at > 0; --at)
       if (wrapOn.test(text.slice(at - 1, at + 1))) break;
+
+    if (at == 0 && !forceBreak) {
+      // didn't find a break point before column, in non-forceBreak mode try to
+      // find one after 'column'.
+      for (at = column + 1; at < text.length - 1; ++at) {
+        if (wrapOn.test(text.slice(at - 1, at + 1))) break;
+      }
+    }
+
     for (var first = true;; first = false) {
       var endOfText = at;
       if (killTrailingSpace)
@@ -47,6 +56,7 @@
     from = cm.clipPos(from); to = cm.clipPos(to);
     var column = options.column || 80;
     var wrapOn = options.wrapOn || /\s\S|-[^\.\d]/;
+    var forceBreak = options.forceBreak !== false;
     var killTrailing = options.killTrailingSpace !== false;
     var changes = [], curLine = "", curNo = from.line;
     var lines = cm.getRange(from, to, false);
@@ -68,7 +78,7 @@
       curLine += text;
       if (i) {
         var firstBreak = curLine.length > column && leadingSpace == spaceTrimmed &&
-          findBreakPoint(curLine, column, wrapOn, killTrailing);
+          findBreakPoint(curLine, column, wrapOn, killTrailing, forceBreak);
         // If this isn't broken, or is broken at a different point, remove old break
         if (!firstBreak || firstBreak.from != oldLen || firstBreak.to != oldLen + spaceInserted) {
           changes.push({text: [spaceInserted ? " " : ""],
@@ -80,12 +90,16 @@
         }
       }
       while (curLine.length > column) {
-        var bp = findBreakPoint(curLine, column, wrapOn, killTrailing);
-        changes.push({text: ["", leadingSpace],
-                      from: Pos(curNo, bp.from),
-                      to: Pos(curNo, bp.to)});
-        curLine = leadingSpace + curLine.slice(bp.to);
-        ++curNo;
+        var bp = findBreakPoint(curLine, column, wrapOn, killTrailing, forceBreak);
+        if (bp.from != bp.to || forceBreak) {
+          changes.push({text: ["", leadingSpace],
+                        from: Pos(curNo, bp.from),
+                        to: Pos(curNo, bp.to)});
+          curLine = leadingSpace + curLine.slice(bp.to);
+          ++curNo;
+        } else {
+          break;
+        }
       }
     }
     if (changes.length) cm.operation(function() {
diff --git a/front_end/third_party/codemirror/package/keymap/vim.js b/front_end/third_party/codemirror/package/keymap/vim.js
index b5be59c..5a4860c 100644
--- a/front_end/third_party/codemirror/package/keymap/vim.js
+++ b/front_end/third_party/codemirror/package/keymap/vim.js
@@ -2069,6 +2069,8 @@
             if (operatorArgs) { operatorArgs.linewise = true; }
             tmp.end.line--;
           }
+        } else if (character === 't') {
+          tmp = expandTagUnderCursor(cm, head, inclusive);
         } else {
           // No text object defined for this, don't move.
           return null;
@@ -3203,7 +3205,7 @@
       vim.visualMode = false;
       vim.visualLine = false;
       vim.visualBlock = false;
-      CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
+      if (!vim.insertMode) CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
       clearFakeCursor(vim);
     }
 
@@ -3295,6 +3297,49 @@
       return { start: Pos(cur.line, start), end: Pos(cur.line, end) };
     }
 
+    /**
+     * Depends on the following:
+     *
+     * - editor mode should be htmlmixedmode / xml
+     * - mode/xml/xml.js should be loaded
+     * - addon/fold/xml-fold.js should be loaded
+     *
+     * If any of the above requirements are not true, this function noops.
+     *
+     * This is _NOT_ a 100% accurate implementation of vim tag text objects.
+     * The following caveats apply (based off cursory testing, I'm sure there
+     * are other discrepancies):
+     *
+     * - Does not work inside comments:
+     *   ```
+     *   <!-- <div>broken</div> -->
+     *   ```
+     * - Does not work when tags have different cases:
+     *   ```
+     *   <div>broken</DIV>
+     *   ```
+     * - Does not work when cursor is inside a broken tag:
+     *   ```
+     *   <div><brok><en></div>
+     *   ```
+     */
+    function expandTagUnderCursor(cm, head, inclusive) {
+      var cur = head;
+      if (!CodeMirror.findMatchingTag || !CodeMirror.findEnclosingTag) {
+        return { start: cur, end: cur };
+      }
+
+      var tags = CodeMirror.findMatchingTag(cm, head) || CodeMirror.findEnclosingTag(cm, head);
+      if (!tags || !tags.open || !tags.close) {
+        return { start: cur, end: cur };
+      }
+
+      if (inclusive) {
+        return { start: tags.open.from, end: tags.close.to };
+      }
+      return { start: tags.open.to, end: tags.close.from };
+    }
+
     function recordJumpPosition(cm, oldCur, newCur) {
       if (!cursorEqual(oldCur, newCur)) {
         vimGlobalState.jumpList.add(cm, oldCur, newCur);
@@ -3836,7 +3881,7 @@
       return Pos(curr_index.ln, curr_index.pos);
     }
 
-    // TODO: perhaps this finagling of start and end positions belonds
+    // TODO: perhaps this finagling of start and end positions belongs
     // in codemirror/replaceRange?
     function selectCompanionObject(cm, head, symb, inclusive) {
       var cur = head, start, end;
diff --git a/front_end/third_party/codemirror/package/lib/codemirror.js b/front_end/third_party/codemirror/package/lib/codemirror.js
index b6eaa72..7cee409 100644
--- a/front_end/third_party/codemirror/package/lib/codemirror.js
+++ b/front_end/third_party/codemirror/package/lib/codemirror.js
@@ -2960,7 +2960,7 @@
     var x, y, space = display.lineSpace.getBoundingClientRect();
     // Fails unpredictably on IE[67] when mouse is dragged around quickly.
     try { x = e.clientX - space.left; y = e.clientY - space.top; }
-    catch (e) { return null }
+    catch (e$1) { return null }
     var coords = coordsChar(cm, x, y), line;
     if (forRect && coords.xRel > 0 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {
       var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length;
@@ -6545,7 +6545,7 @@
           cm.display.input.focus();
         }
       }
-      catch(e){}
+      catch(e$1){}
     }
   }
 
@@ -6641,7 +6641,7 @@
     46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod",
     106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 145: "ScrollLock",
     173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
-    221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
+    221: "]", 222: "'", 224: "Mod", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
     63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"
   };
 
@@ -6776,7 +6776,7 @@
     var base = name;
     if (event.altKey && base != "Alt") { name = "Alt-" + name; }
     if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name; }
-    if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") { name = "Cmd-" + name; }
+    if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Mod") { name = "Cmd-" + name; }
     if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name; }
     return name
   }
@@ -7597,7 +7597,7 @@
       mY = e.touches[0].clientY;
     } else {
       try { mX = e.clientX; mY = e.clientY; }
-      catch(e) { return false }
+      catch(e$1) { return false }
     }
     if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false }
     if (prevent) { e_preventDefault(e); }
@@ -7697,7 +7697,7 @@
       for (var i = newBreaks.length - 1; i >= 0; i--)
         { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)); }
     });
-    option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g, function (cm, val, old) {
+    option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200c\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g, function (cm, val, old) {
       cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
       if (old != Init) { cm.refresh(); }
     });
@@ -8117,7 +8117,7 @@
           { from = Pos(from.line, from.ch - deleted); }
         else if (cm.state.overwrite && !paste) // Handle overwrite
           { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); }
-        else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == inserted)
+        else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == textLines.join("\n"))
           { from = to = Pos(from.line, 0); }
       }
       var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines,
@@ -9771,7 +9771,7 @@
 
   addLegacyProps(CodeMirror);
 
-  CodeMirror.version = "5.54.0";
+  CodeMirror.version = "5.57.0";
 
   return CodeMirror;
 
diff --git a/front_end/third_party/codemirror/package/mode/css/css.js b/front_end/third_party/codemirror/package/mode/css/css.js
index 441ba4a..77ca0c1 100644
--- a/front_end/third_party/codemirror/package/mode/css/css.js
+++ b/front_end/third_party/codemirror/package/mode/css/css.js
@@ -442,17 +442,18 @@
     "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", "any-pointer", "hover", "any-hover"
+    "pointer", "any-pointer", "hover", "any-hover", "prefers-color-scheme"
   ], mediaFeatures = keySet(mediaFeatures_);
 
   var mediaValueKeywords_ = [
     "landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover",
-    "interlace", "progressive"
+    "interlace", "progressive",
+    "dark", "light"
   ], mediaValueKeywords = keySet(mediaValueKeywords_);
 
   var propertyKeywords_ = [
     "align-content", "align-items", "align-self", "alignment-adjust",
-    "alignment-baseline", "anchor-point", "animation", "animation-delay",
+    "alignment-baseline", "all", "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", "backdrop-filter",
@@ -503,7 +504,9 @@
     "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-block-size", "max-height", "max-inline-size",
+    "marquee-style", "mask-clip", "mask-composite", "mask-image", "mask-mode",
+    "mask-origin", "mask-position", "mask-repeat", "mask-size","mask-type",
+    "max-block-size", "max-height", "max-inline-size",
     "max-width", "min-block-size", "min-height", "min-inline-size", "min-width",
     "mix-blend-mode", "move-to", "nav-down", "nav-index", "nav-left", "nav-right",
     "nav-up", "object-fit", "object-position", "offset", "offset-anchor",
@@ -540,7 +543,7 @@
     "text-height", "text-indent", "text-justify", "text-orientation",
     "text-outline", "text-overflow", "text-rendering", "text-shadow",
     "text-size-adjust", "text-space-collapse", "text-transform",
-    "text-underline-position", "text-wrap", "top", "transform", "transform-origin",
+    "text-underline-position", "text-wrap", "top", "touch-action", "transform", "transform-origin",
     "transform-style", "transition", "transition-delay", "transition-duration",
     "transition-property", "transition-timing-function", "translate",
     "unicode-bidi", "user-select", "vertical-align", "visibility", "voice-balance",
@@ -552,11 +555,11 @@
     "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",
+    "marker", "marker-end", "marker-mid", "marker-start", "paint-order", "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"
+    "glyph-orientation-vertical", "text-anchor", "writing-mode",
   ], propertyKeywords = keySet(propertyKeywords_);
 
   var nonStandardPropertyKeywords_ = [
@@ -623,7 +626,7 @@
     "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",
+    "avoid-region", "axis-pan", "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-bevel",
     "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian",
@@ -647,7 +650,7 @@
     "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",
+    "extra-expanded", "fantasy", "fast", "fill", "fill-box", "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", "hide", "higher", "highlight", "highlighttext",
@@ -662,7 +665,7 @@
     "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",
+    "lower-roman", "lowercase", "ltr", "luminosity", "malayalam", "manipulation", "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",
@@ -671,13 +674,13 @@
     "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",
+    "mix", "mongolian", "monospace", "move", "multiple", "multiple_mask_images", "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",
+    "painted", "page", "paused", "persian", "perspective", "pinch-zoom", "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",
@@ -695,8 +698,8 @@
     "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",
+    "square-button", "start", "static", "status-bar", "stretch", "stroke", "stroke-box", "sub",
+    "subpixel-antialiased", "svg_masks", "super", "sw-resize", "symbolic", "symbols", "system-ui", "table",
     "table-caption", "table-cell", "table-column", "table-column-group",
     "table-footer-group", "table-header-group", "table-row", "table-row-group",
     "tamil",
@@ -706,10 +709,10 @@
     "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",
+    "transparent", "ultra-condensed", "ultra-expanded", "underline", "unidirectional-pan", "unset", "up",
     "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
     "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
-    "var", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
+    "var", "vertical", "vertical-text", "view-box", "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"
diff --git a/front_end/third_party/codemirror/package/mode/javascript/javascript.js b/front_end/third_party/codemirror/package/mode/javascript/javascript.js
index c657763..9c751d2 100644
--- a/front_end/third_party/codemirror/package/mode/javascript/javascript.js
+++ b/front_end/third_party/codemirror/package/mode/javascript/javascript.js
@@ -103,7 +103,8 @@
       return ret("meta", "meta");
     } else if (ch == "#" && stream.eatWhile(wordRE)) {
       return ret("variable", "property")
-    } else if (ch == "<" && stream.match("!--") || ch == "-" && stream.match("->")) {
+    } else if (ch == "<" && stream.match("!--") ||
+               (ch == "-" && stream.match("->") && !/\S/.test(stream.string.slice(0, stream.start)))) {
       stream.skipToEnd()
       return ret("comment", "comment")
     } else if (isOperatorChar.test(ch)) {
diff --git a/front_end/third_party/codemirror/package/mode/julia/julia.js b/front_end/third_party/codemirror/package/mode/julia/julia.js
index eaef97e..f1d2cd5 100644
--- a/front_end/third_party/codemirror/package/mode/julia/julia.js
+++ b/front_end/third_party/codemirror/package/mode/julia/julia.js
@@ -401,9 +401,9 @@
 
     indent: function(state, textAfter) {
       var delta = 0;
-      if ( textAfter === ']' || textAfter === ')' || textAfter === "end" ||
-           textAfter === "else" || textAfter === "catch" || textAfter === "elseif" ||
-           textAfter === "finally" ) {
+      if ( textAfter === ']' || textAfter === ')' || /^end\b/.test(textAfter) ||
+           /^else/.test(textAfter) || /^catch\b/.test(textAfter) || /^elseif\b/.test(textAfter) ||
+           /^finally/.test(textAfter) ) {
         delta = -1;
       }
       return (state.scopes.length + delta) * config.indentUnit;
diff --git a/front_end/third_party/codemirror/package/mode/markdown/markdown.js b/front_end/third_party/codemirror/package/mode/markdown/markdown.js
index dcb048c..287f39b 100644
--- a/front_end/third_party/codemirror/package/mode/markdown/markdown.js
+++ b/front_end/third_party/codemirror/package/mode/markdown/markdown.js
@@ -47,9 +47,9 @@
 
   if (modeCfg.fencedCodeBlockHighlighting === undefined)
     modeCfg.fencedCodeBlockHighlighting = true;
-  
+
   if (modeCfg.fencedCodeBlockDefaultMode === undefined)
-    modeCfg.fencedCodeBlockDefaultMode = '';
+    modeCfg.fencedCodeBlockDefaultMode = 'text/plain';
 
   if (modeCfg.xml === undefined)
     modeCfg.xml = true;
@@ -92,7 +92,7 @@
   ,   atxHeaderRE = modeCfg.allowAtxHeaderWithoutSpace ? /^(#+)/ : /^(#+)(?: |$)/
   ,   setextHeaderRE = /^ {0,3}(?:\={1,}|-{2,})\s*$/
   ,   textRE = /^[^#!\[\]*_\\<>` "'(~:]+/
-  ,   fencedCodeRE = /^(~~~+|```+)[ \t]*([\w+#-]*)[^\n`]*$/
+  ,   fencedCodeRE = /^(~~~+|```+)[ \t]*([\w\/+#-]*)[^\n`]*$/
   ,   linkDefRE = /^\s*\[[^\]]+?\]:.*$/ // naive link-definition
   ,   punctuation = /[!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E42\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC9\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDF3C-\uDF3E]|\uD809[\uDC70-\uDC74]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]/
   ,   expandedTab = "    " // CommonMark specifies tab as 4 spaces
diff --git a/front_end/third_party/codemirror/package/mode/meta.js b/front_end/third_party/codemirror/package/mode/meta.js
index 9f64f41..d3efdc1 100644
--- a/front_end/third_party/codemirror/package/mode/meta.js
+++ b/front_end/third_party/codemirror/package/mode/meta.js
@@ -24,7 +24,7 @@
     {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: "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", "lisp", "el"], alias: ["lisp"]},
     {name: "Cypher", mime: "application/x-cypher-query", mode: "cypher", ext: ["cyp", "cypher"]},
@@ -55,7 +55,7 @@
     {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: ["feature"]},
-    {name: "GitHub Flavored Markdown", mime: "text/x-gfm", mode: "gfm", file: /^(readme|contributing|history).md$/i},
+    {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"]},
diff --git a/front_end/third_party/codemirror/package/mode/nsis/nsis.js b/front_end/third_party/codemirror/package/mode/nsis/nsis.js
index 1081660..636940f 100644
--- a/front_end/third_party/codemirror/package/mode/nsis/nsis.js
+++ b/front_end/third_party/codemirror/package/mode/nsis/nsis.js
@@ -31,7 +31,7 @@
     {regex: /^\s*(?:\!(else|endif|macroend))\b/, token: "keyword", dedent: true},
 
     // Runtime Commands
-    {regex: /^\s*(?:Abort|AddBrandingImage|AddSize|AllowRootDirInstall|AllowSkipFiles|AutoCloseWindow|BGFont|BGGradient|BrandingText|BringToFront|Call|CallInstDLL|Caption|ChangeUI|CheckBitmap|ClearErrors|CompletedText|ComponentText|CopyFiles|CRCCheck|CreateDirectory|CreateFont|CreateShortCut|Delete|DeleteINISec|DeleteINIStr|DeleteRegKey|DeleteRegValue|DetailPrint|DetailsButtonText|DirText|DirVar|DirVerify|EnableWindow|EnumRegKey|EnumRegValue|Exch|Exec|ExecShell|ExecShellWait|ExecWait|ExpandEnvStrings|File|FileBufSize|FileClose|FileErrorText|FileOpen|FileRead|FileReadByte|FileReadUTF16LE|FileReadWord|FileWriteUTF16LE|FileSeek|FileWrite|FileWriteByte|FileWriteWord|FindClose|FindFirst|FindNext|FindWindow|FlushINI|GetCurInstType|GetCurrentAddress|GetDlgItem|GetDLLVersion|GetDLLVersionLocal|GetErrorLevel|GetFileTime|GetFileTimeLocal|GetFullPathName|GetFunctionAddress|GetInstDirError|GetLabelAddress|GetTempFileName|Goto|HideWindow|Icon|IfAbort|IfErrors|IfFileExists|IfRebootFlag|IfSilent|InitPluginsDir|InstallButtonText|InstallColors|InstallDir|InstallDirRegKey|InstProgressFlags|InstType|InstTypeGetText|InstTypeSetText|Int64Cmp|Int64CmpU|Int64Fmt|IntCmp|IntCmpU|IntFmt|IntOp|IntPtrCmp|IntPtrCmpU|IntPtrOp|IsWindow|LangString|LicenseBkColor|LicenseData|LicenseForceSelection|LicenseLangString|LicenseText|LoadAndSetImage|LoadLanguageFile|LockWindow|LogSet|LogText|ManifestDPIAware|ManifestLongPathAware|ManifestMaxVersionTested|ManifestSupportedOS|MessageBox|MiscButtonText|Name|Nop|OutFile|Page|PageCallbacks|PEAddResource|PEDllCharacteristics|PERemoveResource|PESubsysVer|Pop|Push|Quit|ReadEnvStr|ReadINIStr|ReadRegDWORD|ReadRegStr|Reboot|RegDLL|Rename|RequestExecutionLevel|ReserveFile|Return|RMDir|SearchPath|SectionGetFlags|SectionGetInstTypes|SectionGetSize|SectionGetText|SectionIn|SectionSetFlags|SectionSetInstTypes|SectionSetSize|SectionSetText|SendMessage|SetAutoClose|SetBrandingImage|SetCompress|SetCompressor|SetCompressorDictSize|SetCtlColors|SetCurInstType|SetDatablockOptimize|SetDateSave|SetDetailsPrint|SetDetailsView|SetErrorLevel|SetErrors|SetFileAttributes|SetFont|SetOutPath|SetOverwrite|SetRebootFlag|SetRegView|SetShellVarContext|SetSilent|ShowInstDetails|ShowUninstDetails|ShowWindow|SilentInstall|SilentUnInstall|Sleep|SpaceTexts|StrCmp|StrCmpS|StrCpy|StrLen|SubCaption|Unicode|UninstallButtonText|UninstallCaption|UninstallIcon|UninstallSubCaption|UninstallText|UninstPage|UnRegDLL|Var|VIAddVersionKey|VIFileVersion|VIProductVersion|WindowIcon|WriteINIStr|WriteRegBin|WriteRegDWORD|WriteRegExpandStr|WriteRegMultiStr|WriteRegNone|WriteRegStr|WriteUninstaller|XPStyle)\b/, token: "keyword"},
+    {regex: /^\s*(?:Abort|AddBrandingImage|AddSize|AllowRootDirInstall|AllowSkipFiles|AutoCloseWindow|BGFont|BGGradient|BrandingText|BringToFront|Call|CallInstDLL|Caption|ChangeUI|CheckBitmap|ClearErrors|CompletedText|ComponentText|CopyFiles|CRCCheck|CreateDirectory|CreateFont|CreateShortCut|Delete|DeleteINISec|DeleteINIStr|DeleteRegKey|DeleteRegValue|DetailPrint|DetailsButtonText|DirText|DirVar|DirVerify|EnableWindow|EnumRegKey|EnumRegValue|Exch|Exec|ExecShell|ExecShellWait|ExecWait|ExpandEnvStrings|File|FileBufSize|FileClose|FileErrorText|FileOpen|FileRead|FileReadByte|FileReadUTF16LE|FileReadWord|FileWriteUTF16LE|FileSeek|FileWrite|FileWriteByte|FileWriteWord|FindClose|FindFirst|FindNext|FindWindow|FlushINI|GetCurInstType|GetCurrentAddress|GetDlgItem|GetDLLVersion|GetDLLVersionLocal|GetErrorLevel|GetFileTime|GetFileTimeLocal|GetFullPathName|GetFunctionAddress|GetInstDirError|GetKnownFolderPath|GetLabelAddress|GetTempFileName|Goto|HideWindow|Icon|IfAbort|IfErrors|IfFileExists|IfRebootFlag|IfRtlLanguage|IfShellVarContextAll|IfSilent|InitPluginsDir|InstallButtonText|InstallColors|InstallDir|InstallDirRegKey|InstProgressFlags|InstType|InstTypeGetText|InstTypeSetText|Int64Cmp|Int64CmpU|Int64Fmt|IntCmp|IntCmpU|IntFmt|IntOp|IntPtrCmp|IntPtrCmpU|IntPtrOp|IsWindow|LangString|LicenseBkColor|LicenseData|LicenseForceSelection|LicenseLangString|LicenseText|LoadAndSetImage|LoadLanguageFile|LockWindow|LogSet|LogText|ManifestDPIAware|ManifestLongPathAware|ManifestMaxVersionTested|ManifestSupportedOS|MessageBox|MiscButtonText|Name|Nop|OutFile|Page|PageCallbacks|PEAddResource|PEDllCharacteristics|PERemoveResource|PESubsysVer|Pop|Push|Quit|ReadEnvStr|ReadINIStr|ReadRegDWORD|ReadRegStr|Reboot|RegDLL|Rename|RequestExecutionLevel|ReserveFile|Return|RMDir|SearchPath|SectionGetFlags|SectionGetInstTypes|SectionGetSize|SectionGetText|SectionIn|SectionSetFlags|SectionSetInstTypes|SectionSetSize|SectionSetText|SendMessage|SetAutoClose|SetBrandingImage|SetCompress|SetCompressor|SetCompressorDictSize|SetCtlColors|SetCurInstType|SetDatablockOptimize|SetDateSave|SetDetailsPrint|SetDetailsView|SetErrorLevel|SetErrors|SetFileAttributes|SetFont|SetOutPath|SetOverwrite|SetRebootFlag|SetRegView|SetShellVarContext|SetSilent|ShowInstDetails|ShowUninstDetails|ShowWindow|SilentInstall|SilentUnInstall|Sleep|SpaceTexts|StrCmp|StrCmpS|StrCpy|StrLen|SubCaption|Unicode|UninstallButtonText|UninstallCaption|UninstallIcon|UninstallSubCaption|UninstallText|UninstPage|UnRegDLL|Var|VIAddVersionKey|VIFileVersion|VIProductVersion|WindowIcon|WriteINIStr|WriteRegBin|WriteRegDWORD|WriteRegExpandStr|WriteRegMultiStr|WriteRegNone|WriteRegStr|WriteUninstaller|XPStyle)\b/, token: "keyword"},
     {regex: /^\s*(?:Function|PageEx|Section(?:Group)?)\b/, token: "keyword", indent: true},
     {regex: /^\s*(?:(Function|PageEx|Section(?:Group)?)End)\b/, token: "keyword", dedent: true},
 
diff --git a/front_end/third_party/codemirror/package/mode/pascal/pascal.js b/front_end/third_party/codemirror/package/mode/pascal/pascal.js
index dc3b1a3..c48698b 100644
--- a/front_end/third_party/codemirror/package/mode/pascal/pascal.js
+++ b/front_end/third_party/codemirror/package/mode/pascal/pascal.js
@@ -50,7 +50,11 @@
       state.tokenize = tokenComment;
       return tokenComment(stream, state);
     }
-    if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
+    if (ch == "{") {
+      state.tokenize = tokenCommentBraces;
+      return tokenCommentBraces(stream, state);
+    }
+    if (/[\[\]\(\),;\:\.]/.test(ch)) {
       return null;
     }
     if (/\d/.test(ch)) {
@@ -98,6 +102,17 @@
     return "comment";
   }
 
+  function tokenCommentBraces(stream, state) {
+    var ch;
+    while (ch = stream.next()) {
+      if (ch == "}") {
+        state.tokenize = null;
+        break;
+      }
+    }
+    return "comment";
+  }
+
   // Interface
 
   return {
diff --git a/front_end/third_party/codemirror/package/mode/sas/sas.js b/front_end/third_party/codemirror/package/mode/sas/sas.js
index c6f528e..49b96b6 100755
--- a/front_end/third_party/codemirror/package/mode/sas/sas.js
+++ b/front_end/third_party/codemirror/package/mode/sas/sas.js
@@ -88,7 +88,7 @@
     define('def', 'source2 nosource2 page pageno pagesize', ['ALL']);
 
     //proc and datastep
-    define('def', '_all_ _character_ _cmd_ _freq_ _i_ _infile_ _last_ _msg_ _null_ _numeric_ _temporary_ _type_ abort abs addr adjrsq airy alpha alter altlog altprint and arcos array arsin as atan attrc attrib attrn authserver autoexec awscontrol awsdef awsmenu awsmenumerge awstitle backward band base betainv between blocksize blshift bnot bor brshift bufno bufsize bxor by byerr byline byte calculated call cards cards4 catcache cbufno cdf ceil center cexist change chisq cinv class cleanup close cnonct cntllev coalesce codegen col collate collin column comamid comaux1 comaux2 comdef compbl compound compress config continue convert cos cosh cpuid create cross crosstab css curobs cv daccdb daccdbsl daccsl daccsyd dacctab dairy datalines datalines4 datejul datepart datetime day dbcslang dbcstype dclose ddm delete delimiter depdb depdbsl depsl depsyd deptab dequote descending descript design= device dflang dhms dif digamma dim dinfo display distinct dkricond dkrocond dlm dnum do dopen doptname doptnum dread drop dropnote dsname dsnferr echo else emaildlg emailid emailpw emailserver emailsys encrypt end endsas engine eof eov erf erfc error errorcheck errors exist exp fappend fclose fcol fdelete feedback fetch fetchobs fexist fget file fileclose fileexist filefmt filename fileref  fmterr fmtsearch fnonct fnote font fontalias  fopen foptname foptnum force formatted formchar formdelim formdlim forward fpoint fpos fput fread frewind frlen from fsep fuzz fwrite gaminv gamma getoption getvarc getvarn go goto group gwindow hbar hbound helpenv helploc hms honorappearance hosthelp hostprint hour hpct html hvar ibessel ibr id if index indexc indexw initcmd initstmt inner input inputc inputn inr insert int intck intnx into intrr invaliddata irr is jbessel join juldate keep kentb kurtosis label lag last lbound leave left length levels lgamma lib  library libref line linesize link list log log10 log2 logpdf logpmf logsdf lostcard lowcase lrecl ls macro macrogen maps mautosource max maxdec maxr mdy mean measures median memtype merge merror min minute missing missover mlogic mod mode model modify month mopen mort mprint mrecall msglevel msymtabmax mvarsize myy n nest netpv new news nmiss no nobatch nobs nocaps nocardimage nocenter nocharcode nocmdmac nocol nocum nodate nodbcs nodetails nodmr nodms nodmsbatch nodup nodupkey noduplicates noechoauto noequals noerrorabend noexitwindows nofullstimer noicon noimplmac noint nolist noloadlist nomiss nomlogic nomprint nomrecall nomsgcase nomstored nomultenvappl nonotes nonumber noobs noovp nopad nopercent noprint noprintinit normal norow norsasuser nosetinit  nosplash nosymbolgen note notes notitle notitles notsorted noverbose noxsync noxwait npv null number numkeys nummousekeys nway obs  on open     order ordinal otherwise out outer outp= output over ovp p(1 5 10 25 50 75 90 95 99) pad pad2  paired parm parmcards path pathdll pathname pdf peek peekc pfkey pmf point poisson poke position printer probbeta probbnml probchi probf probgam probhypr probit probnegb probnorm probsig probt procleave prt ps  pw pwreq qtr quote r ranbin rancau ranexp rangam range ranks rannor ranpoi rantbl rantri ranuni read recfm register regr remote remove rename repeat replace resolve retain return reuse reverse rewind right round rsquare rtf rtrace rtraceloc s s2 samploc sasautos sascontrol sasfrscr sasmsg sasmstore sasscript sasuser saving scan sdf second select selection separated seq serror set setcomm setot sign simple sin sinh siteinfo skewness skip sle sls sortedby sortpgm sortseq sortsize soundex  spedis splashlocation split spool sqrt start std stderr stdin stfips stimer stname stnamel stop stopover subgroup subpopn substr sum sumwgt symbol symbolgen symget symput sysget sysin sysleave sysmsg sysparm sysprint sysprintfont sysprod sysrc system t table tables tan tanh tapeclose tbufsize terminal test then timepart tinv  tnonct to today tol tooldef totper transformout translate trantab tranwrd trigamma trim trimn trunc truncover type unformatted uniform union until upcase update user usericon uss validate value var  weight when where while wincharset window work workinit workterm write wsum xsync xwait yearcutoff yes yyq  min max', ['inDataStep', 'inProc']);
+    define('def', '_all_ _character_ _cmd_ _freq_ _i_ _infile_ _last_ _msg_ _null_ _numeric_ _temporary_ _type_ abort abs addr adjrsq airy alpha alter altlog altprint and arcos array arsin as atan attrc attrib attrn authserver autoexec awscontrol awsdef awsmenu awsmenumerge awstitle backward band base betainv between blocksize blshift bnot bor brshift bufno bufsize bxor by byerr byline byte calculated call cards cards4 catcache cbufno cdf ceil center cexist change chisq cinv class cleanup close cnonct cntllev coalesce codegen col collate collin column comamid comaux1 comaux2 comdef compbl compound compress config continue convert cos cosh cpuid create cross crosstab css curobs cv daccdb daccdbsl daccsl daccsyd dacctab dairy datalines datalines4 datejul datepart datetime day dbcslang dbcstype dclose ddfm ddm delete delimiter depdb depdbsl depsl depsyd deptab dequote descending descript design= device dflang dhms dif digamma dim dinfo display distinct dkricond dkrocond dlm dnum do dopen doptname doptnum dread drop dropnote dsname dsnferr echo else emaildlg emailid emailpw emailserver emailsys encrypt end endsas engine eof eov erf erfc error errorcheck errors exist exp fappend fclose fcol fdelete feedback fetch fetchobs fexist fget file fileclose fileexist filefmt filename fileref  fmterr fmtsearch fnonct fnote font fontalias  fopen foptname foptnum force formatted formchar formdelim formdlim forward fpoint fpos fput fread frewind frlen from fsep fuzz fwrite gaminv gamma getoption getvarc getvarn go goto group gwindow hbar hbound helpenv helploc hms honorappearance hosthelp hostprint hour hpct html hvar ibessel ibr id if index indexc indexw initcmd initstmt inner input inputc inputn inr insert int intck intnx into intrr invaliddata irr is jbessel join juldate keep kentb kurtosis label lag last lbound leave left length levels lgamma lib  library libref line linesize link list log log10 log2 logpdf logpmf logsdf lostcard lowcase lrecl ls macro macrogen maps mautosource max maxdec maxr mdy mean measures median memtype merge merror min minute missing missover mlogic mod mode model modify month mopen mort mprint mrecall msglevel msymtabmax mvarsize myy n nest netpv new news nmiss no nobatch nobs nocaps nocardimage nocenter nocharcode nocmdmac nocol nocum nodate nodbcs nodetails nodmr nodms nodmsbatch nodup nodupkey noduplicates noechoauto noequals noerrorabend noexitwindows nofullstimer noicon noimplmac noint nolist noloadlist nomiss nomlogic nomprint nomrecall nomsgcase nomstored nomultenvappl nonotes nonumber noobs noovp nopad nopercent noprint noprintinit normal norow norsasuser nosetinit  nosplash nosymbolgen note notes notitle notitles notsorted noverbose noxsync noxwait npv null number numkeys nummousekeys nway obs  on open     order ordinal otherwise out outer outp= output over ovp p(1 5 10 25 50 75 90 95 99) pad pad2  paired parm parmcards path pathdll pathname pdf peek peekc pfkey pmf point poisson poke position printer probbeta probbnml probchi probf probgam probhypr probit probnegb probnorm probsig probt procleave prt ps  pw pwreq qtr quote r ranbin rancau random ranexp rangam range ranks rannor ranpoi rantbl rantri ranuni rcorr read recfm register regr remote remove rename repeat repeated replace resolve retain return reuse reverse rewind right round rsquare rtf rtrace rtraceloc s s2 samploc sasautos sascontrol sasfrscr sasmsg sasmstore sasscript sasuser saving scan sdf second select selection separated seq serror set setcomm setot sign simple sin sinh siteinfo skewness skip sle sls sortedby sortpgm sortseq sortsize soundex  spedis splashlocation split spool sqrt start std stderr stdin stfips stimer stname stnamel stop stopover sub subgroup subpopn substr sum sumwgt symbol symbolgen symget symput sysget sysin sysleave sysmsg sysparm sysprint sysprintfont sysprod sysrc system t table tables tan tanh tapeclose tbufsize terminal test then timepart tinv  tnonct to today tol tooldef totper transformout translate trantab tranwrd trigamma trim trimn trunc truncover type unformatted uniform union until upcase update user usericon uss validate value var  weight when where while wincharset window work workinit workterm write wsum xsync xwait yearcutoff yes yyq  min max', ['inDataStep', 'inProc']);
     define('operator', 'and not ', ['inDataStep', 'inProc']);
 
     // Main function
diff --git a/front_end/third_party/codemirror/package/mode/soy/soy.js b/front_end/third_party/codemirror/package/mode/soy/soy.js
index 1b19923..d31c947 100644
--- a/front_end/third_party/codemirror/package/mode/soy/soy.js
+++ b/front_end/third_party/codemirror/package/mode/soy/soy.js
@@ -34,9 +34,9 @@
     "switch": {},
     "case": { noEndTag: true, reduceIndent: true},
     "default": { noEndTag: true, reduceIndent: true},
-    "foreach": { variableScope: true, soyState: "var-def" },
+    "foreach": { variableScope: true, soyState: "for-loop" },
     "ifempty": { noEndTag: true, reduceIndent: true},
-    "for": { variableScope: true, soyState: "var-def" },
+    "for": { variableScope: true, soyState: "for-loop" },
     "call": { soyState: "templ-ref" },
     "param": { soyState: "param-ref"},
     "print": { noEndTag: true },
@@ -129,6 +129,7 @@
       var match;
       if (stream.match(/[[]/)) {
         state.soyState.push("list-literal");
+        state.context = new Context(state.context, "list-literal", state.variables);
         state.lookupVariables = false;
         return null;
       } else if (stream.match(/map\b/)) {
@@ -256,6 +257,11 @@
               // Otherwise
               return "variable";
             }
+            if (match = stream.match(/^\$([\w]+)/)) {
+              state.soyState.pop();
+              return ref(state.variables, match[1], !state.lookupVariables);
+            }
+
             stream.next();
             return null;
 
@@ -300,6 +306,9 @@
             } else if (peekChar == "[") {
               state.soyState.push('param-type-record');
               return null;
+            } else if (peekChar == "(") {
+              state.soyState.push('param-type-template');
+              return null;
             } else if (peekChar == "<") {
               state.soyState.push('param-type-parameter');
               return null;
@@ -334,6 +343,19 @@
             stream.next();
             return null;
 
+          case "param-type-template":
+            if (stream.match(/[>]/)) {
+              state.soyState.pop();
+              state.soyState.push('param-type');
+              return null;
+            }
+            if (stream.match(/^\w+/)) {
+              state.soyState.push('param-type');
+              return "def";
+            }
+            stream.next();
+            return null;
+
           case "var-def":
             if (match = stream.match(/^\$([\w]+)/)) {
               state.variables = prepend(state.variables, match[1]);
@@ -343,6 +365,18 @@
             stream.next();
             return null;
 
+          case "for-loop":
+            if (stream.match(/\bin\b/)) {
+              state.soyState.pop();
+              return "keyword";
+            }
+            if (stream.peek() == "$") {
+              state.soyState.push('var-def');
+              return null;
+            }
+            stream.next();
+            return null;
+
           case "record-literal":
             if (stream.match(/^[)]/)) {
               state.soyState.pop();
@@ -373,13 +407,12 @@
             if (stream.match(/\]/)) {
               state.soyState.pop();
               state.lookupVariables = true;
+              popcontext(state);
               return null;
             }
-            if (stream.match(/for\b/)) {
-              state.soyState.push("var-def")
-              return "keyword";
-            } else if (stream.match(/in\b/)) {
+            if (stream.match(/\bfor\b/)) {
               state.lookupVariables = true;
+              state.soyState.push('for-loop');
               return "keyword";
             }
             return expression(stream, state);
@@ -402,6 +435,26 @@
             }
             return expression(stream, state);
 
+          case "import":
+            if (stream.eat(";")) {
+              state.soyState.pop();
+              state.indent -= 2 * config.indentUnit;
+              return null;
+            }
+            if (stream.match(/\w+(?=\s+as)/)) {
+              return "variable";
+            }
+            if (match = stream.match(/\w+/)) {
+              return /(from|as)/.test(match[0]) ? "keyword" : "def";
+            }
+            if (match = stream.match(/^["']/)) {
+              state.soyState.push("string");
+              state.quoteKind = match[0];
+              return "string";
+            }
+            stream.next();
+            return null;
+
           case "tag":
             var endTag = state.tag[0] == "/";
             var tagName = endTag ? state.tag.substring(1) : state.tag;
@@ -499,6 +552,10 @@
           state.indent += 2 * config.indentUnit;
           state.soyState.push("tag");
           return "keyword";
+        } else if (!state.context && stream.match(/\bimport\b/)) {
+          state.soyState.push("import");
+          state.indent += 2 * config.indentUnit;
+          return "keyword";
         }
 
         return tokenUntil(stream, state, /\{|\s+\/\/|\/\*/);
diff --git a/front_end/third_party/codemirror/package/mode/sql/sql.js b/front_end/third_party/codemirror/package/mode/sql/sql.js
index e43495d..4127cd9 100644
--- a/front_end/third_party/codemirror/package/mode/sql/sql.js
+++ b/front_end/third_party/codemirror/package/mode/sql/sql.js
@@ -96,7 +96,7 @@
         return null
       // .table_name (ODBC)
       // // ref: http://dev.mysql.com/doc/refman/5.6/en/identifier-qualifiers.html
-      if (support.ODBCdotTable && stream.match(/^[\w\d_]+/))
+      if (support.ODBCdotTable && stream.match(/^[\w\d_$#]+/))
         return "variable-2";
     } else if (operatorChars.test(ch)) {
       // operators
diff --git a/front_end/third_party/codemirror/package/package.json b/front_end/third_party/codemirror/package/package.json
index 7956d37..faf0ca0 100644
--- a/front_end/third_party/codemirror/package/package.json
+++ b/front_end/third_party/codemirror/package/package.json
@@ -1,6 +1,6 @@
 {
   "name": "codemirror",
-  "version": "5.54.0",
+  "version": "5.57.0",
   "main": "lib/codemirror.js",
   "style": "lib/codemirror.css",
   "author": {
@@ -21,11 +21,11 @@
     "lint": "bin/lint"
   },
   "devDependencies": {
+    "@rollup/plugin-buble": "^0.21.3",
     "blint": "^1.1.0",
     "node-static": "0.7.11",
     "puppeteer": "^1.20.0",
-    "rollup": "^1.26.3",
-    "rollup-plugin-buble": "^0.19.8"
+    "rollup": "^1.26.3"
   },
   "bugs": "http://github.com/codemirror/CodeMirror/issues",
   "keywords": [
@@ -42,5 +42,6 @@
     "directories": {},
     "dependencies": {},
     "devDependencies": {}
-  }
+  },
+  "dependencies": {}
 }
diff --git a/front_end/third_party/codemirror/package/rollup.config.js b/front_end/third_party/codemirror/package/rollup.config.js
index fbb4357..f50f62f 100644
--- a/front_end/third_party/codemirror/package/rollup.config.js
+++ b/front_end/third_party/codemirror/package/rollup.config.js
@@ -1,9 +1,10 @@
-import buble from 'rollup-plugin-buble';
+import buble from '@rollup/plugin-buble';
 
-export default {
-  input: "src/codemirror.js",
-  output: {
-    banner: `// CodeMirror, copyright (c) by Marijn Haverbeke and others
+export default [
+  {
+    input: "src/codemirror.js",
+    output: {
+      banner: `// CodeMirror, copyright (c) by Marijn Haverbeke and others
 // Distributed under an MIT license: https://codemirror.net/LICENSE
 
 // This is CodeMirror (https://codemirror.net), a code editor
@@ -12,9 +13,30 @@
 // You can find some technical background for some of the code below
 // at http://marijnhaverbeke.nl/blog/#cm-internals .
 `,
-    format: "umd",
-    file: "lib/codemirror.js",
-    name: "CodeMirror"
+      format: "umd",
+      file: "lib/codemirror.js",
+      name: "CodeMirror"
+    },
+    plugins: [ buble({namedFunctionExpressions: false}) ]
   },
-  plugins: [ buble({namedFunctionExpressions: false}) ]
-};
+  {
+    input: ["src/addon/runmode/runmode-standalone.js"],
+    output: {
+      format: "iife",
+      file: "addon/runmode/runmode-standalone.js",
+      name: "CodeMirror",
+      freeze: false, // IE8 doesn't support Object.freeze.
+    },
+    plugins: [ buble({namedFunctionExpressions: false}) ]
+  },
+  {
+    input: ["src/addon/runmode/runmode.node.js"],
+    output: {
+      format: "cjs",
+      file: "addon/runmode/runmode.node.js",
+      name: "CodeMirror",
+      freeze: false, // IE8 doesn't support Object.freeze.
+    },
+    plugins: [ buble({namedFunctionExpressions: false}) ]
+  },
+];
diff --git a/front_end/third_party/codemirror/package/src/addon/runmode/codemirror-standalone.js b/front_end/third_party/codemirror/package/src/addon/runmode/codemirror-standalone.js
new file mode 100644
index 0000000..95ef264
--- /dev/null
+++ b/front_end/third_party/codemirror/package/src/addon/runmode/codemirror-standalone.js
@@ -0,0 +1,22 @@
+import * as modeMethods from "../../modes.js"
+import StringStream from "../../util/StringStream.js"
+
+// declare global: globalThis, CodeMirror
+
+// Create a minimal CodeMirror needed to use runMode, and assign to root.
+var root = typeof globalThis !== 'undefined' ? globalThis : window
+root.CodeMirror = {}
+
+// Copy StringStream and mode methods into CodeMirror object.
+CodeMirror.StringStream = StringStream
+for (var exported in modeMethods) CodeMirror[exported] = modeMethods[exported]
+
+// Minimal default mode.
+CodeMirror.defineMode("null", () => ({token: stream => stream.skipToEnd()}))
+CodeMirror.defineMIME("text/plain", "null")
+
+CodeMirror.registerHelper = CodeMirror.registerGlobalHelper = Math.min
+CodeMirror.splitLines = function(string) { return string.split(/\r?\n|\r/) }
+
+CodeMirror.defaults = { indentUnit: 2 }
+export default CodeMirror
diff --git a/front_end/third_party/codemirror/package/src/addon/runmode/codemirror.node.js b/front_end/third_party/codemirror/package/src/addon/runmode/codemirror.node.js
new file mode 100644
index 0000000..4e6ee49
--- /dev/null
+++ b/front_end/third_party/codemirror/package/src/addon/runmode/codemirror.node.js
@@ -0,0 +1,21 @@
+import * as modeMethods from "../../modes.js"
+import {countColumn} from "../../util/misc.js"
+import StringStream from "../../util/StringStream.js"
+
+// Copy StringStream and mode methods into exports (CodeMirror) object.
+exports.StringStream = StringStream
+exports.countColumn = countColumn
+for (var exported in modeMethods) exports[exported] = modeMethods[exported]
+
+// Shim library CodeMirror with the minimal CodeMirror defined above.
+require.cache[require.resolve("../../lib/codemirror")] = require.cache[require.resolve("./runmode.node")]
+require.cache[require.resolve("../../addon/runmode/runmode")] = require.cache[require.resolve("./runmode.node")]
+
+// Minimal default mode.
+exports.defineMode("null", () => ({token: stream => stream.skipToEnd()}))
+exports.defineMIME("text/plain", "null")
+
+exports.registerHelper = exports.registerGlobalHelper = Math.min
+exports.splitLines = function(string) { return string.split(/\r?\n|\r/) }
+
+exports.defaults = { indentUnit: 2 }
diff --git a/front_end/third_party/codemirror/package/src/addon/runmode/runmode-standalone.js b/front_end/third_party/codemirror/package/src/addon/runmode/runmode-standalone.js
new file mode 100644
index 0000000..0d7aa6b
--- /dev/null
+++ b/front_end/third_party/codemirror/package/src/addon/runmode/runmode-standalone.js
@@ -0,0 +1,2 @@
+import "./codemirror-standalone.js"
+import "../../../addon/runmode/runmode.js"
\ No newline at end of file
diff --git a/front_end/third_party/codemirror/package/src/addon/runmode/runmode.node.js b/front_end/third_party/codemirror/package/src/addon/runmode/runmode.node.js
new file mode 100644
index 0000000..4f2ed81
--- /dev/null
+++ b/front_end/third_party/codemirror/package/src/addon/runmode/runmode.node.js
@@ -0,0 +1,2 @@
+import "./codemirror.node.js"
+import "../../../addon/runmode/runmode.js"
\ No newline at end of file
diff --git a/front_end/third_party/codemirror/package/src/edit/main.js b/front_end/third_party/codemirror/package/src/edit/main.js
index e7fec69..e68fbe9 100644
--- a/front_end/third_party/codemirror/package/src/edit/main.js
+++ b/front_end/third_party/codemirror/package/src/edit/main.js
@@ -66,4 +66,4 @@
 
 addLegacyProps(CodeMirror)
 
-CodeMirror.version = "5.54.0"
+CodeMirror.version = "5.57.0"
diff --git a/front_end/third_party/codemirror/package/src/edit/options.js b/front_end/third_party/codemirror/package/src/edit/options.js
index 225f549..400e000 100644
--- a/front_end/third_party/codemirror/package/src/edit/options.js
+++ b/front_end/third_party/codemirror/package/src/edit/options.js
@@ -68,7 +68,7 @@
     for (let i = newBreaks.length - 1; i >= 0; i--)
       replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length))
   })
-  option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g, (cm, val, old) => {
+  option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200c\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g, (cm, val, old) => {
     cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g")
     if (old != Init) cm.refresh()
   })
diff --git a/front_end/third_party/codemirror/package/src/input/input.js b/front_end/third_party/codemirror/package/src/input/input.js
index 4431ebc..3c196f2 100644
--- a/front_end/third_party/codemirror/package/src/input/input.js
+++ b/front_end/third_party/codemirror/package/src/input/input.js
@@ -51,7 +51,7 @@
         from = Pos(from.line, from.ch - deleted)
       else if (cm.state.overwrite && !paste) // Handle overwrite
         to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length))
-      else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == inserted)
+      else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == textLines.join("\n"))
         from = to = Pos(from.line, 0)
     }
     let changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines,
@@ -132,4 +132,4 @@
   if (ios) te.style.border = "1px solid black"
   disableBrowserMagic(te)
   return div
-}
\ No newline at end of file
+}
diff --git a/front_end/third_party/codemirror/package/src/input/keymap.js b/front_end/third_party/codemirror/package/src/input/keymap.js
index 046b350..f29f2bb 100644
--- a/front_end/third_party/codemirror/package/src/input/keymap.js
+++ b/front_end/third_party/codemirror/package/src/input/keymap.js
@@ -127,7 +127,7 @@
   let base = name
   if (event.altKey && base != "Alt") name = "Alt-" + name
   if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") name = "Ctrl-" + name
-  if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") name = "Cmd-" + name
+  if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Mod") name = "Cmd-" + name
   if (!noShift && event.shiftKey && base != "Shift") name = "Shift-" + name
   return name
 }
diff --git a/front_end/third_party/codemirror/package/src/input/keynames.js b/front_end/third_party/codemirror/package/src/input/keynames.js
index d333903..eb09ca1 100644
--- a/front_end/third_party/codemirror/package/src/input/keynames.js
+++ b/front_end/third_party/codemirror/package/src/input/keynames.js
@@ -5,7 +5,7 @@
   46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod",
   106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 145: "ScrollLock",
   173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
-  221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
+  221: "]", 222: "'", 224: "Mod", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
   63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"
 }