Parcourir la source

Merge remote-tracking branch 'origin/master' into pr/xadegunt/108

Alex Dima il y a 4 ans
Parent
commit
bd35c01ba9

+ 147 - 126
package-lock.json

@@ -5,30 +5,30 @@
   "requires": true,
   "dependencies": {
     "@types/node": {
-      "version": "13.9.1",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-13.9.1.tgz",
-      "integrity": "sha512-E6M6N0blf/jiZx8Q3nb0vNaswQeEyn0XlupO+xN6DtJ6r6IT4nXrTry7zhIfYvFCl3/8Cu6WIysmUBKiqV0bqQ==",
+      "version": "14.6.0",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.0.tgz",
+      "integrity": "sha512-mikldZQitV94akrc4sCcSjtJfsTKt4p+e/s0AGscVA6XArQ9kFclP+ZiYUMnq987rc6QlYxXv/EivqlfSLxpKA==",
       "dev": true
     },
     "@types/tape": {
-      "version": "4.2.34",
-      "resolved": "https://registry.npmjs.org/@types/tape/-/tape-4.2.34.tgz",
-      "integrity": "sha512-d3mILzYSlsPEALCiDYkRnkiYN4cl62dkaCg00Uql/FShIvdMOBFGtjP0N/cm0aCXwaAPVBS5weD4ciHAD8RtsA==",
+      "version": "4.13.0",
+      "resolved": "https://registry.npmjs.org/@types/tape/-/tape-4.13.0.tgz",
+      "integrity": "sha512-0V8cKowBdsiA9nbxAg7531sF2cdPZNiUogcfIUeUGm+bejUBE/bvibz3rH36iQP9bQjO/sOzFwU97/uC5mCyoA==",
       "dev": true,
       "requires": {
         "@types/node": "*"
       }
     },
     "abab": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz",
-      "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==",
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.4.tgz",
+      "integrity": "sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==",
       "dev": true
     },
     "acorn": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz",
-      "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==",
+      "version": "7.4.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz",
+      "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==",
       "dev": true
     },
     "acorn-globals": {
@@ -42,15 +42,15 @@
       }
     },
     "acorn-walk": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz",
-      "integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==",
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
+      "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
       "dev": true
     },
     "ajv": {
-      "version": "6.12.0",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz",
-      "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==",
+      "version": "6.12.4",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz",
+      "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==",
       "dev": true,
       "requires": {
         "fast-deep-equal": "^3.1.1",
@@ -87,9 +87,9 @@
       "dev": true
     },
     "aws4": {
-      "version": "1.9.1",
-      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz",
-      "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==",
+      "version": "1.10.1",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz",
+      "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==",
       "dev": true
     },
     "balanced-match": {
@@ -169,9 +169,9 @@
       "dev": true
     },
     "cssstyle": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.2.0.tgz",
-      "integrity": "sha512-sEb3XFPx3jNnCAMtqrXPDeSgQr+jojtCeNf8cvMNMh1cG970+lljssvQDzPq6lmmJu2Vhqood/gtEomBiHOGnA==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz",
+      "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==",
       "dev": true,
       "requires": {
         "cssom": "~0.3.6"
@@ -259,6 +259,14 @@
       "dev": true,
       "requires": {
         "webidl-conversions": "^5.0.0"
+      },
+      "dependencies": {
+        "webidl-conversions": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz",
+          "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==",
+          "dev": true
+        }
       }
     },
     "dotignore": {
@@ -281,22 +289,33 @@
       }
     },
     "es-abstract": {
-      "version": "1.17.4",
-      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz",
-      "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==",
+      "version": "1.17.6",
+      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
+      "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
       "dev": true,
       "requires": {
         "es-to-primitive": "^1.2.1",
         "function-bind": "^1.1.1",
         "has": "^1.0.3",
         "has-symbols": "^1.0.1",
-        "is-callable": "^1.1.5",
-        "is-regex": "^1.0.5",
+        "is-callable": "^1.2.0",
+        "is-regex": "^1.1.0",
         "object-inspect": "^1.7.0",
         "object-keys": "^1.1.1",
         "object.assign": "^4.1.0",
-        "string.prototype.trimleft": "^2.1.1",
-        "string.prototype.trimright": "^2.1.1"
+        "string.prototype.trimend": "^1.0.1",
+        "string.prototype.trimstart": "^1.0.1"
+      },
+      "dependencies": {
+        "is-regex": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
+          "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
+          "dev": true,
+          "requires": {
+            "has-symbols": "^1.0.1"
+          }
+        }
       }
     },
     "es-to-primitive": {
@@ -311,9 +330,9 @@
       }
     },
     "escodegen": {
-      "version": "1.14.1",
-      "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.1.tgz",
-      "integrity": "sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==",
+      "version": "1.14.3",
+      "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz",
+      "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==",
       "dev": true,
       "requires": {
         "esprima": "^4.0.1",
@@ -354,9 +373,9 @@
       "dev": true
     },
     "fast-deep-equal": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
-      "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
       "dev": true
     },
     "fast-json-stable-stringify": {
@@ -439,12 +458,12 @@
       "dev": true
     },
     "har-validator": {
-      "version": "5.1.3",
-      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
-      "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
+      "version": "5.1.5",
+      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
+      "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
       "dev": true,
       "requires": {
-        "ajv": "^6.5.5",
+        "ajv": "^6.12.3",
         "har-schema": "^2.0.0"
       }
     },
@@ -521,9 +540,9 @@
       "dev": true
     },
     "is-callable": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
-      "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
+      "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==",
       "dev": true
     },
     "is-date-object": {
@@ -575,9 +594,9 @@
       "dev": true
     },
     "jsdom": {
-      "version": "16.2.1",
-      "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.2.1.tgz",
-      "integrity": "sha512-3p0gHs5EfT7PxW9v8Phz3mrq//4Dy8MQenU/PoKxhdT+c45S7NjIjKbGT3Ph0nkICweE1r36+yaknXA5WfVNAg==",
+      "version": "16.4.0",
+      "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.4.0.tgz",
+      "integrity": "sha512-lYMm3wYdgPhrl7pDcRmvzPhhrGVBeVhPIqeHjzeiHN3DFmD1RBpbExbi8vU7BJdH8VAZYovR8DMt0PNNDM7k8w==",
       "dev": true,
       "requires": {
         "abab": "^2.0.3",
@@ -600,11 +619,11 @@
         "tough-cookie": "^3.0.1",
         "w3c-hr-time": "^1.0.2",
         "w3c-xmlserializer": "^2.0.0",
-        "webidl-conversions": "^5.0.0",
+        "webidl-conversions": "^6.1.0",
         "whatwg-encoding": "^1.0.5",
         "whatwg-mimetype": "^2.3.0",
         "whatwg-url": "^8.0.0",
-        "ws": "^7.2.1",
+        "ws": "^7.2.3",
         "xml-name-validator": "^3.0.0"
       }
     },
@@ -649,9 +668,9 @@
       }
     },
     "lodash": {
-      "version": "4.17.15",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+      "version": "4.17.20",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
+      "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
       "dev": true
     },
     "lodash.sortby": {
@@ -661,18 +680,18 @@
       "dev": true
     },
     "mime-db": {
-      "version": "1.43.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
-      "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==",
+      "version": "1.44.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
+      "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==",
       "dev": true
     },
     "mime-types": {
-      "version": "2.1.26",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
-      "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
+      "version": "2.1.27",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
+      "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
       "dev": true,
       "requires": {
-        "mime-db": "1.43.0"
+        "mime-db": "1.44.0"
       }
     },
     "minimatch": {
@@ -684,6 +703,12 @@
         "brace-expansion": "^1.1.7"
       }
     },
