diff --git a/package-lock.json b/package-lock.json index 3fe55baed..b76c0ae1f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,19 +11,12 @@ "dependencies": { "@chakra-ui/icons": "^1.1.5", "@chakra-ui/react": "^1.8.7", - "@codemirror/autocomplete": "^0.19.13", - "@codemirror/closebrackets": "^0.19.1", - "@codemirror/commands": "^0.19.8", - "@codemirror/comment": "^0.19.1", - "@codemirror/fold": "^0.19.3", - "@codemirror/gutter": "^0.19.9", - "@codemirror/highlight": "^0.19.7", - "@codemirror/history": "^0.19.2", - "@codemirror/lang-python": "^0.19.4", - "@codemirror/language": "^0.19.7", - "@codemirror/panel": "^0.19.1", - "@codemirror/state": "^0.19.9", - "@codemirror/view": "^0.19.44", + "@codemirror/autocomplete": "^6.3.0", + "@codemirror/commands": "6.1.1", + "@codemirror/lang-python": "^6.0.2", + "@codemirror/language": "^6.2.1", + "@codemirror/state": "^6.1.2", + "@codemirror/view": "^6.3.0", "@emotion/react": "^11.7.1", "@emotion/styled": "^11.6.0", "@microbit/lunr-languages": "^1.9.0-microbit.1", @@ -3520,177 +3513,66 @@ } }, "node_modules/@codemirror/autocomplete": { - "version": "0.19.13", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-0.19.13.tgz", - "integrity": "sha512-fI6lgTH2PlyTQqF2eWKDRBRUC+9MqvS2TfvE7aJ4Pu1oHM1w8JI16J9Qvwrd0iabJeF/QodU51Clok98c7fpCQ==", - "dependencies": { - "@codemirror/language": "^0.19.0", - "@codemirror/state": "^0.19.4", - "@codemirror/text": "^0.19.2", - "@codemirror/tooltip": "^0.19.12", - "@codemirror/view": "^0.19.0", - "@lezer/common": "^0.15.0" - } - }, - "node_modules/@codemirror/closebrackets": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@codemirror/closebrackets/-/closebrackets-0.19.1.tgz", - "integrity": "sha512-ZiLXT6u+VuBK5QnfBbt/Vmfd9Pg6449wn1DIOWFZHUOldg5eFn3VGGjYY2XWuHQz5WuK+7dXamV2KE885O1gyA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.3.0.tgz", + "integrity": "sha512-4jEvh3AjJZTDKazd10J6ZsCIqaYxDMCeua5ouQxY8hlFIml+nr7le0SgBhT3SIytFBmdzPK3AUhXGuW3T79nVg==", "dependencies": { - "@codemirror/language": "^0.19.0", - "@codemirror/rangeset": "^0.19.0", - "@codemirror/state": "^0.19.2", - "@codemirror/text": "^0.19.0", - "@codemirror/view": "^0.19.44" + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + }, + "peerDependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" } }, "node_modules/@codemirror/commands": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-0.19.8.tgz", - "integrity": "sha512-65LIMSGUGGpY3oH6mzV46YWRrgao6NmfJ+AuC7jNz3K5NPnH6GCV1H5I6SwOFyVbkiygGyd0EFwrWqywTBD1aw==", - "dependencies": { - "@codemirror/language": "^0.19.0", - "@codemirror/matchbrackets": "^0.19.0", - "@codemirror/state": "^0.19.2", - "@codemirror/text": "^0.19.6", - "@codemirror/view": "^0.19.22", - "@lezer/common": "^0.15.0" - } - }, - "node_modules/@codemirror/comment": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@codemirror/comment/-/comment-0.19.1.tgz", - "integrity": "sha512-uGKteBuVWAC6fW+Yt8u27DOnXMT/xV4Ekk2Z5mRsiADCZDqYvryrJd6PLL5+8t64BVyocwQwNfz1UswYS2CtFQ==", - "dependencies": { - "@codemirror/state": "^0.19.9", - "@codemirror/text": "^0.19.0", - "@codemirror/view": "^0.19.0" - } - }, - "node_modules/@codemirror/fold": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@codemirror/fold/-/fold-0.19.3.tgz", - "integrity": "sha512-8hT+Eq2G68mL0yPRvSD2ewhnLQAX6sbUJmtGVKFcj8oAXtfpYCX8LIcfXsuI19Qs7gZkOSpqZvn+KKj8IhZoAw==", - "dependencies": { - "@codemirror/gutter": "^0.19.0", - "@codemirror/language": "^0.19.0", - "@codemirror/rangeset": "^0.19.0", - "@codemirror/state": "^0.19.0", - "@codemirror/view": "^0.19.22" - } - }, - "node_modules/@codemirror/gutter": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@codemirror/gutter/-/gutter-0.19.9.tgz", - "integrity": "sha512-PFrtmilahin1g6uL27aG5tM/rqR9DZzZYZsIrCXA5Uc2OFTFqx4owuhoU9hqfYxHp5ovfvBwQ+txFzqS4vog6Q==", - "dependencies": { - "@codemirror/rangeset": "^0.19.0", - "@codemirror/state": "^0.19.0", - "@codemirror/view": "^0.19.23" - } - }, - "node_modules/@codemirror/highlight": { - "version": "0.19.7", - "resolved": "https://registry.npmjs.org/@codemirror/highlight/-/highlight-0.19.7.tgz", - "integrity": "sha512-3W32hBCY0pbbv/xidismw+RDMKuIag+fo4kZIbD7WoRj+Ttcaxjf+vP6RttRHXLaaqbWh031lTeON8kMlDhMYw==", - "dependencies": { - "@codemirror/language": "^0.19.0", - "@codemirror/rangeset": "^0.19.0", - "@codemirror/state": "^0.19.3", - "@codemirror/view": "^0.19.0", - "@lezer/common": "^0.15.0", - "style-mod": "^4.0.0" - } - }, - "node_modules/@codemirror/history": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@codemirror/history/-/history-0.19.2.tgz", - "integrity": "sha512-unhP4t3N2smzmHoo/Yio6ueWi+il8gm9VKrvi6wlcdGH5fOfVDNkmjHQ495SiR+EdOG35+3iNebSPYww0vN7ow==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.1.1.tgz", + "integrity": "sha512-ibDohwkk7vyu3VsnZNlQhwk0OETBtlkYV+6AHfn5Zgq0sxa+yGVX+apwtC3M4wh6AH7yU5si/NysoECs5EGS3Q==", "dependencies": { - "@codemirror/state": "^0.19.2", - "@codemirror/view": "^0.19.0" + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" } }, "node_modules/@codemirror/lang-python": { - "version": "0.19.4", - "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-0.19.4.tgz", - "integrity": "sha512-eSH1JXbf0D30y+f3nWy/+bTLAIV8RmcQbbVD8DsBxkxOHMVKcILgxFRHCovba8YEMtmq45I1DoWcNt1CeKnrYQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.0.2.tgz", + "integrity": "sha512-5BidNrfhab3s9LYNSN7JWFjL1+1zGAIw0dxUyalNwsUN+uCVE62sTk3uJlMZux4SsyT6fR8LbOLtWu52XQL6Yw==", "dependencies": { - "@codemirror/highlight": "^0.19.7", - "@codemirror/language": "^0.19.0", - "@lezer/python": "^0.15.0" + "@codemirror/language": "^6.0.0", + "@lezer/python": "^1.0.0" } }, "node_modules/@codemirror/language": { - "version": "0.19.7", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-0.19.7.tgz", - "integrity": "sha512-pNNUtYWMIMG0lUSKyUXJr8U0rFiCKsKFXbA2Oj17PC+S1FY99hV0z1vcntW67ekAIZw9DMEUQnLsKBuIbAUX7Q==", - "dependencies": { - "@codemirror/state": "^0.19.0", - "@codemirror/text": "^0.19.0", - "@codemirror/view": "^0.19.0", - "@lezer/common": "^0.15.5", - "@lezer/lr": "^0.15.0" - } - }, - "node_modules/@codemirror/matchbrackets": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@codemirror/matchbrackets/-/matchbrackets-0.19.1.tgz", - "integrity": "sha512-jBEW2Uu3hWcrrkwkauaikCAE7s5liCwbccFa6rLK6DzwaynOqCKJGyDsbkfrhikofNRc1yh4V3vwUuxt2u4QbA==", - "dependencies": { - "@codemirror/language": "^0.19.0", - "@codemirror/state": "^0.19.0", - "@codemirror/view": "^0.19.0", - "@lezer/common": "^0.15.0" - } - }, - "node_modules/@codemirror/panel": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@codemirror/panel/-/panel-0.19.1.tgz", - "integrity": "sha512-sYeOCMA3KRYxZYJYn5PNlt9yNsjy3zTNTrbYSfVgjgL9QomIVgOJWPO5hZ2sTN8lufO6lw0vTBsIPL9MSidmBg==", - "dependencies": { - "@codemirror/state": "^0.19.0", - "@codemirror/view": "^0.19.0" - } - }, - "node_modules/@codemirror/rangeset": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@codemirror/rangeset/-/rangeset-0.19.8.tgz", - "integrity": "sha512-1vusIkxSD0vK5KQ22JO/4Ejfww5268PgM/CpKNBSpTpWZEFlZbmOPyRiY4HXO2oEzOpypbA/walMiNInWnrT0Q==", - "dependencies": { - "@codemirror/state": "^0.19.0" + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.2.1.tgz", + "integrity": "sha512-MC3svxuvIj0MRpFlGHxLS6vPyIdbTr2KKPEW46kCoCXw2ktb4NTkpkPBI/lSP/FoNXLCBJ0mrnUi1OoZxtpW1Q==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" } }, "node_modules/@codemirror/state": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-0.19.9.tgz", - "integrity": "sha512-psOzDolKTZkx4CgUqhBQ8T8gBc0xN5z4gzed109aF6x7D7umpDRoimacI/O6d9UGuyl4eYuDCZmDFr2Rq7aGOw==", - "dependencies": { - "@codemirror/text": "^0.19.0" - } - }, - "node_modules/@codemirror/text": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@codemirror/text/-/text-0.19.6.tgz", - "integrity": "sha512-T9jnREMIygx+TPC1bOuepz18maGq/92q2a+n4qTqObKwvNMg+8cMTslb8yxeEDEq7S3kpgGWxgO1UWbQRij0dA==" - }, - "node_modules/@codemirror/tooltip": { - "version": "0.19.15", - "resolved": "https://registry.npmjs.org/@codemirror/tooltip/-/tooltip-0.19.15.tgz", - "integrity": "sha512-Fb4fKgVziUNSOAhclsvsqHw+1bCfh5po8xT/hw2UQW0UV41t73tJqX5AiqSwmtaDHExN7DFyzG8VQa05d/7g3Q==", - "dependencies": { - "@codemirror/state": "^0.19.0", - "@codemirror/view": "^0.19.0" - } + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.1.2.tgz", + "integrity": "sha512-Mxff85Hp5va+zuj+H748KbubXjrinX/k28lj43H14T2D0+4kuvEFIEIO7hCEcvBT8ubZyIelt9yGOjj2MWOEQA==" }, "node_modules/@codemirror/view": { - "version": "0.19.44", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-0.19.44.tgz", - "integrity": "sha512-vahNUE6hSXdjzs1gcztKPJQhZu+ZIwRpK4ZGZTSD81/CZUVqtlF75W3RCYVgEdjTI1l6ogJmIL6FM2Xj7ltn7Q==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.3.0.tgz", + "integrity": "sha512-jMN9OGKmzRPJ+kksfMrB5e/A9heQncirHsz8XNBpgEbYONCk5tWHMKVWKTNwznkUGD5mnigXI1i5YIcWpscSPg==", "dependencies": { - "@codemirror/rangeset": "^0.19.5", - "@codemirror/state": "^0.19.3", - "@codemirror/text": "^0.19.0", + "@codemirror/state": "^6.0.0", "style-mod": "^4.0.0", "w3c-keyname": "^2.2.4" } @@ -5541,24 +5423,33 @@ "dev": true }, "node_modules/@lezer/common": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.15.11.tgz", - "integrity": "sha512-vv0nSdIaVCRcJ8rPuDdsrNVfBOYe/4Szr/LhF929XyDmBndLDuWiCCHooGlGlJfzELyO608AyDhVsuX/ZG36NA==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.1.tgz", + "integrity": "sha512-8TR5++Q/F//tpDsLd5zkrvEX5xxeemafEaek7mUp7Y+bI8cKQXdSqhzTOBaOogETcMOVr0pT3BBPXp13477ciw==" + }, + "node_modules/@lezer/highlight": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.1.1.tgz", + "integrity": "sha512-duv9D23O9ghEDnnUDmxu+L8pJy4nYo4AbCOHIudUhscrLSazqeJeK1V50EU6ZufWF1zv0KJwu/frFRyZWXxHBQ==", + "dependencies": { + "@lezer/common": "^1.0.0" + } }, "node_modules/@lezer/lr": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.15.0.tgz", - "integrity": "sha512-gbxAiC4X9BBOfPfHNgozbH0kPREDt7zjoy/DVxPubpZYG7Hmr6QJTriCSjjTOkKnaQCGxpxFaCGS1QyZFTsYMg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.2.3.tgz", + "integrity": "sha512-qpB7rBzH8f6Mzjv2AVZRahcm+2Cf7nbIH++uXbvVOL1yIRvVWQ3HAM/saeBLCyz/togB7LGo76qdJYL1uKQlqA==", "dependencies": { - "@lezer/common": "^0.15.0" + "@lezer/common": "^1.0.0" } }, "node_modules/@lezer/python": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@lezer/python/-/python-0.15.0.tgz", - "integrity": "sha512-KkbNfjLZCs/Ibx+3mekGu31qz+zCVkXHL+oNftRxB/lsINlz25SURR5z6wb94JpJt0yDFCEtn/2siAUybLOXiA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.0.tgz", + "integrity": "sha512-FVPp2usfj3zZuc+2RidXAY94WAcsHQ3dbKDbXuZgoAwUungAcXwd3EWXiWQvwNqbae+ek51bWi8dwbiQqweWCg==", "dependencies": { - "@lezer/lr": "^0.15.0" + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" } }, "node_modules/@microbit/lunr-languages": { @@ -26279,177 +26170,60 @@ } }, "@codemirror/autocomplete": { - "version": "0.19.13", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-0.19.13.tgz", - "integrity": "sha512-fI6lgTH2PlyTQqF2eWKDRBRUC+9MqvS2TfvE7aJ4Pu1oHM1w8JI16J9Qvwrd0iabJeF/QodU51Clok98c7fpCQ==", - "requires": { - "@codemirror/language": "^0.19.0", - "@codemirror/state": "^0.19.4", - "@codemirror/text": "^0.19.2", - "@codemirror/tooltip": "^0.19.12", - "@codemirror/view": "^0.19.0", - "@lezer/common": "^0.15.0" - } - }, - "@codemirror/closebrackets": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@codemirror/closebrackets/-/closebrackets-0.19.1.tgz", - "integrity": "sha512-ZiLXT6u+VuBK5QnfBbt/Vmfd9Pg6449wn1DIOWFZHUOldg5eFn3VGGjYY2XWuHQz5WuK+7dXamV2KE885O1gyA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.3.0.tgz", + "integrity": "sha512-4jEvh3AjJZTDKazd10J6ZsCIqaYxDMCeua5ouQxY8hlFIml+nr7le0SgBhT3SIytFBmdzPK3AUhXGuW3T79nVg==", "requires": { - "@codemirror/language": "^0.19.0", - "@codemirror/rangeset": "^0.19.0", - "@codemirror/state": "^0.19.2", - "@codemirror/text": "^0.19.0", - "@codemirror/view": "^0.19.44" + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" } }, "@codemirror/commands": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-0.19.8.tgz", - "integrity": "sha512-65LIMSGUGGpY3oH6mzV46YWRrgao6NmfJ+AuC7jNz3K5NPnH6GCV1H5I6SwOFyVbkiygGyd0EFwrWqywTBD1aw==", - "requires": { - "@codemirror/language": "^0.19.0", - "@codemirror/matchbrackets": "^0.19.0", - "@codemirror/state": "^0.19.2", - "@codemirror/text": "^0.19.6", - "@codemirror/view": "^0.19.22", - "@lezer/common": "^0.15.0" - } - }, - "@codemirror/comment": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@codemirror/comment/-/comment-0.19.1.tgz", - "integrity": "sha512-uGKteBuVWAC6fW+Yt8u27DOnXMT/xV4Ekk2Z5mRsiADCZDqYvryrJd6PLL5+8t64BVyocwQwNfz1UswYS2CtFQ==", - "requires": { - "@codemirror/state": "^0.19.9", - "@codemirror/text": "^0.19.0", - "@codemirror/view": "^0.19.0" - } - }, - "@codemirror/fold": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@codemirror/fold/-/fold-0.19.3.tgz", - "integrity": "sha512-8hT+Eq2G68mL0yPRvSD2ewhnLQAX6sbUJmtGVKFcj8oAXtfpYCX8LIcfXsuI19Qs7gZkOSpqZvn+KKj8IhZoAw==", - "requires": { - "@codemirror/gutter": "^0.19.0", - "@codemirror/language": "^0.19.0", - "@codemirror/rangeset": "^0.19.0", - "@codemirror/state": "^0.19.0", - "@codemirror/view": "^0.19.22" - } - }, - "@codemirror/gutter": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@codemirror/gutter/-/gutter-0.19.9.tgz", - "integrity": "sha512-PFrtmilahin1g6uL27aG5tM/rqR9DZzZYZsIrCXA5Uc2OFTFqx4owuhoU9hqfYxHp5ovfvBwQ+txFzqS4vog6Q==", - "requires": { - "@codemirror/rangeset": "^0.19.0", - "@codemirror/state": "^0.19.0", - "@codemirror/view": "^0.19.23" - } - }, - "@codemirror/highlight": { - "version": "0.19.7", - "resolved": "https://registry.npmjs.org/@codemirror/highlight/-/highlight-0.19.7.tgz", - "integrity": "sha512-3W32hBCY0pbbv/xidismw+RDMKuIag+fo4kZIbD7WoRj+Ttcaxjf+vP6RttRHXLaaqbWh031lTeON8kMlDhMYw==", - "requires": { - "@codemirror/language": "^0.19.0", - "@codemirror/rangeset": "^0.19.0", - "@codemirror/state": "^0.19.3", - "@codemirror/view": "^0.19.0", - "@lezer/common": "^0.15.0", - "style-mod": "^4.0.0" - } - }, - "@codemirror/history": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@codemirror/history/-/history-0.19.2.tgz", - "integrity": "sha512-unhP4t3N2smzmHoo/Yio6ueWi+il8gm9VKrvi6wlcdGH5fOfVDNkmjHQ495SiR+EdOG35+3iNebSPYww0vN7ow==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.1.1.tgz", + "integrity": "sha512-ibDohwkk7vyu3VsnZNlQhwk0OETBtlkYV+6AHfn5Zgq0sxa+yGVX+apwtC3M4wh6AH7yU5si/NysoECs5EGS3Q==", "requires": { - "@codemirror/state": "^0.19.2", - "@codemirror/view": "^0.19.0" + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" } }, "@codemirror/lang-python": { - "version": "0.19.4", - "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-0.19.4.tgz", - "integrity": "sha512-eSH1JXbf0D30y+f3nWy/+bTLAIV8RmcQbbVD8DsBxkxOHMVKcILgxFRHCovba8YEMtmq45I1DoWcNt1CeKnrYQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.0.2.tgz", + "integrity": "sha512-5BidNrfhab3s9LYNSN7JWFjL1+1zGAIw0dxUyalNwsUN+uCVE62sTk3uJlMZux4SsyT6fR8LbOLtWu52XQL6Yw==", "requires": { - "@codemirror/highlight": "^0.19.7", - "@codemirror/language": "^0.19.0", - "@lezer/python": "^0.15.0" + "@codemirror/language": "^6.0.0", + "@lezer/python": "^1.0.0" } }, "@codemirror/language": { - "version": "0.19.7", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-0.19.7.tgz", - "integrity": "sha512-pNNUtYWMIMG0lUSKyUXJr8U0rFiCKsKFXbA2Oj17PC+S1FY99hV0z1vcntW67ekAIZw9DMEUQnLsKBuIbAUX7Q==", - "requires": { - "@codemirror/state": "^0.19.0", - "@codemirror/text": "^0.19.0", - "@codemirror/view": "^0.19.0", - "@lezer/common": "^0.15.5", - "@lezer/lr": "^0.15.0" - } - }, - "@codemirror/matchbrackets": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@codemirror/matchbrackets/-/matchbrackets-0.19.1.tgz", - "integrity": "sha512-jBEW2Uu3hWcrrkwkauaikCAE7s5liCwbccFa6rLK6DzwaynOqCKJGyDsbkfrhikofNRc1yh4V3vwUuxt2u4QbA==", - "requires": { - "@codemirror/language": "^0.19.0", - "@codemirror/state": "^0.19.0", - "@codemirror/view": "^0.19.0", - "@lezer/common": "^0.15.0" - } - }, - "@codemirror/panel": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@codemirror/panel/-/panel-0.19.1.tgz", - "integrity": "sha512-sYeOCMA3KRYxZYJYn5PNlt9yNsjy3zTNTrbYSfVgjgL9QomIVgOJWPO5hZ2sTN8lufO6lw0vTBsIPL9MSidmBg==", - "requires": { - "@codemirror/state": "^0.19.0", - "@codemirror/view": "^0.19.0" - } - }, - "@codemirror/rangeset": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@codemirror/rangeset/-/rangeset-0.19.8.tgz", - "integrity": "sha512-1vusIkxSD0vK5KQ22JO/4Ejfww5268PgM/CpKNBSpTpWZEFlZbmOPyRiY4HXO2oEzOpypbA/walMiNInWnrT0Q==", - "requires": { - "@codemirror/state": "^0.19.0" + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.2.1.tgz", + "integrity": "sha512-MC3svxuvIj0MRpFlGHxLS6vPyIdbTr2KKPEW46kCoCXw2ktb4NTkpkPBI/lSP/FoNXLCBJ0mrnUi1OoZxtpW1Q==", + "requires": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" } }, "@codemirror/state": { - "version": "0.19.9", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-0.19.9.tgz", - "integrity": "sha512-psOzDolKTZkx4CgUqhBQ8T8gBc0xN5z4gzed109aF6x7D7umpDRoimacI/O6d9UGuyl4eYuDCZmDFr2Rq7aGOw==", - "requires": { - "@codemirror/text": "^0.19.0" - } - }, - "@codemirror/text": { - "version": "0.19.6", - "resolved": "https://registry.npmjs.org/@codemirror/text/-/text-0.19.6.tgz", - "integrity": "sha512-T9jnREMIygx+TPC1bOuepz18maGq/92q2a+n4qTqObKwvNMg+8cMTslb8yxeEDEq7S3kpgGWxgO1UWbQRij0dA==" - }, - "@codemirror/tooltip": { - "version": "0.19.15", - "resolved": "https://registry.npmjs.org/@codemirror/tooltip/-/tooltip-0.19.15.tgz", - "integrity": "sha512-Fb4fKgVziUNSOAhclsvsqHw+1bCfh5po8xT/hw2UQW0UV41t73tJqX5AiqSwmtaDHExN7DFyzG8VQa05d/7g3Q==", - "requires": { - "@codemirror/state": "^0.19.0", - "@codemirror/view": "^0.19.0" - } + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.1.2.tgz", + "integrity": "sha512-Mxff85Hp5va+zuj+H748KbubXjrinX/k28lj43H14T2D0+4kuvEFIEIO7hCEcvBT8ubZyIelt9yGOjj2MWOEQA==" }, "@codemirror/view": { - "version": "0.19.44", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-0.19.44.tgz", - "integrity": "sha512-vahNUE6hSXdjzs1gcztKPJQhZu+ZIwRpK4ZGZTSD81/CZUVqtlF75W3RCYVgEdjTI1l6ogJmIL6FM2Xj7ltn7Q==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.3.0.tgz", + "integrity": "sha512-jMN9OGKmzRPJ+kksfMrB5e/A9heQncirHsz8XNBpgEbYONCk5tWHMKVWKTNwznkUGD5mnigXI1i5YIcWpscSPg==", "requires": { - "@codemirror/rangeset": "^0.19.5", - "@codemirror/state": "^0.19.3", - "@codemirror/text": "^0.19.0", + "@codemirror/state": "^6.0.0", "style-mod": "^4.0.0", "w3c-keyname": "^2.2.4" } @@ -27877,24 +27651,33 @@ "dev": true }, "@lezer/common": { - "version": "0.15.11", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-0.15.11.tgz", - "integrity": "sha512-vv0nSdIaVCRcJ8rPuDdsrNVfBOYe/4Szr/LhF929XyDmBndLDuWiCCHooGlGlJfzELyO608AyDhVsuX/ZG36NA==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.1.tgz", + "integrity": "sha512-8TR5++Q/F//tpDsLd5zkrvEX5xxeemafEaek7mUp7Y+bI8cKQXdSqhzTOBaOogETcMOVr0pT3BBPXp13477ciw==" + }, + "@lezer/highlight": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.1.1.tgz", + "integrity": "sha512-duv9D23O9ghEDnnUDmxu+L8pJy4nYo4AbCOHIudUhscrLSazqeJeK1V50EU6ZufWF1zv0KJwu/frFRyZWXxHBQ==", + "requires": { + "@lezer/common": "^1.0.0" + } }, "@lezer/lr": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-0.15.0.tgz", - "integrity": "sha512-gbxAiC4X9BBOfPfHNgozbH0kPREDt7zjoy/DVxPubpZYG7Hmr6QJTriCSjjTOkKnaQCGxpxFaCGS1QyZFTsYMg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.2.3.tgz", + "integrity": "sha512-qpB7rBzH8f6Mzjv2AVZRahcm+2Cf7nbIH++uXbvVOL1yIRvVWQ3HAM/saeBLCyz/togB7LGo76qdJYL1uKQlqA==", "requires": { - "@lezer/common": "^0.15.0" + "@lezer/common": "^1.0.0" } }, "@lezer/python": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@lezer/python/-/python-0.15.0.tgz", - "integrity": "sha512-KkbNfjLZCs/Ibx+3mekGu31qz+zCVkXHL+oNftRxB/lsINlz25SURR5z6wb94JpJt0yDFCEtn/2siAUybLOXiA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.0.tgz", + "integrity": "sha512-FVPp2usfj3zZuc+2RidXAY94WAcsHQ3dbKDbXuZgoAwUungAcXwd3EWXiWQvwNqbae+ek51bWi8dwbiQqweWCg==", "requires": { - "@lezer/lr": "^0.15.0" + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" } }, "@microbit/lunr-languages": { diff --git a/package.json b/package.json index bde999019..4c9c4210d 100644 --- a/package.json +++ b/package.json @@ -7,19 +7,12 @@ "dependencies": { "@chakra-ui/icons": "^1.1.5", "@chakra-ui/react": "^1.8.7", - "@codemirror/autocomplete": "^0.19.13", - "@codemirror/closebrackets": "^0.19.1", - "@codemirror/commands": "^0.19.8", - "@codemirror/comment": "^0.19.1", - "@codemirror/fold": "^0.19.3", - "@codemirror/gutter": "^0.19.9", - "@codemirror/highlight": "^0.19.7", - "@codemirror/history": "^0.19.2", - "@codemirror/lang-python": "^0.19.4", - "@codemirror/language": "^0.19.7", - "@codemirror/panel": "^0.19.1", - "@codemirror/state": "^0.19.9", - "@codemirror/view": "^0.19.44", + "@codemirror/autocomplete": "^6.3.0", + "@codemirror/commands": "6.1.1", + "@codemirror/lang-python": "^6.0.2", + "@codemirror/language": "^6.2.1", + "@codemirror/state": "^6.1.2", + "@codemirror/view": "^6.3.0", "@emotion/react": "^11.7.1", "@emotion/styled": "^11.6.0", "@microbit/lunr-languages": "^1.9.0-microbit.1", diff --git a/src/editor/active-editor-hooks.tsx b/src/editor/active-editor-hooks.tsx index 207ee2d6b..9d1ed3c37 100644 --- a/src/editor/active-editor-hooks.tsx +++ b/src/editor/active-editor-hooks.tsx @@ -5,7 +5,7 @@ * * SPDX-License-Identifier: MIT */ -import { redo, undo } from "@codemirror/history"; +import { redo, undo } from "@codemirror/commands"; import { EditorView } from "@codemirror/view"; import React, { Dispatch, diff --git a/src/editor/codemirror/CodeMirror.tsx b/src/editor/codemirror/CodeMirror.tsx index 89a7dd44a..31d155dd1 100644 --- a/src/editor/codemirror/CodeMirror.tsx +++ b/src/editor/codemirror/CodeMirror.tsx @@ -3,10 +3,15 @@ * * SPDX-License-Identifier: MIT */ -import { highlightActiveLineGutter, lineNumbers } from "@codemirror/gutter"; -import { redoDepth, undoDepth } from "@codemirror/history"; +import { redoDepth, undoDepth } from "@codemirror/commands"; import { EditorSelection, EditorState, Extension } from "@codemirror/state"; -import { EditorView, highlightActiveLine, ViewUpdate } from "@codemirror/view"; +import { + EditorView, + highlightActiveLine, + highlightActiveLineGutter, + lineNumbers, + ViewUpdate, +} from "@codemirror/view"; import { useEffect, useMemo, useRef } from "react"; import { useIntl } from "react-intl"; import { lineNumFromUint8Array } from "../../common/text-util"; @@ -117,7 +122,7 @@ const CodeMirror = ({ dndSupport({ sessionSettings, setSessionSettings }), // Extensions only relevant for editing: // Order of lintGutter and lineNumbers determines how they are displayed. - lintGutter(), + lintGutter({ hoverTime: 0 }), lineNumbers(), highlightActiveLineGutter(), highlightActiveLine(), diff --git a/src/editor/codemirror/config.ts b/src/editor/codemirror/config.ts index c4862bf74..4c4db52b2 100644 --- a/src/editor/codemirror/config.ts +++ b/src/editor/codemirror/config.ts @@ -3,14 +3,25 @@ * * SPDX-License-Identifier: MIT */ -import { completionKeymap } from "@codemirror/autocomplete"; -import { closeBrackets, closeBracketsKeymap } from "@codemirror/closebrackets"; -import { defaultKeymap, indentLess, indentMore } from "@codemirror/commands"; -import { commentKeymap } from "@codemirror/comment"; -import { defaultHighlightStyle } from "@codemirror/highlight"; -import { history, historyKeymap } from "@codemirror/history"; +import { + closeBrackets, + closeBracketsKeymap, + completionKeymap, +} from "@codemirror/autocomplete"; +import { + defaultKeymap, + history, + historyKeymap, + indentLess, + indentMore, +} from "@codemirror/commands"; import { python } from "@codemirror/lang-python"; -import { indentOnInput, indentUnit } from "@codemirror/language"; +import { + defaultHighlightStyle, + indentOnInput, + indentUnit, + syntaxHighlighting, +} from "@codemirror/language"; import { Compartment, EditorState, Extension, Prec } from "@codemirror/state"; import { drawSelection, @@ -47,9 +58,9 @@ export const editorConfig: Extension = [ history(), drawSelection(), indentOnInput(), - Prec.fallback(defaultHighlightStyle), + Prec.lowest(syntaxHighlighting(defaultHighlightStyle)), closeBrackets(), - highlightStyle(), + syntaxHighlighting(highlightStyle()), keymap.of([ // Added, but see https://codemirror.net/6/examples/tab/ for accessibility discussion. @@ -57,7 +68,6 @@ export const editorConfig: Extension = [ ...closeBracketsKeymap, ...defaultKeymap, ...historyKeymap, - ...commentKeymap, ...completionKeymap, ...lintKeymap, ]), diff --git a/src/editor/codemirror/debug.ts b/src/editor/codemirror/debug.ts index a09653e38..57b285471 100644 --- a/src/editor/codemirror/debug.ts +++ b/src/editor/codemirror/debug.ts @@ -28,15 +28,15 @@ export const debug = () => tree.iterate({ from: 0, to: tree.length, - enter: (type, start) => { - if (isInteresting(type)) { + enter: (node) => { + if (isInteresting(node.type)) { depth++; let indent = " ".repeat(depth); - console.log(`${indent} ${type.name} ${start}`); + console.log(`${indent} ${node.type.name} ${node.from}`); } }, - leave: (type, _start, _end) => { - if (isInteresting(type)) { + leave: (node) => { + if (isInteresting(node.type)) { depth--; } }, diff --git a/src/editor/codemirror/dnd-decorations.ts b/src/editor/codemirror/dnd-decorations.ts index 00370a3f2..57854ef3c 100644 --- a/src/editor/codemirror/dnd-decorations.ts +++ b/src/editor/codemirror/dnd-decorations.ts @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: MIT */ +import { RangeSetBuilder, StateEffect } from "@codemirror/state"; import { Decoration, DecorationSet, @@ -10,8 +11,6 @@ import { ViewPlugin, ViewUpdate, } from "@codemirror/view"; -import { RangeSetBuilder } from "@codemirror/rangeset"; -import { StateEffect } from "@codemirror/state"; export const timeoutEffect = StateEffect.define<{}>({}); diff --git a/src/editor/codemirror/dnd.ts b/src/editor/codemirror/dnd.ts index c068883c3..78dbd4ee8 100644 --- a/src/editor/codemirror/dnd.ts +++ b/src/editor/codemirror/dnd.ts @@ -218,7 +218,8 @@ const findLogicalPosition = ( view: EditorView, event: DragEvent ): { line: number; indent: number | undefined } => { - const visualLine = view.visualLineAtHeight(event.y || event.clientY); + const height = (event.y || event.clientY) - view.documentTop; + const visualLine = view.lineBlockAtHeight(height); const line = view.state.doc.lineAt(visualLine.from); const pos = view.posAtCoords({ x: event.x || event.clientX, diff --git a/src/editor/codemirror/edits.ts b/src/editor/codemirror/edits.ts index 6ba8888ba..ca6a9a686 100644 --- a/src/editor/codemirror/edits.ts +++ b/src/editor/codemirror/edits.ts @@ -414,7 +414,7 @@ const indentLevelOfContainingWhileTrue = ( return -1; } let done = false; - for (const cursor = tree.cursor(pos, 0); !done; done = !cursor.parent()) { + for (const cursor = tree.cursorAt(pos, 0); !done; done = !cursor.parent()) { if (cursor.type.name === "WhileStatement") { const maybeTrueNode = cursor.node.firstChild?.nextSibling; if ( diff --git a/src/editor/codemirror/highlightStyle.ts b/src/editor/codemirror/highlightStyle.ts index 0fa4ac482..c57158de6 100644 --- a/src/editor/codemirror/highlightStyle.ts +++ b/src/editor/codemirror/highlightStyle.ts @@ -15,7 +15,8 @@ // https://github.com/codemirror/highlight/blob/main/src/highlight.ts#L480 // This file shows the mapping of grammar nodes to tags for Python // https://github.com/codemirror/lang-python/blob/main/src/python.ts#L17 -import { HighlightStyle, tags } from "@codemirror/highlight"; +import { HighlightStyle } from "@codemirror/language"; +import { tags } from "@lezer/highlight"; export const highlightStyle = () => { const dark = "var(--chakra-colors-code-default)"; diff --git a/src/editor/codemirror/language-server/autocompletion.ts b/src/editor/codemirror/language-server/autocompletion.ts index 85d9cb607..6077ed5c7 100644 --- a/src/editor/codemirror/language-server/autocompletion.ts +++ b/src/editor/codemirror/language-server/autocompletion.ts @@ -8,8 +8,8 @@ import { Completion, CompletionContext, CompletionResult, + insertBracket, } from "@codemirror/autocomplete"; -import { insertBracket } from "@codemirror/closebrackets"; import { TransactionSpec } from "@codemirror/state"; import sortBy from "lodash.sortby"; import { IntlShape } from "react-intl"; @@ -92,7 +92,7 @@ export const autocompletion = ( // Could vary these based on isIncomplete? Needs investigation. // Very desirable to set most of the time to remove flicker. filter: true, - span: identifierLike, + validFor: identifierLike, options: sortBy( results.items // For now we don't support these edits (they usually add imports). @@ -137,6 +137,7 @@ export const autocompletion = ( }; }, ], + closeOnBlur: false, }); const createDocumentationResolver = diff --git a/src/editor/codemirror/language-server/diagnostics.ts b/src/editor/codemirror/language-server/diagnostics.ts index b6070d4b9..015acc360 100644 --- a/src/editor/codemirror/language-server/diagnostics.ts +++ b/src/editor/codemirror/language-server/diagnostics.ts @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: MIT */ -import { Text } from "@codemirror/text"; +import { Text } from "@codemirror/state"; import * as LSP from "vscode-languageserver-protocol"; import { Diagnostic } from "../lint/lint"; import { positionToOffset } from "./positions"; diff --git a/src/editor/codemirror/language-server/signatureHelp.ts b/src/editor/codemirror/language-server/signatureHelp.ts index 8926f0370..2fcc6dfc8 100644 --- a/src/editor/codemirror/language-server/signatureHelp.ts +++ b/src/editor/codemirror/language-server/signatureHelp.ts @@ -8,7 +8,6 @@ * SPDX-License-Identifier: MIT */ import { StateEffect, StateField } from "@codemirror/state"; -import { showTooltip, Tooltip } from "@codemirror/tooltip"; import { Command, EditorView, @@ -16,6 +15,8 @@ import { keymap, logException, PluginValue, + showTooltip, + Tooltip, ViewPlugin, ViewUpdate, } from "@codemirror/view"; diff --git a/src/editor/codemirror/lint/lint.ts b/src/editor/codemirror/lint/lint.ts index c5bc69b09..b633b5d58 100644 --- a/src/editor/codemirror/lint/lint.ts +++ b/src/editor/codemirror/lint/lint.ts @@ -1,7 +1,7 @@ /** -Modified copy of the lint extension from CodeMirror 0.19.6 -git revision 084c4ad59be7562c739d2e8fff12c7852e106b15 -sha1 of source lint.ts facbdc305d2b5a318dbcb9bcd41f992073ecfff5 +Modified copy of the lint extension from CodeMirror 6.0.0 +git revision 6f209208918744c37d62902c34e3f04f85f54965 +sha1 of source lint.ts 165f647c49d87591ab8a7dd67212e0ddd570fb9e To aid comparison to the original, this file is not auto-formatted and we've disabled our eslint rules. @@ -41,13 +41,11 @@ THE SOFTWARE. /* eslint-disable */ import {EditorView, ViewPlugin, Decoration, DecorationSet, - WidgetType, ViewUpdate, Command, logException, KeyBinding} from "@codemirror/view" -import {Text, StateEffect, StateField, Extension, TransactionSpec, - EditorState, Facet, combineConfig} from "@codemirror/state" -import {hoverTooltip, Tooltip, showTooltip} from "@codemirror/tooltip" -import {PanelConstructor, Panel, showPanel, getPanel} from "@codemirror/panel" -import {gutter, GutterMarker} from "@codemirror/gutter" -import {RangeSet, Range} from "@codemirror/rangeset" + WidgetType, ViewUpdate, Command, logException, KeyBinding, + hoverTooltip, Tooltip, showTooltip, gutter, GutterMarker, + PanelConstructor, Panel, showPanel, getPanel} from "@codemirror/view" +import {Text, StateEffect, StateField, Extension, TransactionSpec, Transaction, + EditorState, Facet, combineConfig, RangeSet, Range} from "@codemirror/state" import elt from "crelt" import { editingLineState, editingLinePlugin, setEditingLineEffect } from "./editingLine" @@ -67,6 +65,9 @@ export interface Diagnostic { source?: string /// The message associated with this diagnostic. message: string + /// An optional custom rendering function that displays the message + /// as a DOM node. + renderMessage?: () => Node /// An optional array of actions that can be taken on this /// diagnostic. actions?: readonly Action[] @@ -82,13 +83,33 @@ export interface Action { name: string /// The function to call when the user activates this action. Is /// given the diagnostic's _current_ position, which may have - /// changed since the creation of the diagnostic due to editing. + /// changed since the creation of the diagnostic, due to editing. apply: (view: EditorView, from: number, to: number) => void } +type DiagnosticFilter = (diagnostics: readonly Diagnostic[]) => Diagnostic[] + +interface LintConfig { + /// Time to wait (in milliseconds) after a change before running + /// the linter. Defaults to 750ms. + delay?: number + /// Optional filter to determine which diagnostics produce markers + /// in the content. + markerFilter?: null | DiagnosticFilter, + /// Filter applied to a set of diagnostics shown in a tooltip. No + /// tooltip will appear if the empty set is returned. + tooltipFilter?: null | DiagnosticFilter +} + interface LintGutterConfig { /// The delay before showing a tooltip when hovering over a lint gutter marker. - hoverTime?: number + hoverTime?: number, + /// Optional filter determining which diagnostics show a marker in + /// the gutter. + markerFilter?: null | DiagnosticFilter, + /// Optional filter for diagnostics displayed in a tooltip, which + /// can also be used to prevent a tooltip appearing. + tooltipFilter?: null | DiagnosticFilter } class SelectedDiagnostic { @@ -101,7 +122,13 @@ export class LintState { readonly selected: SelectedDiagnostic | null) {} static init(diagnostics: readonly Diagnostic[], panel: PanelConstructor | null, state: EditorState) { - let ranges = Decoration.set(diagnostics.map((d: Diagnostic) => { + // Filter the list of diagnostics for which to create markers + let markedDiagnostics = diagnostics + let diagnosticFilter = state.facet(lintConfig).markerFilter + if (diagnosticFilter) + markedDiagnostics = diagnosticFilter(markedDiagnostics) + + let ranges = Decoration.set(markedDiagnostics.map((d: Diagnostic) => { // For zero-length ranges or ranges covering only a line break, create a widget return d.from == d.to || (d.from == d.to - 1 && state.doc.lineAt(d.from).to == d.from) ? Decoration.widget({ @@ -133,6 +160,10 @@ function findDiagnostic(diagnostics: DecorationSet, diagnostic: Diagnostic | nul return found } +function hideTooltip(tr: Transaction, tooltip: Tooltip) { + return !!(tr.effects.some(e => e.is(setDiagnosticsEffect)) || tr.changes.touchesRange(tooltip.pos)) +} + function maybeEnableLint(state: EditorState, effects: readonly StateEffect[]) { return state.field(lintState, false) ? effects : effects.concat(StateEffect.appendConfig.of([ lintState, @@ -142,7 +173,7 @@ function maybeEnableLint(state: EditorState, effects: readonly StateEffect { /// - Ctrl-Shift-m (Cmd-Shift-m on macOS): [`openLintPanel`](#lint.openLintPanel) /// - F8: [`nextDiagnostic`](#lint.nextDiagnostic) export const lintKeymap: readonly KeyBinding[] = [ - {key: "Mod-Shift-m", run: openLintPanel}, + {key: "Mod-Shift-m", run: openLintPanel, preventDefault: true}, {key: "F8", run: nextDiagnostic} ] -type LintSource = (view: EditorView) => readonly Diagnostic[] | Promise +/// The type of a function that produces diagnostics. +export type LintSource = (view: EditorView) => readonly Diagnostic[] | Promise const lintPlugin = ViewPlugin.fromClass(class { lintTime: number @@ -277,7 +313,7 @@ const lintPlugin = ViewPlugin.fromClass(class { set = true constructor(readonly view: EditorView) { - let {delay} = view.state.facet(lintSource) + let {delay} = view.state.facet(lintConfig) this.lintTime = Date.now() + delay this.run = this.run.bind(this) this.timeout = setTimeout(this.run, delay) @@ -289,7 +325,7 @@ const lintPlugin = ViewPlugin.fromClass(class { setTimeout(this.run, this.lintTime - now) } else { this.set = false - let {state} = this.view, {sources} = state.facet(lintSource) + let {state} = this.view, {sources} = state.facet(lintConfig) Promise.all(sources.map(source => Promise.resolve(source(this.view)))).then( annotations => { let all = annotations.reduce((a, b) => a.concat(b)) @@ -302,12 +338,12 @@ const lintPlugin = ViewPlugin.fromClass(class { } update(update: ViewUpdate) { - let source = update.state.facet(lintSource) - if (update.docChanged || source != update.startState.facet(lintSource)) { - this.lintTime = Date.now() + source.delay + let config = update.state.facet(lintConfig) + if (update.docChanged || config != update.startState.facet(lintConfig)) { + this.lintTime = Date.now() + config.delay if (!this.set) { this.set = true - this.timeout = setTimeout(this.run, source.delay) + this.timeout = setTimeout(this.run, config.delay) } } } @@ -324,9 +360,17 @@ const lintPlugin = ViewPlugin.fromClass(class { } }) -const lintSource = Facet.define<{source: LintSource, delay: number}, {sources: readonly LintSource[], delay: number}>({ +const lintConfig = Facet.define<{source: LintSource, config: LintConfig}, + Required & {sources: readonly LintSource[]}>({ combine(input) { - return {sources: input.map(i => i.source), delay: input.length ? Math.max(...input.map(i => i.delay)) : 750} + return { + sources: input.map(i => i.source), + ...combineConfig(input.map(i => i.config), { + delay: 750, + markerFilter: null, + tooltipFilter: null + }) + } }, enables: lintPlugin }) @@ -336,13 +380,9 @@ const lintSource = Facet.define<{source: LintSource, delay: number}, {sources: r /// editor is idle (after its content changed). export function linter( source: LintSource, - config: { - /// Time to wait (in milliseconds) after a change before running - /// the linter. Defaults to 750ms. - delay?: number - } = {} + config: LintConfig = {} ): Extension { - return lintSource.of({source, delay: config.delay ?? 750}) + return lintConfig.of({source, config}) } /// Forces any linters [configured](#lint.linter) to run when the @@ -371,7 +411,7 @@ function renderDiagnostic(view: EditorView, diagnostic: Diagnostic, inPanel: boo let keys = inPanel ? assignKeys(diagnostic.actions) : [] return elt( "li", {class: "cm-diagnostic cm-diagnostic-" + diagnostic.severity}, - elt("span", {class: "cm-diagnosticText"}, diagnostic.message), + elt("span", {class: "cm-diagnosticText"}, diagnostic.renderMessage ? diagnostic.renderMessage() : diagnostic.message), diagnostic.actions?.map((action, i) => { let click = (e: Event) => { e.preventDefault() @@ -681,12 +721,11 @@ function severityRanking(severity: "hint" | "info" | "warning" | "error") { return 3 } } - class LintGutterMarker extends GutterMarker { severity: "hint" | "info" | "warning" | "error" // Diagnostics stored here may have had their 'from' field values // changed in order to maintain the gutter markers in the correct position. - constructor(public diagnostics: Diagnostic[], readonly editingLine: boolean) { + constructor(public diagnostics: readonly Diagnostic[], readonly editingLine: boolean) { super() this.severity = diagnostics.reduce((max, d) => { let s = d.severity @@ -701,7 +740,14 @@ class LintGutterMarker extends GutterMarker { ? "editing" : this.severity }`; - elt.onmouseover = () => gutterMarkerMouseOver(view, elt, this.diagnostics) + + let diagnostics = this.diagnostics + let diagnosticsFilter = view.state.facet(lintGutterConfig).tooltipFilter + if (diagnosticsFilter) diagnostics = diagnosticsFilter(diagnostics) + + if (diagnostics.length) + elt.onmouseover = () => gutterMarkerMouseOver(view, elt, diagnostics) + return elt } } @@ -747,7 +793,6 @@ function gutterMarkerMouseOver(view: EditorView, marker: HTMLElement, diagnostic } })}) } - marker.onmouseout = marker.onmousemove = null trackHoverOn(view, marker) } @@ -791,9 +836,14 @@ const lintGutterMarkers = StateField.define>({ }, update(markers, tr) { markers = markers.map(tr.changes) + let diagnosticFilter = tr.state.facet(lintGutterConfig).markerFilter for (let effect of tr.effects) { if (effect.is(setDiagnosticsEffect)) { - markers = markersForDiagnostics(tr.state.doc, effect.value, tr.state.field(editingLineState)) + let diagnostics = effect.value + if (diagnosticFilter) { + diagnostics = diagnosticFilter(diagnostics || []) + } + markers = markersForDiagnostics(tr.state.doc, diagnostics.slice(0), tr.state.field(editingLineState)) } if (effect.is(setEditingLineEffect)) { const diagnostics: Diagnostic[] = [] @@ -821,7 +871,8 @@ const setLintGutterTooltip = StateEffect.define() const lintGutterTooltip = StateField.define({ create() { return null }, update(tooltip, tr) { - if (tooltip && tr.docChanged) tooltip = {...tooltip, pos: tr.changes.mapPos(tooltip.pos)} + if (tooltip && tr.docChanged) + tooltip = hideTooltip(tr, tooltip) ? null : {...tooltip, pos: tr.changes.mapPos(tooltip.pos)} return tr.effects.reduce((t, e) => e.is(setLintGutterTooltip) ? e.value : t, tooltip) }, provide: field => showTooltip.from(field) @@ -857,9 +908,11 @@ const lintGutterConfig = Facet.define const indentWidth = state.facet(indentUnit).length * view.defaultCharacterWidth; - let topLine = view.visualLineAt(start); + let topLine = view.lineBlockAt(start); if (body) { - topLine = view.visualLineAt(topLine.to + 1); + topLine = view.lineBlockAt(topLine.to + 1); if (topLine.from > end) { // If we've fallen out of the scope of the body then the statement is all on // one line, e.g. "if True: pass". Avoid highlighting for now. @@ -123,7 +123,7 @@ export const codeStructureView = (option: "full" | "simple") => // but best to bail if we encounter it in error scenarios. return undefined; } - const bottomLine = view.visualLineAt(bottomPos); + const bottomLine = view.lineBlockAt(bottomPos); const top = topLine.top; const bottom = bottomLine.bottom; const height = bottom - top; @@ -153,14 +153,14 @@ export const codeStructureView = (option: "full" | "simple") => }[] = []; if (tree) { tree.iterate({ - enter: (type, _start) => { - parents.push({ name: type.name }); - if (type.name === "Body") { + enter: (node) => { + parents.push({ name: node.type.name }); + if (node.type.name === "Body") { depth++; } }, - leave: (type, start, end) => { - if (type.name === "Body") { + leave: (node) => { + if (node.type.name === "Body") { depth--; } @@ -209,7 +209,11 @@ export const codeStructureView = (option: "full" | "simple") => if (!parent.children) { parent.children = []; } - parent.children.push({ name: type.name, start, end }); + parent.children.push({ + name: node.type.name, + start: node.from, + end: node.to, + }); } }, });