+    "minimist": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+      "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
+      "dev": true
+    },
     "monaco-editor-core": {
       "version": "0.20.0",
       "resolved": "https://registry.npmjs.org/monaco-editor-core/-/monaco-editor-core-0.20.0.tgz",
@@ -691,9 +716,9 @@
       "dev": true
     },
     "monaco-plugin-helpers": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/monaco-plugin-helpers/-/monaco-plugin-helpers-1.0.2.tgz",
-      "integrity": "sha512-7kUx8dtd5qVNVgUARBRhnM8oftPglYwlINfigC4yGUiuzqtIN22u1tly8umiOCIPR0eFiBLjt6aN23oZh2QJgg==",
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/monaco-plugin-helpers/-/monaco-plugin-helpers-1.0.3.tgz",
+      "integrity": "sha512-6AYI3ONAy8ki74qG2JqtFrLdiJHQlgeO5l4Rwr0OMyIpGXhc94y5rZuFxOtgGkxgSrZfHSwOt/MulUNZ/mOQOw==",
       "dev": true,
       "requires": {
         "typescript": "^2.7.2"
@@ -726,10 +751,14 @@
       "dev": true
     },
     "object-is": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz",
-      "integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==",
-      "dev": true
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz",
+      "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==",
+      "dev": true,
+      "requires": {
+        "define-properties": "^1.1.3",
+        "es-abstract": "^1.17.5"
+      }
     },
     "object-keys": {
       "version": "1.1.1",
@@ -803,9 +832,9 @@
       "dev": true
     },
     "psl": {
-      "version": "1.7.0",
-      "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz",
-      "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==",
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
+      "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
       "dev": true
     },
     "punycode": {
@@ -871,21 +900,21 @@
       }
     },
     "request-promise-core": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz",
-      "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==",
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
+      "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
       "dev": true,
       "requires": {
-        "lodash": "^4.17.15"
+        "lodash": "^4.17.19"
       }
     },
     "request-promise-native": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz",
-      "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==",
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz",
+      "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==",
       "dev": true,
       "requires": {
-        "request-promise-core": "1.1.3",
+        "request-promise-core": "1.1.4",
         "stealthy-require": "^1.1.1",
         "tough-cookie": "^2.3.3"
       },
@@ -909,9 +938,9 @@
       "dev": true
     },
     "resolve": {
-      "version": "1.15.1",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz",
-      "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==",
+      "version": "1.17.0",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
+      "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
       "dev": true,
       "requires": {
         "path-parse": "^1.0.6"
@@ -927,9 +956,9 @@
       }
     },
     "safe-buffer": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
-      "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==",
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
       "dev": true
     },
     "safer-buffer": {
@@ -939,9 +968,9 @@
       "dev": true
     },
     "saxes": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.0.tgz",
-      "integrity": "sha512-LXTZygxhf8lfwKaTP/8N9CsVdjTlea3teze4lL6u37ivbgGbV0GGMuNtS/I9rnD/HC2/txUM7Df4S2LVl1qhiA==",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz",
+      "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==",
       "dev": true,
       "requires": {
         "xmlchars": "^2.2.0"
@@ -954,9 +983,9 @@
       "dev": true
     },
     "source-map-support": {
-      "version": "0.5.16",
-      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz",
-      "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==",
+      "version": "0.5.19",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
+      "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
       "dev": true,
       "requires": {
         "buffer-from": "^1.0.0",
@@ -997,24 +1026,24 @@
         "function-bind": "^1.1.1"
       }
     },
-    "string.prototype.trimleft": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz",
-      "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==",
+    "string.prototype.trimend": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
+      "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
       "dev": true,
       "requires": {
         "define-properties": "^1.1.3",
-        "function-bind": "^1.1.1"
+        "es-abstract": "^1.17.5"
       }
     },
-    "string.prototype.trimright": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz",
-      "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==",
+    "string.prototype.trimstart": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
+      "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
       "dev": true,
       "requires": {
         "define-properties": "^1.1.3",
-        "function-bind": "^1.1.1"
+        "es-abstract": "^1.17.5"
       }
     },
     "symbol-tree": {
@@ -1024,9 +1053,9 @@
       "dev": true
     },
     "tape": {
-      "version": "4.13.2",
-      "resolved": "https://registry.npmjs.org/tape/-/tape-4.13.2.tgz",
-      "integrity": "sha512-waWwC/OqYVE9TS6r1IynlP2sEdk4Lfo6jazlgkuNkPTHIbuG2BTABIaKdlQWwPeB6Oo4ksZ1j33Yt0NTOAlYMQ==",
+      "version": "4.13.3",
+      "resolved": "https://registry.npmjs.org/tape/-/tape-4.13.3.tgz",
+      "integrity": "sha512-0/Y20PwRIUkQcTCSi4AASs+OANZZwqPKaipGCEwp10dQMipVvSZwUUCi01Y/OklIGyHKFhIcjock+DKnBfLAFw==",
       "dev": true,
       "requires": {
         "deep-equal": "~1.1.1",
@@ -1038,26 +1067,18 @@
         "has": "~1.0.3",
         "inherits": "~2.0.4",
         "is-regex": "~1.0.5",
-        "minimist": "~1.2.0",
+        "minimist": "~1.2.5",
         "object-inspect": "~1.7.0",
-        "resolve": "~1.15.1",
+        "resolve": "~1.17.0",
         "resumer": "~0.0.0",
         "string.prototype.trim": "~1.2.1",
         "through": "~2.3.8"
-      },
-      "dependencies": {
-        "minimist": {
-          "version": "1.2.5",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
-          "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
-          "dev": true
-        }
       }
     },
     "terser": {
-      "version": "4.6.6",
-      "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.6.tgz",
-      "integrity": "sha512-4lYPyeNmstjIIESr/ysHg2vUPRGf2tzF9z2yYwnowXVuVzLEamPN1Gfrz7f8I9uEPuHcbFlW4PLIAsJoxXyJ1g==",
+      "version": "4.8.0",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz",
+      "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==",
       "dev": true,
       "requires": {
         "commander": "^2.20.0",
@@ -1166,9 +1187,9 @@
       }
     },
     "webidl-conversions": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz",
-      "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==",
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz",
+      "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==",
       "dev": true
     },
     "whatwg-encoding": {
@@ -1187,14 +1208,14 @@
       "dev": true
     },
     "whatwg-url": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.0.0.tgz",
-      "integrity": "sha512-41ou2Dugpij8/LPO5Pq64K5q++MnRCBpEHvQr26/mArEKTkCV5aoXIqyhuYtE0pkqScXwhf2JP57rkRTYM29lQ==",
+      "version": "8.2.1",
+      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.2.1.tgz",
+      "integrity": "sha512-ZmVCr6nfBeaMxEHALLEGy0LszYjpJqf6PVNQUQ1qd9Et+q7Jpygd4rGGDXgHjD8e99yLFseD69msHDM4YwPZ4A==",
       "dev": true,
       "requires": {
         "lodash.sortby": "^4.7.0",
-        "tr46": "^2.0.0",
-        "webidl-conversions": "^5.0.0"
+        "tr46": "^2.0.2",
+        "webidl-conversions": "^6.1.0"
       }
     },
     "word-wrap": {
@@ -1210,9 +1231,9 @@
       "dev": true
     },
     "ws": {
-      "version": "7.2.3",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz",
-      "integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==",
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz",
+      "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==",
       "dev": true
     },
     "xml-name-validator": {

+ 1 - 1
package.json

@@ -21,7 +21,7 @@
   "devDependencies": {
     "@types/tape": "^4.2.34",
     "glob": "^7.1.6",
-    "jsdom": "^16.2.1",
+    "jsdom": "^16.4.0",
     "monaco-editor-core": "0.20.0",
     "monaco-plugin-helpers": "^1.0.2",
     "requirejs": "^2.3.6",

+ 31 - 1
src/handlebars/handlebars.test.ts

@@ -281,5 +281,35 @@ testTokenization(['handlebars', 'css'], [
 			{ startIndex: 30, type: 'delimiter.handlebars' },
 			{ startIndex: 32, type: '' }
 		]
-	}]
+	}],
+
+	// Block comment
+	[{
+		line: '{{!-- block comment --}}',
+		tokens: [
+			{ startIndex: 0, type: 'comment.block.start.handlebars' },
+			{ startIndex: 5, type: 'comment.content.handlebars' },
+			{ startIndex: 20, type: 'comment.block.end.handlebars' }
+		]
+	}],
+
+	// Block comment with mustache
+	[{
+		line: '{{!-- block comment }} with mustache --}}',
+		tokens: [
+			{ startIndex: 0, type: 'comment.block.start.handlebars' },
+			{ startIndex: 5, type: 'comment.content.handlebars' },
+			{ startIndex: 37, type: 'comment.block.end.handlebars' }
+		]
+	}],
+
+	// Handlebars comment
+	[{
+		line: '{{! comment }}',
+		tokens: [
+			{ startIndex: 0, type: 'comment.start.handlebars' },
+			{ startIndex: 3, type: 'comment.content.handlebars' },
+			{ startIndex: 12, type: 'comment.end.handlebars' }
+		]
+	}],
 ]);

+ 13 - 1
src/handlebars/handlebars.ts

@@ -63,9 +63,11 @@ export const language = <ILanguage>{
 	// The main tokenizer for our languages
 	tokenizer: {
 		root: [
+			[/\{\{!--/, 'comment.block.start.handlebars', '@commentBlock'],
+			[/\{\{!/, 'comment.start.handlebars', '@comment'],
 			[/\{\{/, { token: '@rematch', switchTo: '@handlebarsInSimpleState.root' }],
 			[/<!DOCTYPE/, 'metatag.html', '@doctype'],
-			[/<!--/, 'comment.html', '@comment'],
+			[/<!--/, 'comment.html', '@commentHtml'],
 			[/(<)(\w+)(\/>)/, ['delimiter.html', 'tag.html', 'delimiter.html']],
 			[/(<)(script)/, ['delimiter.html', { token: 'tag.html', next: '@script' }]],
 			[/(<)(style)/, ['delimiter.html', { token: 'tag.html', next: '@style' }]],
@@ -83,6 +85,16 @@ export const language = <ILanguage>{
 		],
 
 		comment: [
+			[/\}\}/, 'comment.end.handlebars', '@pop'],
+			[/./, 'comment.content.handlebars']
+		],
+
+		commentBlock: [
+			[/--\}\}/, 'comment.block.end.handlebars', '@pop'],
+			[/./, 'comment.content.handlebars']
+		],
+
+		commentHtml: [
 			[/\{\{/, { token: '@rematch', switchTo: '@handlebarsInSimpleState.comment' }],
 			[/-->/, 'comment.html', '@pop'],
 			[/[^-]+/, 'comment.content.html'],

+ 1 - 1
src/javascript/javascript.contribution.ts

@@ -8,7 +8,7 @@ import { registerLanguage } from '../_.contribution';
 
 registerLanguage({
 	id: 'javascript',
-	extensions: ['.js', '.es6', '.jsx'],
+	extensions: ['.js', '.es6', '.jsx', '.mjs'],
 	firstLine: '^#!.*\\bnode',
 	filenames: ['jakefile'],
 	aliases: ['JavaScript', 'javascript', 'js'],

+ 1 - 0
src/monaco.contribution.ts

@@ -53,6 +53,7 @@ import './restructuredtext/restructuredtext.contribution';
 import './ruby/ruby.contribution';
 import './rust/rust.contribution';
 import './sb/sb.contribution';
+import './scala/scala.contribution';
 import './scheme/scheme.contribution';
 import './scss/scss.contribution';
 import './shell/shell.contribution';

+ 13 - 7
src/python/python.ts

@@ -55,9 +55,18 @@ export const language = <ILanguage>{
 	tokenPostfix: '.python',
 
 	keywords: [
+		// This section is the result of running
+		// `for k in keyword.kwlist: print('  "' + k + '",')` in a Python REPL,
+		// though note that the output from Python 3 is not a strict superset of the
+		// output from Python 2.
+		'False', // promoted to keyword.kwlist in Python 3
+		'None', // promoted to keyword.kwlist in Python 3
+		'True', // promoted to keyword.kwlist in Python 3
 		'and',
 		'as',
 		'assert',
+		'async', // new in Python 3
+		'await', // new in Python 3
 		'break',
 		'class',
 		'continue',
@@ -66,7 +75,7 @@ export const language = <ILanguage>{
 		'elif',
 		'else',
 		'except',
-		'exec',
+		'exec', // Python 2, but not 3.
 		'finally',
 		'for',
 		'from',
@@ -76,14 +85,13 @@ export const language = <ILanguage>{
 		'in',
 		'is',
 		'lambda',
-		'None',
+		'nonlocal', // new in Python 3
 		'not',
 		'or',
 		'pass',
-		'print',
+		'print', // Python 2, but not 3.
 		'raise',
 		'return',
-		'self',
 		'try',
 		'while',
 		'with',
@@ -156,6 +164,7 @@ export const language = <ILanguage>{
 		'repr',
 		'reversed',
 		'round',
+		'self',
 		'set',
 		'setattr',
 		'slice',
@@ -172,9 +181,6 @@ export const language = <ILanguage>{
 		'xrange',
 		'zip',
 
-		'True',
-		'False',
-
 		'__dict__',
 		'__methods__',
 		'__members__',

+ 15 - 0
src/scala/scala.contribution.ts

@@ -0,0 +1,15 @@
+/*---------------------------------------------------------------------------------------------
+ *  Copyright (c) Microsoft Corporation. All rights reserved.
+ *  Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+'use strict';
+
+import { registerLanguage } from '../_.contribution';
+
+registerLanguage({
+	id: 'scala',
+	extensions: ['.scala', '.sc', '.sbt'],
+	aliases: ['Scala', 'scala', 'SBT', 'Sbt', 'sbt', 'Dotty', 'dotty'],
+	mimetypes: ['text/x-scala-source', 'text/x-scala', 'text/x-sbt', 'text/x-dotty'],
+	loader: () => import('./scala')
+});

+ 674 - 0
src/scala/scala.test.ts

@@ -0,0 +1,674 @@
+/*---------------------------------------------------------------------------------------------
+ *  Copyright (c) Microsoft Corporation. All rights reserved.
+ *  Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+'use strict';
+
+import { testTokenization } from '../test/testRunner';
+
+testTokenization('scala', [
+
+	[{
+		line: 'var a = 1',
+		tokens: [
+			{startIndex: 0, type: 'keyword.scala'},
+			{startIndex: 3, type: 'white.scala'},
+			{startIndex: 4, type: 'variable.scala'},
+			{startIndex: 5, type: 'white.scala'},
+			{startIndex: 6, type: 'operator.scala'},
+			{startIndex: 7, type: 'white.scala'},
+			{startIndex: 8, type: 'number.scala'}
+		]
+	}],
+
+	// Comments - single line
+	[{
+		line: '//',
+		tokens: [
+			{ startIndex: 0, type: 'comment.scala' }
+		]
+	}],
+
+	[{
+		line: '    // a comment',
+		tokens: [
+			{ startIndex: 0, type: 'white.scala' },
+			{ startIndex: 4, type: 'comment.scala' }
+		]
+	}],
+
+	// Broken nested tokens due to invalid comment tokenization
+	[{
+		line: '/* //*/ a',
+		tokens: [
+			{ startIndex: 0, type: 'comment.scala' }
+		]
+	}],
+
+	[{
+		line: '// a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.scala' }
+		]
+	}],
+
+	[{
+		line: '//sticky comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.scala' }
+		]
+	}],
+
+	[{
+		line: '/almost a comment',
+		tokens: [
+			{ startIndex: 0, type: 'operator.scala' },
+			{ startIndex: 1, type: 'identifier.scala' },
+			{ startIndex: 7, type: 'white.scala' },
+			{ startIndex: 8, type: 'identifier.scala' },
+			{ startIndex: 9, type: 'white.scala' },
+			{ startIndex: 10, type: 'identifier.scala' }
+		]
+	}],
+
+	[{
+		line: '1 / 2; /* comment',
+		tokens: [
+			{ startIndex: 0, type: 'number.scala' },
+			{ startIndex: 1, type: 'white.scala' },
+			{ startIndex: 2, type: 'operator.scala' },
+			{ startIndex: 3, type: 'white.scala' },
+			{ startIndex: 4, type: 'number.scala' },
+			{ startIndex: 5, type: 'delimiter.scala' },
+			{ startIndex: 6, type: 'white.scala' },
+			{ startIndex: 7, type: 'comment.scala' }
+		]
+	}],
+
+	[{
+		line: 'val x: Int = 1; // my comment // is a nice one',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.scala' },
+			{ startIndex: 3, type: 'white.scala' },
+			{ startIndex: 4, type: 'variable.scala' },
+			{ startIndex: 5, type: 'operator.scala' },
+			{ startIndex: 6, type: 'white.scala' },
+			{ startIndex: 7, type: 'type.scala' },
+			{ startIndex: 10, type: 'white.scala' },
+			{ startIndex: 11, type: 'operator.scala' },
+			{ startIndex: 12, type: 'white.scala' },
+			{ startIndex: 13, type: 'number.scala' },
+			{ startIndex: 14, type: 'delimiter.scala' },
+			{ startIndex: 15, type: 'white.scala' },
+			{ startIndex: 16, type: 'comment.scala' }
+		]
+	}],
+
+	// Comments - range comment, single line
+	[{
+		line: '/* a simple comment */',
+		tokens: [
+			{ startIndex: 0, type: 'comment.scala' }
+		]
+	}],
+
+	[{
+		line: 'val x: Int = /* a simple comment */ 1;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.scala' },
+			{ startIndex: 3, type: 'white.scala' },
+			{ startIndex: 4, type: 'variable.scala' },
+			{ startIndex: 5, type: 'operator.scala' },
+			{ startIndex: 6, type: 'white.scala' },
+			{ startIndex: 7, type: 'type.scala' },
+			{ startIndex: 10, type: 'white.scala' },
+			{ startIndex: 11, type: 'operator.scala' },
+			{ startIndex: 12, type: 'white.scala' },
+			{ startIndex: 13, type: 'comment.scala' },
+			{ startIndex: 35, type: 'white.scala' },
+			{ startIndex: 36, type: 'number.scala' },
+			{ startIndex: 37, type: 'delimiter.scala' }
+		]
+	}],
+
+	[{
+		line: 'val x: Int = /* a simple comment */ 1; */',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.scala' },
+			{ startIndex: 3, type: 'white.scala' },
+			{ startIndex: 4, type: 'variable.scala' },
+			{ startIndex: 5, type: 'operator.scala' },
+			{ startIndex: 6, type: 'white.scala' },
+			{ startIndex: 7, type: 'type.scala' },
+			{ startIndex: 10, type: 'white.scala' },
+			{ startIndex: 11, type: 'operator.scala' },
+			{ startIndex: 12, type: 'white.scala' },
+			{ startIndex: 13, type: 'comment.scala' },
+			{ startIndex: 35, type: 'white.scala' },
+			{ startIndex: 36, type: 'number.scala' },
+			{ startIndex: 37, type: 'delimiter.scala' },
+			{ startIndex: 38, type: 'white.scala' },
+			{ startIndex: 39, type: 'operator.scala' },
+		]
+	}],
+
+	[{
+		line: 'x = /**/;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.scala' },
+			{ startIndex: 1, type: 'white.scala' },
+			{ startIndex: 2, type: 'operator.scala' },
+			{ startIndex: 3, type: 'white.scala' },
+			{ startIndex: 4, type: 'comment.scala' },
+			{ startIndex: 8, type: 'delimiter.scala' }
+		]
+	}],
+
+	[{
+		line: 'x = /*/;',
+		tokens: [
+			{ startIndex: 0, type: 'identifier.scala' },
+			{ startIndex: 1, type: 'white.scala' },
+			{ startIndex: 2, type: 'operator.scala' },
+			{ startIndex: 3, type: 'white.scala' },
+			{ startIndex: 4, type: 'comment.scala' }
+		]
+	}],
+
+	// Comments - range comment, multiple lines
+	[{
+		line: '/* start of multiline comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.scala' }
+		]
+	}, {
+		line: 'a comment between without a star',
+		tokens: [
+			{ startIndex: 0, type: 'comment.scala' }
+		]
+	}, {
+		line: 'end of multiline comment*/',
+		tokens: [
+			{ startIndex: 0, type: 'comment.scala' }
+		]
+	}],
+
+	[{
+		line: 'val x: Int = /* start a comment',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.scala' },
+			{ startIndex: 3, type: 'white.scala' },
+			{ startIndex: 4, type: 'variable.scala' },
+			{ startIndex: 5, type: 'operator.scala' },
+			{ startIndex: 6, type: 'white.scala' },
+			{ startIndex: 7, type: 'type.scala' },
+			{ startIndex: 10, type: 'white.scala' },
+			{ startIndex: 11, type: 'operator.scala' },
+			{ startIndex: 12, type: 'white.scala' },
+			{ startIndex: 13, type: 'comment.scala' },
+		]
+	}, {
+		line: ' a ',
+		tokens: [
+			{ startIndex: 0, type: 'comment.scala' },
+		]
+	}, {
+		line: 'and end it */ 2;',
+		tokens: [
+			{ startIndex: 0, type: 'comment.scala' },
+			{ startIndex: 13, type: 'white.scala' },
+			{ startIndex: 14, type: 'number.scala' },
+			{ startIndex: 15, type: 'delimiter.scala' }
+		]
+	}],
+
+	// Scala Doc, multiple lines
+	[{
+		line: '/** start of Scala Doc',
+		tokens: [
+			{ startIndex: 0, type: 'comment.scala' }
+		]
+	}, {
+		line: 'a comment between without a star',
+		tokens: [
+			{ startIndex: 0, type: 'comment.scala' }
+		]
+	}, {
+		line: 'end of multiline comment*/',
+		tokens: [
+			{ startIndex: 0, type: 'comment.scala' }
+		]
+	}],
+
+	// Keywords
+	[{
+		line: 'package test; object Program { def main(args: Array[String]): Unit = {} }',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.scala' },
+			{ startIndex: 7, type: 'white.scala' },
+			{ startIndex: 8, type: 'identifier.scala' },
+			{ startIndex: 12, type: 'delimiter.scala' },
+			{ startIndex: 13, type: 'white.scala' },
+			{ startIndex: 14, type: 'keyword.scala' },
+			{ startIndex: 20, type: 'white.scala' },
+			{ startIndex: 21, type: 'type.scala' },
+			{ startIndex: 28, type: 'white.scala' },
+			{ startIndex: 29, type: 'delimiter.curly.scala' },
+			{ startIndex: 30, type: 'white.scala' },
+			{ startIndex: 31, type: 'keyword.scala' },
+			{ startIndex: 34, type: 'white.scala' },
+			{ startIndex: 35, type: 'identifier.scala' },
+			{ startIndex: 39, type: 'delimiter.parenthesis.scala' },
+			{ startIndex: 40, type: 'variable.scala' },
+			{ startIndex: 44, type: 'operator.scala' },
+			{ startIndex: 45, type: 'white.scala' },
+			{ startIndex: 46, type: 'type.scala' },
+			{ startIndex: 51, type: 'operator.square.scala' },
+			{ startIndex: 52, type: 'type.scala' },
+			{ startIndex: 58, type: 'operator.square.scala' },
+			{ startIndex: 59, type: 'delimiter.parenthesis.scala' },
+			{ startIndex: 60, type: 'operator.scala' },
+			{ startIndex: 61, type: 'white.scala' },
+			{ startIndex: 62, type: 'type.scala' },
+			{ startIndex: 66, type: 'white.scala' },
+			{ startIndex: 67, type: 'operator.scala' },
+			{ startIndex: 68, type: 'white.scala' },
+			{ startIndex: 69, type: 'delimiter.curly.scala' },
+			{ startIndex: 71, type: 'white.scala' },
+			{ startIndex: 72, type: 'delimiter.curly.scala' }
+		]
+	}],
+
+	// Numbers
+	[{
+		line: '0',
+		tokens: [
+			{ startIndex: 0, type: 'number.scala' }
+		]
+	}],
+
+	[{
+		line: '0.10',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '0x',
+		tokens: [
+			{ startIndex: 0, type: 'number.scala' },
+			{ startIndex: 1, type: 'identifier.scala' }
+		]
+	}],
+
+	[{
+		line: '0x123',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.scala' }
+		]
+	}],
+
+	[{
+		line: '0x5_2',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.scala' }
+		]
+	}],
+
+	[{
+		line: '10e3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '10f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '23.5',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '23.5e3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '23.5e-3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '23.5E3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '23.5E-3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '23.5F',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '23.5f',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '23.5D',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '23.5d',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '1.72E3D',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '1.72E3d',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '1.72E-3d',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '1.72e3D',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '1.72e3d',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '1.72e-3d',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '23L',
+		tokens: [
+			{ startIndex: 0, type: 'number.scala' }
+		]
+	}],
+
+	[{
+		line: '23l',
+		tokens: [
+			{ startIndex: 0, type: 'number.scala' }
+		]
+	}],
+
+	[{
+		line: '5_2',
+		tokens: [
+			{ startIndex: 0, type: 'number.scala' }
+		]
+	}],
+
+	[{
+		line: '5_______2',
+		tokens: [
+			{ startIndex: 0, type: 'number.scala' }
+		]
+	}],
+
+	[{
+		line: '3_.1415F',
+		tokens: [
+			{ startIndex: 0, type: 'number.scala' },
+			{ startIndex: 1, type: 'keyword.scala' },
+			{ startIndex: 2, type: 'delimiter.scala' },
+			{ startIndex: 3, type: 'number.float.scala' }
+		]
+	}],
+
+	[{
+		line: '3._1415F',
+		tokens: [
+			{ startIndex: 0, type: 'number.scala' },
+			{ startIndex: 1, type: 'operator.scala' },
+			{ startIndex: 2, type: 'identifier.scala' }
+		]
+	}],
+
+	[{
+		line: '999_99_9999_L',
+		tokens: [
+			{ startIndex: 0, type: 'number.scala' },
+			{ startIndex: 11, type: 'identifier.scala' }
+		]
+	}],
+
+	[{
+		line: '52_',
+		tokens: [
+			{ startIndex: 0, type: 'number.scala' },
+			{ startIndex: 2, type: 'keyword.scala' }
+		]
+	}],
+
+	[{
+		line: '0_x52',
+		tokens: [
+			{ startIndex: 0, type: 'number.scala' },
+			{ startIndex: 1, type: 'identifier.scala' }
+		]
+	}],
+
+	[{
+		line: '0x_52',
+		tokens: [
+			{ startIndex: 0, type: 'number.scala' },
+			{ startIndex: 1, type: 'identifier.scala' }
+		]
+	}],
+
+	[{
+		line: '0x52_',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.scala' },
+			{ startIndex: 4, type: 'keyword.scala' } // TODO
+		]
+	}],
+
+	[{
+		line: '23.5L',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.scala' },
+			{ startIndex: 4, type: 'type.scala' }
+		]
+	}],
+
+	[{
+		line: '0+0',
+		tokens: [
+			{ startIndex: 0, type: 'number.scala' },
+			{ startIndex: 1, type: 'operator.scala' },
+			{ startIndex: 2, type: 'number.scala' }
+		]
+	}],
+
+	[{
+		line: '100+10',
+		tokens: [
+			{ startIndex: 0, type: 'number.scala' },
+			{ startIndex: 3, type: 'operator.scala' },
+			{ startIndex: 4, type: 'number.scala' }
+		]
+	}],
+
+	[{
+		line: '0 + 0',
+		tokens: [
+			{ startIndex: 0, type: 'number.scala' },
+			{ startIndex: 1, type: 'white.scala' },
+			{ startIndex: 2, type: 'operator.scala' },
+			{ startIndex: 3, type: 'white.scala' },
+			{ startIndex: 4, type: 'number.scala' }
+		]
+	}],
+
+	// single line Strings
+	[{
+		line: 'val s: String = "I\'m a Scala String";',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.scala' },
+			{ startIndex: 3, type: 'white.scala' },
+			{ startIndex: 4, type: 'variable.scala' },
+			{ startIndex: 5, type: 'operator.scala' },
+			{ startIndex: 6, type: 'white.scala' },
+			{ startIndex: 7, type: 'type.scala' },
+			{ startIndex: 13, type: 'white.scala' },
+			{ startIndex: 14, type: 'operator.scala' },
+			{ startIndex: 15, type: 'white.scala' },
+			{ startIndex: 16, type: 'string.quote.scala' },
+			{ startIndex: 17, type: 'string.scala' },
+			{ startIndex: 35, type: 'string.quote.scala' },
+			{ startIndex: 36, type: 'delimiter.scala' }
+		]
+	}],
+
+	[{
+		line: 'val s: String = "concatenated" + " String" ;',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.scala' },
+			{ startIndex: 3, type: 'white.scala' },
+			{ startIndex: 4, type: 'variable.scala' },
+			{ startIndex: 5, type: 'operator.scala' },
+			{ startIndex: 6, type: 'white.scala' },
+			{ startIndex: 7, type: 'type.scala' },
+			{ startIndex: 13, type: 'white.scala' },
+			{ startIndex: 14, type: 'operator.scala' },
+			{ startIndex: 15, type: 'white.scala' },
+			{ startIndex: 16, type: 'string.quote.scala' },
+			{ startIndex: 17, type: 'string.scala' },
+			{ startIndex: 29, type: 'string.quote.scala' },
+			{ startIndex: 30, type: 'white.scala' },
+			{ startIndex: 31, type: 'operator.scala' },
+			{ startIndex: 32, type: 'white.scala' },
+			{ startIndex: 33, type: 'string.quote.scala' },
+			{ startIndex: 34, type: 'string.scala' },
+			{ startIndex: 41, type: 'string.quote.scala' },
+			{ startIndex: 42, type: 'white.scala' },
+			{ startIndex: 43, type: 'delimiter.scala' }
+		]
+	}],
+
+	[{
+		line: '"quote in a string"',
+		tokens: [
+			{ startIndex: 0, type: 'string.quote.scala' },
+			{ startIndex: 1, type: 'string.scala' },
+			{ startIndex: 18, type: 'string.quote.scala' }
+		]
+	}],
+
+	[{
+		line: '"escaping \\"quotes\\" is cool"',
+		tokens: [
+			{ startIndex: 0, type: 'string.quote.scala' },
+			{ startIndex: 1, type: 'string.scala' },
+			{ startIndex: 10, type: 'string.escape.scala' },
+			{ startIndex: 12, type: 'string.scala' },
+			{ startIndex: 18, type: 'string.escape.scala' },
+			{ startIndex: 20, type: 'string.scala' },
+			{ startIndex: 28, type: 'string.quote.scala' },
+		]
+	}],
+
+	[{
+		line: '"\\"',
+		tokens: [
+			{ startIndex: 0, type: 'string.quote.scala' },
+			{ startIndex: 1, type: 'string.escape.scala' }
+		]
+	}],
+
+	// Annotations
+	[{
+		line: '@',
+		tokens: [
+			{ startIndex: 0, type: 'operator.scala' }
+		]
+	}],
+
+	[{
+		line: '@uncheckedStable',
+		tokens: [
+			{ startIndex: 0, type: 'annotation.scala' }
+		]
+	}],
+
+	[{
+		line: '@silent("deprecated")',
+		tokens: [
+			{ startIndex: 0, type: 'annotation.scala' },
+			{ startIndex: 7, type: 'delimiter.parenthesis.scala' },
+			{ startIndex: 8, type: 'string.quote.scala' },
+			{ startIndex: 9, type: 'string.scala' },
+			{ startIndex: 19, type: 'string.quote.scala' },
+			{ startIndex: 20, type: 'delimiter.parenthesis.scala' }
+		]
+	}],
+
+	[{
+		line: '@AnnotationWithKeywordAfter private',
+		tokens: [
+			{ startIndex: 0, type: 'annotation.scala' },
+			{ startIndex: 27, type: 'white.scala' },
+			{ startIndex: 28, type: 'keyword.modifier.scala' }
+		]
+	}]
+]);

+ 325 - 0
src/scala/scala.ts

@@ -0,0 +1,325 @@
+/*---------------------------------------------------------------------------------------------
+ *  Copyright (c) Microsoft Corporation. All rights reserved.
+ *  Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+'use strict';
+
+import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
+import ILanguage = monaco.languages.IMonarchLanguage;
+
+export const conf: IRichLanguageConfiguration = {
+	/*
+	 * `...` is allowed as an identifier.
+	 * $ is allowed in identifiers.
+	 * unary_<op> is allowed as an identifier.
+	 * <name>_= is allowed as an identifier.
+	 */
+	wordPattern: /(unary_[@~!#%^&*()\-=+\\|:<>\/?]+)|([a-zA-Z_$][\w$]*?_=)|(`[^`]+`)|([a-zA-Z_$][\w$]*)/g,
+	comments: {
+		lineComment: '//',
+		blockComment: ['/*', '*/'],
+	},
+	brackets: [
+		['{', '}'],
+		['[', ']'],
+		['(', ')'],
+	],
+	autoClosingPairs: [
+		{ open: '{', close: '}' },
+		{ open: '[', close: ']' },
+		{ open: '(', close: ')' },
+		{ open: '"', close: '"' },
+		{ open: '\'', close: '\'' },
+	],
+	surroundingPairs: [
+		{ open: '{', close: '}' },
+		{ open: '[', close: ']' },
+		{ open: '(', close: ')' },
+		{ open: '"', close: '"' },
+		{ open: '\'', close: '\'' },
+	],
+	folding: {
+		markers: {
+			start: new RegExp("^\\s*//\\s*(?:(?:#?region\\b)|(?:<editor-fold\\b))"),
+			end: new RegExp("^\\s*//\\s*(?:(?:#?endregion\\b)|(?:</editor-fold>))")
+		}
+	}
+};
+
+export const language = <ILanguage>{
+	tokenPostfix: '.scala',
+
+	// We can't easily add everything from Dotty, but we can at least add some of its keywords
+	keywords: [
+		'asInstanceOf',
+		'catch', 'class', 'classOf',
+		'def', 'do',
+		'else', 'extends',
+		'finally', 'for', 'foreach', 'forSome',
+		'if', 'import', 'isInstanceOf',
+		'macro', 'match',
+		'new',
+		'object',
+		'package',
+		'return',
+		'throw', 'trait', 'try', 'type',
+		'until',
+		'val', 'var',
+		'while', 'with',
+		'yield',
+
+		// Dotty-specific:
+		'given', 'enum', 'then'
+	],
+
+	// Dotty-specific:
+	softKeywords: [
+		'as', 'export', 'extension', 'end',
+		'derives', 'on'
+	],
+
+	constants: [
+		'true', 'false', 'null',
+		'this', 'super'
+	],
+
+	modifiers: [
+		'abstract', 'final', 'implicit', 'lazy', 'override',
+		'private', 'protected', 'sealed'
+	],
+
+	// Dotty-specific:
+	softModifiers: [
+		'inline', 'opaque', 'open', 'transparent', 'using'
+	],
+
+	name: /(?:[a-z_$][\w$]*|`[^`]+`)/,
+	type: /(?:[A-Z][\w$]*)/,
+
+	// we include these common regular expressions
+	symbols: /[=><!~?:&|+\-*\/^\\%@#]+/,
+	digits: /\d+(_+\d+)*/,
+	hexdigits: /[[0-9a-fA-F]+(_+[0-9a-fA-F]+)*/,
+
+	// C# style strings
+	escapes: /\\(?:[btnfr\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
+
+	fstring_conv: /[bBhHsScCdoxXeEfgGaAt]|[Tn](?:[HIklMSLNpzZsQ]|[BbhAaCYyjmde]|[RTrDFC])/,
+
+	// The main tokenizer for our languages
+	tokenizer: {
+		root: [
+			// strings
+			[/\braw"""/, {token: 'string.quote', bracket: '@open', next: '@rawstringt'}],
+			[/\braw"/, {token: 'string.quote', bracket: '@open', next: '@rawstring'}],
+
+			[/\bs"""/, {token: 'string.quote', bracket: '@open', next: '@sstringt'}],
+			[/\bs"/, {token: 'string.quote', bracket: '@open', next: '@sstring'}],
+
+			[/\bf""""/, {token: 'string.quote', bracket: '@open', next: '@fstringt'}],
+			[/\bf"/, {token: 'string.quote', bracket: '@open', next: '@fstring'}],
+
+			[/"""/, {token: 'string.quote', bracket: '@open', next: '@stringt'}],
+			[/"/, {token: 'string.quote', bracket: '@open', next: '@string'}],
+
+			// numbers
+			[/(@digits)[eE]([\-+]?(@digits))?[fFdD]?/, 'number.float', '@allowMethod'],
+			[/(@digits)\.(@digits)([eE][\-+]?(@digits))?[fFdD]?/, 'number.float', '@allowMethod'],
+			[/0[xX](@hexdigits)[Ll]?/, 'number.hex', '@allowMethod'],
+			[/(@digits)[fFdD]/, 'number.float', '@allowMethod'],
+			[/(@digits)[lL]?/, 'number', '@allowMethod'],
+
+			[/\b_\*/, 'key'],
+			[/\b(_)\b/, 'keyword', '@allowMethod'],
+
+			// identifiers and keywords
+			[/\bimport\b/, 'keyword', '@import'],
+			[/\b(case)([ \t]+)(class)\b/, ['keyword.modifier', 'white', 'keyword']],
+			[/\bcase\b/, 'keyword', '@case'],
+			[/\bva[lr]\b/, 'keyword', '@vardef'],
+			[/\b(def)([ \t]+)((?:unary_)?@symbols|@name(?:_=)|@name)/, ['keyword', 'white', 'identifier']],
+			[/@name(?=[ \t]*:(?!:))/, 'variable'],
+			[/(\.)(@name|@symbols)/, ['operator', {token: '@rematch', next: '@allowMethod'}]],
+			[/([{(])(\s*)(@name(?=\s*=>))/, ['@brackets', 'white', 'variable']],
+			[/@name/, {cases: {
+				'@keywords': 'keyword',
+				'@softKeywords': 'keyword',
+				'@modifiers': 'keyword.modifier',
+				'@softModifiers': 'keyword.modifier',
+				'@constants': {token: 'constant', next: '@allowMethod'},
+				'@default': {token: 'identifier', next: '@allowMethod'}
+			}}],
+			[/@type/, 'type', '@allowMethod'],
+
+			// whitespace
+			{include: '@whitespace'},
+
+			// @ annotations.
+			[/@[a-zA-Z_$][\w$]*(?:\.[a-zA-Z_$][\w$]*)*/, 'annotation'],
+
+			// delimiters and operators
+			[/[{(]/, '@brackets'],
+			[/[})]/, '@brackets', '@allowMethod'],
+			[/\[/, 'operator.square'],
+			[/](?!\s*(?:va[rl]|def|type)\b)/, 'operator.square', '@allowMethod'],
+			[/]/, 'operator.square'],
+			[/([=-]>|<-|>:|<:|:>|<%)(?=[\s\w()[\]{},\."'`])/, 'keyword'],
+			[/@symbols/, 'operator'],
+
+			// delimiter: after number because of .\d floats
+			[/[;,\.]/, 'delimiter'],
+
+			// symbols
+			[/'[a-zA-Z$][\w$]*(?!')/, 'attribute.name'],
+
+			// characters
+			[/'[^\\']'/, 'string', '@allowMethod'],
+			[/(')(@escapes)(')/, ['string', 'string.escape', {token: 'string', next: '@allowMethod'}]],
+			[/'/, 'string.invalid']
+		],
+
+		import: [
+			[/;/, 'delimiter', '@pop'],
+			[/^|$/, '', '@pop'],
+			[/[ \t]+/, 'white'],
+			[/[\n\r]+/, 'white', '@pop'],
+			[/\/\*/, 'comment', '@comment'],
+			[/@name|@type/, 'type'],
+			[/[(){}]/, '@brackets'],
+			[/[[\]]/, 'operator.square'],
+			[/[\.,]/, 'delimiter'],
+		],
+
+		allowMethod: [
+			[/^|$/, '', '@pop'],
+			[/[ \t]+/, 'white'],
+			[/[\n\r]+/, 'white', '@pop'],
+			[/\/\*/, 'comment', '@comment'],
+			[/(?==>[\s\w([{])/, 'keyword', '@pop'],
+			[/(@name|@symbols)(?=[ \t]*[[({"'`]|[ \t]+(?:[+-]?\.?\d|\w))/, {
+				cases: {
+				'@keywords': {token: 'keyword', next: '@pop'},
+				'->|<-|>:|<:|<%': {token: 'keyword', next: '@pop'},
+				'@default': {token: '@rematch', next: '@pop'}
+				}
+			}],
+			["", "", "@pop"]
+		],
+
+		comment: [
+			[/[^\/*]+/, 'comment'],
+			[/\/\*/, 'comment', '@push'], // nested comment
+			[/\*\//, 'comment', '@pop'],
+			[/[\/*]/, 'comment']
+		],
+
+		case: [
+			[/\b_\*/, 'key'],
+			[/\b(_|true|false|null|this|super)\b/, 'keyword', '@allowMethod'],
+			[/\bif\b|=>/, 'keyword', '@pop'],
+			[/`[^`]+`/, 'identifier', '@allowMethod'],
+			[/@name/, 'variable', '@allowMethod'],
+			[/:::?|\||@(?![a-z_$])/, 'keyword'],
+			{include: '@root'}
+		],
+
+		vardef: [
+			[/\b_\*/, 'key'],
+			[/\b(_|true|false|null|this|super)\b/, 'keyword'],
+			[/@name/, 'variable'],
+			[/:::?|\||@(?![a-z_$])/, 'keyword'],
+			[/=|:(?!:)/, 'operator', '@pop'],
+			[/$/, 'white', '@pop'],
+			{include: '@root'}
+		],
+
+		string: [
+			[/[^\\"\n\r]+/, 'string'],
+			[/@escapes/, 'string.escape'],
+			[/\\./, 'string.escape.invalid'],
+			[/"/, {token: 'string.quote', bracket: '@close', switchTo: '@allowMethod'}],
+		],
+
+		stringt: [
+			[/[^\\"\n\r]+/,	'string'],
+			[/@escapes/, 'string.escape'],
+			[/\\./, 'string.escape.invalid'],
+			[/"(?=""")/, 'string'],
+			[/"""/, {token: 'string.quote', bracket: '@close', switchTo: '@allowMethod'}],
+			[/"/, 'string']
+		],
+
+		fstring: [
+			[/@escapes/, 'string.escape'],
+			[/"/, {token: 'string.quote', bracket: '@close', switchTo: '@allowMethod'}],
+			[/\$\$/, 'string'],
+			[/(\$)([a-z_]\w*)/, ['operator', 'identifier']],
+			[/\$\{/, 'operator', '@interp'],
+			[/%%/, 'string'],
+			[/(%)([\-#+ 0,(])(\d+|\.\d+|\d+\.\d+)(@fstring_conv)/, ['metatag', 'keyword.modifier', 'number', 'metatag']],
+			[/(%)(\d+|\.\d+|\d+\.\d+)(@fstring_conv)/, ['metatag', 'number', 'metatag']],
+			[/(%)([\-#+ 0,(])(@fstring_conv)/, ['metatag', 'keyword.modifier', 'metatag']],
+			[/(%)(@fstring_conv)/, ['metatag', 'metatag']],
+			[/./, 'string']
+		],
+
+		fstringt: [
+			[/@escapes/, 'string.escape'],
+			[/"(?=""")/, 'string'],
+			[/"""/, {token: 'string.quote', bracket: '@close', switchTo: '@allowMethod'}],
+			[/\$\$/, 'string'],
+			[/(\$)([a-z_]\w*)/, ['operator', 'identifier']],
+			[/\$\{/, 'operator', '@interp'],
+			[/%%/, 'string'],
+			[/(%)([\-#+ 0,(])(\d+|\.\d+|\d+\.\d+)(@fstring_conv)/, ['metatag', 'keyword.modifier', 'number', 'metatag']],
+			[/(%)(\d+|\.\d+|\d+\.\d+)(@fstring_conv)/, ['metatag', 'number', 'metatag']],
+			[/(%)([\-#+ 0,(])(@fstring_conv)/, ['metatag', 'keyword.modifier', 'metatag']],
+			[/(%)(@fstring_conv)/, ['metatag', 'metatag']],
+			[/./, 'string']
+		],
+
+		sstring: [
+			[/@escapes/, 'string.escape'],
+			[/"/, {token: 'string.quote', bracket: '@close', switchTo: '@allowMethod'}],
+			[/\$\$/, 'string'],
+			[/(\$)([a-z_]\w*)/, ['operator', 'identifier']],
+			[/\$\{/, 'operator', '@interp'],
+			[/./, 'string']
+		],
+
+		sstringt: [
+			[/@escapes/, 'string.escape'],
+			[/"(?=""")/, 'string'],
+			[/"""/, {token: 'string.quote', bracket: '@close', switchTo: '@allowMethod'}],
+			[/\$\$/, 'string'],
+			[/(\$)([a-z_]\w*)/, ['operator', 'identifier']],
+			[/\$\{/, 'operator', '@interp'],
+			[/./, 'string']
+		],
+
+		interp: [
+			[/{/, 'operator', '@push'],
+			[/}/, 'operator', '@pop'],
+			{include: '@root'}
+		],
+
+		rawstring: [
+			[/[^"]/, 'string'],
+			[/"/, {token: 'string.quote', bracket: '@close', switchTo: '@allowMethod'}]
+		],
+
+		rawstringt: [
+			[/[^"]/, 'string'],
+			[/"(?=""")/, 'string'],
+			[/"""/, {token: 'string.quote', bracket: '@close', switchTo: '@allowMethod'}],
+			[/"/, 'string']
+		],
+
+		whitespace: [
+			[/[ \t\r\n]+/, 'white'],
+			[/\/\*/, 'comment', '@comment'],
+			[/\/\/.*$/, 'comment'],
+		],
+	},
+};

+ 11 - 14
src/typescript/typescript.ts

@@ -73,19 +73,17 @@ export const language = {
 	tokenPostfix: '.ts',
 
 	keywords: [
-		'abstract', 'as', 'break', 'case', 'catch', 'class', 'continue', 'const',
-		'constructor', 'debugger', 'declare', 'default', 'delete', 'do', 'else',
-		'enum', 'export', 'extends', 'false', 'finally', 'for', 'from', 'function',
-		'get', 'if', 'implements', 'import', 'in', 'infer', 'instanceof', 'interface',
-		'is', 'keyof', 'let', 'module', 'namespace', 'never', 'new', 'null', 'package',
-		'private', 'protected', 'public', 'readonly', 'require', 'global', 'return',
-		'set', 'static', 'super', 'switch', 'symbol', 'this', 'throw', 'true', 'try',
-		'type', 'typeof', 'unique', 'var', 'void', 'while', 'with', 'yield', 'async',
-		'await', 'of'
-	],
-
-	typeKeywords: [
-		'any', 'boolean', 'number', 'object', 'string', 'undefined'
+		// Should match the keys of textToKeywordObj in
+		// https://github.com/microsoft/TypeScript/blob/master/src/compiler/scanner.ts
+		'abstract', 'any', 'as', 'asserts', 'bigint', 'boolean', 'break', 'case', 'catch',
+		'class', 'continue', 'const', 'constructor', 'debugger', 'declare', 'default',
+		'delete', 'do', 'else', 'enum', 'export', 'extends', 'false', 'finally', 'for',
+		'from', 'function', 'get', 'if', 'implements', 'import', 'in', 'infer',
+		'instanceof', 'interface', 'is', 'keyof', 'let', 'module', 'namespace', 'never',
+		'new', 'null', 'number', 'object', 'package', 'private', 'protected', 'public',
+		'readonly', 'require', 'global', 'return', 'set', 'static', 'string', 'super',
+		'switch', 'symbol', 'this', 'throw', 'true', 'try', 'type', 'typeof', 'undefined',
+		'unique', 'unknown', 'var', 'void', 'while', 'with', 'yield', 'async', 'await', 'of'
 	],
 
 	operators: [
@@ -118,7 +116,6 @@ export const language = {
 			// identifiers and keywords
 			[/[a-z_$][\w$]*/, {
 				cases: {
-					'@typeKeywords': 'keyword',
 					'@keywords': 'keyword',
 					'@default': 'identifier'
 				}

+ 82 - 3
src/vb/vb.test.ts

@@ -289,18 +289,95 @@ testTokenization('vb', [
 			{ startIndex: 8, type: '' },
 			{ startIndex: 9, type: 'delimiter.vb' },
 			{ startIndex: 10, type: '' },
-			{ startIndex: 11, type: 'string.vb' }
+			{ startIndex: 11, type: 'string.quote.vb' },
+			{ startIndex: 12, type: 'string.vb' },
+			{ startIndex: 18, type: 'string.quote.vb' }
 		]
 	}],
 
 	[{
 		line: '"use strict";',
 		tokens: [
-			{ startIndex: 0, type: 'string.vb' },
+			{ startIndex: 0, type: 'string.quote.vb' },
+			{ startIndex: 1, type: 'string.vb' },
+			{ startIndex: 11, type: 'string.quote.vb' },
 			{ startIndex: 12, type: 'delimiter.vb' }
 		]
 	}],
 
+	[{
+		line: '"a""b"',
+		tokens: [
+			{ startIndex: 0, type: 'string.quote.vb' },
+			{ startIndex: 1, type: 'string.vb' },
+			{ startIndex: 2, type: 'string.escape.vb' },
+			{ startIndex: 4, type: 'string.vb' },
+			{ startIndex: 5, type: 'string.quote.vb' }
+		]
+	}, {
+		line: '"a““b"',
+		tokens: [
+			{ startIndex: 0, type: 'string.quote.vb' },
+			{ startIndex: 1, type: 'string.vb' },
+			{ startIndex: 2, type: 'string.escape.vb' },
+			{ startIndex: 4, type: 'string.vb' },
+			{ startIndex: 5, type: 'string.quote.vb' }
+		]
+	}, {
+		line: '"a””b"',
+		tokens: [
+			{ startIndex: 0, type: 'string.quote.vb' },
+			{ startIndex: 1, type: 'string.vb' },
+			{ startIndex: 2, type: 'string.escape.vb' },
+			{ startIndex: 4, type: 'string.vb' },
+			{ startIndex: 5, type: 'string.quote.vb' }
+		]
+	}],
+
+	[{
+		line: '"mixed quotes 1“',
+		tokens: [
+			{ startIndex: 0, type: 'string.quote.vb' },
+			{ startIndex: 1, type: 'string.vb' },
+			{ startIndex: 15, type: 'string.quote.vb' }
+		]
+	}, {
+		line: '"mixed quotes 2”',
+		tokens: [
+			{ startIndex: 0, type: 'string.quote.vb' },
+			{ startIndex: 1, type: 'string.vb' },
+			{ startIndex: 15, type: 'string.quote.vb' }
+		]
+	}, {
+		line: '“mixed quotes 3"',
+		tokens: [
+			{ startIndex: 0, type: 'string.quote.vb' },
+			{ startIndex: 1, type: 'string.vb' },
+			{ startIndex: 15, type: 'string.quote.vb' }
+		]
+	}, {
+		line: '“mixed quotes 4”',
+		tokens: [
+			{ startIndex: 0, type: 'string.quote.vb' },
+			{ startIndex: 1, type: 'string.vb' },
+			{ startIndex: 15, type: 'string.quote.vb' }
+		]
+	}, {
+		line: '”mixed quotes 5"',
+		tokens: [
+			{ startIndex: 0, type: 'string.quote.vb' },
+			{ startIndex: 1, type: 'string.vb' },
+			{ startIndex: 15, type: 'string.quote.vb' }
+		]
+	}, {
+		line: '”mixed quotes 6“',
+		tokens: [
+			{ startIndex: 0, type: 'string.quote.vb' },
+			{ startIndex: 1, type: 'string.vb' },
+			{ startIndex: 15, type: 'string.quote.vb' }
+		]
+	}],
+
 	// Tags
 	[{
 		line: 'Public Sub ToString()',
@@ -445,12 +522,14 @@ testTokenization('vb', [
 			{ startIndex: 5, type: '' },
 			{ startIndex: 6, type: 'delimiter.vb' },
 			{ startIndex: 7, type: '' },
-			{ startIndex: 8, type: 'string.vb' }
+			{ startIndex: 8, type: 'string.quote.vb' },
+			{ startIndex: 9, type: 'string.vb' }
 		]
 	}, {
 		line: 'world"',
 		tokens: [
 			{ startIndex: 0, type: 'string.vb' },
+			{ startIndex: 5, type: 'string.quote.vb' }
 		]
 	}],
 

+ 4 - 6
src/vb/vb.ts

@@ -124,7 +124,6 @@ export const language = <ILanguage>{
 
 	// we include these common regular expressions
 	symbols: /[=><!~?;\.,:&|+\-*\/\^%]+/,
-	escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
 	integersuffix: /U?[DI%L&S@]?/,
 	floatsuffix: /[R#F!]?/,
 
@@ -169,7 +168,7 @@ export const language = <ILanguage>{
 			[/@symbols/, 'delimiter'],
 
 			// strings
-			[/"/, 'string', '@string'],
+			[/["\u201c\u201d]/, { token: 'string.quote', next: '@string' }],
 
 		],
 
@@ -179,10 +178,9 @@ export const language = <ILanguage>{
 		],
 
 		string: [
-			[/[^\\"]+/, 'string'],
-			[/@escapes/, 'string.escape'],
-			[/\\./, 'string.escape.invalid'],
-			[/"C?/, 'string', '@pop']
+			[/[^"\u201c\u201d]+/, 'string'],
+			[/["\u201c\u201d]{2}/, 'string.escape'],
+			[/["\u201c\u201d]C?/, { token: 'string.quote', next: '@pop' }]
 		],
 	},
 };