diff --git a/.gitignore b/.gitignore index f561f81dd..211059b16 100644 --- a/.gitignore +++ b/.gitignore @@ -42,4 +42,9 @@ src/test/testCode.doenet **/cypress/videos **/cypress/screenshots runner-results -parallel-weights.json \ No newline at end of file +parallel-weights.json + +out +node_modules +client/server +.vscode-test diff --git a/package-lock.json b/package-lock.json index d443ddd13..860783be7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "./packages/ui-components", "./packages/utils", "./packages/parser", + "./packages/lsp-tools", "./packages/doenetml-worker", "./packages/static-assets", "./packages/virtual-keyboard", @@ -114,11 +115,11 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", - "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dependencies": { - "@babel/highlight": "^7.22.10", + "@babel/highlight": "^7.22.13", "chalk": "^2.4.2" }, "engines": { @@ -126,32 +127,32 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", - "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", + "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz", - "integrity": "sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", + "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.10", - "@babel/generator": "^7.22.10", - "@babel/helper-compilation-targets": "^7.22.10", - "@babel/helper-module-transforms": "^7.22.9", - "@babel/helpers": "^7.22.10", - "@babel/parser": "^7.22.10", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.10", - "@babel/types": "^7.22.10", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.2", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", + "json5": "^2.2.3", "semver": "^6.3.1" }, "engines": { @@ -162,12 +163,17 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, "node_modules/@babel/generator": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", - "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dependencies": { - "@babel/types": "^7.22.10", + "@babel/types": "^7.23.0", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -200,12 +206,12 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz", - "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", "dependencies": { "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", "browserslist": "^4.21.9", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -228,20 +234,20 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" @@ -259,26 +265,26 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", - "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", - "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", "@babel/helper-simple-access": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.5" + "@babel/helper-validator-identifier": "^7.22.20" }, "engines": { "node": ">=6.9.0" @@ -327,40 +333,40 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", - "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz", - "integrity": "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", + "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", "dependencies": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.10", - "@babel/types": "^7.22.10" + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", - "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, @@ -369,9 +375,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz", - "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "bin": { "parser": "bin/babel-parser.js" }, @@ -433,31 +439,31 @@ } }, "node_modules/@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz", - "integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==", - "dependencies": { - "@babel/code-frame": "^7.22.10", - "@babel/generator": "^7.22.10", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.10", - "@babel/types": "^7.22.10", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -466,12 +472,12 @@ } }, "node_modules/@babel/types": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", - "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dependencies": { "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -1788,14 +1794,14 @@ } }, "node_modules/@codemirror/commands": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.2.5.tgz", - "integrity": "sha512-dSi7ow2P2YgPBZflR9AJoaTHvqmeGIgkhignYMd5zK5y6DANTvxKxp6eMEpIDUJkRAaOY/TFZ4jP1ADIO/GLVA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.3.0.tgz", + "integrity": "sha512-tFfcxRIlOWiQDFhjBSWJ10MxcvbCIsRr6V64SgrcaY0MwNk32cUOcCuNlWo8VjV4qRQCgNgUAnIeo0svkk4R5Q==", "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.2.0", "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0" + "@lezer/common": "^1.1.0" } }, "node_modules/@codemirror/lang-xml": { @@ -1811,13 +1817,13 @@ } }, "node_modules/@codemirror/language": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.9.0.tgz", - "integrity": "sha512-nFu311/0ne/qGuGCL3oKuktBgzVOaxCHZPZv1tLSZkNjPYxxvkjSbzno3MlErG2tgw1Yw1yF8BxMCegeMXqpiw==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.9.1.tgz", + "integrity": "sha512-lWRP3Y9IUdOms6DXuBpoWwjkR7yRmnS0hKYCbSfPz9v6Em1A1UCRujAkDiCrdYfs1Z0Eu4dGtwovNPStIfkgNA==", "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0", + "@lezer/common": "^1.1.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0", "style-mod": "^4.0.0" @@ -1844,14 +1850,14 @@ } }, "node_modules/@codemirror/state": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.1.tgz", - "integrity": "sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.3.1.tgz", + "integrity": "sha512-88e4HhMtKJyw6fKprGaN/yZfiaoGYOi2nM45YCUC6R/kex9sxFWBDGatS1vk4lMgnWmdIIB9tk8Gj1LmL8YfvA==" }, "node_modules/@codemirror/view": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.18.1.tgz", - "integrity": "sha512-xcsXcMkIMd7l3WZEWoc4ljteAiqzxb5gVerRxk5132p5cLix6rTydWTQjsj2oxORepfsrwy1fC4r20iMa9plrg==", + "version": "6.21.3", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.21.3.tgz", + "integrity": "sha512-8l1aSQ6MygzL4Nx7GVYhucSXvW4jQd0F6Zm3v9Dg+6nZEfwzJVqi4C2zHfDljID+73gsQrWp9TgHc81xU15O4A==", "dependencies": { "@codemirror/state": "^6.1.4", "style-mod": "^4.1.0", @@ -1953,6 +1959,10 @@ "resolved": "packages/doenetml-worker", "link": true }, + "node_modules/@doenet/lsp-tools": { + "resolved": "packages/lsp-tools", + "link": true + }, "node_modules/@doenet/parser": { "resolved": "packages/parser", "link": true @@ -2565,18 +2575,6 @@ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/@eslint-community/regexpp": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", @@ -2637,9 +2635,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz", - "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", + "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2707,9 +2705,9 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", @@ -2910,9 +2908,9 @@ } }, "node_modules/@lezer/common": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.4.tgz", - "integrity": "sha512-lZHlk8p67x4aIDtJl6UQrXSOP6oi7dQR3W/geFVrENdA1JDaAJWldnVqVjPMJupbTKbzDfFcePfKttqVidS/dg==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.1.0.tgz", + "integrity": "sha512-XPIN3cYDXsoJI/oDWoR2tD++juVrhgIago9xyKhZ7IhGlzdDM9QgC8D8saKNCz5pindGcznFr2HBSsEQSWnSjw==" }, "node_modules/@lezer/generator": { "version": "1.5.0", @@ -2935,9 +2933,9 @@ } }, "node_modules/@lezer/lr": { - "version": "1.3.10", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.10.tgz", - "integrity": "sha512-BZfVvf7Re5BIwJHlZXbJn9L8lus5EonxQghyn+ih8Wl36XMFBPTXC0KM0IdUtj9w/diPHsKlXVgL+AlX2jYJ0Q==", + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.13.tgz", + "integrity": "sha512-RLAbau/4uSzKgIKj96mI5WUtG1qtiR0Frn0Ei9zhPj8YOkHM+1Bb8SgdVvmR/aWJCFIzjo2KFnDiRZ75Xf5NdQ==", "dependencies": { "@lezer/common": "^1.0.0" } @@ -3013,6 +3011,52 @@ "node": ">=12.20" } }, + "node_modules/@microsoft/fast-element": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@microsoft/fast-element/-/fast-element-1.12.0.tgz", + "integrity": "sha512-gQutuDHPKNxUEcQ4pypZT4Wmrbapus+P9s3bR/SEOLsMbNqNoXigGImITygI5zhb+aA5rzflM6O8YWkmRbGkPA==", + "dev": true + }, + "node_modules/@microsoft/fast-foundation": { + "version": "2.49.2", + "resolved": "https://registry.npmjs.org/@microsoft/fast-foundation/-/fast-foundation-2.49.2.tgz", + "integrity": "sha512-xA7WP/Td33SW0zkpHRH5LUDxyLOPnPQQXieRxc080uLWxoGXhVxo6Rz7b6qwiL+e2IadNCm7X7KcrgsUhJwvBg==", + "dev": true, + "dependencies": { + "@microsoft/fast-element": "^1.12.0", + "@microsoft/fast-web-utilities": "^5.4.1", + "tabbable": "^5.2.0", + "tslib": "^1.13.0" + } + }, + "node_modules/@microsoft/fast-foundation/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@microsoft/fast-react-wrapper": { + "version": "0.1.48", + "resolved": "https://registry.npmjs.org/@microsoft/fast-react-wrapper/-/fast-react-wrapper-0.1.48.tgz", + "integrity": "sha512-9NvEjru9Kn5ZKjomAMX6v+eF0DR+eDkxKDwDfi+Wb73kTbrNzcnmlwd4diN15ygH97kldgj2+lpvI4CKLQQWLg==", + "dev": true, + "dependencies": { + "@microsoft/fast-element": "^1.9.0", + "@microsoft/fast-foundation": "^2.41.1" + }, + "peerDependencies": { + "react": ">=16.9.0" + } + }, + "node_modules/@microsoft/fast-web-utilities": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@microsoft/fast-web-utilities/-/fast-web-utilities-5.4.1.tgz", + "integrity": "sha512-ReWYncndjV3c8D8iq9tp7NcFNc1vbVHvcBFPME2nNFKNbS1XCesYZGlIlf3ot5EmuOXPlrzUHOWzQ2vFpIkqDg==", + "dev": true, + "dependencies": { + "exenv-es6": "^1.1.1" + } + }, "node_modules/@microsoft/tsdoc": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", @@ -3258,6 +3302,47 @@ "integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==", "dev": true }, + "node_modules/@types/babel__core": { + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.3.tgz", + "integrity": "sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.6", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.6.tgz", + "integrity": "sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.3.tgz", + "integrity": "sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.3.tgz", + "integrity": "sha512-Lsh766rGEFbaxMIDH7Qa+Yha8cMVI3qAK6CHt3OR0YfxOIn5Z54iHiyDRycHrBqeIiqGa20Kpsv1cavfBKkRSw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, "node_modules/@types/chai": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", @@ -3287,6 +3372,12 @@ "@types/node": "*" } }, + "node_modules/@types/json-schema": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", + "dev": true + }, "node_modules/@types/lodash": { "version": "4.14.192", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.192.tgz", @@ -3304,9 +3395,19 @@ "version": "5.1.2", "license": "MIT" }, + "node_modules/@types/mocha": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz", + "integrity": "sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==", + "dev": true + }, "node_modules/@types/node": { - "version": "18.11.4", - "license": "MIT" + "version": "20.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", + "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "dependencies": { + "undici-types": "~5.25.1" + } }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", @@ -3354,6 +3455,12 @@ "devOptional": true, "license": "MIT" }, + "node_modules/@types/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", + "dev": true + }, "node_modules/@types/sinonjs__fake-timers": { "version": "8.1.1", "dev": true, @@ -3369,6 +3476,18 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.0.tgz", "integrity": "sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w==" }, + "node_modules/@types/vscode": { + "version": "1.83.1", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.83.1.tgz", + "integrity": "sha512-BHu51NaNKOtDf3BOonY3sKFFmZKEpRkzqkZVpSYxowLbs5JqjOQemYFob7Gs5rpxE5tiGhfpnMpcdF/oKrLg4w==", + "dev": true + }, + "node_modules/@types/vscode-webview": { + "version": "1.57.3", + "resolved": "https://registry.npmjs.org/@types/vscode-webview/-/vscode-webview-1.57.3.tgz", + "integrity": "sha512-8at2UVGjA/6gcLOay+J8wOars6VsDqAqPxRHYihH0XFUaXt+2AZ+Hd9hSoUbnhjicb6V1xe7rfjb7j4Ri2n1fg==", + "dev": true + }, "node_modules/@types/xast": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/xast/-/xast-2.0.0.tgz", @@ -3377,21 +3496,261 @@ "@types/unist": "*" } }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.8.0.tgz", + "integrity": "sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.8.0", + "@typescript-eslint/type-utils": "6.8.0", + "@typescript-eslint/utils": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.8.0.tgz", + "integrity": "sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.8.0", + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/typescript-estree": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", + "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.8.0.tgz", + "integrity": "sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.8.0", + "@typescript-eslint/utils": "6.8.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", + "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", + "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.8.0.tgz", + "integrity": "sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.8.0", + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/typescript-estree": "6.8.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", + "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.8.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + }, "node_modules/@vitejs/plugin-react": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.4.tgz", - "integrity": "sha512-7wU921ABnNYkETiMaZy7XqpueMnpu5VxvVps13MjmCo+utBdD79sZzrApHawHtVX66cCJQQTXFcjH0y9dSUK8g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.1.0.tgz", + "integrity": "sha512-rM0SqazU9iqPUraQ2JlIvReeaxOoRj6n+PzB1C0cBzIbd8qP336nC39/R9yPi3wVcah7E7j/kdU1uCUqMEU4OQ==", "dev": true, "dependencies": { - "@babel/core": "^7.22.9", + "@babel/core": "^7.22.20", "@babel/plugin-transform-react-jsx-self": "^7.22.5", "@babel/plugin-transform-react-jsx-source": "^7.22.5", + "@types/babel__core": "^7.20.2", "react-refresh": "^0.14.0" }, "engines": { @@ -3549,6 +3908,20 @@ "@volar/language-core": "1.10.1" } }, + "node_modules/@vscode/webview-ui-toolkit": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-1.2.2.tgz", + "integrity": "sha512-xIQoF4FC3Xh6d7KNKIoIezSiFWYFuf6gQMdDyKueKBFGeKwaHWEn+dY2g3makvvEsNMEDji/woEwvg9QSbuUsw==", + "dev": true, + "dependencies": { + "@microsoft/fast-element": "^1.6.2", + "@microsoft/fast-foundation": "^2.38.0", + "@microsoft/fast-react-wrapper": "^0.1.18" + }, + "peerDependencies": { + "react": ">=16.9.0" + } + }, "node_modules/@vue/compiler-core": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz", @@ -3780,7 +4153,8 @@ }, "node_modules/ansi-styles": { "version": "3.2.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dependencies": { "color-convert": "^1.9.0" }, @@ -3875,6 +4249,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/array-uniq": { "version": "1.0.3", "license": "MIT", @@ -4408,6 +4791,15 @@ "which": "bin/which" } }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "license": "MIT" @@ -4477,7 +4869,29 @@ "react": ">=16.8" } }, - "node_modules/binary-extensions": { + "node_modules/big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", + "dev": true, + "dependencies": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { "version": "2.2.0", "devOptional": true, "license": "MIT", @@ -4615,9 +5029,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.10", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", - "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", "funding": [ { "type": "opencollective", @@ -4633,10 +5047,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001517", - "electron-to-chromium": "^1.4.477", + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.11" + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" @@ -4684,12 +5098,30 @@ "optional": true, "peer": true }, + "node_modules/buffer-indexof-polyfill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, "node_modules/buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", "dev": true }, + "node_modules/buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", + "dev": true, + "engines": { + "node": ">=0.2.0" + } + }, "node_modules/builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", @@ -4773,9 +5205,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001520", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001520.tgz", - "integrity": "sha512-tahF5O9EiiTzwTUqAeFjIZbn4Dnqxzz7ktrgGlMYNLH43Ul26IgTMH/zvL3DG0lZxBYnlT04axvInszUsZULdA==", + "version": "1.0.30001551", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001551.tgz", + "integrity": "sha512-vtBAez47BoGMMzlbYhfXrMV1kvRF2WP/lqiMuDu1Sb4EE4LKEgjopFDSRtZfdVnslNRpOqV/woE+Xgrwj6VQlg==", "funding": [ { "type": "opencollective", @@ -4824,9 +5256,22 @@ "node": ">=4" } }, + "node_modules/chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", + "dev": true, + "dependencies": { + "traverse": ">=0.3.0 <0.4" + }, + "engines": { + "node": "*" + } + }, "node_modules/chalk": { "version": "2.4.2", - "license": "MIT", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -5087,14 +5532,16 @@ }, "node_modules/color-convert": { "version": "1.9.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { "color-name": "1.1.3" } }, "node_modules/color-name": { "version": "1.1.3", - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/color2k": { "version": "2.0.2", @@ -5574,15 +6021,6 @@ "node": ">=0.10.0" } }, - "node_modules/cypress-parallel/node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/cypress-parallel/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -5768,15 +6206,6 @@ "node": ">=8" } }, - "node_modules/cypress-parallel/node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/cypress-parallel/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -6139,6 +6568,14 @@ "node": ">=0.4.0" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, "node_modules/des.js": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", @@ -6161,6 +6598,27 @@ "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -6187,6 +6645,18 @@ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/doctrine": { "version": "3.0.0", "dev": true, @@ -6198,6 +6668,10 @@ "node": ">=6.0.0" } }, + "node_modules/doenet-vscode-extension": { + "resolved": "packages/doenet-vscode-extension", + "link": true + }, "node_modules/domain-browser": { "version": "4.22.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz", @@ -6226,6 +6700,45 @@ "version": "2.4.0", "license": "(MPL-2.0 OR Apache-2.0)" }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexer2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/duplexer2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -6257,9 +6770,9 @@ "integrity": "sha512-9xUSSj7qcUxz+0r4X3+bwUNttEfGfK5AH+LVa1aTpqdAfrN5VhROYCfcF+up4hp5OL7IUKcZJJrzAGipQRDoiQ==" }, "node_modules/electron-to-chromium": { - "version": "1.4.492", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.492.tgz", - "integrity": "sha512-36K9b/6skMVwAIEsC7GiQ8I8N3soCALVSHqWHzNDtGemAcI9Xu8hP02cywWM0A794rTHm0b0zHPeLJHtgFVamQ==" + "version": "1.4.562", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.562.tgz", + "integrity": "sha512-kMGVZLP65O2/oH7zzaoIA5hcr4/xPYO6Sa83FrIpWcd7YPPtSlxqwxTd8lJIwKxaiXM6FGsYK4ukyJ40XkW7jg==" }, "node_modules/elliptic": { "version": "6.5.4", @@ -6449,16 +6962,16 @@ } }, "node_modules/eslint": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz", - "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", + "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "^8.47.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint/js": "8.51.0", + "@humanwhocodes/config-array": "^0.11.11", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.12.4", @@ -6578,6 +7091,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/eslint/node_modules/ansi-styles": { "version": "4.3.0", "dev": true, @@ -6650,18 +7175,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/eslint/node_modules/glob-parent": { "version": "6.0.2", "dev": true, @@ -6747,18 +7260,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/esquery": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", @@ -6874,6 +7375,12 @@ "node": ">=4" } }, + "node_modules/exenv-es6": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exenv-es6/-/exenv-es6-1.1.1.tgz", + "integrity": "sha512-vlVu3N8d6yEMpMsEm+7sUBAI81aqYYuEvfK0jNqmdb/OPXzzH7QWDDnVjMvDSY47JdHEqx/dfC/q8WkfoTmpGQ==", + "dev": true + }, "node_modules/expand-brackets": { "version": "2.1.4", "license": "MIT", @@ -7406,6 +7913,33 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/fstream/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/function-bind": { "version": "1.1.1", "license": "MIT" @@ -7586,6 +8120,26 @@ "node": ">=4" } }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -7944,9 +8498,10 @@ "license": "BSD-3-Clause" }, "node_modules/ignore": { - "version": "5.2.0", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true, - "license": "MIT", "engines": { "node": ">= 4" } @@ -8472,9 +9027,9 @@ "dev": true }, "node_modules/jackspeak": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.0.tgz", - "integrity": "sha512-uKmsITSsF4rUWQHzqaRUuyAir3fZfW3f202Ee34lz/gZCi970CPZwyQXLGNgWJvvZbvFyzeyGq0+4fcG/mBKZg==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" @@ -8699,6 +9254,12 @@ "version": "1.2.4", "license": "MIT" }, + "node_modules/listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", + "dev": true + }, "node_modules/listr2": { "version": "3.14.0", "dev": true, @@ -9193,6 +9754,17 @@ "version": "0.6.1", "license": "Apache-2.0" }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/mlly": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.1.tgz", @@ -9256,16 +9828,6 @@ "node": ">=6" } }, - "node_modules/mocha/node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/mocha/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -9366,16 +9928,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/mocha/node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "peer": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -10026,7 +10578,6 @@ "node_modules/path-type": { "version": "4.0.0", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -10062,6 +10613,29 @@ "node": ">=0.12" } }, + "node_modules/peggy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/peggy/-/peggy-3.0.2.tgz", + "integrity": "sha512-n7chtCbEoGYRwZZ0i/O3t1cPr6o+d9Xx4Zwy2LYfzv0vjchMBU0tO+qYYyvZloBPcgRgzYvALzGWHe609JjEpg==", + "dependencies": { + "commander": "^10.0.0", + "source-map-generator": "0.8.0" + }, + "bin": { + "peggy": "bin/peggy.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/peggy/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "engines": { + "node": ">=14" + } + }, "node_modules/pend": { "version": "1.2.0", "dev": true, @@ -10196,10 +10770,9 @@ } }, "node_modules/prettier": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.2.tgz", - "integrity": "sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ==", - "dev": true, + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", + "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", "bin": { "prettier": "bin/prettier.cjs" }, @@ -10210,6 +10783,18 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/prettier-plugin-pegjs": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/prettier-plugin-pegjs/-/prettier-plugin-pegjs-2.0.2.tgz", + "integrity": "sha512-Be4LyuLM6CPxPDCTvcpi7R9zSLHPDijvmzk2bk2Wba8V3m3AThSuwtSaX6c8sug/v5PYSE+aVc8ZvQG7xr3Azg==", + "dependencies": { + "@types/node": "^20.5.6", + "prettier": "^3.0.2" + }, + "engines": { + "node": ">= 16.0" + } + }, "node_modules/pretty-bytes": { "version": "5.6.0", "dev": true, @@ -10264,6 +10849,12 @@ "node": ">= 0.6.0" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, "node_modules/prop-types": { "version": "15.8.1", "license": "MIT", @@ -10617,6 +11208,15 @@ "react-dom": ">=16.0.0" } }, + "node_modules/react18-json-view": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/react18-json-view/-/react18-json-view-0.2.6.tgz", + "integrity": "sha512-RHAY880UwC7SClyQBoij50q2InpSrj5zmP2DCL73vEaaVTyj/QbMPBk4FRKMQ7LF8FSxhh+VI6mK3AhlBaCBxw==", + "dev": true, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/read-pkg": { "version": "5.2.0", "license": "MIT", @@ -11113,6 +11713,15 @@ "semver": "bin/semver.js" } }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -11214,6 +11823,15 @@ "version": "3.0.7", "license": "ISC" }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/slice-ansi": { "version": "3.0.0", "dev": true, @@ -11439,6 +12057,14 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-generator": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/source-map-generator/-/source-map-generator-0.8.0.tgz", + "integrity": "sha512-psgxdGMwl5MZM9S3FWee4EgsEaIjahYV5AzGnwUvPhWeITz/j6rKpysQHlQ4USdxvINlb8lKfWGIXwfkrgtqkA==", + "engines": { + "node": ">= 10" + } + }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", @@ -11920,6 +12546,12 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "node_modules/tabbable": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz", + "integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==", + "dev": true + }, "node_modules/terser": { "version": "5.15.1", "dev": true, @@ -12108,11 +12740,41 @@ "node": ">=14" } }, - "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, + "node_modules/traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/trough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz", + "integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, "node_modules/tty-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", @@ -12212,6 +12874,40 @@ "version": "1.13.6", "license": "MIT" }, + "node_modules/undici-types": { + "version": "5.25.3", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", + "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==" + }, + "node_modules/unified": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.2.tgz", + "integrity": "sha512-Zta++onvS/dJ6xUvXQOR5q8XJZOkiMCE5wQ8Yv9mLR25pxRS567EX0GO6HZRxxNV/lznwfsvRZ/1pqe9K9QLeQ==", + "dependencies": { + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unified/node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/union-value": { "version": "1.0.1", "license": "MIT", @@ -12232,6 +12928,18 @@ "node": ">=0.10.0" } }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/universalify": { "version": "2.0.0", "dev": true, @@ -12296,10 +13004,64 @@ "node": ">=8" } }, + "node_modules/unzipper": { + "version": "0.10.14", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz", + "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", + "dev": true, + "dependencies": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "^1.0.12", + "graceful-fs": "^4.2.2", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + } + }, + "node_modules/unzipper/node_modules/bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", + "dev": true + }, + "node_modules/unzipper/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/unzipper/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/unzipper/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "funding": [ { "type": "opencollective", @@ -12471,10 +13233,37 @@ "extsprintf": "^1.2.0" } }, + "node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/vite": { - "version": "4.4.9", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz", - "integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", + "integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==", "dev": true, "dependencies": { "esbuild": "^0.18.10", @@ -12550,12 +13339,12 @@ } }, "node_modules/vite-plugin-dts": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-3.5.2.tgz", - "integrity": "sha512-iKc851+jdHEoN1ifbOEsoMs+/Zg26PE1EyO2Jc+4apOWRoaeK2zRJnaStgUuJaVaEcAjTqWzpNgCAMq7iO6DWA==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-3.6.0.tgz", + "integrity": "sha512-doxhDRFJCZD2sGjIp4V800nm8Y19GvmwckjG5vYPuiqJ7OBjc9NlW1Vp9Gkyh2aXlUs1jTDRH/lxWfcsPLOQHg==", "dev": true, "dependencies": { - "@microsoft/api-extractor": "^7.36.3", + "@microsoft/api-extractor": "^7.36.4", "@rollup/pluginutils": "^5.0.2", "@vue/language-core": "^1.8.8", "debug": "^4.3.4", @@ -12747,6 +13536,82 @@ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "dev": true }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "dev": true, + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dev": true, + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "dev": true + }, + "node_modules/vscode-test": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.6.1.tgz", + "integrity": "sha512-086q88T2ca1k95mUzffvbzb7esqQNvJgiwY4h29ukPhFo8u+vXOOmelUoU5EQUHs3Of8+JuQ3oGdbVCqaxuTXA==", + "deprecated": "This package has been renamed to @vscode/test-electron, please update to the new name", + "dev": true, + "dependencies": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "rimraf": "^3.0.2", + "unzipper": "^0.10.11" + }, + "engines": { + "node": ">=8.9.3" + } + }, + "node_modules/vscode-test/node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/vscode-test/node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/vue-template-compiler": { "version": "2.7.14", "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.14.tgz", @@ -13132,16 +13997,6 @@ "node": ">=4" } }, - "node_modules/write/node_modules/mkdirp": { - "version": "0.5.6", - "license": "MIT", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/ws": { "version": "8.13.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", @@ -13252,7 +14107,6 @@ "version": "16.2.0", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -13270,7 +14124,6 @@ "version": "20.2.9", "dev": true, "license": "ISC", - "peer": true, "engines": { "node": ">=10" } @@ -13360,21 +14213,21 @@ "version": "*", "license": "AGPL-3.0-or-later", "dependencies": { - "@codemirror/commands": "^6.2.5", + "@codemirror/commands": "^6.3.0", "@codemirror/lang-xml": "^6.0.2", - "@codemirror/language": "^6.9.0", - "@codemirror/state": "^6.2.1", - "@codemirror/view": "^6.18.1", - "@lezer/common": "^1.0.4", + "@codemirror/language": "^6.9.1", + "@codemirror/state": "^6.3.1", + "@codemirror/view": "^6.21.3", + "@lezer/common": "^1.1.0", "@lezer/highlight": "^1.1.6", - "@lezer/lr": "^1.3.10", + "@lezer/lr": "^1.3.13", "@lezer/xml": "^1.0.2", "codemirror": "6.0.1" }, "devDependencies": { - "glob": "^10.3.3", - "vite": "^4.4.9", - "vite-plugin-dts": "^3.5.2" + "glob": "^10.3.10", + "vite": "^4.5.0", + "vite-plugin-dts": "^3.6.0" } }, "packages/codemirror/node_modules/brace-expansion": { @@ -13387,19 +14240,19 @@ } }, "packages/codemirror/node_modules/glob": { - "version": "10.3.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", - "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", + "jackspeak": "^2.3.5", "minimatch": "^9.0.1", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", "path-scurry": "^1.10.1" }, "bin": { - "glob": "dist/cjs/src/bin.js" + "glob": "dist/esm/bin.mjs" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -13426,125 +14279,687 @@ "packages/codemirror/parser": { "extraneous": true }, - "packages/doenetml": { - "name": "@doenet/doenetml", - "version": "0.7.0-alpha1", - "license": "AGPL-3.0-or-later", - "dependencies": { - "@chakra-ui/icons": "^2.0.19", - "@chakra-ui/react": "^2.7.0", - "@fortawesome/fontawesome-svg-core": "^6.1.2", - "@fortawesome/free-regular-svg-icons": "^6.1.2", - "@fortawesome/free-solid-svg-icons": "^6.1.2", - "@fortawesome/react-fontawesome": "^0.2.0", - "@handsontable/react": "^12.4.0", - "axios": "^0.27.2", - "better-react-mathjax": "^2.0.1", - "copy-to-clipboard": "^3.3.2", - "crypto-js": "^4.1.1", - "cssesc": "^3.0.0", - "esm-seedrandom": "^3.0.5", - "handsontable": "^12.4.0", - "hi-base32": "^0.5.1", - "hyperformula": "^2.5.0", - "idb-keyval": "^6.2.1", - "json-stringify-deterministic": "^1.0.8", - "lorem-ipsum": "^2.0.8", - "math-expressions": "^2.0.0-alpha64", - "nanoid": "^4.0.0", - "prismjs": "^1.29.0", - "react-copy-to-clipboard": "^5.0.3", - "react-icons": "^4.9.0", - "react-mathquill": "^1.0.3", - "react-measure": "^2.5.2", - "react-router": "^6.11.2", - "react-router-dom": "^6.11.2", - "react-simple-code-editor": "^0.13.0", - "react-visibility-sensor-v2": "^1.0.0", - "recoil": "^0.7.7", - "styled-components": "^5.3.11" - }, + "packages/doenet-vscode-extension": { + "version": "1.0.0", + "hasInstallScript": true, + "license": "AGPL", "devDependencies": { - "@babel/core": "^7.18.9", - "@esbuild-plugins/node-globals-polyfill": "^0.2.3", - "@esbuild-plugins/node-modules-polyfill": "^0.2.2", - "@types/react": "^18.0.37", - "@types/react-dom": "^18.0.11", - "@vitejs/plugin-react": "^4.0.0", - "cypress": "^12.13.0", - "cypress-parallel": "^0.13.0", - "cypress-plugin-tab": "^1.0.5", - "cypress-wait-until": "^1.7.2", - "eslint": "^8.38.0", - "eslint-plugin-react": "^7.32.2", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.3.4", - "prettier": "^3.0.2", + "@types/mocha": "^9.1.1", + "@types/node": "^20.8.7", + "@types/vscode": "^1.83.1", + "@types/vscode-webview": "^1.57.3", + "@typescript-eslint/eslint-plugin": "^6.8.0", + "@typescript-eslint/parser": "^6.8.0", + "@vitejs/plugin-react": "^4.1.0", + "@vscode/webview-ui-toolkit": "^1.2.2", + "eslint": "^8.51.0", + "mocha": "^9.2.2", "react": "^18.2.0", "react-dom": "^18.2.0", - "rollup-plugin-polyfill-node": "^0.12.0", - "vite": "^4.3.9" + "typescript": "^5.2.2", + "vite": "^4.5.0", + "vscode-test": "^1.6.1" }, - "peerDependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0", - "styled-components": "^5.3.11" + "engines": { + "vscode": "^1.76.0" + } + }, + "packages/doenet-vscode-extension/node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "packages/doenet-vscode-extension/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "packages/doenet-vscode-extension/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/doenet-vscode-extension/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/doenet-vscode-extension/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "packages/doenet-vscode-extension/node_modules/mocha": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", + "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.3", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "4.2.1", + "ms": "2.1.3", + "nanoid": "3.3.1", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.2.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "packages/doenet-vscode-extension/node_modules/mocha/node_modules/minimatch": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", + "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": ">=10" + } + }, + "packages/doenet-vscode-extension/node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "packages/doenet-vscode-extension/node_modules/nanoid": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "packages/doenet-vscode-extension/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "packages/doenet-vscode-extension/node_modules/workerpool": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", + "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", + "dev": true + }, + "packages/doenet-vscode-extension/node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "packages/doenetml": { + "name": "@doenet/doenetml", + "version": "0.7.0-alpha1", + "license": "AGPL-3.0-or-later", + "dependencies": { + "@chakra-ui/icons": "^2.0.19", + "@chakra-ui/react": "^2.7.0", + "@fortawesome/fontawesome-svg-core": "^6.1.2", + "@fortawesome/free-regular-svg-icons": "^6.1.2", + "@fortawesome/free-solid-svg-icons": "^6.1.2", + "@fortawesome/react-fontawesome": "^0.2.0", + "@handsontable/react": "^12.4.0", + "axios": "^0.27.2", + "better-react-mathjax": "^2.0.1", + "copy-to-clipboard": "^3.3.2", + "crypto-js": "^4.1.1", + "cssesc": "^3.0.0", + "esm-seedrandom": "^3.0.5", + "handsontable": "^12.4.0", + "hi-base32": "^0.5.1", + "hyperformula": "^2.5.0", + "idb-keyval": "^6.2.1", + "json-stringify-deterministic": "^1.0.8", + "lorem-ipsum": "^2.0.8", + "math-expressions": "^2.0.0-alpha64", + "nanoid": "^4.0.0", + "prismjs": "^1.29.0", + "react-copy-to-clipboard": "^5.0.3", + "react-icons": "^4.9.0", + "react-mathquill": "^1.0.3", + "react-measure": "^2.5.2", + "react-router": "^6.11.2", + "react-router-dom": "^6.11.2", + "react-simple-code-editor": "^0.13.0", + "react-visibility-sensor-v2": "^1.0.0", + "recoil": "^0.7.7", + "styled-components": "^5.3.11" + }, + "devDependencies": { + "@babel/core": "^7.18.9", + "@esbuild-plugins/node-globals-polyfill": "^0.2.3", + "@esbuild-plugins/node-modules-polyfill": "^0.2.2", + "@types/react": "^18.0.37", + "@types/react-dom": "^18.0.11", + "@vitejs/plugin-react": "^4.0.0", + "cypress": "^12.13.0", + "cypress-parallel": "^0.13.0", + "cypress-plugin-tab": "^1.0.5", + "cypress-wait-until": "^1.7.2", + "eslint": "^8.38.0", + "eslint-plugin-react": "^7.32.2", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.3.4", + "prettier": "^3.0.3", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "rollup-plugin-polyfill-node": "^0.12.0", + "vite": "^4.5.0" + }, + "peerDependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "styled-components": "^5.3.11" + } + }, + "packages/doenetml-worker": { + "name": "@doenet/doenetml-worker", + "version": "*", + "license": "AGPL-3.0-or-later", + "dependencies": { + "compromise": "^13.11.4", + "compromise-numbers": "^1.4.0" + }, + "devDependencies": { + "node-stdlib-browser": "^1.2.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "rollup-plugin-polyfill-node": "^0.12.0", + "vite": "^4.5.0", + "vite-plugin-static-copy": "^0.17.0" + }, + "peerDependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "styled-components": "^5.3.11" + } + }, + "packages/doenetml-worker/doenetlml": { + "extraneous": true + }, + "packages/doenetml-worker/node_modules/compromise": { + "version": "13.11.4", + "resolved": "https://registry.npmjs.org/compromise/-/compromise-13.11.4.tgz", + "integrity": "sha512-nBITcNdqIHSVDDluaG6guyFFCSNXN+Hu87fU8VlhkE5Z0PwTZN1nro2O7a8JcUH88nB5EOzrxd9zKfXLSNFqcg==", + "dependencies": { + "efrt-unpack": "2.2.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "packages/doenetml/virtual-keyboard": { + "extraneous": true + }, + "packages/lsp-tools": { + "name": "@doenet/lsp-tools", + "version": "1.0.0", + "license": "AGPL-3.0-or-later", + "devDependencies": { + "vite": "^4.5.0", + "vite-plugin-dts": "^3.6.0", + "vscode-languageserver": "^9.0.1" + } + }, + "packages/parser": { + "name": "@doenet/parser", + "version": "*", + "license": "AGPL-3.0-or-later", + "dependencies": { + "@lezer/common": "^1.0.4", + "@lezer/generator": "^1.5.0", + "@lezer/lr": "^1.3.10", + "@types/xast": "^2.0.0", + "peggy": "^3.0.2", + "prettier-plugin-pegjs": "^2.0.2", + "unified": "^11.0.2", + "xast-util-to-xml": "^4.0.0" + }, + "devDependencies": { + "esbuild": "^0.19.5", + "glob": "^10.3.10", + "react18-json-view": "^0.2.6", + "vite": "^4.5.0", + "vite-plugin-dts": "^3.6.0" + } + }, + "packages/parser/node_modules/@esbuild/android-arm": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.5.tgz", + "integrity": "sha512-bhvbzWFF3CwMs5tbjf3ObfGqbl/17ict2/uwOSfr3wmxDE6VdS2GqY/FuzIPe0q0bdhj65zQsvqfArI9MY6+AA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "packages/parser/node_modules/@esbuild/android-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.5.tgz", + "integrity": "sha512-5d1OkoJxnYQfmC+Zd8NBFjkhyCNYwM4n9ODrycTFY6Jk1IGiZ+tjVJDDSwDt77nK+tfpGP4T50iMtVi4dEGzhQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "packages/parser/node_modules/@esbuild/android-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.5.tgz", + "integrity": "sha512-9t+28jHGL7uBdkBjL90QFxe7DVA+KGqWlHCF8ChTKyaKO//VLuoBricQCgwhOjA1/qOczsw843Fy4cbs4H3DVA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "packages/parser/node_modules/@esbuild/darwin-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.5.tgz", + "integrity": "sha512-mvXGcKqqIqyKoxq26qEDPHJuBYUA5KizJncKOAf9eJQez+L9O+KfvNFu6nl7SCZ/gFb2QPaRqqmG0doSWlgkqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "packages/parser/node_modules/@esbuild/darwin-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.5.tgz", + "integrity": "sha512-Ly8cn6fGLNet19s0X4unjcniX24I0RqjPv+kurpXabZYSXGM4Pwpmf85WHJN3lAgB8GSth7s5A0r856S+4DyiA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "packages/parser/node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.5.tgz", + "integrity": "sha512-GGDNnPWTmWE+DMchq1W8Sd0mUkL+APvJg3b11klSGUDvRXh70JqLAO56tubmq1s2cgpVCSKYywEiKBfju8JztQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "packages/parser/node_modules/@esbuild/freebsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.5.tgz", + "integrity": "sha512-1CCwDHnSSoA0HNwdfoNY0jLfJpd7ygaLAp5EHFos3VWJCRX9DMwWODf96s9TSse39Br7oOTLryRVmBoFwXbuuQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "packages/parser/node_modules/@esbuild/linux-arm": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.5.tgz", + "integrity": "sha512-lrWXLY/vJBzCPC51QN0HM71uWgIEpGSjSZZADQhq7DKhPcI6NH1IdzjfHkDQws2oNpJKpR13kv7/pFHBbDQDwQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "packages/parser/node_modules/@esbuild/linux-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.5.tgz", + "integrity": "sha512-o3vYippBmSrjjQUCEEiTZ2l+4yC0pVJD/Dl57WfPwwlvFkrxoSO7rmBZFii6kQB3Wrn/6GwJUPLU5t52eq2meA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "packages/parser/node_modules/@esbuild/linux-ia32": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.5.tgz", + "integrity": "sha512-MkjHXS03AXAkNp1KKkhSKPOCYztRtK+KXDNkBa6P78F8Bw0ynknCSClO/ztGszILZtyO/lVKpa7MolbBZ6oJtQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "packages/parser/node_modules/@esbuild/linux-loong64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.5.tgz", + "integrity": "sha512-42GwZMm5oYOD/JHqHska3Jg0r+XFb/fdZRX+WjADm3nLWLcIsN27YKtqxzQmGNJgu0AyXg4HtcSK9HuOk3v1Dw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "packages/parser/node_modules/@esbuild/linux-mips64el": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.5.tgz", + "integrity": "sha512-kcjndCSMitUuPJobWCnwQ9lLjiLZUR3QLQmlgaBfMX23UEa7ZOrtufnRds+6WZtIS9HdTXqND4yH8NLoVVIkcg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "packages/parser/node_modules/@esbuild/linux-ppc64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.5.tgz", + "integrity": "sha512-yJAxJfHVm0ZbsiljbtFFP1BQKLc8kUF6+17tjQ78QjqjAQDnhULWiTA6u0FCDmYT1oOKS9PzZ2z0aBI+Mcyj7Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "packages/parser/node_modules/@esbuild/linux-riscv64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.5.tgz", + "integrity": "sha512-5u8cIR/t3gaD6ad3wNt1MNRstAZO+aNyBxu2We8X31bA8XUNyamTVQwLDA1SLoPCUehNCymhBhK3Qim1433Zag==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "packages/doenetml-worker": { - "name": "@doenet/doenetml-worker", - "version": "*", - "license": "AGPL-3.0-or-later", - "dependencies": { - "compromise": "^13.11.4", - "compromise-numbers": "^1.4.0" - }, - "devDependencies": { - "node-stdlib-browser": "^1.2.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "rollup-plugin-polyfill-node": "^0.12.0", - "vite": "^4.3.9", - "vite-plugin-static-copy": "^0.17.0" - }, - "peerDependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0", - "styled-components": "^5.3.11" + "packages/parser/node_modules/@esbuild/linux-s390x": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.5.tgz", + "integrity": "sha512-Z6JrMyEw/EmZBD/OFEFpb+gao9xJ59ATsoTNlj39jVBbXqoZm4Xntu6wVmGPB/OATi1uk/DB+yeDPv2E8PqZGw==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "packages/doenetml-worker/doenetlml": { - "extraneous": true + "packages/parser/node_modules/@esbuild/linux-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.5.tgz", + "integrity": "sha512-psagl+2RlK1z8zWZOmVdImisMtrUxvwereIdyJTmtmHahJTKb64pAcqoPlx6CewPdvGvUKe2Jw+0Z/0qhSbG1A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } }, - "packages/doenetml-worker/node_modules/compromise": { - "version": "13.11.4", - "resolved": "https://registry.npmjs.org/compromise/-/compromise-13.11.4.tgz", - "integrity": "sha512-nBITcNdqIHSVDDluaG6guyFFCSNXN+Hu87fU8VlhkE5Z0PwTZN1nro2O7a8JcUH88nB5EOzrxd9zKfXLSNFqcg==", - "dependencies": { - "efrt-unpack": "2.2.0" - }, + "packages/parser/node_modules/@esbuild/netbsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.5.tgz", + "integrity": "sha512-kL2l+xScnAy/E/3119OggX8SrWyBEcqAh8aOY1gr4gPvw76la2GlD4Ymf832UCVbmuWeTf2adkZDK+h0Z/fB4g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=8.0.0" + "node": ">=12" } }, - "packages/doenetml/virtual-keyboard": { - "extraneous": true + "packages/parser/node_modules/@esbuild/openbsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.5.tgz", + "integrity": "sha512-sPOfhtzFufQfTBgRnE1DIJjzsXukKSvZxloZbkJDG383q0awVAq600pc1nfqBcl0ice/WN9p4qLc39WhBShRTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } }, - "packages/parser": { - "name": "@doenet/parser", - "version": "*", - "license": "AGPL-3.0-or-later", - "dependencies": { - "@lezer/common": "^1.0.4", - "@lezer/generator": "^1.5.0", - "@lezer/lr": "^1.3.10", - "@types/xast": "^2.0.0", - "xast-util-to-xml": "^4.0.0" - }, - "devDependencies": { - "glob": "^10.3.3", - "vite": "^4.4.9", - "vite-plugin-dts": "^3.5.2" + "packages/parser/node_modules/@esbuild/sunos-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.5.tgz", + "integrity": "sha512-dGZkBXaafuKLpDSjKcB0ax0FL36YXCvJNnztjKV+6CO82tTYVDSH2lifitJ29jxRMoUhgkg9a+VA/B03WK5lcg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "packages/parser/node_modules/@esbuild/win32-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.5.tgz", + "integrity": "sha512-dWVjD9y03ilhdRQ6Xig1NWNgfLtf2o/STKTS+eZuF90fI2BhbwD6WlaiCGKptlqXlURVB5AUOxUj09LuwKGDTg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "packages/parser/node_modules/@esbuild/win32-ia32": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.5.tgz", + "integrity": "sha512-4liggWIA4oDgUxqpZwrDhmEfAH4d0iljanDOK7AnVU89T6CzHon/ony8C5LeOdfgx60x5cnQJFZwEydVlYx4iw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "packages/parser/node_modules/@esbuild/win32-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.5.tgz", + "integrity": "sha512-czTrygUsB/jlM8qEW5MD8bgYU2Xg14lo6kBDXW6HdxKjh8M5PzETGiSHaz9MtbXBYDloHNUAUW2tMiKW4KM9Mw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" } }, "packages/parser/node_modules/brace-expansion": { @@ -13556,20 +14971,57 @@ "balanced-match": "^1.0.0" } }, + "packages/parser/node_modules/esbuild": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.5.tgz", + "integrity": "sha512-bUxalY7b1g8vNhQKdB24QDmHeY4V4tw/s6Ak5z+jJX9laP5MoQseTOMemAr0gxssjNcH0MCViG8ONI2kksvfFQ==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.19.5", + "@esbuild/android-arm64": "0.19.5", + "@esbuild/android-x64": "0.19.5", + "@esbuild/darwin-arm64": "0.19.5", + "@esbuild/darwin-x64": "0.19.5", + "@esbuild/freebsd-arm64": "0.19.5", + "@esbuild/freebsd-x64": "0.19.5", + "@esbuild/linux-arm": "0.19.5", + "@esbuild/linux-arm64": "0.19.5", + "@esbuild/linux-ia32": "0.19.5", + "@esbuild/linux-loong64": "0.19.5", + "@esbuild/linux-mips64el": "0.19.5", + "@esbuild/linux-ppc64": "0.19.5", + "@esbuild/linux-riscv64": "0.19.5", + "@esbuild/linux-s390x": "0.19.5", + "@esbuild/linux-x64": "0.19.5", + "@esbuild/netbsd-x64": "0.19.5", + "@esbuild/openbsd-x64": "0.19.5", + "@esbuild/sunos-x64": "0.19.5", + "@esbuild/win32-arm64": "0.19.5", + "@esbuild/win32-ia32": "0.19.5", + "@esbuild/win32-x64": "0.19.5" + } + }, "packages/parser/node_modules/glob": { - "version": "10.3.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", - "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", + "jackspeak": "^2.3.5", "minimatch": "^9.0.1", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", "path-scurry": "^1.10.1" }, "bin": { - "glob": "dist/cjs/src/bin.js" + "glob": "dist/esm/bin.mjs" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -13598,7 +15050,7 @@ "version": "*", "license": "AGPL-3.0-or-later", "devDependencies": { - "vite": "^4.3.9" + "vite": "^4.5.0" }, "peerDependencies": { "react": "^18.2.0", @@ -13639,7 +15091,7 @@ "version": "*", "license": "AGPL-3.0-or-later", "devDependencies": { - "vite": "^4.3.9" + "vite": "^4.5.0" }, "peerDependencies": { "react": "^18.2.0", @@ -13680,8 +15132,8 @@ "recoil": "^0.7.7" }, "devDependencies": { - "vite": "^4.4.9", - "vite-plugin-dts": "^3.5.2" + "vite": "^4.5.0", + "vite-plugin-dts": "^3.6.0" } } }, @@ -13735,47 +15187,54 @@ } }, "@babel/code-frame": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", - "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "requires": { - "@babel/highlight": "^7.22.10", + "@babel/highlight": "^7.22.13", "chalk": "^2.4.2" } }, "@babel/compat-data": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", - "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==" + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", + "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==" }, "@babel/core": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz", - "integrity": "sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", + "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", "requires": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.10", - "@babel/generator": "^7.22.10", - "@babel/helper-compilation-targets": "^7.22.10", - "@babel/helper-module-transforms": "^7.22.9", - "@babel/helpers": "^7.22.10", - "@babel/parser": "^7.22.10", - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.10", - "@babel/types": "^7.22.10", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.2", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", + "json5": "^2.2.3", "semver": "^6.3.1" + }, + "dependencies": { + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + } } }, "@babel/generator": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", - "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "requires": { - "@babel/types": "^7.22.10", + "@babel/types": "^7.23.0", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -13800,12 +15259,12 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz", - "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", "requires": { "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", "browserslist": "^4.21.9", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -13827,17 +15286,17 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==" + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==" }, "@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "requires": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" } }, "@babel/helper-hoist-variables": { @@ -13849,23 +15308,23 @@ } }, "@babel/helper-module-imports": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", - "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", "requires": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.22.15" } }, "@babel/helper-module-transforms": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", - "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", "requires": { - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", "@babel/helper-simple-access": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.5" + "@babel/helper-validator-identifier": "^7.22.20" } }, "@babel/helper-plugin-utils": { @@ -13896,39 +15355,39 @@ "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==" }, "@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==" + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==" }, "@babel/helper-validator-option": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", - "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==" + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==" }, "@babel/helpers": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz", - "integrity": "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", + "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", "requires": { - "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.10", - "@babel/types": "^7.22.10" + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.2", + "@babel/types": "^7.23.0" } }, "@babel/highlight": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", - "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "requires": { - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", "js-tokens": "^4.0.0" } }, "@babel/parser": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz", - "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==" + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==" }, "@babel/plugin-transform-react-jsx-self": { "version": "7.22.5", @@ -13967,39 +15426,39 @@ } }, "@babel/template": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", - "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/parser": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" } }, "@babel/traverse": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz", - "integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==", - "requires": { - "@babel/code-frame": "^7.22.10", - "@babel/generator": "^7.22.10", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.10", - "@babel/types": "^7.22.10", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", - "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "requires": { "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" } }, @@ -15009,14 +16468,14 @@ } }, "@codemirror/commands": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.2.5.tgz", - "integrity": "sha512-dSi7ow2P2YgPBZflR9AJoaTHvqmeGIgkhignYMd5zK5y6DANTvxKxp6eMEpIDUJkRAaOY/TFZ4jP1ADIO/GLVA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.3.0.tgz", + "integrity": "sha512-tFfcxRIlOWiQDFhjBSWJ10MxcvbCIsRr6V64SgrcaY0MwNk32cUOcCuNlWo8VjV4qRQCgNgUAnIeo0svkk4R5Q==", "requires": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.2.0", "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0" + "@lezer/common": "^1.1.0" } }, "@codemirror/lang-xml": { @@ -15032,13 +16491,13 @@ } }, "@codemirror/language": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.9.0.tgz", - "integrity": "sha512-nFu311/0ne/qGuGCL3oKuktBgzVOaxCHZPZv1tLSZkNjPYxxvkjSbzno3MlErG2tgw1Yw1yF8BxMCegeMXqpiw==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.9.1.tgz", + "integrity": "sha512-lWRP3Y9IUdOms6DXuBpoWwjkR7yRmnS0hKYCbSfPz9v6Em1A1UCRujAkDiCrdYfs1Z0Eu4dGtwovNPStIfkgNA==", "requires": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", - "@lezer/common": "^1.0.0", + "@lezer/common": "^1.1.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0", "style-mod": "^4.0.0" @@ -15065,14 +16524,14 @@ } }, "@codemirror/state": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.1.tgz", - "integrity": "sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.3.1.tgz", + "integrity": "sha512-88e4HhMtKJyw6fKprGaN/yZfiaoGYOi2nM45YCUC6R/kex9sxFWBDGatS1vk4lMgnWmdIIB9tk8Gj1LmL8YfvA==" }, "@codemirror/view": { - "version": "6.18.1", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.18.1.tgz", - "integrity": "sha512-xcsXcMkIMd7l3WZEWoc4ljteAiqzxb5gVerRxk5132p5cLix6rTydWTQjsj2oxORepfsrwy1fC4r20iMa9plrg==", + "version": "6.21.3", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.21.3.tgz", + "integrity": "sha512-8l1aSQ6MygzL4Nx7GVYhucSXvW4jQd0F6Zm3v9Dg+6nZEfwzJVqi4C2zHfDljID+73gsQrWp9TgHc81xU15O4A==", "requires": { "@codemirror/state": "^6.1.4", "style-mod": "^4.1.0", @@ -15151,19 +16610,19 @@ "@doenet/codemirror": { "version": "file:packages/codemirror", "requires": { - "@codemirror/commands": "^6.2.5", + "@codemirror/commands": "^6.3.0", "@codemirror/lang-xml": "^6.0.2", - "@codemirror/language": "^6.9.0", - "@codemirror/state": "^6.2.1", - "@codemirror/view": "^6.18.1", - "@lezer/common": "^1.0.4", + "@codemirror/language": "^6.9.1", + "@codemirror/state": "^6.3.1", + "@codemirror/view": "^6.21.3", + "@lezer/common": "^1.1.0", "@lezer/highlight": "^1.1.6", - "@lezer/lr": "^1.3.10", + "@lezer/lr": "^1.3.13", "@lezer/xml": "^1.0.2", "codemirror": "6.0.1", - "glob": "^10.3.3", - "vite": "^4.4.9", - "vite-plugin-dts": "^3.5.2" + "glob": "^10.3.10", + "vite": "^4.5.0", + "vite-plugin-dts": "^3.6.0" }, "dependencies": { "brace-expansion": { @@ -15176,13 +16635,13 @@ } }, "glob": { - "version": "10.3.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", - "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dev": true, "requires": { "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", + "jackspeak": "^2.3.5", "minimatch": "^9.0.1", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", "path-scurry": "^1.10.1" @@ -15237,7 +16696,7 @@ "lorem-ipsum": "^2.0.8", "math-expressions": "^2.0.0-alpha64", "nanoid": "^4.0.0", - "prettier": "^3.0.2", + "prettier": "^3.0.3", "prismjs": "^1.29.0", "react": "^18.2.0", "react-copy-to-clipboard": "^5.0.3", @@ -15252,7 +16711,7 @@ "recoil": "^0.7.7", "rollup-plugin-polyfill-node": "^0.12.0", "styled-components": "^5.3.11", - "vite": "^4.3.9" + "vite": "^4.5.0" } }, "@doenet/doenetml-worker": { @@ -15264,7 +16723,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "rollup-plugin-polyfill-node": "^0.12.0", - "vite": "^4.3.9", + "vite": "^4.5.0", "vite-plugin-static-copy": "^0.17.0" }, "dependencies": { @@ -15278,6 +16737,14 @@ } } }, + "@doenet/lsp-tools": { + "version": "file:packages/lsp-tools", + "requires": { + "vite": "^4.5.0", + "vite-plugin-dts": "^3.6.0", + "vscode-languageserver": "^9.0.1" + } + }, "@doenet/parser": { "version": "file:packages/parser", "requires": { @@ -15285,12 +16752,171 @@ "@lezer/generator": "^1.5.0", "@lezer/lr": "^1.3.10", "@types/xast": "^2.0.0", - "glob": "^10.3.3", - "vite": "^4.4.9", - "vite-plugin-dts": "^3.5.2", + "esbuild": "^0.19.5", + "glob": "^10.3.10", + "peggy": "^3.0.2", + "prettier-plugin-pegjs": "^2.0.2", + "react18-json-view": "^0.2.6", + "unified": "^11.0.2", + "vite": "^4.5.0", + "vite-plugin-dts": "^3.6.0", "xast-util-to-xml": "^4.0.0" }, "dependencies": { + "@esbuild/android-arm": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.5.tgz", + "integrity": "sha512-bhvbzWFF3CwMs5tbjf3ObfGqbl/17ict2/uwOSfr3wmxDE6VdS2GqY/FuzIPe0q0bdhj65zQsvqfArI9MY6+AA==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.5.tgz", + "integrity": "sha512-5d1OkoJxnYQfmC+Zd8NBFjkhyCNYwM4n9ODrycTFY6Jk1IGiZ+tjVJDDSwDt77nK+tfpGP4T50iMtVi4dEGzhQ==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.5.tgz", + "integrity": "sha512-9t+28jHGL7uBdkBjL90QFxe7DVA+KGqWlHCF8ChTKyaKO//VLuoBricQCgwhOjA1/qOczsw843Fy4cbs4H3DVA==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.5.tgz", + "integrity": "sha512-mvXGcKqqIqyKoxq26qEDPHJuBYUA5KizJncKOAf9eJQez+L9O+KfvNFu6nl7SCZ/gFb2QPaRqqmG0doSWlgkqw==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.5.tgz", + "integrity": "sha512-Ly8cn6fGLNet19s0X4unjcniX24I0RqjPv+kurpXabZYSXGM4Pwpmf85WHJN3lAgB8GSth7s5A0r856S+4DyiA==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.5.tgz", + "integrity": "sha512-GGDNnPWTmWE+DMchq1W8Sd0mUkL+APvJg3b11klSGUDvRXh70JqLAO56tubmq1s2cgpVCSKYywEiKBfju8JztQ==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.5.tgz", + "integrity": "sha512-1CCwDHnSSoA0HNwdfoNY0jLfJpd7ygaLAp5EHFos3VWJCRX9DMwWODf96s9TSse39Br7oOTLryRVmBoFwXbuuQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.5.tgz", + "integrity": "sha512-lrWXLY/vJBzCPC51QN0HM71uWgIEpGSjSZZADQhq7DKhPcI6NH1IdzjfHkDQws2oNpJKpR13kv7/pFHBbDQDwQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.5.tgz", + "integrity": "sha512-o3vYippBmSrjjQUCEEiTZ2l+4yC0pVJD/Dl57WfPwwlvFkrxoSO7rmBZFii6kQB3Wrn/6GwJUPLU5t52eq2meA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.5.tgz", + "integrity": "sha512-MkjHXS03AXAkNp1KKkhSKPOCYztRtK+KXDNkBa6P78F8Bw0ynknCSClO/ztGszILZtyO/lVKpa7MolbBZ6oJtQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.5.tgz", + "integrity": "sha512-42GwZMm5oYOD/JHqHska3Jg0r+XFb/fdZRX+WjADm3nLWLcIsN27YKtqxzQmGNJgu0AyXg4HtcSK9HuOk3v1Dw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.5.tgz", + "integrity": "sha512-kcjndCSMitUuPJobWCnwQ9lLjiLZUR3QLQmlgaBfMX23UEa7ZOrtufnRds+6WZtIS9HdTXqND4yH8NLoVVIkcg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.5.tgz", + "integrity": "sha512-yJAxJfHVm0ZbsiljbtFFP1BQKLc8kUF6+17tjQ78QjqjAQDnhULWiTA6u0FCDmYT1oOKS9PzZ2z0aBI+Mcyj7Q==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.5.tgz", + "integrity": "sha512-5u8cIR/t3gaD6ad3wNt1MNRstAZO+aNyBxu2We8X31bA8XUNyamTVQwLDA1SLoPCUehNCymhBhK3Qim1433Zag==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.5.tgz", + "integrity": "sha512-Z6JrMyEw/EmZBD/OFEFpb+gao9xJ59ATsoTNlj39jVBbXqoZm4Xntu6wVmGPB/OATi1uk/DB+yeDPv2E8PqZGw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.5.tgz", + "integrity": "sha512-psagl+2RlK1z8zWZOmVdImisMtrUxvwereIdyJTmtmHahJTKb64pAcqoPlx6CewPdvGvUKe2Jw+0Z/0qhSbG1A==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.5.tgz", + "integrity": "sha512-kL2l+xScnAy/E/3119OggX8SrWyBEcqAh8aOY1gr4gPvw76la2GlD4Ymf832UCVbmuWeTf2adkZDK+h0Z/fB4g==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.5.tgz", + "integrity": "sha512-sPOfhtzFufQfTBgRnE1DIJjzsXukKSvZxloZbkJDG383q0awVAq600pc1nfqBcl0ice/WN9p4qLc39WhBShRTA==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.5.tgz", + "integrity": "sha512-dGZkBXaafuKLpDSjKcB0ax0FL36YXCvJNnztjKV+6CO82tTYVDSH2lifitJ29jxRMoUhgkg9a+VA/B03WK5lcg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.5.tgz", + "integrity": "sha512-dWVjD9y03ilhdRQ6Xig1NWNgfLtf2o/STKTS+eZuF90fI2BhbwD6WlaiCGKptlqXlURVB5AUOxUj09LuwKGDTg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.5.tgz", + "integrity": "sha512-4liggWIA4oDgUxqpZwrDhmEfAH4d0iljanDOK7AnVU89T6CzHon/ony8C5LeOdfgx60x5cnQJFZwEydVlYx4iw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.5.tgz", + "integrity": "sha512-czTrygUsB/jlM8qEW5MD8bgYU2Xg14lo6kBDXW6HdxKjh8M5PzETGiSHaz9MtbXBYDloHNUAUW2tMiKW4KM9Mw==", + "dev": true, + "optional": true + }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -15300,14 +16926,44 @@ "balanced-match": "^1.0.0" } }, + "esbuild": { + "version": "0.19.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.5.tgz", + "integrity": "sha512-bUxalY7b1g8vNhQKdB24QDmHeY4V4tw/s6Ak5z+jJX9laP5MoQseTOMemAr0gxssjNcH0MCViG8ONI2kksvfFQ==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.19.5", + "@esbuild/android-arm64": "0.19.5", + "@esbuild/android-x64": "0.19.5", + "@esbuild/darwin-arm64": "0.19.5", + "@esbuild/darwin-x64": "0.19.5", + "@esbuild/freebsd-arm64": "0.19.5", + "@esbuild/freebsd-x64": "0.19.5", + "@esbuild/linux-arm": "0.19.5", + "@esbuild/linux-arm64": "0.19.5", + "@esbuild/linux-ia32": "0.19.5", + "@esbuild/linux-loong64": "0.19.5", + "@esbuild/linux-mips64el": "0.19.5", + "@esbuild/linux-ppc64": "0.19.5", + "@esbuild/linux-riscv64": "0.19.5", + "@esbuild/linux-s390x": "0.19.5", + "@esbuild/linux-x64": "0.19.5", + "@esbuild/netbsd-x64": "0.19.5", + "@esbuild/openbsd-x64": "0.19.5", + "@esbuild/sunos-x64": "0.19.5", + "@esbuild/win32-arm64": "0.19.5", + "@esbuild/win32-ia32": "0.19.5", + "@esbuild/win32-x64": "0.19.5" + } + }, "glob": { - "version": "10.3.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", - "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dev": true, "requires": { "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", + "jackspeak": "^2.3.5", "minimatch": "^9.0.1", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", "path-scurry": "^1.10.1" @@ -15327,7 +16983,7 @@ "@doenet/standalone": { "version": "file:packages/standalone", "requires": { - "vite": "^4.3.9" + "vite": "^4.5.0" } }, "@doenet/static-assets": { @@ -15344,7 +17000,7 @@ "@doenet/test-viewer": { "version": "file:packages/test-viewer", "requires": { - "vite": "^4.3.9" + "vite": "^4.5.0" } }, "@doenet/ui-components": { @@ -15364,8 +17020,8 @@ "react": "^18.2.0", "react-icons": "^4.9.0", "recoil": "^0.7.7", - "vite": "^4.4.9", - "vite-plugin-dts": "^3.5.2" + "vite": "^4.5.0", + "vite-plugin-dts": "^3.6.0" } }, "@emotion/babel-plugin": { @@ -15702,14 +17358,6 @@ "dev": true, "requires": { "eslint-visitor-keys": "^3.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - } } }, "@eslint-community/regexpp": { @@ -15753,9 +17401,9 @@ } }, "@eslint/js": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz", - "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", + "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", "dev": true }, "@fortawesome/fontawesome-common-types": { @@ -15794,9 +17442,9 @@ "requires": {} }, "@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", @@ -15935,9 +17583,9 @@ } }, "@lezer/common": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.4.tgz", - "integrity": "sha512-lZHlk8p67x4aIDtJl6UQrXSOP6oi7dQR3W/geFVrENdA1JDaAJWldnVqVjPMJupbTKbzDfFcePfKttqVidS/dg==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.1.0.tgz", + "integrity": "sha512-XPIN3cYDXsoJI/oDWoR2tD++juVrhgIago9xyKhZ7IhGlzdDM9QgC8D8saKNCz5pindGcznFr2HBSsEQSWnSjw==" }, "@lezer/generator": { "version": "1.5.0", @@ -15957,9 +17605,9 @@ } }, "@lezer/lr": { - "version": "1.3.10", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.10.tgz", - "integrity": "sha512-BZfVvf7Re5BIwJHlZXbJn9L8lus5EonxQghyn+ih8Wl36XMFBPTXC0KM0IdUtj9w/diPHsKlXVgL+AlX2jYJ0Q==", + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.13.tgz", + "integrity": "sha512-RLAbau/4uSzKgIKj96mI5WUtG1qtiR0Frn0Ei9zhPj8YOkHM+1Bb8SgdVvmR/aWJCFIzjo2KFnDiRZ75Xf5NdQ==", "requires": { "@lezer/common": "^1.0.0" } @@ -16021,6 +17669,51 @@ "@rushstack/node-core-library": "3.59.7" } }, + "@microsoft/fast-element": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@microsoft/fast-element/-/fast-element-1.12.0.tgz", + "integrity": "sha512-gQutuDHPKNxUEcQ4pypZT4Wmrbapus+P9s3bR/SEOLsMbNqNoXigGImITygI5zhb+aA5rzflM6O8YWkmRbGkPA==", + "dev": true + }, + "@microsoft/fast-foundation": { + "version": "2.49.2", + "resolved": "https://registry.npmjs.org/@microsoft/fast-foundation/-/fast-foundation-2.49.2.tgz", + "integrity": "sha512-xA7WP/Td33SW0zkpHRH5LUDxyLOPnPQQXieRxc080uLWxoGXhVxo6Rz7b6qwiL+e2IadNCm7X7KcrgsUhJwvBg==", + "dev": true, + "requires": { + "@microsoft/fast-element": "^1.12.0", + "@microsoft/fast-web-utilities": "^5.4.1", + "tabbable": "^5.2.0", + "tslib": "^1.13.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "@microsoft/fast-react-wrapper": { + "version": "0.1.48", + "resolved": "https://registry.npmjs.org/@microsoft/fast-react-wrapper/-/fast-react-wrapper-0.1.48.tgz", + "integrity": "sha512-9NvEjru9Kn5ZKjomAMX6v+eF0DR+eDkxKDwDfi+Wb73kTbrNzcnmlwd4diN15ygH97kldgj2+lpvI4CKLQQWLg==", + "dev": true, + "requires": { + "@microsoft/fast-element": "^1.9.0", + "@microsoft/fast-foundation": "^2.41.1" + } + }, + "@microsoft/fast-web-utilities": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@microsoft/fast-web-utilities/-/fast-web-utilities-5.4.1.tgz", + "integrity": "sha512-ReWYncndjV3c8D8iq9tp7NcFNc1vbVHvcBFPME2nNFKNbS1XCesYZGlIlf3ot5EmuOXPlrzUHOWzQ2vFpIkqDg==", + "dev": true, + "requires": { + "exenv-es6": "^1.1.1" + } + }, "@microsoft/tsdoc": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", @@ -16209,6 +17902,47 @@ "integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==", "dev": true }, + "@types/babel__core": { + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.3.tgz", + "integrity": "sha512-54fjTSeSHwfan8AyHWrKbfBWiEUrNTZsUwPTDSNaaP1QDQIZbeNUg3a59E9D+375MzUw/x1vx2/0F5LBz+AeYA==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.6", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.6.tgz", + "integrity": "sha512-66BXMKb/sUWbMdBNdMvajU7i/44RkrA3z/Yt1c7R5xejt8qh84iU54yUWCtm0QwGJlDcf/gg4zd/x4mpLAlb/w==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.3.tgz", + "integrity": "sha512-ciwyCLeuRfxboZ4isgdNZi/tkt06m8Tw6uGbBSBgWrnnZGNXiEyM27xc/PjXGQLqlZ6ylbgHMnm7ccF9tCkOeQ==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.3", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.3.tgz", + "integrity": "sha512-Lsh766rGEFbaxMIDH7Qa+Yha8cMVI3qAK6CHt3OR0YfxOIn5Z54iHiyDRycHrBqeIiqGa20Kpsv1cavfBKkRSw==", + "dev": true, + "requires": { + "@babel/types": "^7.20.7" + } + }, "@types/chai": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", @@ -16237,6 +17971,12 @@ "@types/node": "*" } }, + "@types/json-schema": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", + "dev": true + }, "@types/lodash": { "version": "4.14.192", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.192.tgz", @@ -16253,8 +17993,19 @@ "@types/minimatch": { "version": "5.1.2" }, + "@types/mocha": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz", + "integrity": "sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==", + "dev": true + }, "@types/node": { - "version": "18.11.4" + "version": "20.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", + "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "requires": { + "undici-types": "~5.25.1" + } }, "@types/normalize-package-data": { "version": "2.4.1" @@ -16297,6 +18048,12 @@ "version": "0.16.2", "devOptional": true }, + "@types/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", + "dev": true + }, "@types/sinonjs__fake-timers": { "version": "8.1.1", "dev": true @@ -16310,6 +18067,18 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.0.tgz", "integrity": "sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w==" }, + "@types/vscode": { + "version": "1.83.1", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.83.1.tgz", + "integrity": "sha512-BHu51NaNKOtDf3BOonY3sKFFmZKEpRkzqkZVpSYxowLbs5JqjOQemYFob7Gs5rpxE5tiGhfpnMpcdF/oKrLg4w==", + "dev": true + }, + "@types/vscode-webview": { + "version": "1.57.3", + "resolved": "https://registry.npmjs.org/@types/vscode-webview/-/vscode-webview-1.57.3.tgz", + "integrity": "sha512-8at2UVGjA/6gcLOay+J8wOars6VsDqAqPxRHYihH0XFUaXt+2AZ+Hd9hSoUbnhjicb6V1xe7rfjb7j4Ri2n1fg==", + "dev": true + }, "@types/xast": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/xast/-/xast-2.0.0.tgz", @@ -16318,21 +18087,160 @@ "@types/unist": "*" } }, + "@typescript-eslint/eslint-plugin": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.8.0.tgz", + "integrity": "sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.8.0", + "@typescript-eslint/type-utils": "6.8.0", + "@typescript-eslint/utils": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.8.0.tgz", + "integrity": "sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "6.8.0", + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/typescript-estree": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz", + "integrity": "sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.8.0.tgz", + "integrity": "sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "6.8.0", + "@typescript-eslint/utils": "6.8.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/types": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.8.0.tgz", + "integrity": "sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz", + "integrity": "sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/visitor-keys": "6.8.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/utils": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.8.0.tgz", + "integrity": "sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.8.0", + "@typescript-eslint/types": "6.8.0", + "@typescript-eslint/typescript-estree": "6.8.0", + "semver": "^7.5.4" + }, + "dependencies": { + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz", + "integrity": "sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.8.0", + "eslint-visitor-keys": "^3.4.1" + } + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + }, "@vitejs/plugin-react": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.4.tgz", - "integrity": "sha512-7wU921ABnNYkETiMaZy7XqpueMnpu5VxvVps13MjmCo+utBdD79sZzrApHawHtVX66cCJQQTXFcjH0y9dSUK8g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.1.0.tgz", + "integrity": "sha512-rM0SqazU9iqPUraQ2JlIvReeaxOoRj6n+PzB1C0cBzIbd8qP336nC39/R9yPi3wVcah7E7j/kdU1uCUqMEU4OQ==", "dev": true, "requires": { - "@babel/core": "^7.22.9", + "@babel/core": "^7.22.20", "@babel/plugin-transform-react-jsx-self": "^7.22.5", "@babel/plugin-transform-react-jsx-source": "^7.22.5", + "@types/babel__core": "^7.20.2", "react-refresh": "^0.14.0" }, "dependencies": { @@ -16456,6 +18364,17 @@ "@volar/language-core": "1.10.1" } }, + "@vscode/webview-ui-toolkit": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-1.2.2.tgz", + "integrity": "sha512-xIQoF4FC3Xh6d7KNKIoIezSiFWYFuf6gQMdDyKueKBFGeKwaHWEn+dY2g3makvvEsNMEDji/woEwvg9QSbuUsw==", + "dev": true, + "requires": { + "@microsoft/fast-element": "^1.6.2", + "@microsoft/fast-foundation": "^2.38.0", + "@microsoft/fast-react-wrapper": "^0.1.18" + } + }, "@vue/compiler-core": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz", @@ -16638,6 +18557,8 @@ }, "ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { "color-convert": "^1.9.0" } @@ -16688,6 +18609,12 @@ "is-string": "^1.0.7" } }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, "array-uniq": { "version": "1.0.3" }, @@ -17060,6 +18987,11 @@ } } }, + "bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==" + }, "balanced-match": { "version": "1.0.2" }, @@ -17104,6 +19036,22 @@ "mathjax-full": "^3.2.2" } }, + "big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true + }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", + "dev": true, + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } + }, "binary-extensions": { "version": "2.2.0", "devOptional": true @@ -17231,14 +19179,14 @@ } }, "browserslist": { - "version": "4.21.10", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", - "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", "requires": { - "caniuse-lite": "^1.0.30001517", - "electron-to-chromium": "^1.4.477", + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.11" + "update-browserslist-db": "^1.0.13" } }, "buffer": { @@ -17261,12 +19209,24 @@ "optional": true, "peer": true }, + "buffer-indexof-polyfill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", + "dev": true + }, "buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", "dev": true }, + "buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", + "dev": true + }, "builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", @@ -17319,9 +19279,9 @@ "version": "1.0.1" }, "caniuse-lite": { - "version": "1.0.30001520", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001520.tgz", - "integrity": "sha512-tahF5O9EiiTzwTUqAeFjIZbn4Dnqxzz7ktrgGlMYNLH43Ul26IgTMH/zvL3DG0lZxBYnlT04axvInszUsZULdA==" + "version": "1.0.30001551", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001551.tgz", + "integrity": "sha512-vtBAez47BoGMMzlbYhfXrMV1kvRF2WP/lqiMuDu1Sb4EE4LKEgjopFDSRtZfdVnslNRpOqV/woE+Xgrwj6VQlg==" }, "caseless": { "version": "0.12.0", @@ -17349,8 +19309,19 @@ "type-detect": "^4.0.5" } }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", + "dev": true, + "requires": { + "traverse": ">=0.3.0 <0.4" + } + }, "chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -17528,12 +19499,16 @@ }, "color-convert": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "requires": { "color-name": "1.1.3" } }, "color-name": { - "version": "1.1.3" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "color2k": { "version": "2.0.2", @@ -17965,12 +19940,6 @@ "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -18105,15 +20074,6 @@ "p-limit": "^2.2.0" } }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -18312,6 +20272,11 @@ "delayed-stream": { "version": "1.0.0" }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" + }, "des.js": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", @@ -18330,6 +20295,20 @@ "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" }, + "devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "requires": { + "dequal": "^2.0.0" + } + }, + "diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true + }, "diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -18355,13 +20334,161 @@ } } }, - "doctrine": { - "version": "3.0.0", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "doenet-vscode-extension": { + "version": "file:packages/doenet-vscode-extension", + "requires": { + "@types/mocha": "^9.1.1", + "@types/node": "^20.8.7", + "@types/vscode": "^1.83.1", + "@types/vscode-webview": "^1.57.3", + "@typescript-eslint/eslint-plugin": "^6.8.0", + "@typescript-eslint/parser": "^6.8.0", + "@vitejs/plugin-react": "^4.1.0", + "@vscode/webview-ui-toolkit": "^1.2.2", + "eslint": "^8.51.0", + "mocha": "^9.2.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "typescript": "^5.2.2", + "vite": "^4.5.0", + "vscode-test": "^1.6.1" + }, + "dependencies": { + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "mocha": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", + "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", + "dev": true, + "requires": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.3", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "4.2.1", + "ms": "2.1.3", + "nanoid": "3.3.1", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.2.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "dependencies": { + "minimatch": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", + "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "nanoid": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "workerpool": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", + "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", + "dev": true + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true + } + } + }, "domain-browser": { "version": "4.22.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz", @@ -18380,6 +20507,47 @@ "dompurify": { "version": "2.4.0" }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -18408,9 +20576,9 @@ "integrity": "sha512-9xUSSj7qcUxz+0r4X3+bwUNttEfGfK5AH+LVa1aTpqdAfrN5VhROYCfcF+up4hp5OL7IUKcZJJrzAGipQRDoiQ==" }, "electron-to-chromium": { - "version": "1.4.492", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.492.tgz", - "integrity": "sha512-36K9b/6skMVwAIEsC7GiQ8I8N3soCALVSHqWHzNDtGemAcI9Xu8hP02cywWM0A794rTHm0b0zHPeLJHtgFVamQ==" + "version": "1.4.562", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.562.tgz", + "integrity": "sha512-kMGVZLP65O2/oH7zzaoIA5hcr4/xPYO6Sa83FrIpWcd7YPPtSlxqwxTd8lJIwKxaiXM6FGsYK4ukyJ40XkW7jg==" }, "elliptic": { "version": "6.5.4", @@ -18559,16 +20727,16 @@ "version": "1.0.5" }, "eslint": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz", - "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", + "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "^8.47.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint/js": "8.51.0", + "@humanwhocodes/config-array": "^0.11.11", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.12.4", @@ -18643,12 +20811,6 @@ "estraverse": "^5.2.0" } }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - }, "glob-parent": { "version": "6.0.2", "dev": true, @@ -18737,6 +20899,12 @@ "dev": true, "requires": {} }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + }, "esm": { "version": "3.2.25" }, @@ -18752,14 +20920,6 @@ "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - } } }, "esquery": { @@ -18841,6 +21001,12 @@ "pify": "^2.2.0" } }, + "exenv-es6": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exenv-es6/-/exenv-es6-1.1.1.tgz", + "integrity": "sha512-vlVu3N8d6yEMpMsEm+7sUBAI81aqYYuEvfK0jNqmdb/OPXzzH7QWDDnVjMvDSY47JdHEqx/dfC/q8WkfoTmpGQ==", + "dev": true + }, "expand-brackets": { "version": "2.1.4", "requires": { @@ -19189,6 +21355,29 @@ "dev": true, "optional": true }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "function-bind": { "version": "1.1.1" }, @@ -19300,6 +21489,20 @@ "globals": { "version": "11.12.0" }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, "gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -19553,7 +21756,9 @@ "dev": true }, "ignore": { - "version": "5.2.0", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true }, "import-fresh": { @@ -19859,9 +22064,9 @@ "dev": true }, "jackspeak": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.0.tgz", - "integrity": "sha512-uKmsITSsF4rUWQHzqaRUuyAir3fZfW3f202Ee34lz/gZCi970CPZwyQXLGNgWJvvZbvFyzeyGq0+4fcG/mBKZg==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", "dev": true, "requires": { "@isaacs/cliui": "^8.0.2", @@ -20020,6 +22225,12 @@ "lines-and-columns": { "version": "1.2.4" }, + "listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", + "dev": true + }, "listr2": { "version": "3.14.0", "dev": true, @@ -20357,6 +22568,14 @@ "mj-context-menu": { "version": "0.6.1" }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + }, "mlly": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.1.tgz", @@ -20406,13 +22625,6 @@ "dev": true, "peer": true }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "peer": true - }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -20490,16 +22702,6 @@ "dev": true, "peer": true }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "peer": true, - "requires": { - "randombytes": "^2.1.0" - } - }, "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -20946,8 +23148,7 @@ } }, "path-type": { - "version": "4.0.0", - "peer": true + "version": "4.0.0" }, "pathe": { "version": "1.1.1", @@ -20974,6 +23175,22 @@ "sha.js": "^2.4.8" } }, + "peggy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/peggy/-/peggy-3.0.2.tgz", + "integrity": "sha512-n7chtCbEoGYRwZZ0i/O3t1cPr6o+d9Xx4Zwy2LYfzv0vjchMBU0tO+qYYyvZloBPcgRgzYvALzGWHe609JjEpg==", + "requires": { + "commander": "^10.0.0", + "source-map-generator": "0.8.0" + }, + "dependencies": { + "commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==" + } + } + }, "pend": { "version": "1.2.0", "dev": true @@ -21057,10 +23274,18 @@ "dev": true }, "prettier": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.2.tgz", - "integrity": "sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ==", - "dev": true + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", + "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==" + }, + "prettier-plugin-pegjs": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/prettier-plugin-pegjs/-/prettier-plugin-pegjs-2.0.2.tgz", + "integrity": "sha512-Be4LyuLM6CPxPDCTvcpi7R9zSLHPDijvmzk2bk2Wba8V3m3AThSuwtSaX6c8sug/v5PYSE+aVc8ZvQG7xr3Azg==", + "requires": { + "@types/node": "^20.5.6", + "prettier": "^3.0.2" + } }, "pretty-bytes": { "version": "5.6.0", @@ -21096,6 +23321,12 @@ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", "dev": true }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, "prop-types": { "version": "15.8.1", "requires": { @@ -21333,6 +23564,13 @@ "prop-types": "^15.7.2" } }, + "react18-json-view": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/react18-json-view/-/react18-json-view-0.2.6.tgz", + "integrity": "sha512-RHAY880UwC7SClyQBoij50q2InpSrj5zmP2DCL73vEaaVTyj/QbMPBk4FRKMQ7LF8FSxhh+VI6mK3AhlBaCBxw==", + "dev": true, + "requires": {} + }, "read-pkg": { "version": "5.2.0", "requires": { @@ -21650,6 +23888,15 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -21724,6 +23971,12 @@ "signal-exit": { "version": "3.0.7" }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, "slice-ansi": { "version": "3.0.0", "dev": true, @@ -21876,6 +24129,11 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, + "source-map-generator": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/source-map-generator/-/source-map-generator-0.8.0.tgz", + "integrity": "sha512-psgxdGMwl5MZM9S3FWee4EgsEaIjahYV5AzGnwUvPhWeITz/j6rKpysQHlQ4USdxvINlb8lKfWGIXwfkrgtqkA==" + }, "source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", @@ -22232,6 +24490,12 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "tabbable": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz", + "integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==", + "dev": true + }, "terser": { "version": "5.15.1", "dev": true, @@ -22371,6 +24635,24 @@ "punycode": "^2.3.0" } }, + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", + "dev": true + }, + "trough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz", + "integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==" + }, + "ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "requires": {} + }, "tslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", @@ -22444,6 +24726,32 @@ "underscore": { "version": "1.13.6" }, + "undici-types": { + "version": "5.25.3", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", + "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==" + }, + "unified": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.2.tgz", + "integrity": "sha512-Zta++onvS/dJ6xUvXQOR5q8XJZOkiMCE5wQ8Yv9mLR25pxRS567EX0GO6HZRxxNV/lznwfsvRZ/1pqe9K9QLeQ==", + "requires": { + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "dependencies": { + "is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==" + } + } + }, "union-value": { "version": "1.0.1", "requires": { @@ -22458,6 +24766,14 @@ } } }, + "unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "requires": { + "@types/unist": "^3.0.0" + } + }, "universalify": { "version": "2.0.0", "dev": true @@ -22499,10 +24815,66 @@ "version": "4.0.0", "dev": true }, + "unzipper": { + "version": "0.10.14", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz", + "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", + "dev": true, + "requires": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "^1.0.12", + "graceful-fs": "^4.2.2", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + }, + "dependencies": { + "bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", + "dev": true + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", "requires": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -22617,10 +24989,29 @@ "extsprintf": "^1.2.0" } }, + "vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "requires": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + } + }, + "vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "requires": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + } + }, "vite": { - "version": "4.4.9", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz", - "integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", + "integrity": "sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==", "dev": true, "requires": { "esbuild": "^0.18.10", @@ -22655,12 +25046,12 @@ } }, "vite-plugin-dts": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-3.5.2.tgz", - "integrity": "sha512-iKc851+jdHEoN1ifbOEsoMs+/Zg26PE1EyO2Jc+4apOWRoaeK2zRJnaStgUuJaVaEcAjTqWzpNgCAMq7iO6DWA==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-3.6.0.tgz", + "integrity": "sha512-doxhDRFJCZD2sGjIp4V800nm8Y19GvmwckjG5vYPuiqJ7OBjc9NlW1Vp9Gkyh2aXlUs1jTDRH/lxWfcsPLOQHg==", "dev": true, "requires": { - "@microsoft/api-extractor": "^7.36.3", + "@microsoft/api-extractor": "^7.36.4", "@rollup/pluginutils": "^5.0.2", "@vue/language-core": "^1.8.8", "debug": "^4.3.4", @@ -22762,6 +25153,68 @@ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "dev": true }, + "vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "dev": true + }, + "vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "dev": true, + "requires": { + "vscode-languageserver-protocol": "3.17.5" + } + }, + "vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dev": true, + "requires": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "dev": true + }, + "vscode-test": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.6.1.tgz", + "integrity": "sha512-086q88T2ca1k95mUzffvbzb7esqQNvJgiwY4h29ukPhFo8u+vXOOmelUoU5EQUHs3Of8+JuQ3oGdbVCqaxuTXA==", + "dev": true, + "requires": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "rimraf": "^3.0.2", + "unzipper": "^0.10.11" + }, + "dependencies": { + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + } + } + }, "vue-template-compiler": { "version": "2.7.14", "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.14.tgz", @@ -22967,14 +25420,6 @@ "version": "1.0.3", "requires": { "mkdirp": "^0.5.1" - }, - "dependencies": { - "mkdirp": { - "version": "0.5.6", - "requires": { - "minimist": "^1.2.6" - } - } } }, "write-file-atomic": { @@ -23112,7 +25557,6 @@ "yargs": { "version": "16.2.0", "dev": true, - "peer": true, "requires": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -23125,8 +25569,7 @@ }, "yargs-parser": { "version": "20.2.9", - "dev": true, - "peer": true + "dev": true }, "yargs-unparser": { "version": "2.0.0", diff --git a/package.json b/package.json index 8cbda90e5..936282cb4 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "./packages/ui-components", "./packages/utils", "./packages/parser", + "./packages/lsp-tools", "./packages/doenetml-worker", "./packages/static-assets", "./packages/virtual-keyboard", diff --git a/packages/codemirror/package.json b/packages/codemirror/package.json index a970828d9..e3143329a 100644 --- a/packages/codemirror/package.json +++ b/packages/codemirror/package.json @@ -26,19 +26,19 @@ }, "dependencies": { "codemirror": "6.0.1", - "@codemirror/commands": "^6.2.5", + "@codemirror/commands": "^6.3.0", "@codemirror/lang-xml": "^6.0.2", - "@codemirror/language": "^6.9.0", - "@codemirror/state": "^6.2.1", - "@codemirror/view": "^6.18.1", - "@lezer/common": "^1.0.4", + "@codemirror/language": "^6.9.1", + "@codemirror/state": "^6.3.1", + "@codemirror/view": "^6.21.3", + "@lezer/common": "^1.1.0", "@lezer/highlight": "^1.1.6", - "@lezer/lr": "^1.3.10", + "@lezer/lr": "^1.3.13", "@lezer/xml": "^1.0.2" }, "devDependencies": { - "glob": "^10.3.3", - "vite": "^4.4.9", - "vite-plugin-dts": "^3.5.2" + "glob": "^10.3.10", + "vite": "^4.5.0", + "vite-plugin-dts": "^3.6.0" } } diff --git a/packages/codemirror/src/CodeMirror.tsx b/packages/codemirror/src/CodeMirror.tsx index 44b2ccc8a..fd17abdc6 100644 --- a/packages/codemirror/src/CodeMirror.tsx +++ b/packages/codemirror/src/CodeMirror.tsx @@ -5,7 +5,12 @@ import React, { useRef, useState, } from "react"; -import { EditorState, Transaction, StateEffect } from "@codemirror/state"; +import { + EditorState, + Transaction, + StateEffect, + EditorSelection, +} from "@codemirror/state"; import { selectLine, deleteLine, cursorLineUp } from "@codemirror/commands"; import { EditorView, keymap, Command } from "@codemirror/view"; import { basicSetup } from "codemirror"; @@ -25,6 +30,7 @@ import { doenetSchema } from "@doenet/static-assets"; export function CodeMirror({ setInternalValueTo, onBeforeChange, + onCursorChange, readOnly, onBlur, onFocus, @@ -32,6 +38,7 @@ export function CodeMirror({ }: { setInternalValueTo: string; onBeforeChange: (str: string) => void; + onCursorChange?: (selection: EditorSelection) => any; readOnly?: boolean; onBlur?: () => void; onFocus?: () => void; @@ -86,6 +93,9 @@ export function CodeMirror({ const [count, setCount] = useState(0); const changeFunc = useCallback((tr: Transaction) => { + if (tr.selection && onCursorChange) { + onCursorChange(tr.selection); + } if (tr.docChanged) { let strOfDoc = tr.state.sliceDoc(); onBeforeChange(strOfDoc); @@ -206,6 +216,7 @@ export function CodeMirror({ onBlurExtension, onFocusExtension, EditorState.changeFilter.of(changeFunc), + // XXX This type appears to be incorrect, but I am not sure what this function is doing... // @ts-ignore EditorView.updateListener.of(changeFunc), @@ -233,7 +244,7 @@ export function CodeMirror({ tagNameNode?.to, ); - //an ineffecient hack to make it so the modified document is saved directly after tagMatch + //an inefficient hack to make it so the modified document is saved directly after tagMatch let tra = tr.state.update({ changes: { from: cursorPos, diff --git a/packages/doenet-vscode-extension/.eslintignore b/packages/doenet-vscode-extension/.eslintignore new file mode 100644 index 000000000..1d3909694 --- /dev/null +++ b/packages/doenet-vscode-extension/.eslintignore @@ -0,0 +1,5 @@ +node_modules/** +client/node_modules/** +client/out/** +server/node_modules/** +server/out/** \ No newline at end of file diff --git a/packages/doenet-vscode-extension/.eslintrc.js b/packages/doenet-vscode-extension/.eslintrc.js new file mode 100644 index 000000000..f17e605fe --- /dev/null +++ b/packages/doenet-vscode-extension/.eslintrc.js @@ -0,0 +1,16 @@ +/**@type {import('eslint').Linter.Config} */ +// eslint-disable-next-line no-undef +module.exports = { + root: true, + parser: "@typescript-eslint/parser", + plugins: ["@typescript-eslint"], + extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"], + rules: { + semi: [2, "always"], + "@typescript-eslint/no-unused-vars": 0, + "@typescript-eslint/no-explicit-any": 0, + "@typescript-eslint/explicit-module-boundary-types": 0, + "@typescript-eslint/no-non-null-assertion": 0, + "@typescript-eslint/ban-ts-comment": 0, + }, +}; diff --git a/packages/doenet-vscode-extension/.vscode/extensions.json b/packages/doenet-vscode-extension/.vscode/extensions.json new file mode 100644 index 000000000..af515502d --- /dev/null +++ b/packages/doenet-vscode-extension/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. + // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp + + // List of extensions which should be recommended for users of this workspace. + "recommendations": [ + "dbaeumer.vscode-eslint" + ] +} \ No newline at end of file diff --git a/packages/doenet-vscode-extension/.vscode/launch.json b/packages/doenet-vscode-extension/.vscode/launch.json new file mode 100644 index 000000000..7728c8e9d --- /dev/null +++ b/packages/doenet-vscode-extension/.vscode/launch.json @@ -0,0 +1,30 @@ +// A launch configuration that compiles the extension and then opens it inside a new window +{ + "version": "0.2.0", + "configurations": [ + { + "type": "extensionHost", + "request": "launch", + "name": "Launch Client", + "runtimeExecutable": "${execPath}", + "args": ["--extensionDevelopmentPath=${workspaceRoot}"], + "outFiles": ["${workspaceRoot}/client/out/**/*.js"], + "preLaunchTask": { + "type": "npm", + "script": "watch" + } + }, + { + "name": "Language Server E2E Test", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + "--extensionDevelopmentPath=${workspaceRoot}", + "--extensionTestsPath=${workspaceRoot}/client/out/test/index", + "${workspaceRoot}/client/testFixture" + ], + "outFiles": ["${workspaceRoot}/client/out/test/**/*.js"] + } + ] +} diff --git a/packages/doenet-vscode-extension/.vscode/settings.json b/packages/doenet-vscode-extension/.vscode/settings.json new file mode 100644 index 000000000..b99cab318 --- /dev/null +++ b/packages/doenet-vscode-extension/.vscode/settings.json @@ -0,0 +1,19 @@ +{ + "editor.insertSpaces": false, + "typescript.tsc.autoDetect": "off", + "typescript.preferences.quoteStyle": "single", + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + }, + "cSpell.ignoreWords": [ + "Dast", + "clientrc", + "documentroot", + "doublequoted", + "entitytype", + "internalsubset", + "localname", + "singlequoted", + "taglib" + ] +} \ No newline at end of file diff --git a/packages/doenet-vscode-extension/.vscode/tasks.json b/packages/doenet-vscode-extension/.vscode/tasks.json new file mode 100644 index 000000000..5efd80488 --- /dev/null +++ b/packages/doenet-vscode-extension/.vscode/tasks.json @@ -0,0 +1,33 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "compile", + "group": "build", + "presentation": { + "panel": "dedicated", + "reveal": "never" + }, + "problemMatcher": [ + "$tsc" + ] + }, + { + "type": "npm", + "script": "watch", + "isBackground": true, + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "panel": "dedicated", + "reveal": "never" + }, + "problemMatcher": [ + "$tsc-watch" + ] + } + ] +} \ No newline at end of file diff --git a/packages/doenet-vscode-extension/.vscodeignore b/packages/doenet-vscode-extension/.vscodeignore new file mode 100644 index 000000000..2a6b6a990 --- /dev/null +++ b/packages/doenet-vscode-extension/.vscodeignore @@ -0,0 +1,15 @@ +.vscode/** +**/*.ts +**/*.map +.gitignore +**/tsconfig.json +**/tsconfig.base.json +contributing.md +.travis.yml +client/node_modules/** +!client/node_modules/vscode-jsonrpc/** +!client/node_modules/vscode-languageclient/** +!client/node_modules/vscode-languageserver-protocol/** +!client/node_modules/vscode-languageserver-types/** +!client/node_modules/{minimatch,brace-expansion,concat-map,balanced-match}/** +!client/node_modules/{semver,lru-cache,yallist}/** \ No newline at end of file diff --git a/packages/doenet-vscode-extension/README.md b/packages/doenet-vscode-extension/README.md new file mode 100644 index 000000000..b81c1d293 --- /dev/null +++ b/packages/doenet-vscode-extension/README.md @@ -0,0 +1,37 @@ +# LSP Example + +Heavily documented sample code for https://code.visualstudio.com/api/language-extensions/language-server-extension-guide + +## Functionality + +This Language Server works for plain text file. It has the following language features: +- Completions +- Diagnostics regenerated on each file change or configuration change + +It also includes an End-to-End test. + +## Structure + +``` +. +├── client // Language Client +│ ├── src +│ │ ├── test // End to End tests for Language Client / Server +│ │ └── extension.ts // Language Client entry point +├── package.json // The extension manifest. +└── server // Language Server + └── src + └── server.ts // Language Server entry point +``` + +## Running the Sample + +- Run `npm install` in this folder. This installs all necessary npm modules in both the client and server folder +- Open VS Code on this folder. +- Press Ctrl+Shift+B to start compiling the client and server in [watch mode](https://code.visualstudio.com/docs/editor/tasks#:~:text=The%20first%20entry%20executes,the%20HelloWorld.js%20file.). +- Switch to the Run and Debug View in the Sidebar (Ctrl+Shift+D). +- Select `Launch Client` from the drop down (if it is not already). +- Press ▷ to run the launch config (F5). +- In the [Extension Development Host](https://code.visualstudio.com/api/get-started/your-first-extension#:~:text=Then%2C%20inside%20the%20editor%2C%20press%20F5.%20This%20will%20compile%20and%20run%20the%20extension%20in%20a%20new%20Extension%20Development%20Host%20window.) instance of VSCode, open a document in 'plain text' language mode. + - Type `j` or `t` to see `Javascript` and `TypeScript` completion. + - Enter text content such as `AAA aaa BBB`. The extension will emit diagnostics for all words in all-uppercase. diff --git a/packages/doenet-vscode-extension/client/package-lock.json b/packages/doenet-vscode-extension/client/package-lock.json new file mode 100644 index 000000000..39fde3f71 --- /dev/null +++ b/packages/doenet-vscode-extension/client/package-lock.json @@ -0,0 +1,548 @@ +{ + "name": "lsp-sample-client", + "version": "0.0.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "lsp-sample-client", + "version": "0.0.1", + "license": "MIT", + "dependencies": { + "vscode-languageclient": "^9.0.1" + }, + "devDependencies": { + "@types/vscode": "^1.83.0", + "@vscode/test-electron": "^2.2.5" + }, + "engines": { + "vscode": "^1.75.0" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/vscode": { + "version": "1.83.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.83.0.tgz", + "integrity": "sha512-3mUtHqLAVz9hegut9au4xehuBrzRE3UJiQMpoEHkNl6XHliihO7eATx2BMHs0odsmmrwjJrlixx/Pte6M3ygDQ==", + "dev": true + }, + "node_modules/@vscode/test-electron": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.5.tgz", + "integrity": "sha512-lAW7nQ0HuPqJnGJrtCzEKZCICtRizeP6qNanyCrjmdCOAAWjX3ixiG8RVPwqsYPQBWLPgYuE12qQlwXsOR/2fQ==", + "dev": true, + "dependencies": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "jszip": "^3.10.1", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@vscode/test-electron/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@vscode/test-electron/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@vscode/test-electron/node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@vscode/test-electron/node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@vscode/test-electron/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", + "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", + "dependencies": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.5" + }, + "engines": { + "vscode": "^1.82.0" + } + }, + "node_modules/vscode-languageclient/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/vscode-languageclient/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "@types/vscode": { + "version": "1.83.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.83.0.tgz", + "integrity": "sha512-3mUtHqLAVz9hegut9au4xehuBrzRE3UJiQMpoEHkNl6XHliihO7eATx2BMHs0odsmmrwjJrlixx/Pte6M3ygDQ==", + "dev": true + }, + "@vscode/test-electron": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.5.tgz", + "integrity": "sha512-lAW7nQ0HuPqJnGJrtCzEKZCICtRizeP6qNanyCrjmdCOAAWjX3ixiG8RVPwqsYPQBWLPgYuE12qQlwXsOR/2fQ==", + "dev": true, + "requires": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "jszip": "^3.10.1", + "semver": "^7.5.2" + }, + "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, + "requires": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "requires": { + "immediate": "~3.0.5" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==" + }, + "vscode-languageclient": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", + "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", + "requires": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.5" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "requires": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/packages/doenet-vscode-extension/client/package.json b/packages/doenet-vscode-extension/client/package.json new file mode 100644 index 000000000..8c5ba4f1d --- /dev/null +++ b/packages/doenet-vscode-extension/client/package.json @@ -0,0 +1,22 @@ +{ + "name": "lsp-sample-client", + "description": "VSCode part of a language server", + "author": "Microsoft Corporation", + "license": "MIT", + "version": "0.0.1", + "publisher": "vscode", + "repository": { + "type": "git", + "url": "https://github.com/Microsoft/vscode-extension-samples" + }, + "engines": { + "vscode": "^1.75.0" + }, + "dependencies": { + "vscode-languageclient": "^9.0.1" + }, + "devDependencies": { + "@types/vscode": "^1.83.0", + "@vscode/test-electron": "^2.2.5" + } +} \ No newline at end of file diff --git a/packages/doenet-vscode-extension/client/src/extension.ts b/packages/doenet-vscode-extension/client/src/extension.ts new file mode 100644 index 000000000..802b905dd --- /dev/null +++ b/packages/doenet-vscode-extension/client/src/extension.ts @@ -0,0 +1,122 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + +import * as path from "path"; +import { + workspace, + ExtensionContext, + commands, + TextDocumentChangeEvent, +} from "vscode"; +import * as vscode from "vscode"; + +import { + LanguageClient, + LanguageClientOptions, + ServerOptions, + TransportKind, +} from "vscode-languageclient/node"; +import { DoenetPreviewPanel } from "./panels/doenet-preview-panel"; + +let client: LanguageClient; + +export function activate(context: ExtensionContext) { + // The server is implemented in node + const serverModule = context.asAbsolutePath( + path.join("server", "out", "server.js"), + ); + + // If the extension is launched in debug mode then the debug server options are used + // Otherwise the run options are used + const serverOptions: ServerOptions = { + run: { module: serverModule, transport: TransportKind.ipc }, + debug: { + module: serverModule, + transport: TransportKind.ipc, + }, + }; + + // Options to control the language client + const clientOptions: LanguageClientOptions = { + // Register the server for plain text documents + documentSelector: [{ scheme: "file", language: "doenet" }], + synchronize: { + // Notify the server about file changes to '.clientrc files contained in the workspace + fileEvents: workspace.createFileSystemWatcher("**/.clientrc"), + }, + }; + + // Create the language client and start the client. + client = new LanguageClient( + "DoenetLanguageServer", + "Doenet Language Server", + serverOptions, + clientOptions, + ); + + // Start the client. This will also launch the server + client.start(); + + setupPreviewWindow(context); +} + +export function deactivate(): Thenable | undefined { + if (!client) { + return undefined; + } + return client.stop(); +} + +/** + * Allow a user to open a Doenet preview window. + */ +function setupPreviewWindow(context: ExtensionContext) { + // Register the preview window + const showPreviewWindow = commands.registerCommand( + "doenet.showPreview", + () => { + const currentDocument = vscode.window.activeTextEditor?.document; + if (currentDocument?.languageId === "doenet") { + DoenetPreviewPanel.currentSource = currentDocument.getText(); + } + + DoenetPreviewPanel.render(context.extensionUri); + DoenetPreviewPanel.triggerRefresh(); + }, + ); + context.subscriptions.push(showPreviewWindow); + + // Every time a Doenet document changes, update the source in the preview window + workspace.onDidChangeTextDocument((e: TextDocumentChangeEvent) => { + if ( + e.document.languageId !== "doenet" || + e.document.fileName !== + vscode.window.activeTextEditor?.document?.fileName + ) { + return; + } + DoenetPreviewPanel.setSource(e.document.getText()); + }); + + workspace.onDidSaveTextDocument((document) => { + if ( + document.languageId !== "doenet" || + document.fileName !== + vscode.window.activeTextEditor?.document?.fileName + ) { + return; + } + DoenetPreviewPanel.setSource(document.getText()); + DoenetPreviewPanel.triggerRefresh(); + }); + + vscode.window.onDidChangeActiveTextEditor((e) => { + if (e.document.languageId !== "doenet") { + return; + } + DoenetPreviewPanel.setSource(e.document.getText()); + DoenetPreviewPanel.triggerRefresh(); + }); +} diff --git a/packages/doenet-vscode-extension/client/src/panels/doenet-preview-panel.ts b/packages/doenet-vscode-extension/client/src/panels/doenet-preview-panel.ts new file mode 100644 index 000000000..68791b64d --- /dev/null +++ b/packages/doenet-vscode-extension/client/src/panels/doenet-preview-panel.ts @@ -0,0 +1,200 @@ +// Code modified from https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/frameworks/hello-world-react-vite/src/extension.ts +// MIT License +import { + Disposable, + Webview, + WebviewPanel, + window, + Uri, + ViewColumn, +} from "vscode"; +import { getUri } from "../utilities/getUri"; +import { getNonce } from "../utilities/getNonce"; + +/** + * This class manages the state and behavior of DoenetPreviewPanel webview panels. + * + * It contains all the data and methods for: + * + * - Creating and rendering DoenetPreviewPanel webview panels + * - Properly cleaning up and disposing of webview resources when the panel is closed + * - Setting the HTML (and by proxy CSS/JavaScript) content of the webview panel + * - Setting message listeners so data can be passed between the webview and extension + */ +export class DoenetPreviewPanel { + public static currentPanel: DoenetPreviewPanel | undefined; + public static currentSource: string = "Sample Code"; + private readonly _panel: WebviewPanel; + private _disposables: Disposable[] = []; + + private constructor(panel: WebviewPanel, extensionUri: Uri) { + this._panel = panel; + + // Set an event listener to listen for when the panel is disposed (i.e. when the user closes + // the panel or when the panel is closed programmatically) + this._panel.onDidDispose(() => this.dispose(), null, this._disposables); + + // Set the HTML content for the webview panel + this._panel.webview.html = this._getWebviewContent( + this._panel.webview, + extensionUri, + ); + + // Set an event listener to listen for messages passed from the webview context + this._setWebviewMessageListener(this._panel.webview); + } + + /** + * Renders the current webview panel if it exists otherwise a new webview panel + * will be created and displayed. + * + * @param extensionUri The URI of the directory containing the extension. + */ + public static render(extensionUri: Uri) { + if (DoenetPreviewPanel.currentPanel) { + // If the webview panel already exists reveal it + DoenetPreviewPanel.currentPanel._panel.reveal(ViewColumn.Two); + } else { + // If a webview panel does not already exist create and show a new one + const panel = window.createWebviewPanel( + // Panel view type + "doenetPreview", + // Panel title + "Doenet Preview", + // The editor column the panel should be displayed in + ViewColumn.Two, + // Extra panel configurations + { + // Enable JavaScript in the webview + enableScripts: true, + // Restrict the webview to only load resources from the `out` and `webview-ui/build` directories + localResourceRoots: [ + Uri.joinPath(extensionUri, "out"), + Uri.joinPath(extensionUri, "webview-ui/build"), + ], + }, + ); + + DoenetPreviewPanel.currentPanel = new DoenetPreviewPanel( + panel, + extensionUri, + ); + } + } + + /** + * Cleans up and disposes of webview resources when the webview panel is closed. + */ + public dispose() { + DoenetPreviewPanel.currentPanel = undefined; + + // Dispose of the current webview panel + this._panel.dispose(); + + // Dispose of all disposables (i.e. commands) for the current webview panel + while (this._disposables.length) { + const disposable = this._disposables.pop(); + if (disposable) { + disposable.dispose(); + } + } + } + + /** + * Defines and returns the HTML that should be rendered within the webview panel. + * + * @remarks This is also the place where references to the React webview build files + * are created and inserted into the webview HTML. + * + * @param webview A reference to the extension webview + * @param extensionUri The URI of the directory containing the extension + * @returns A template string literal containing the HTML that should be + * rendered within the webview panel + */ + private _getWebviewContent(webview: Webview, extensionUri: Uri) { + // The CSS file from the React build output + const stylesUri = getUri(webview, extensionUri, [ + "webview-ui", + "build", + "assets", + "index.css", + ]); + // The JS file from the React build output + const scriptUri = getUri(webview, extensionUri, [ + "webview-ui", + "build", + "assets", + "index.js", + ]); + + const nonce = getNonce(); + + // Tip: Install the es6-string-html VS Code extension to enable code highlighting below + return /*html*/ ` + + + + + + + + Doenet Preview + + +
+ + + + `; + } + + /** + * Sets up an event listener to listen for messages passed from the webview context and + * executes code based on the message that is received. + * + * @param webview A reference to the extension webview + * @param context A reference to the extension context + */ + private _setWebviewMessageListener(webview: Webview) { + webview.onDidReceiveMessage( + (message: any) => { + const command = message.command; + const text = message.text; + + switch (command) { + case "refresh": + webview.postMessage({ + command: "setSource", + text: DoenetPreviewPanel.currentSource, + }); + return; + } + }, + undefined, + this._disposables, + ); + } + + static triggerRefresh() { + if (!DoenetPreviewPanel.currentPanel) { + return; + } + DoenetPreviewPanel.currentPanel._panel.webview.postMessage({ + command: "setSource", + text: DoenetPreviewPanel.currentSource, + }); + } + + static setSource(source: string) { + const dirty = this.currentSource !== source; + this.currentSource = source; + if (dirty && this.currentPanel) { + DoenetPreviewPanel.currentPanel._panel.webview.postMessage({ + command: "dirty", + text: "", + }); + } + } +} diff --git a/packages/doenet-vscode-extension/client/src/test/helper.ts b/packages/doenet-vscode-extension/client/src/test/helper.ts new file mode 100644 index 000000000..6e6724d37 --- /dev/null +++ b/packages/doenet-vscode-extension/client/src/test/helper.ts @@ -0,0 +1,47 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ + +import * as vscode from 'vscode'; +import * as path from 'path'; + +export let doc: vscode.TextDocument; +export let editor: vscode.TextEditor; +export let documentEol: string; +export let platformEol: string; + +/** + * Activates the vscode.lsp-sample extension + */ +export async function activate(docUri: vscode.Uri) { + // The extensionId is `publisher.name` from package.json + const ext = vscode.extensions.getExtension('vscode-samples.lsp-sample')!; + await ext.activate(); + try { + doc = await vscode.workspace.openTextDocument(docUri); + editor = await vscode.window.showTextDocument(doc); + await sleep(2000); // Wait for server activation + } catch (e) { + console.error(e); + } +} + +async function sleep(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +export const getDocPath = (p: string) => { + return path.resolve(__dirname, '../../testFixture', p); +}; +export const getDocUri = (p: string) => { + return vscode.Uri.file(getDocPath(p)); +}; + +export async function setTestContent(content: string): Promise { + const all = new vscode.Range( + doc.positionAt(0), + doc.positionAt(doc.getText().length) + ); + return editor.edit(eb => eb.replace(all, content)); +} diff --git a/packages/doenet-vscode-extension/client/src/test/index.ts b/packages/doenet-vscode-extension/client/src/test/index.ts new file mode 100644 index 000000000..b9de4dcd8 --- /dev/null +++ b/packages/doenet-vscode-extension/client/src/test/index.ts @@ -0,0 +1,43 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +import * as path from 'path'; +import * as Mocha from 'mocha'; +import * as glob from 'glob'; + +export function run(): Promise { + // Create the mocha test + const mocha = new Mocha({ + ui: 'tdd', + color: true + }); + mocha.timeout(100000); + + const testsRoot = __dirname; + + return new Promise((resolve, reject) => { + glob('**.test.js', { cwd: testsRoot }, (err, files) => { + if (err) { + return reject(err); + } + + // Add files to the test suite + files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); + + try { + // Run the mocha test + mocha.run(failures => { + if (failures > 0) { + reject(new Error(`${failures} tests failed.`)); + } else { + resolve(); + } + }); + } catch (err) { + console.error(err); + reject(err); + } + }); + }); +} \ No newline at end of file diff --git a/packages/doenet-vscode-extension/client/src/test/runTest.ts b/packages/doenet-vscode-extension/client/src/test/runTest.ts new file mode 100644 index 000000000..f06f788e1 --- /dev/null +++ b/packages/doenet-vscode-extension/client/src/test/runTest.ts @@ -0,0 +1,27 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import * as path from 'path'; + +import { runTests } from '@vscode/test-electron'; + +async function main() { + try { + // The folder containing the Extension Manifest package.json + // Passed to `--extensionDevelopmentPath` + const extensionDevelopmentPath = path.resolve(__dirname, '../../../'); + + // The path to test runner + // Passed to --extensionTestsPath + const extensionTestsPath = path.resolve(__dirname, './index'); + + // Download VS Code, unzip it and run the integration test + await runTests({ extensionDevelopmentPath, extensionTestsPath }); + } catch (err) { + console.error('Failed to run tests'); + process.exit(1); + } +} + +main(); diff --git a/packages/doenet-vscode-extension/client/src/utilities/getNonce.ts b/packages/doenet-vscode-extension/client/src/utilities/getNonce.ts new file mode 100644 index 000000000..c57706ea0 --- /dev/null +++ b/packages/doenet-vscode-extension/client/src/utilities/getNonce.ts @@ -0,0 +1,16 @@ +/** + * A helper function that returns a unique alphanumeric identifier called a nonce. + * + * @remarks This function is primarily used to help enforce content security + * policies for resources/scripts being executed in a webview context. + * + * @returns A nonce + */ +export function getNonce() { + let text = ""; + const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + for (let i = 0; i < 32; i++) { + text += possible.charAt(Math.floor(Math.random() * possible.length)); + } + return text; +} diff --git a/packages/doenet-vscode-extension/client/src/utilities/getUri.ts b/packages/doenet-vscode-extension/client/src/utilities/getUri.ts new file mode 100644 index 000000000..7145499ee --- /dev/null +++ b/packages/doenet-vscode-extension/client/src/utilities/getUri.ts @@ -0,0 +1,16 @@ +import { Uri, Webview } from "vscode"; + +/** + * A helper function which will get the webview URI of a given file or resource. + * + * @remarks This URI can be used within a webview's HTML as a link to the + * given file/resource. + * + * @param webview A reference to the extension webview + * @param extensionUri The URI of the directory containing the extension + * @param pathList An array of strings representing the path to a file/resource + * @returns A URI pointing to the file/resource + */ +export function getUri(webview: Webview, extensionUri: Uri, pathList: string[]) { + return webview.asWebviewUri(Uri.joinPath(extensionUri, ...pathList)); +} diff --git a/packages/doenet-vscode-extension/client/tsconfig.json b/packages/doenet-vscode-extension/client/tsconfig.json new file mode 100644 index 000000000..23e35e19a --- /dev/null +++ b/packages/doenet-vscode-extension/client/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2020", + "lib": ["es2020"], + "outDir": "out", + "rootDir": "src", + "sourceMap": true + }, + "include": ["src"], + "exclude": ["node_modules", ".vscode-test"] +} diff --git a/packages/doenet-vscode-extension/language-configuration.json b/packages/doenet-vscode-extension/language-configuration.json new file mode 100644 index 000000000..f404c70b7 --- /dev/null +++ b/packages/doenet-vscode-extension/language-configuration.json @@ -0,0 +1,73 @@ +{ + "comments": { + // symbols used for start and end a block comment. Remove this entry if your language does not support block comments + "blockComment": [""] + }, + // symbols used as brackets + "brackets": [ + [""], + ["<", ">"], + ["{", "}"], + ["(", ")"] + ], + // symbols that are auto closed when typing + "autoClosingPairs": [ + { + "open": "{", + "close": "}" + }, + { + "open": "[", + "close": "]" + }, + { + "open": "(", + "close": ")" + }, + { + "open": "'", + "close": "'" + }, + { + "open": "\"", + "close": "\"" + }, + { + "open": "", + "notIn": ["comment", "string"] + }, + { + "open": "", + "notIn": ["comment", "string"] + } + ], + // symbols that that can be used to surround a selection + "surroundingPairs": [ + { + "open": "'", + "close": "'" + }, + { + "open": "\"", + "close": "\"" + }, + { + "open": "{", + "close": "}" + }, + { + "open": "[", + "close": "]" + }, + { + "open": "(", + "close": ")" + }, + { + "open": "<", + "close": ">" + } + ] +} diff --git a/packages/doenet-vscode-extension/package-lock.json b/packages/doenet-vscode-extension/package-lock.json new file mode 100644 index 000000000..43cb0683c --- /dev/null +++ b/packages/doenet-vscode-extension/package-lock.json @@ -0,0 +1,3703 @@ +{ + "name": "lsp-sample", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "lsp-sample", + "version": "1.0.0", + "hasInstallScript": true, + "license": "MIT", + "devDependencies": { + "@types/mocha": "^9.1.0", + "@types/node": "^16.18.34", + "@typescript-eslint/eslint-plugin": "^6.7.0", + "@typescript-eslint/parser": "^6.7.0", + "eslint": "^8.35.0", + "mocha": "^9.2.1", + "typescript": "^5.2.2" + }, + "engines": { + "vscode": "^1.75.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.1.tgz", + "integrity": "sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz", + "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz", + "integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "dev": true + }, + "node_modules/@types/mocha": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.0.tgz", + "integrity": "sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg==", + "dev": true + }, + "node_modules/@types/node": { + "version": "16.18.34", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.34.tgz", + "integrity": "sha512-VmVm7gXwhkUimRfBwVI1CHhwp86jDWR04B5FGebMMyxV90SlCmFujwUHrxTD4oO+SOYU86SoxvhgeRQJY7iXFg==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.0.tgz", + "integrity": "sha512-gUqtknHm0TDs1LhY12K2NA3Rmlmp88jK9Tx8vGZMfHeNMLE3GH2e9TRub+y+SOjuYgtOmok+wt1AyDPZqxbNag==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.7.0", + "@typescript-eslint/type-utils": "6.7.0", + "@typescript-eslint/utils": "6.7.0", + "@typescript-eslint/visitor-keys": "6.7.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.0.tgz", + "integrity": "sha512-jZKYwqNpNm5kzPVP5z1JXAuxjtl2uG+5NpaMocFPTNC2EdYIgbXIPImObOkhbONxtFTTdoZstLZefbaK+wXZng==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.7.0", + "@typescript-eslint/types": "6.7.0", + "@typescript-eslint/typescript-estree": "6.7.0", + "@typescript-eslint/visitor-keys": "6.7.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.0.tgz", + "integrity": "sha512-lAT1Uau20lQyjoLUQ5FUMSX/dS07qux9rYd5FGzKz/Kf8W8ccuvMyldb8hadHdK/qOI7aikvQWqulnEq2nCEYA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.7.0", + "@typescript-eslint/visitor-keys": "6.7.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.0.tgz", + "integrity": "sha512-f/QabJgDAlpSz3qduCyQT0Fw7hHpmhOzY/Rv6zO3yO+HVIdPfIWhrQoAyG+uZVtWAIS85zAyzgAFfyEr+MgBpg==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.7.0", + "@typescript-eslint/utils": "6.7.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.0.tgz", + "integrity": "sha512-ihPfvOp7pOcN/ysoj0RpBPOx3HQTJTrIN8UZK+WFd3/iDeFHHqeyYxa4hQk4rMhsz9H9mXpR61IzwlBVGXtl9Q==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.0.tgz", + "integrity": "sha512-dPvkXj3n6e9yd/0LfojNU8VMUGHWiLuBZvbM6V6QYD+2qxqInE7J+J/ieY2iGwR9ivf/R/haWGkIj04WVUeiSQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.7.0", + "@typescript-eslint/visitor-keys": "6.7.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.0.tgz", + "integrity": "sha512-MfCq3cM0vh2slSikQYqK2Gq52gvOhe57vD2RM3V4gQRZYX4rDPnKLu5p6cm89+LJiGlwEXU8hkYxhqqEC/V3qA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.7.0", + "@typescript-eslint/types": "6.7.0", + "@typescript-eslint/typescript-estree": "6.7.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.0.tgz", + "integrity": "sha512-/C1RVgKFDmGMcVGeD8HjKv2bd72oI1KxQDeY8uc66gw9R0OK0eMq48cA+jv9/2Ag6cdrsUGySm1yzYmfz0hxwQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.7.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz", + "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==", + "dev": true, + "dependencies": { + "@eslint/eslintrc": "^2.0.0", + "@eslint/js": "8.35.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.4.0", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/espree": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", + "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz", + "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "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 + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/js-sdsl": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", + "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", + "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.3", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "4.2.1", + "ms": "2.1.3", + "nanoid": "3.3.1", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.2.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", + "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "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, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workerpool": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", + "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.6.tgz", + "integrity": "sha512-PlVX4Y0lDTN6E2V4ES2tEdyvXkeKzxa8c/vo0pxPr/TqbztddTP0yn7zZylIyiAuxerqj0Q5GhpJ1YJCP8LaZQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.1.tgz", + "integrity": "sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz", + "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + } + }, + "@eslint/js": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz", + "integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==", + "dev": true + }, + "@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "dev": true + }, + "@types/mocha": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.0.tgz", + "integrity": "sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg==", + "dev": true + }, + "@types/node": { + "version": "16.18.34", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.34.tgz", + "integrity": "sha512-VmVm7gXwhkUimRfBwVI1CHhwp86jDWR04B5FGebMMyxV90SlCmFujwUHrxTD4oO+SOYU86SoxvhgeRQJY7iXFg==", + "dev": true + }, + "@types/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.0.tgz", + "integrity": "sha512-gUqtknHm0TDs1LhY12K2NA3Rmlmp88jK9Tx8vGZMfHeNMLE3GH2e9TRub+y+SOjuYgtOmok+wt1AyDPZqxbNag==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.7.0", + "@typescript-eslint/type-utils": "6.7.0", + "@typescript-eslint/utils": "6.7.0", + "@typescript-eslint/visitor-keys": "6.7.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.0.tgz", + "integrity": "sha512-jZKYwqNpNm5kzPVP5z1JXAuxjtl2uG+5NpaMocFPTNC2EdYIgbXIPImObOkhbONxtFTTdoZstLZefbaK+wXZng==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "6.7.0", + "@typescript-eslint/types": "6.7.0", + "@typescript-eslint/typescript-estree": "6.7.0", + "@typescript-eslint/visitor-keys": "6.7.0", + "debug": "^4.3.4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + } + } + }, + "@typescript-eslint/scope-manager": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.0.tgz", + "integrity": "sha512-lAT1Uau20lQyjoLUQ5FUMSX/dS07qux9rYd5FGzKz/Kf8W8ccuvMyldb8hadHdK/qOI7aikvQWqulnEq2nCEYA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.7.0", + "@typescript-eslint/visitor-keys": "6.7.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.0.tgz", + "integrity": "sha512-f/QabJgDAlpSz3qduCyQT0Fw7hHpmhOzY/Rv6zO3yO+HVIdPfIWhrQoAyG+uZVtWAIS85zAyzgAFfyEr+MgBpg==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "6.7.0", + "@typescript-eslint/utils": "6.7.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + } + } + }, + "@typescript-eslint/types": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.0.tgz", + "integrity": "sha512-ihPfvOp7pOcN/ysoj0RpBPOx3HQTJTrIN8UZK+WFd3/iDeFHHqeyYxa4hQk4rMhsz9H9mXpR61IzwlBVGXtl9Q==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.0.tgz", + "integrity": "sha512-dPvkXj3n6e9yd/0LfojNU8VMUGHWiLuBZvbM6V6QYD+2qxqInE7J+J/ieY2iGwR9ivf/R/haWGkIj04WVUeiSQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.7.0", + "@typescript-eslint/visitor-keys": "6.7.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + } + } + }, + "@typescript-eslint/utils": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.0.tgz", + "integrity": "sha512-MfCq3cM0vh2slSikQYqK2Gq52gvOhe57vD2RM3V4gQRZYX4rDPnKLu5p6cm89+LJiGlwEXU8hkYxhqqEC/V3qA==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.7.0", + "@typescript-eslint/types": "6.7.0", + "@typescript-eslint/typescript-estree": "6.7.0", + "semver": "^7.5.4" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.0.tgz", + "integrity": "sha512-/C1RVgKFDmGMcVGeD8HjKv2bd72oI1KxQDeY8uc66gw9R0OK0eMq48cA+jv9/2Ag6cdrsUGySm1yzYmfz0hxwQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.7.0", + "eslint-visitor-keys": "^3.4.1" + } + }, + "@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "8.35.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz", + "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==", + "dev": true, + "requires": { + "@eslint/eslintrc": "^2.0.0", + "@eslint/js": "8.35.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.4.0", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "dependencies": { + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + }, + "espree": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", + "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "dev": true, + "requires": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + } + }, + "esquery": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz", + "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "fast-deep-equal": { + "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-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-sdsl": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", + "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "mocha": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", + "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", + "dev": true, + "requires": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.3", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "4.2.1", + "ms": "2.1.3", + "nanoid": "3.3.1", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.2.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "dependencies": { + "minimatch": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", + "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nanoid": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-buffer": { + "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 + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "requires": {} + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "workerpool": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", + "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "y18n": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.6.tgz", + "integrity": "sha512-PlVX4Y0lDTN6E2V4ES2tEdyvXkeKzxa8c/vo0pxPr/TqbztddTP0yn7zZylIyiAuxerqj0Q5GhpJ1YJCP8LaZQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true + }, + "yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "requires": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/packages/doenet-vscode-extension/package.json b/packages/doenet-vscode-extension/package.json new file mode 100644 index 000000000..690a4f80c --- /dev/null +++ b/packages/doenet-vscode-extension/package.json @@ -0,0 +1,79 @@ +{ + "name": "doenet-vscode-extension", + "displayName": "DoenetML support", + "description": "A language server for DoenetML", + "author": "Jason Siefken", + "license": "AGPL", + "version": "1.0.0", + "repository": { + "type": "git", + "url": "https://github.com/Doenet/DoenetML" + }, + "categories": [], + "keywords": [ + "Doenet DoenetML" + ], + "engines": { + "vscode": "^1.76.0" + }, + "main": "./client/out/extension", + "contributes": { + "languages": [ + { + "id": "doenet", + "aliases": [ + "Doenet", + "doenet", + "DoenetML" + ], + "extensions": [ + ".doenet" + ], + "configuration": "./language-configuration.json" + } + ], + "grammars": [ + { + "language": "doenet", + "scopeName": "text.doenet", + "path": "./syntaxes/doenet.tmLanguage.json" + } + ], + "commands": [ + { + "command": "doenet.showPreview", + "title": "Show DoenetML Preview" + } + ] + }, + "scripts": { + "vscode:prepublish": "npm run compile", + "build": "npm run compile", + "compile": "npm run build:client && npm run build:server && npm run build:webview", + "build:server": "cd ./server && vite build", + "build:client": "cd ./client && tsc -b", + "build:webview": "cd ./webview-ui && npm run build", + "watch": "npm run build && cd ./server && vite build --watch", + "lint": "eslint ./client/src ./server/src --ext .ts,.tsx", + "postinstall": "cd client && npm install && cd ../server && npm install && cd ..", + "test": "echo \"No CI tests. You can use `npm run e2e-test` to run the end-to-end tests (requires a display)\" && exit 0", + "e2e-test": "sh ./scripts/e2e.sh" + }, + "devDependencies": { + "@types/mocha": "^9.1.1", + "@types/node": "^20.8.7", + "@typescript-eslint/eslint-plugin": "^6.8.0", + "@typescript-eslint/parser": "^6.8.0", + "@types/vscode-webview": "^1.57.3", + "@types/vscode": "^1.83.1", + "@vitejs/plugin-react": "^4.1.0", + "@vscode/webview-ui-toolkit": "^1.2.2", + "eslint": "^8.51.0", + "mocha": "^9.2.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "vite": "^4.5.0", + "typescript": "^5.2.2", + "vscode-test": "^1.6.1" + } +} diff --git a/packages/doenet-vscode-extension/scripts/e2e.sh b/packages/doenet-vscode-extension/scripts/e2e.sh new file mode 100755 index 000000000..860c62ef8 --- /dev/null +++ b/packages/doenet-vscode-extension/scripts/e2e.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +export CODE_TESTS_PATH="$(pwd)/client/out/test" +export CODE_TESTS_WORKSPACE="$(pwd)/client/testFixture" + +node "$(pwd)/client/out/test/runTest" \ No newline at end of file diff --git a/packages/doenet-vscode-extension/server/package-lock.json b/packages/doenet-vscode-extension/server/package-lock.json new file mode 100644 index 000000000..2ca80d822 --- /dev/null +++ b/packages/doenet-vscode-extension/server/package-lock.json @@ -0,0 +1,92 @@ +{ + "name": "lsp-sample-server", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "lsp-sample-server", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "vscode-languageserver": "^9.0.1", + "vscode-languageserver-textdocument": "^1.0.11" + }, + "engines": { + "node": "*" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", + "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" + } + }, + "dependencies": { + "vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==" + }, + "vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "requires": { + "vscode-languageserver-protocol": "3.17.5" + } + }, + "vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "requires": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "vscode-languageserver-textdocument": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", + "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==" + }, + "vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" + } + } +} diff --git a/packages/doenet-vscode-extension/server/package.json b/packages/doenet-vscode-extension/server/package.json new file mode 100644 index 000000000..92d7eafaa --- /dev/null +++ b/packages/doenet-vscode-extension/server/package.json @@ -0,0 +1,19 @@ +{ + "name": "lsp-sample-server", + "description": "Example implementation of a language server in node.", + "version": "1.0.0", + "author": "Microsoft Corporation", + "license": "MIT", + "engines": { + "node": "*" + }, + "repository": { + "type": "git", + "url": "https://github.com/Microsoft/vscode-extension-samples" + }, + "dependencies": { + "vscode-languageserver": "^9.0.1", + "vscode-languageserver-textdocument": "^1.0.11" + }, + "scripts": {} +} diff --git a/packages/doenet-vscode-extension/server/src/server.ts b/packages/doenet-vscode-extension/server/src/server.ts new file mode 100644 index 000000000..faaae6532 --- /dev/null +++ b/packages/doenet-vscode-extension/server/src/server.ts @@ -0,0 +1,267 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +import { + createConnection, + TextDocuments, + Diagnostic, + DiagnosticSeverity, + ProposedFeatures, + InitializeParams, + DidChangeConfigurationNotification, + CompletionItem, + CompletionItemKind, + TextDocumentPositionParams, + TextDocumentSyncKind, + InitializeResult, + DiagnosticTag, +} from "vscode-languageserver/node"; + +import { TextDocument } from "vscode-languageserver-textdocument"; +import { AutoCompleter } from "@doenet/lsp-tools"; +import { extractDastErrors, prettyPrint } from "@doenet/parser"; + +// Create a connection for the server, using Node's IPC as a transport. +// Also include all preview / proposed LSP features. +const connection = createConnection(ProposedFeatures.all); + +// Create a simple text document manager. +const documents: TextDocuments = new TextDocuments(TextDocument); + +let hasConfigurationCapability = false; +let hasWorkspaceFolderCapability = false; +let hasDiagnosticRelatedInformationCapability = false; + +connection.onInitialize((params: InitializeParams) => { + const capabilities = params.capabilities; + + // Does the client support the `workspace/configuration` request? + // If not, we fall back using global settings. + hasConfigurationCapability = !!( + capabilities.workspace && !!capabilities.workspace.configuration + ); + hasWorkspaceFolderCapability = !!( + capabilities.workspace && !!capabilities.workspace.workspaceFolders + ); + hasDiagnosticRelatedInformationCapability = !!( + capabilities.textDocument && + capabilities.textDocument.publishDiagnostics && + capabilities.textDocument.publishDiagnostics.relatedInformation + ); + + const result: InitializeResult = { + capabilities: { + textDocumentSync: TextDocumentSyncKind.Incremental, + // Tell the client that this server supports code completion. + completionProvider: { + resolveProvider: true, + }, + documentFormattingProvider: true, + foldingRangeProvider: true, + documentSymbolProvider: true, + hoverProvider: true, + }, + }; + if (hasWorkspaceFolderCapability) { + result.capabilities.workspace = { + workspaceFolders: { + supported: true, + }, + }; + } + return result; +}); + +connection.onInitialized(() => { + if (hasConfigurationCapability) { + // Register for all configuration changes. + connection.client.register( + DidChangeConfigurationNotification.type, + undefined, + ); + } + if (hasWorkspaceFolderCapability) { + connection.workspace.onDidChangeWorkspaceFolders((_event) => { + connection.console.log("Workspace folder change event received."); + }); + } +}); + +// The example settings +interface DoenetDocumentSettings {} + +// The global settings, used when the `workspace/configuration` request is not supported by the client. +// Please note that this is not the case when using this server with the client provided in this example +// but could happen with other clients. +const defaultSettings: DoenetDocumentSettings = {}; +let globalSettings: DoenetDocumentSettings = defaultSettings; + +// Cache the settings of all open documents +const documentSettings: Map< + string, + Thenable +> = new Map(); +const documentInfo: Map = new Map(); + +connection.onDidChangeConfiguration((change) => { + if (hasConfigurationCapability) { + // Reset all cached document settings + documentSettings.clear(); + } else { + globalSettings = ( + (change.settings.doenetLanguageServer || defaultSettings) + ); + } + + // Revalidate all open text documents + documents.all().forEach(validateTextDocument); +}); + +async function getDocumentSettings( + resource: string, +): Promise { + if (!hasConfigurationCapability) { + return Promise.resolve(globalSettings); + } + let result: Thenable | undefined = + documentSettings.get(resource); + if (!result) { + result = connection.workspace.getConfiguration({ + scopeUri: resource, + section: "doenetLanguageServer", + }); + documentSettings.set(resource, result); + } + return result; +} + +// Only keep settings for open documents +documents.onDidClose((e) => { + documentSettings.delete(e.document.uri); +}); + +// The content of a text document has changed. This event is emitted +// when the text document first opened or when its content has changed. +documents.onDidChangeContent((change) => { + let info = documentInfo.get(change.document.uri); + if (!info) { + const autoCompleter = new AutoCompleter(); + info = { autoCompleter }; + documentInfo.set(change.document.uri, info); + } + info.autoCompleter.setSource(change.document.getText()); + validateTextDocument(change.document); +}); + +async function validateTextDocument(textDocument: TextDocument): Promise { + // In this simple example we get the settings for every validate run. + const settings = await getDocumentSettings(textDocument.uri); + const info = documentInfo.get(textDocument.uri); + if (!info) { + return; + } + const errors = extractDastErrors(info.autoCompleter.sourceObj.dast); + const diagnostics: Diagnostic[] = errors.map((error) => { + const diagnostic: Diagnostic = { + message: error.message, + severity: DiagnosticSeverity.Error, + range: { + start: textDocument.positionAt( + error.position?.start?.offset || 0, + ), + end: textDocument.positionAt(error.position?.end?.offset || 0), + }, + }; + if (hasDiagnosticRelatedInformationCapability) { + diagnostic.relatedInformation = []; + } + return diagnostic; + }); + + const schemaErrors = info.autoCompleter.getSchemaViolations(); + diagnostics.push(...schemaErrors); + + // Send the computed diagnostics to VSCode. + connection.sendDiagnostics({ uri: textDocument.uri, diagnostics }); +} + +connection.onDidChangeWatchedFiles((_change) => { + // Monitored files have change in VSCode + connection.console.log("We received an file change event"); +}); + +// This handler provides the initial list of the completion items. +connection.onCompletion( + (textDocumentPosition: TextDocumentPositionParams): CompletionItem[] => { + const info = documentInfo.get(textDocumentPosition.textDocument.uri); + if (!info) { + return []; + } + const offset = info.autoCompleter.sourceObj.rowColToOffset( + textDocumentPosition.position, + ); + console.log( + "offset", + offset, + textDocumentPosition.position, + info.autoCompleter.source.slice(offset, offset + 10), + ); + const completions = info.autoCompleter.getCompletionItems( + textDocumentPosition.position, + ); + + return completions; + }, +); + +// This handler resolves additional information for the item selected in +// the completion list. +connection.onCompletionResolve((item: CompletionItem): CompletionItem => { + if (item.data === 1) { + item.detail = "TypeScript details"; + item.documentation = "TypeScript documentation"; + } else if (item.data === 2) { + item.detail = "JavaScript details"; + item.documentation = "JavaScript documentation"; + } + return item; +}); + +connection.onDocumentFormatting(async (params) => { + const info = documentInfo.get(params.textDocument.uri); + if (!info) { + return []; + } + const sourceObj = info.autoCompleter.sourceObj; + const rootPos = sourceObj.dast.position!; + const printed = await prettyPrint(sourceObj.source); + return [ + { + newText: printed, + range: { + start: sourceObj.offsetToLSPPosition(0), + end: sourceObj.offsetToLSPPosition(rootPos.end.offset!), + }, + }, + ]; +}); + +connection.onFoldingRanges((params) => { + return []; +}); + +connection.onHover((params) => { + return null; +}); + +connection.onDocumentSymbol((params) => { + return []; +}); + +// Make the text document manager listen on the connection +// for open, change and close text document events +documents.listen(connection); + +// Listen on the connection +connection.listen(); diff --git a/packages/doenet-vscode-extension/server/tsconfig.json b/packages/doenet-vscode-extension/server/tsconfig.json new file mode 100644 index 000000000..ec7af5680 --- /dev/null +++ b/packages/doenet-vscode-extension/server/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "es2020", + "lib": ["es2020"], + "module": "commonjs", + "moduleResolution": "node", + "sourceMap": true, + "strict": true, + "outDir": "out", + "rootDir": "src", + "paths": { + "@doenet/*": ["../../../packages/*/dist"] + }, + "skipLibCheck": true + }, + "include": ["src"], + "exclude": ["node_modules", ".vscode-test"] +} diff --git a/packages/doenet-vscode-extension/server/vite.config.ts b/packages/doenet-vscode-extension/server/vite.config.ts new file mode 100644 index 000000000..4fa196feb --- /dev/null +++ b/packages/doenet-vscode-extension/server/vite.config.ts @@ -0,0 +1,24 @@ +import { defineConfig } from "vite"; +import dts from "vite-plugin-dts"; + +// https://vitejs.dev/config/ +export default defineConfig({ + base: "./", + plugins: [dts()], + build: { + outDir: "out", + minify: false, + sourcemap: true, + lib: { + entry: "./src/server.ts", + fileName: "server", + formats: ["cjs"], + }, + rollupOptions: { + external: [ + "vscode-languageserver/node", + "vscode-languageserver-textdocument", + ], + }, + }, +}); diff --git a/packages/doenet-vscode-extension/syntaxes/doenet.tmLanguage.json b/packages/doenet-vscode-extension/syntaxes/doenet.tmLanguage.json new file mode 100644 index 000000000..03525e1a1 --- /dev/null +++ b/packages/doenet-vscode-extension/syntaxes/doenet.tmLanguage.json @@ -0,0 +1,391 @@ +{ + "information_for_contributors": [ + "This file modified from https://github.com/microsoft/vscode/blob/main/extensions/xml/syntaxes/xml.tmLanguage.json", + "to support DoenetML syntax." + ], + "version": "1.0", + "name": "doenet", + "scopeName": "text.doenet", + "patterns": [ + { + "begin": "(<\\?)\\s*([-_a-zA-Z0-9]+)", + "captures": { + "1": { + "name": "punctuation.definition.tag.xml" + }, + "2": { + "name": "entity.name.tag.xml" + } + }, + "end": "(\\?>)", + "name": "meta.tag.preprocessor.xml", + "patterns": [ + { + "match": " ([a-zA-Z-]+)", + "name": "entity.other.attribute-name.xml" + }, + { + "include": "#doublequotedString" + }, + { + "include": "#singlequotedString" + } + ] + }, + { + "begin": "()", + "name": "meta.tag.sgml.doctype.xml", + "patterns": [ + { + "include": "#internalSubset" + } + ] + }, + { + "include": "#comments" + }, + { + "begin": "(<)((?:([-_a-zA-Z0-9]+)(:))?([-_a-zA-Z0-9:]+))(?=(\\s[^>]*)?>)", + "beginCaptures": { + "1": { + "name": "punctuation.definition.tag.xml" + }, + "2": { + "name": "entity.name.tag.xml" + }, + "3": { + "name": "entity.name.tag.namespace.xml" + }, + "4": { + "name": "punctuation.separator.namespace.xml" + }, + "5": { + "name": "entity.name.tag.localname.xml" + } + }, + "end": "(>)()", + "endCaptures": { + "1": { + "name": "punctuation.definition.tag.xml" + }, + "2": { + "name": "punctuation.definition.tag.xml" + }, + "3": { + "name": "entity.name.tag.xml" + }, + "4": { + "name": "entity.name.tag.namespace.xml" + }, + "5": { + "name": "punctuation.separator.namespace.xml" + }, + "6": { + "name": "entity.name.tag.localname.xml" + }, + "7": { + "name": "punctuation.definition.tag.xml" + } + }, + "name": "meta.tag.no-content.xml", + "patterns": [ + { + "include": "#tagStuff" + } + ] + }, + { + "begin": "()", + "name": "meta.tag.xml", + "patterns": [ + { + "include": "#tagStuff" + } + ] + }, + { + "include": "#entity" + }, + { + "include": "#bare-ampersand" + }, + { + "begin": "<%@", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.xml" + } + }, + "end": "%>", + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.xml" + } + }, + "name": "source.java-props.embedded.xml", + "patterns": [ + { + "match": "page|include|taglib", + "name": "keyword.other.page-props.xml" + } + ] + }, + { + "begin": "<%[!=]?(?!--)", + "beginCaptures": { + "0": { + "name": "punctuation.section.embedded.begin.xml" + } + }, + "end": "(?!--)%>", + "endCaptures": { + "0": { + "name": "punctuation.section.embedded.end.xml" + } + }, + "name": "source.java.embedded.xml", + "patterns": [ + { + "include": "source.java" + } + ] + }, + { + "begin": "", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.xml" + } + }, + "name": "string.unquoted.cdata.xml" + }, + { "include": "#variable" } + ], + "repository": { + "EntityDecl": { + "begin": "()", + "patterns": [ + { + "include": "#doublequotedString" + }, + { + "include": "#singlequotedString" + } + ] + }, + "bare-ampersand": { + "match": "&", + "name": "invalid.illegal.bad-ampersand.xml" + }, + "doublequotedString": { + "begin": "\"", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.xml" + } + }, + "end": "\"", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.xml" + } + }, + "name": "string.quoted.double.xml", + "patterns": [ + { + "include": "#entity" + }, + { + "include": "#bare-ampersand" + } + ] + }, + "entity": { + "captures": { + "1": { + "name": "punctuation.definition.constant.xml" + }, + "3": { + "name": "punctuation.definition.constant.xml" + } + }, + "match": "(&)([:a-zA-Z_][:a-zA-Z0-9_.-]*|#[0-9]+|#x[0-9a-fA-F]+)(;)", + "name": "constant.character.entity.xml" + }, + "internalSubset": { + "begin": "(\\[)", + "captures": { + "1": { + "name": "punctuation.definition.constant.xml" + } + }, + "end": "(\\])", + "name": "meta.internalsubset.xml", + "patterns": [ + { + "include": "#EntityDecl" + }, + { + "include": "#parameterEntity" + }, + { + "include": "#comments" + } + ] + }, + "parameterEntity": { + "captures": { + "1": { + "name": "punctuation.definition.constant.xml" + }, + "3": { + "name": "punctuation.definition.constant.xml" + } + }, + "match": "(%)([:a-zA-Z_][:a-zA-Z0-9_.-]*)(;)", + "name": "constant.character.parameter-entity.xml" + }, + "singlequotedString": { + "begin": "'", + "beginCaptures": { + "0": { + "name": "punctuation.definition.string.begin.xml" + } + }, + "end": "'", + "endCaptures": { + "0": { + "name": "punctuation.definition.string.end.xml" + } + }, + "name": "string.quoted.single.xml", + "patterns": [ + { + "include": "#entity" + }, + { + "include": "#bare-ampersand" + } + ] + }, + "tagStuff": { + "patterns": [ + { + "captures": { + "1": { + "name": "entity.other.attribute-name.namespace.xml" + }, + "2": { + "name": "entity.other.attribute-name.xml" + }, + "3": { + "name": "punctuation.separator.namespace.xml" + }, + "4": { + "name": "entity.other.attribute-name.localname.xml" + } + }, + "match": "(?:^|\\s+)(?:([-\\w.]+)((:)))?([-\\w.:]+)(\\s*=)?" + }, + { + "include": "#doublequotedString" + }, + { + "include": "#singlequotedString" + } + ] + }, + "comments": { + "patterns": [ + { + "begin": "<%--", + "captures": { + "0": { + "name": "punctuation.definition.comment.xml" + }, + "end": "--%>", + "name": "comment.block.xml" + } + }, + { + "begin": "", + "name": "comment.block.xml", + "patterns": [ + { + "begin": "--(?!>)", + "captures": { + "0": { + "name": "invalid.illegal.bad-comments-or-CDATA.xml" + } + } + } + ] + } + ] + }, + "variable": { + "match": "(\\$)(\\w+(\\[.*?\\])?)(\\.(\\w+(\\[.*?\\])?))*(\\{.*?\\})?", + "name": "variable.other.doenet" + } + } +} diff --git a/packages/doenet-vscode-extension/tsconfig.json b/packages/doenet-vscode-extension/tsconfig.json new file mode 100644 index 000000000..604103ec1 --- /dev/null +++ b/packages/doenet-vscode-extension/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2020", + "lib": ["es2020"], + "outDir": "out", + "rootDir": "src", + "sourceMap": true, + "paths": { + "@doenet/*": ["../../packages/*/dist"] + }, + "skipLibCheck": true + }, + "include": ["src"], + "exclude": ["node_modules", ".vscode-test"], + "references": [{ "path": "./client" }, { "path": "./server" }] +} diff --git a/packages/doenet-vscode-extension/webview-ui/.gitignore b/packages/doenet-vscode-extension/webview-ui/.gitignore new file mode 100644 index 000000000..133f67c00 --- /dev/null +++ b/packages/doenet-vscode-extension/webview-ui/.gitignore @@ -0,0 +1,7 @@ +node_modules +.DS_Store +dist +dist-ssr +build +build-ssr +*.local diff --git a/packages/doenet-vscode-extension/webview-ui/README.md b/packages/doenet-vscode-extension/webview-ui/README.md new file mode 100644 index 000000000..17f210afb --- /dev/null +++ b/packages/doenet-vscode-extension/webview-ui/README.md @@ -0,0 +1,10 @@ +# `webview-ui` Directory + +This directory contains all of the code that will be executed within the webview context. It can be thought of as the place where all the "frontend" code of a webview is contained. + +Types of content that can be contained here: + +- Frontend framework code (i.e. React, Svelte, Vue, etc.) +- JavaScript files +- CSS files +- Assets / resources (i.e. images, illustrations, etc.) diff --git a/packages/doenet-vscode-extension/webview-ui/index.html b/packages/doenet-vscode-extension/webview-ui/index.html new file mode 100644 index 000000000..c9cb61670 --- /dev/null +++ b/packages/doenet-vscode-extension/webview-ui/index.html @@ -0,0 +1,12 @@ + + + + + + Hello World + + +
+ + + diff --git a/packages/doenet-vscode-extension/webview-ui/package.json b/packages/doenet-vscode-extension/webview-ui/package.json new file mode 100644 index 000000000..170063e86 --- /dev/null +++ b/packages/doenet-vscode-extension/webview-ui/package.json @@ -0,0 +1,12 @@ +{ + "name": "webview-ui", + "version": "0.0.1", + "private": true, + "scripts": { + "start": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": {}, + "devDependencies": {} +} diff --git a/packages/doenet-vscode-extension/webview-ui/src/App.css b/packages/doenet-vscode-extension/webview-ui/src/App.css new file mode 100644 index 000000000..3f86a46eb --- /dev/null +++ b/packages/doenet-vscode-extension/webview-ui/src/App.css @@ -0,0 +1,39 @@ +html, +#root, +body, +main { + height: 100%; + width: 100%; + overflow: hidden; + margin: 0; + padding: 0; +} +.main { + display: flex; + flex-direction: column; + justify-content: center; + height: 100%; +} + +.doenet-preview { + border: 2px solid #ccc; + margin: 0.5em; + flex-grow: 1; + overflow: auto; +} + +.doenet-preview #top { + padding: 0.5em !important; +} + +.header { + display: flex; + padding: 1ex; +} + +.header h1 { + padding: 0; + margin-right: 1em; + font-size: 1.1em; + font-weight: bold; +} diff --git a/packages/doenet-vscode-extension/webview-ui/src/App.tsx b/packages/doenet-vscode-extension/webview-ui/src/App.tsx new file mode 100644 index 000000000..8ecdfb343 --- /dev/null +++ b/packages/doenet-vscode-extension/webview-ui/src/App.tsx @@ -0,0 +1,60 @@ +import React from "react"; +import { vscode } from "./utilities/vscode"; +import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"; +// @ts-ignore +import { DoenetML } from "@doenet/doenetml/doenetml-inline-worker.js"; +import "./App.css"; +import "@doenet/doenetml/style.css"; + +function App() { + const [source, setSource] = React.useState( + "Sample Source\n", + ); + const [dirty, setDirty] = React.useState(false); + + React.useEffect(() => { + const callback = (event: MessageEvent) => { + const message = event.data; // The JSON data our extension sent + switch (message.command) { + case "setSource": + setSource(message.text); + setDirty(false); + break; + case "dirty": + setDirty(true); + break; + } + }; + + window.addEventListener("message", callback); + return () => { + window.removeEventListener("message", callback); + }; + }); + + function refreshClick() { + vscode.postMessage({ + command: "refresh", + text: "", + }); + } + + return ( +
+
+

DoenetML Preview

+ + Force Refresh{dirty ? " *" : ""} + +
+
+ +
+
+ ); +} + +export default App; diff --git a/packages/doenet-vscode-extension/webview-ui/src/index.tsx b/packages/doenet-vscode-extension/webview-ui/src/index.tsx new file mode 100644 index 000000000..74cadec44 --- /dev/null +++ b/packages/doenet-vscode-extension/webview-ui/src/index.tsx @@ -0,0 +1,11 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App"; + +const root = ReactDOM.createRoot(document.getElementById("root")!); + +root.render( + + + , +); diff --git a/packages/doenet-vscode-extension/webview-ui/src/utilities/vscode.ts b/packages/doenet-vscode-extension/webview-ui/src/utilities/vscode.ts new file mode 100644 index 000000000..b00e0c4ee --- /dev/null +++ b/packages/doenet-vscode-extension/webview-ui/src/utilities/vscode.ts @@ -0,0 +1,78 @@ +import type { WebviewApi } from "vscode-webview"; + +/** + * A utility wrapper around the acquireVsCodeApi() function, which enables + * message passing and state management between the webview and extension + * contexts. + * + * This utility also enables webview code to be run in a web browser-based + * dev server by using native web browser features that mock the functionality + * enabled by acquireVsCodeApi. + */ +class VSCodeAPIWrapper { + private readonly vsCodeApi: WebviewApi | undefined; + + constructor() { + // Check if the acquireVsCodeApi function exists in the current development + // context (i.e. VS Code development window or web browser) + if (typeof acquireVsCodeApi === "function") { + this.vsCodeApi = acquireVsCodeApi(); + } + } + + /** + * Post a message (i.e. send arbitrary data) to the owner of the webview. + * + * @remarks When running webview code inside a web browser, postMessage will instead + * log the given message to the console. + * + * @param message Abitrary data (must be JSON serializable) to send to the extension context. + */ + public postMessage(message: unknown) { + if (this.vsCodeApi) { + this.vsCodeApi.postMessage(message); + } else { + console.log(message); + } + } + + /** + * Get the persistent state stored for this webview. + * + * @remarks When running webview source code inside a web browser, getState will retrieve state + * from local storage (https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage). + * + * @return The current state or `undefined` if no state has been set. + */ + public getState(): unknown | undefined { + if (this.vsCodeApi) { + return this.vsCodeApi.getState(); + } else { + const state = localStorage.getItem("vscodeState"); + return state ? JSON.parse(state) : undefined; + } + } + + /** + * Set the persistent state stored for this webview. + * + * @remarks When running webview source code inside a web browser, setState will set the given + * state using local storage (https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage). + * + * @param newState New persisted state. This must be a JSON serializable object. Can be retrieved + * using {@link getState}. + * + * @return The new state. + */ + public setState(newState: T): T { + if (this.vsCodeApi) { + return this.vsCodeApi.setState(newState); + } else { + localStorage.setItem("vscodeState", JSON.stringify(newState)); + return newState; + } + } +} + +// Exports class singleton to prevent multiple invocations of acquireVsCodeApi. +export const vscode = new VSCodeAPIWrapper(); diff --git a/packages/doenet-vscode-extension/webview-ui/src/vite-env.d.ts b/packages/doenet-vscode-extension/webview-ui/src/vite-env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/packages/doenet-vscode-extension/webview-ui/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/doenet-vscode-extension/webview-ui/tsconfig.json b/packages/doenet-vscode-extension/webview-ui/tsconfig.json new file mode 100644 index 000000000..e24fc7ec6 --- /dev/null +++ b/packages/doenet-vscode-extension/webview-ui/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "esnext", + "lib": ["dom", "dom.iterable", "esnext"], + "useDefineForClassFields": true, + "allowJs": false, + "skipLibCheck": true, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": ["./src"] +} diff --git a/packages/doenet-vscode-extension/webview-ui/vite.config.ts b/packages/doenet-vscode-extension/webview-ui/vite.config.ts new file mode 100644 index 000000000..1da36e204 --- /dev/null +++ b/packages/doenet-vscode-extension/webview-ui/vite.config.ts @@ -0,0 +1,35 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import { viteStaticCopy } from "vite-plugin-static-copy"; +import * as path from "node:path"; +import { createRequire } from "module"; +const require = createRequire(import.meta.url); + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + react(), + viteStaticCopy({ + targets: [ + { + src: path.join( + require.resolve("@doenet/doenetml"), + "../fonts/*", + ), + dest: "fonts/", + }, + ], + }), + ], + base: "./", + build: { + outDir: "build", + rollupOptions: { + output: { + entryFileNames: `assets/[name].js`, + chunkFileNames: `assets/[name].js`, + assetFileNames: `assets/[name].[ext]`, + }, + }, + }, +}); diff --git a/packages/doenetml-worker/index.ts b/packages/doenetml-worker/index.ts deleted file mode 100644 index 4305c03e2..000000000 --- a/packages/doenetml-worker/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./src/CoreWorker.js"; diff --git a/packages/doenetml-worker/package.json b/packages/doenetml-worker/package.json index af677cd6e..0aa89471f 100644 --- a/packages/doenetml-worker/package.json +++ b/packages/doenetml-worker/package.json @@ -39,7 +39,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "rollup-plugin-polyfill-node": "^0.12.0", - "vite": "^4.3.9", + "vite": "^4.5.0", "vite-plugin-static-copy": "^0.17.0" } } diff --git a/packages/doenetml-worker/src/CoreWorker.js b/packages/doenetml-worker/src/CoreWorker.js index 0e1c4b1db..08b1af2a1 100644 --- a/packages/doenetml-worker/src/CoreWorker.js +++ b/packages/doenetml-worker/src/CoreWorker.js @@ -1,5 +1,4 @@ import Core from "./Core"; -import me from "math-expressions"; import { removeFunctionsMathExpressionClass } from "./utils/math"; import { createComponentInfoObjects } from "./utils/componentInfoObjects"; import { diff --git a/packages/doenetml-worker/src/components/CodeEditor.js b/packages/doenetml-worker/src/components/CodeEditor.js index a1249ecb1..5af7d1c50 100644 --- a/packages/doenetml-worker/src/components/CodeEditor.js +++ b/packages/doenetml-worker/src/components/CodeEditor.js @@ -69,6 +69,14 @@ export default class CodeEditor extends BlockComponent { public: true, }; + attributes.showFormatter = { + createComponentOfType: "boolean", + createStateVariable: "showFormatter", + defaultValue: false, + forRenderer: true, + public: true, + }; + attributes.resultsLocation = { createComponentOfType: "text", createStateVariable: "resultsLocation", diff --git a/packages/doenetml-worker/src/index.ts b/packages/doenetml-worker/src/index.ts new file mode 100644 index 000000000..4cbec4d3a --- /dev/null +++ b/packages/doenetml-worker/src/index.ts @@ -0,0 +1 @@ +export * from "./CoreWorker.js"; diff --git a/packages/doenetml-worker/vite.config.ts b/packages/doenetml-worker/vite.config.ts index 5f43c7849..6ff5b7a82 100644 --- a/packages/doenetml-worker/vite.config.ts +++ b/packages/doenetml-worker/vite.config.ts @@ -8,11 +8,12 @@ export default defineConfig({ minify: true, sourcemap: true, lib: { - entry: "index.ts", + entry: "src/index.ts", fileName: "CoreWorker", formats: ["es"], }, rollupOptions: { + // @ts-ignore plugins: [nodePolyfills()], external: ["react", "react-dom", "styled-components"], output: { diff --git a/packages/doenetml/package.json b/packages/doenetml/package.json index 603099fc2..02a811cc9 100644 --- a/packages/doenetml/package.json +++ b/packages/doenetml/package.json @@ -80,11 +80,11 @@ "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.3.4", - "prettier": "^3.0.2", + "prettier": "^3.0.3", "react": "^18.2.0", "react-dom": "^18.2.0", "rollup-plugin-polyfill-node": "^0.12.0", - "vite": "^4.3.9" + "vite": "^4.5.0" }, "prettier": { "tabWidth": 4 diff --git a/packages/doenetml/src/Viewer/renderers/codeEditor-ts.tsx b/packages/doenetml/src/Viewer/renderers/codeEditor-ts.tsx new file mode 100644 index 000000000..b3adcb897 --- /dev/null +++ b/packages/doenetml/src/Viewer/renderers/codeEditor-ts.tsx @@ -0,0 +1,414 @@ +import React, { useState, useRef, useEffect } from "react"; +import useDoenetRenderer, { rendererState } from "../useDoenetRenderer"; +import { sizeToCSS } from "./utils/css"; +import { CodeMirror } from "@doenet/codemirror"; +import VisibilitySensor from "react-visibility-sensor-v2"; +import { useSetRecoilState } from "recoil"; +import { + Box, + Button, + Flex, + FormControl, + FormLabel, + Stack, + Switch, +} from "@chakra-ui/react"; +import ErrorWarningPopovers from "../../Tools/ChakraBasedComponents/ErrorWarningPopovers"; +import { prettyPrint } from "@doenet/parser"; + +export default React.memo(function CodeEditor(props) { + let { + name, + id, + SVs, + children, + actions, + ignoreUpdate, + rendererName, + callAction, + } = useDoenetRenderer(props) as any; + + // @ts-ignore + CodeEditor.baseStateVariable = "immediateValue"; + + const setRendererState = useSetRecoilState(rendererState(rendererName)); + const [formatAsDoenetML, setFormatAsDoenetML] = useState(true); + + let currentValue = useRef(SVs.immediateValue); + let updateValueTimer = useRef(null); + let updateInternalValueTo = useRef(SVs.immediateValue); + + let componentHeight = { ...SVs.height }; + let editorHeight = { ...SVs.height }; + if (SVs.showResults && SVs.resultsLocation === "bottom") { + editorHeight.size *= 1 - SVs.viewerRatio; + } + + let onChangeVisibility = (isVisible: boolean) => { + callAction({ + action: actions.recordVisibilityChange, + args: { isVisible }, + }); + }; + + const onEditorChange = React.useCallback( + (value: string) => { + if (currentValue.current !== value) { + currentValue.current = value; + + setRendererState((was) => { + let newObj = { ...was }; + newObj.ignoreUpdate = true; + return newObj; + }); + + callAction({ + action: actions.updateImmediateValue, + args: { text: value }, + baseVariableValue: value, + }); + + // Debounce update value at 3 seconds + clearTimeout(updateValueTimer.current ?? undefined); + + //TODO: when you try to leave the page before it saved you will lose work + //so prompt the user on page leave + updateValueTimer.current = window.setTimeout(function () { + callAction({ + action: actions.updateValue, + baseVariableValue: currentValue.current, + }); + updateValueTimer.current = null; + }, 3000); //3 seconds + } + }, + [ + actions.updateImmediateValue, + actions.updateValue, + callAction, + setRendererState, + ], + ); + + useEffect(() => { + return () => { + callAction({ + action: actions.recordVisibilityChange, + args: { isVisible: false }, + }); + if (updateValueTimer.current !== null) { + window.clearTimeout(updateValueTimer.current); + callAction({ + action: actions.updateValue, + baseVariableValue: currentValue.current, + }); + } + }; + }, []); + + if (SVs.hidden) { + return null; + } + + useEffect(() => { + let platform = "Linux"; + if (navigator.platform.indexOf("Win") != -1) { + platform = "Win"; + } else if (navigator.platform.indexOf("Mac") != -1) { + platform = "Mac"; + } + const handleEditorKeyDown = (event: KeyboardEvent) => { + if ( + (platform == "Mac" && event.metaKey && event.code === "KeyS") || + (platform != "Mac" && event.ctrlKey && event.code === "KeyS") + ) { + event.preventDefault(); + event.stopPropagation(); + window.clearTimeout(updateValueTimer.current ?? undefined); + callAction({ + action: actions.updateValue, + baseVariableValue: currentValue.current, + }); + updateValueTimer.current = null; + callAction({ action: actions.updateComponents }); + } + }; + + let codeEditorContainer = document.getElementById(id); + if (SVs.showResults) { + codeEditorContainer?.addEventListener( + "keydown", + handleEditorKeyDown, + ); + } + + return () => { + codeEditorContainer?.removeEventListener( + "keydown", + handleEditorKeyDown, + ); + }; + }, [SVs.showResults]); + + const editorKey = id + "_editor"; + const viewerKey = id + "_viewer"; + + //Received update from core to immediateValue + //NOTE: currently causes a scrolling issue + //https://codemirror.net/doc/manual.html#events + // cm.scrollTo(x: number, y: number) + // Scroll the editor to a given (pixel) position. Both arguments may be left as null or undefined to have no effect. + // cm.getScrollInfo() → {left, top, width, height, clientWidth, clientHeight} + // Get an {left, top, width, height, clientWidth, clientHeight} object that represents the current scroll position, the size of the scrollable area, and the size of the visible area (minus scrollbars). + + if (!ignoreUpdate && SVs.immediateValue !== currentValue.current) { + currentValue.current = SVs.immediateValue; + updateInternalValueTo.current = SVs.immediateValue; + } + + let viewer: React.ReactNode = null; + let editorWidth = SVs.width; + let componentWidth = SVs.width; + if (SVs.showResults && ["left", "right"].includes(SVs.resultsLocation)) { + editorWidth = { size: 100, isAbsolute: false }; + } + + let editorStyle: React.CSSProperties = { + width: sizeToCSS(editorWidth), + height: sizeToCSS(editorHeight), + maxWidth: "100%", + padding: "0px", + overflowX: "hidden", + overflowY: "hidden", + display: "flex", + flexDirection: "column", + }; + + if (SVs.showResults) { + if (SVs.resultsLocation === "bottom") { + viewer = ( + <> +
+
{children}
+ + ); + } else { + viewer =
{children}
; + } + } + + let paddingBottom = { ...editorHeight }; + paddingBottom.size /= 2; + paddingBottom = sizeToCSS(paddingBottom); + + let errorsAndWarnings: React.ReactNode = null; + let errorsAndWarningsHeight = 0; + + if (SVs.errorsAndWarnings) { + errorsAndWarningsHeight = 32; + + const warningsLevel = 1; //TODO: eventually give user ability adjust warning level filter + const warningsObjs = SVs.errorsAndWarnings.warnings.filter( + (w: { level: number }) => w.level <= warningsLevel, + ); + const errorsObjs = [...SVs.errorsAndWarnings.errors]; + + errorsAndWarnings = ( + + + + ); + } + + let formatter: React.ReactNode = null; + if (SVs.showFormatter) { + formatter = ( + + + + + { + setFormatAsDoenetML(e.target.checked); + }} + title="Format as DoenetML or XML. The DoenetML syntax is more compact but may not be compatible with other XML tools." + /> + + Format as {formatAsDoenetML ? "DoenetML" : "XML"} + + + + + ); + } + + let editor = ( +
+ + + readOnly={SVs.disabled} + onBlur={() => { + window.clearTimeout( + updateValueTimer.current ?? undefined, + ); + callAction({ + action: actions.updateValue, + baseVariableValue: currentValue.current, + }); + updateValueTimer.current = null; + }} + onFocus={() => { + // console.log(">>codeEditor FOCUS!!!!!") + }} + onBeforeChange={onEditorChange} + paddingBottom={paddingBottom} + /> + + {errorsAndWarnings} + {formatter} +
+ ); + + let editorWithViewer = editor; + + if (SVs.showResults && SVs.resultsLocation === "bottom") { + editorWithViewer = ( + <> + {editor} + {viewer} + + ); + } + + editorWithViewer = ( +
+
+ {editorWithViewer} +
+
+ ); + + if (SVs.showResults) { + if (SVs.resultsLocation === "left") { + let viewerPercent = SVs.viewerRatio * 100; + let editorPercent = 100 - viewerPercent; + editorWithViewer = ( +
+
+ {viewer} +
+
+ {editorWithViewer} +
+
+ ); + } else if (SVs.resultsLocation === "right") { + let viewerPercent = SVs.viewerRatio * 100; + let editorPercent = 100 - viewerPercent; + editorWithViewer = ( +
+
+ {editorWithViewer} +
+
+ {viewer} +
+
+ ); + } + } + + return ( + + {editorWithViewer} + + ); +}); diff --git a/packages/doenetml/src/Viewer/renderers/codeEditor.jsx b/packages/doenetml/src/Viewer/renderers/codeEditor.jsx index c05b0d09f..b697ce4ec 100644 --- a/packages/doenetml/src/Viewer/renderers/codeEditor.jsx +++ b/packages/doenetml/src/Viewer/renderers/codeEditor.jsx @@ -1,349 +1,2 @@ -import React, { useState, useRef, useEffect } from "react"; -import useDoenetRenderer, { rendererState } from "../useDoenetRenderer"; -import { sizeToCSS } from "./utils/css"; -import { CodeMirror } from "@doenet/codemirror"; -import VisibilitySensor from "react-visibility-sensor-v2"; -import { useSetRecoilState } from "recoil"; -import { Box, Flex } from "@chakra-ui/react"; -import ErrorWarningPopovers from "../../Tools/ChakraBasedComponents/ErrorWarningPopovers"; - -export default React.memo(function CodeEditor(props) { - let { - name, - id, - SVs, - children, - actions, - ignoreUpdate, - rendererName, - callAction, - } = useDoenetRenderer(props); - - CodeEditor.baseStateVariable = "immediateValue"; - - const setRendererState = useSetRecoilState(rendererState(rendererName)); - - let currentValue = useRef(SVs.immediateValue); - let updateValueTimer = useRef(null); - let editorRef = useRef(null); - let updateInternalValueTo = useRef(SVs.immediateValue); - - let componentHeight = { ...SVs.height }; - let editorHeight = { ...SVs.height }; - if (SVs.showResults && SVs.resultsLocation === "bottom") { - editorHeight.size *= 1 - SVs.viewerRatio; - } - - let onChangeVisibility = (isVisible) => { - callAction({ - action: actions.recordVisibilityChange, - args: { isVisible }, - }); - }; - - useEffect(() => { - return () => { - callAction({ - action: actions.recordVisibilityChange, - args: { isVisible: false }, - }); - if (updateValueTimer.current !== null) { - clearTimeout(updateValueTimer.current); - callAction({ - action: actions.updateValue, - baseVariableValue: currentValue.current, - }); - } - }; - }, []); - - if (SVs.hidden) { - return null; - } - - useEffect(() => { - let platform = "Linux"; - if (navigator.platform.indexOf("Win") != -1) { - platform = "Win"; - } else if (navigator.platform.indexOf("Mac") != -1) { - platform = "Mac"; - } - const handleEditorKeyDown = (event) => { - if ( - (platform == "Mac" && event.metaKey && event.code === "KeyS") || - (platform != "Mac" && event.ctrlKey && event.code === "KeyS") - ) { - event.preventDefault(); - event.stopPropagation(); - clearTimeout(updateValueTimer.current); - callAction({ - action: actions.updateValue, - baseVariableValue: currentValue.current, - }); - updateValueTimer.current = null; - callAction({ action: actions.updateComponents }); - } - }; - - let codeEditorContainer = document.getElementById(id); - if (SVs.showResults) { - codeEditorContainer.addEventListener( - "keydown", - handleEditorKeyDown, - ); - } - - return () => { - codeEditorContainer.removeEventListener( - "keydown", - handleEditorKeyDown, - ); - }; - }, [SVs.showResults]); - - const editorKey = id + "_editor"; - const viewerKey = id + "_viewer"; - - //Received update from core to immediateValue - //NOTE: currently causes a scrolling issue - //https://codemirror.net/doc/manual.html#events - // cm.scrollTo(x: number, y: number) - // Scroll the editor to a given (pixel) position. Both arguments may be left as null or undefined to have no effect. - // cm.getScrollInfo() → {left, top, width, height, clientWidth, clientHeight} - // Get an {left, top, width, height, clientWidth, clientHeight} object that represents the current scroll position, the size of the scrollable area, and the size of the visible area (minus scrollbars). - - if (!ignoreUpdate && SVs.immediateValue !== currentValue.current) { - currentValue.current = SVs.immediateValue; - updateInternalValueTo.current = SVs.immediateValue; - } - - let viewer = null; - let editorWidth = SVs.width; - let componentWidth = SVs.width; - if (SVs.showResults && ["left", "right"].includes(SVs.resultsLocation)) { - editorWidth = { size: 100, isAbsolute: false }; - } - - let editorStyle = { - width: sizeToCSS(editorWidth), - height: sizeToCSS(editorHeight), - maxWidth: "100%", - padding: "0px", - overflowX: "hidden", - overflowY: "hidden", - }; - - if (SVs.showResults) { - if (SVs.resultsLocation === "bottom") { - viewer = ( - <> -
-
{children}
- - ); - } else { - viewer =
{children}
; - } - } - - let paddingBottom = { ...editorHeight }; - paddingBottom.size /= 2; - paddingBottom = sizeToCSS(paddingBottom); - - let errorsAndWarnings = null; - let errorsAndWarningsHeight = 0; - - if (SVs.errorsAndWarnings) { - errorsAndWarningsHeight = 32; - - const warningsLevel = 1; //TODO: eventually give user ability adjust warning level filter - const warningsObjs = SVs.errorsAndWarnings.warnings.filter( - (w) => w.level <= warningsLevel, - ); - const errorsObjs = [...SVs.errorsAndWarnings.errors]; - - errorsAndWarnings = ( - - - - ); - } - - let editor = ( -
- - - readOnly={SVs.disabled} - onBlur={() => { - clearTimeout(updateValueTimer.current); - callAction({ - action: actions.updateValue, - baseVariableValue: currentValue.current, - }); - updateValueTimer.current = null; - }} - onFocus={() => { - // console.log(">>codeEditor FOCUS!!!!!") - }} - onBeforeChange={(value) => { - if (currentValue.current !== value) { - currentValue.current = value; - - setRendererState((was) => { - let newObj = { ...was }; - newObj.ignoreUpdate = true; - return newObj; - }); - - callAction({ - action: actions.updateImmediateValue, - args: { text: value }, - baseVariableValue: value, - }); - - // Debounce update value at 3 seconds - clearTimeout(updateValueTimer.current); - - //TODO: when you try to leave the page before it saved you will lose work - //so prompt the user on page leave - updateValueTimer.current = setTimeout(function () { - callAction({ - action: actions.updateValue, - baseVariableValue: currentValue.current, - }); - updateValueTimer.current = null; - }, 3000); //3 seconds - } - }} - paddingBottom={paddingBottom} - /> - - {errorsAndWarnings} -
- ); - - let editorWithViewer = editor; - - if (SVs.showResults && SVs.resultsLocation === "bottom") { - editorWithViewer = ( - <> - {editor} - {viewer} - - ); - } - - editorWithViewer = ( - - ); - - if (SVs.showResults) { - if (SVs.resultsLocation === "left") { - let viewerPercent = SVs.viewerRatio * 100; - let editorPercent = 100 - viewerPercent; - editorWithViewer = ( -
-
- {viewer} -
-
- {editorWithViewer} -
-
- ); - } else if (SVs.resultsLocation === "right") { - let viewerPercent = SVs.viewerRatio * 100; - let editorPercent = 100 - viewerPercent; - editorWithViewer = ( -
-
- {editorWithViewer} -
-
- {viewer} -
-
- ); - } - } - - return ( - - {editorWithViewer} - - ); -}); +import CodeEditor from "./codeEditor-ts"; +export default CodeEditor; diff --git a/packages/lsp-tools/index.html b/packages/lsp-tools/index.html new file mode 100644 index 000000000..b13e757d3 --- /dev/null +++ b/packages/lsp-tools/index.html @@ -0,0 +1,26 @@ + + + + + + + LSP Viewer + + + +
+ + + diff --git a/packages/lsp-tools/package.json b/packages/lsp-tools/package.json new file mode 100644 index 000000000..08d7930da --- /dev/null +++ b/packages/lsp-tools/package.json @@ -0,0 +1,30 @@ +{ + "name": "@doenet/lsp-tools", + "type": "module", + "description": "Tools needed by the language server for DoenetML", + "version": "1.0.0", + "license": "AGPL-3.0-or-later", + "homepage": "https://github.com/Doenet/DoenetML#readme", + "private": false, + "repository": "github:Doenet/DoenetML", + "files": [ + "/dist" + ], + "exports": { + ".": { + "import": "./dist/index.js" + } + }, + "scripts": { + "dev": "vite", + "watch": "vite build --watch", + "build": "vite build", + "test": "vitest", + "compile_grammar": "npx lezer-generator --output src/generated-assets/lezer-doenet.ts src/doenet.grammar" + }, + "devDependencies": { + "vite": "^4.5.0", + "vite-plugin-dts": "^3.6.0", + "vscode-languageserver": "^9.0.1" + } +} diff --git a/packages/lsp-tools/src/auto-completer/get-completion-items.ts b/packages/lsp-tools/src/auto-completer/get-completion-items.ts new file mode 100644 index 000000000..87acbaf48 --- /dev/null +++ b/packages/lsp-tools/src/auto-completer/get-completion-items.ts @@ -0,0 +1,168 @@ +import { RowCol } from "../doenet-source-object"; +import type { CompletionItem } from "vscode-languageserver/browser"; +import { CompletionItemKind } from "vscode-languageserver/browser"; +import { showCursor } from "@doenet/parser"; +import { AutoCompleter } from "."; + +/** + * Get a list of completion items at the given offset. + */ +export function getCompletionItems( + this: AutoCompleter, + offset: number | RowCol, +): CompletionItem[] { + if (typeof offset !== "number") { + offset = this.sourceObj.rowColToOffset(offset); + } + + { + // XXX Debug + const cursor = this.sourceObj.lezerCursor; + cursor.moveTo(offset); + console.log("Cursor at pos:", showCursor(cursor)); + } + + const prevChar = this.sourceObj.source.charAt(offset - 1); + const prevPrevChar = this.sourceObj.source.charAt(offset - 2); + let prevNonWhitespaceCharOffset = offset - 1; + while ( + this.sourceObj.source + .charAt(prevNonWhitespaceCharOffset) + .match(/(\s|\n)/) + ) { + prevNonWhitespaceCharOffset--; + } + const prevNonWhitespaceChar = this.sourceObj.source.charAt( + prevNonWhitespaceCharOffset, + ); + + let containingNode = this.sourceObj.nodeAtOffset(offset); + let containingElement = this.sourceObj.elementAtOffset(offset); + const element = containingElement.node; + let cursorPosition = containingElement.cursorPosition; + if (!element && containingNode && containingNode.type === "text") { + // We're in the root of the document and not inside any special XML tags (like `` or ``) + // Find out what items we can complete. + + // If the previous char is a `<`, we suggest all top-level elements. + if (prevChar === "<") { + return this.schemaTopAllowedElements.map((name) => ({ + label: name, + kind: CompletionItemKind.Property, + })); + } + + return []; + } + + if (!element) { + return []; + } + + if (cursorPosition === "closeTagName") { + // We're in the close tag name. Suggest the close tag name. + return [ + { + label: element.name, + kind: CompletionItemKind.Property, + }, + ]; + } + + const { tagComplete, closed } = this.sourceObj.isCompleteElement(element); + + console.log({ tagComplete, closed, element: element.name }); + + if ( + cursorPosition === "body" && + containingElement.node && + prevChar === "<" + ) { + if (closed) { + // We're in the body of an element. Suggest all allowed children. + return this._getAllowedChildren(containingElement.node.name).map( + (name) => ({ + label: name, + kind: CompletionItemKind.Property, + }), + ); + } + // We are the child of a non-closed tag. Suggest the close tag. + return [ + { + label: `/${element.name}>`, + kind: CompletionItemKind.Property, + }, + ]; + } + if ( + cursorPosition === "body" && + containingElement.node && + prevPrevChar === "<" && + prevChar === "/" && + !closed + ) { + return [ + { + label: `${element.name}>`, + kind: CompletionItemKind.Property, + }, + ]; + } + + if (cursorPosition === "openTagName") { + // We're in the open tag name. Suggest everything that starts with the current text. + const currentText = element.name.toLowerCase(); + const parent = this.sourceObj.getParent(element); + if (!parent) { + return this.schemaTopAllowedElements + .filter((name) => name.toLowerCase().startsWith(currentText)) + .map((name) => ({ + label: name, + kind: CompletionItemKind.Property, + })); + } + + return this._getAllowedChildren(parent.name) + .filter((label) => label.toLowerCase().startsWith(currentText)) + .map((label) => ({ + label, + kind: CompletionItemKind.Property, + })); + } + + if (cursorPosition === "openTag" || cursorPosition === "attributeName") { + const elmName = this.normalizeElementName(element.name); + const allowedAttributes = + this.schemaElementsByName[elmName]?.attributes || []; + return allowedAttributes.map((attr) => ({ + label: attr.name, + kind: CompletionItemKind.Enum, + })); + } + + if ( + cursorPosition === "attributeValue" || + (cursorPosition === "unknown" && prevNonWhitespaceChar === "=") + ) { + const elmName = this.normalizeElementName(element.name); + const allowedAttributes = + this.schemaElementsByName[elmName]?.attributes || []; + const attribute = this._getAttributeLeftOfOffset(element, offset); + const allowedAttrValues = allowedAttributes.find( + (a) => a.name === attribute?.name, + )?.values; + if (!allowedAttrValues) { + return [{ label: '""', kind: CompletionItemKind.Value }]; + } + // If we are right after the =, we should include quotes in the completion, + // otherwise, assume the user has already supplied the quote marks. + const includeQuotes = prevNonWhitespaceChar === "="; + const quote = includeQuotes ? '"' : ""; + return allowedAttrValues.map((value) => ({ + label: `${quote}${value}${quote}`, + kind: CompletionItemKind.Value, + })); + } + return []; +} diff --git a/packages/lsp-tools/src/auto-completer/get-schema-violations.ts b/packages/lsp-tools/src/auto-completer/get-schema-violations.ts new file mode 100644 index 000000000..72134f6e5 --- /dev/null +++ b/packages/lsp-tools/src/auto-completer/get-schema-violations.ts @@ -0,0 +1,205 @@ +import { RowCol } from "../doenet-source-object"; +import type { CompletionItem, Diagnostic } from "vscode-languageserver/browser"; +import { + CompletionItemKind, + DiagnosticSeverity, +} from "vscode-languageserver/browser"; +import { + DastAttribute, + DastElement, + DastNodes, + DastRoot, + showCursor, + toXml, + visit, +} from "@doenet/parser"; +import { AutoCompleter } from "."; + +/** + * Get a list of completion items at the given offset. + */ +export function getSchemaViolations(this: AutoCompleter): Diagnostic[] { + /** + * Get all pairs of elements and their parent. + */ + function getElementPairs( + node: DastElement | DastRoot, + ): { node: DastElement; parent: DastElement | DastRoot }[] { + return node.children.flatMap((child) => { + if (child.type === "element") { + return [ + { node: child, parent: node }, + ...getElementPairs(child), + ]; + } + return []; + }); + } + + const allPairs = getElementPairs(this.sourceObj.dast); + + const ret: Diagnostic[] = allPairs.flatMap(({ node, parent }) => { + const ret: Diagnostic[] = []; + const name = this.normalizeElementName(node.name); + + if (name === "UNKNOWN_NAME") { + // No further checking for unknown elements. + const range = this.sourceObj.getElementTagRanges(node); + return { + range: { + start: this.sourceObj.offsetToLSPPosition(range[0].start), + end: this.sourceObj.offsetToLSPPosition(range[0].end), + }, + message: `Element \`<${node.name}>\` is not a recognized Doenet element.`, + severity: DiagnosticSeverity.Warning, + }; + } + + const schema = this.schemaElementsByName[name]; + // + // Check parent-child relationship + // + if (parent.type === "root") { + if (!schema) { + return []; + } + if (!schema.top) { + const range = this.sourceObj.getElementTagRanges(node); + ret.push({ + range: { + start: this.sourceObj.offsetToLSPPosition( + range[0].start, + ), + end: this.sourceObj.offsetToLSPPosition(range[0].end), + }, + message: `Element \`<${name}>\` is not allowed at the root of the document.`, + severity: DiagnosticSeverity.Warning, + }); + } + } else { + const parentName = this.normalizeElementName(parent.name); + if ( + parentName !== "UNKNOWN_NAME" && + !this.isAllowedChild(parentName, name) + ) { + const range = this.sourceObj.getElementTagRanges(node); + ret.push({ + range: { + start: this.sourceObj.offsetToLSPPosition( + range[0].start, + ), + end: this.sourceObj.offsetToLSPPosition(range[0].end), + }, + message: `Element \`<${name}>\` is not allowed inside of \`<${parentName}>\`.`, + severity: DiagnosticSeverity.Warning, + }); + } + } + + // + // Check attributes + // + for (const attr of node.attributes) { + const attrName = this.normalizeAttributeName(attr.name); + if (attrName === "UNKNOWN_NAME") { + ret.push({ + range: { + start: this.sourceObj.offsetToLSPPosition( + attr.position?.start.offset || 0, + ), + end: this.sourceObj.offsetToLSPPosition( + attr.position?.end.offset || 0, + ), + }, + message: `Element \`<${name}>\` doesn't have an attribute called \`${attr.name}\`.`, + severity: DiagnosticSeverity.Warning, + }); + } else if (!this.isAllowedAttribute(name, attrName)) { + ret.push({ + range: { + start: this.sourceObj.offsetToLSPPosition( + attr.position?.start.offset || 0, + ), + end: this.sourceObj.offsetToLSPPosition( + attr.position?.end.offset || 0, + ), + }, + message: `Element \`<${name}>\` doesn't have an attribute called \`${attrName}\`.`, + severity: DiagnosticSeverity.Warning, + }); + } else { + // If there are no macros/functions in the attribute value and the list of allowed values is non-empty, + // check that the value is in the list of allowed values. + const allowedValues = this.getAttributeAllowedValues( + name, + attrName, + ); + if (!hasMacroOrFunctionChild(attr.children) && allowedValues) { + // Attributes specified without a value are considered to have a value of "true". + const attrValue = + attr.children.length === 0 + ? "true" + : toXml(attr.children); + const range = getAttributeValueRange(attr); + if (!allowedValues.lowerCase.has(attrValue.toLowerCase())) { + ret.push({ + range: { + start: this.sourceObj.offsetToLSPPosition( + range.start, + ), + end: this.sourceObj.offsetToLSPPosition( + range.end, + ), + }, + message: `Attribute \`${attrName}\` of element \`<${name}>\` must be one of: ${[ + ...allowedValues.correctCase, + ] + .map((v) => `"${v}"`) + .join(", ")}`, + severity: DiagnosticSeverity.Warning, + }); + } + } + } + } + return ret; + }); + + return ret; +} + +/** + * Determine if the list of nodes contains a macro or function descendant. + */ +function hasMacroOrFunctionChild(nodes: DastNodes[]): boolean { + let ret = false; + visit(nodes, (node) => { + if (node.type === "macro" || node.type === "function") { + ret = true; + } + }); + + return ret; +} + +/** + * Get the offset of the start and end of the attribute value. + */ +function getAttributeValueRange(node: DastAttribute): { + start: number; + end: number; +} { + if (node.children.length === 0) { + return { + start: node.position?.end.offset || 0, + end: node.position?.end.offset || 0, + }; + } + const first = node.children[0]; + const last = node.children[node.children.length - 1]; + + return { + start: first.position?.start.offset || 0, + end: last.position?.end.offset || 0, + }; +} diff --git a/packages/lsp-tools/src/auto-completer/index.ts b/packages/lsp-tools/src/auto-completer/index.ts new file mode 100644 index 000000000..8dd6948c5 --- /dev/null +++ b/packages/lsp-tools/src/auto-completer/index.ts @@ -0,0 +1,218 @@ +import { DoenetSourceObject, RowCol } from "../doenet-source-object"; +import { doenetSchema } from "@doenet/static-assets"; +import { DastAttribute, DastElement } from "@doenet/parser"; +import { getCompletionItems } from "./get-completion-items"; +import { getSchemaViolations } from "./get-schema-violations"; + +type ElementSchema = { + name: string; + top: boolean; + attributes: { name: string; values?: string[] }[]; + children: string[]; + acceptsStringChildren: boolean; +}; + +/** + * A class to make auto-completion queries on DoenetML source. + */ +export class AutoCompleter { + sourceObj: DoenetSourceObject = new DoenetSourceObject(); + schema: ElementSchema[] = []; + /** + * A map of element names (in lower case) to their canonical capitalization. + */ + schemaLowerToUpper: Record = {}; + /** + * A map of attribute names (in lower case) to their canonical capitalization. + */ + schemaAttributesLowerToUpper: Record = {}; + schemaTopAllowedElements: string[] = []; + schemaElementsByName: Record = {}; + parentChildMap: Map> = new Map(); + nodeAttributeMap: Map< + string, + Map; lowerCase: Set } | null> + > = new Map(); + + constructor( + source?: string, + schema: ElementSchema[] = doenetSchema.elements, + ) { + if (source != null) { + this.sourceObj.setSource(source); + } + if (schema) { + this.setSchema(schema); + } + } + + /** + * Set the schema to be used for auto-completion. + * @param schema + */ + setSchema(schema: ElementSchema[]) { + this.schema = schema; + this.schemaLowerToUpper = Object.fromEntries( + this.schema.map((e) => [e.name.toLowerCase(), e.name]), + ); + this.schemaAttributesLowerToUpper = Object.fromEntries( + this.schema.flatMap((e) => { + return e.attributes.map((a) => [a.name.toLowerCase(), a.name]); + }), + ); + this.schemaElementsByName = Object.fromEntries( + this.schema.map((e) => [e.name, e]), + ); + this.schemaTopAllowedElements = this.schema + .filter((e) => e.top) + .map((e) => e.name); + this.parentChildMap = new Map( + this.schema.map((e) => [e.name, new Set(e.children)]), + ); + this.nodeAttributeMap = new Map( + this.schema.map((e) => [ + e.name, + new Map( + e.attributes.map((a) => [ + a.name, + a.values + ? { + correctCase: new Set(a.values), + lowerCase: new Set( + a.values.map((v) => v.toLowerCase()), + ), + } + : null, + ]), + ), + ]), + ); + } + + /** + * Get a list of completion items at the given offset. + */ + getCompletionItems = getCompletionItems; + + /** + * Get a list of LSP `Diagnostic`s for schema violations. + */ + getSchemaViolations = getSchemaViolations; + + /** + * Get the children allowed inside an `elementName` named element. + * The search is case insensitive. + */ + _getAllowedChildren(elementName: string): string[] { + elementName = this.normalizeElementName(elementName); + return this.schemaElementsByName[elementName]?.children || []; + } + + /** + * Gets the attribute that ends to the left of `offset`, if one exists. + */ + _getAttributeLeftOfOffset( + node: DastElement, + offset: number, + ): DastAttribute | null { + let candidate = node.attributes[0]; + if (!candidate) { + return null; + } + let candidateOffset = candidate.position?.end?.offset!; + for (const attr of node.attributes) { + let attrOffset = attr.position?.end?.offset!; + if (attrOffset > candidateOffset && attrOffset <= offset) { + candidate = attr; + } + } + return candidate || null; + } + + /** + * Set the internal DoenetSourceObject. This should not normally be used, + * but may be used if you want to pool DoenetSourceObjects over multiple + * instances. + */ + setDoenetSourceObject(sourceObj: DoenetSourceObject) { + this.sourceObj = sourceObj; + } + + /** + * Set the DoenetML source string. All future queries will be run on this source. + */ + setSource(source: string) { + this.sourceObj.setSource(source); + return this; + } + + get source() { + return this.sourceObj.source; + } + + /** + * Convert an element name to its standard capitalization. + */ + normalizeElementName(name: string): string | "UNKNOWN_NAME" { + return this.schemaLowerToUpper[name.toLowerCase()] || "UNKNOWN_NAME"; + } + + /** + * Convert an attribute name to its standard capitalization. + */ + normalizeAttributeName(name: string): string | "UNKNOWN_NAME" { + return ( + this.schemaAttributesLowerToUpper[name.toLowerCase()] || + "UNKNOWN_NAME" + ); + } + + /** + * Gets whether the child is allowed inside the parent. This function normalizes the + * name of the parent and child before checking. + */ + isAllowedChild(parentName: string, childName: string): boolean { + parentName = this.normalizeElementName(parentName); + childName = this.normalizeElementName(childName); + if (parentName === "UNKNOWN_NAME" || childName === "UNKNOWN_NAME") { + return false; + } + return this.parentChildMap.get(parentName)?.has(childName) || false; + } + + /** + * Checks whether the given attribute is allowed on the given element. This function + * normalizes the name of the element and attribute before checking. + */ + isAllowedAttribute(elementName: string, attributeName: string): boolean { + elementName = this.normalizeElementName(elementName); + attributeName = this.normalizeAttributeName(attributeName); + if ( + elementName === "UNKNOWN_NAME" || + attributeName === "UNKNOWN_NAME" + ) { + return false; + } + return ( + this.nodeAttributeMap.get(elementName)?.has(attributeName) || false + ); + } + + /** + * Gets the schema for a given attribute of a given element. This function + * normalizes the name of the element and attribute before checking. + */ + getAttributeAllowedValues(elementName: string, attributeName: string) { + elementName = this.normalizeElementName(elementName); + attributeName = this.normalizeAttributeName(attributeName); + if ( + elementName === "UNKNOWN_NAME" || + attributeName === "UNKNOWN_NAME" + ) { + return null; + } + return ( + this.nodeAttributeMap.get(elementName)?.get(attributeName) || null + ); + } +} diff --git a/packages/lsp-tools/src/dev-site.tsx b/packages/lsp-tools/src/dev-site.tsx new file mode 100644 index 000000000..9f3643814 --- /dev/null +++ b/packages/lsp-tools/src/dev-site.tsx @@ -0,0 +1,157 @@ +/* + * This file is for running a dev test of the codemirror component. + * It does not show up in the bundled package. + */ + +import React from "react"; +import ReactDOM from "react-dom/client"; +import { CodeMirror } from "@doenet/codemirror"; +import { lezerToDast, parse, filterPositionInfo } from "@doenet/parser"; +import JsonView from "react18-json-view"; +import "react18-json-view/src/style.css"; +import { DoenetSourceObject } from "./doenet-source-object"; +import { AutoCompleter } from "./auto-completer"; + +const INITIAL_DOENET_SOURCE = ` +

Use this to test DoenetML

+ + + + + + + + + +`; + +ReactDOM.createRoot(document.getElementById("root")!).render(); + +const simpleSchema = { + elements: [ + { + name: "a", + children: ["b", "c", "d"], + attributes: [{ name: "x" }, { name: "y" }, { name: "xyx" }], + top: true, + acceptsStringChildren: false, + }, + { + name: "b", + children: ["www"], + attributes: [{ name: "foo", values: ["true", "false"] }], + top: false, + acceptsStringChildren: false, + }, + { + name: "c", + children: [], + attributes: [], + top: false, + acceptsStringChildren: true, + }, + ], +}; + +const sourceObj = new DoenetSourceObject(INITIAL_DOENET_SOURCE); +const completionObj = new AutoCompleter("", simpleSchema.elements); +completionObj.setDoenetSourceObject(sourceObj); +console.log(sourceObj, completionObj); +(window as any).sourceObj = sourceObj; +(window as any).completionObj = completionObj; + +function App() { + const [doenetSource, setDoenetSource] = React.useState( + INITIAL_DOENET_SOURCE, + ); + const [dast, setDast] = React.useState({}); + const [omitPosition, setOmitPosition] = React.useState(false); + const [rawJson, setRawJson] = React.useState(false); + const [currentPos, setCurrentPos] = React.useState(0); + + React.useEffect(() => { + let dast = lezerToDast(doenetSource); + if (omitPosition) { + dast = filterPositionInfo(dast) as any; + } + setDast(dast); + }, [doenetSource, omitPosition]); + React.useEffect(() => { + sourceObj.setSource(doenetSource); + console.log( + { currentPos }, + sourceObj.elementAtOffset(currentPos), + sourceObj.attributeAtOffset(currentPos), + completionObj.getCompletionItems(currentPos), + ); + }, [currentPos, doenetSource]); + + return ( +
+
+ { + setOmitPosition(e.target.checked); + }} + /> + + { + setRawJson(e.target.checked); + }} + /> + +
+
+
+ { + setDoenetSource(val); + }} + setInternalValueTo={INITIAL_DOENET_SOURCE} + onCursorChange={(selection) => { + const range = selection.ranges[0]; + if (!range) { + return; + } + setCurrentPos(range.from); + }} + /> +
+
+ {rawJson ? ( +
{JSON.stringify(dast, null, 2)}
+ ) : ( + { + if (node.indexOrName === "position") { + return true; + } + return false; + }} + /> + )} +
+
+
+ ); +} diff --git a/packages/lsp-tools/src/doenet-source-object/element-at-offset.ts b/packages/lsp-tools/src/doenet-source-object/element-at-offset.ts new file mode 100644 index 000000000..b30cd30f2 --- /dev/null +++ b/packages/lsp-tools/src/doenet-source-object/element-at-offset.ts @@ -0,0 +1,183 @@ +import { CursorPosition, DoenetSourceObject, RowCol } from "./index"; +import { DastElement, LezerSyntaxNodeName } from "@doenet/parser"; + +/** + * Get the element containing the position `offset`. `null` is returned if the position is not + * contained in an element. + * + * Details about the `offset` position within the element are also returned, e.g., if `offset` is in + * the open tag, etc.. + */ +export function elementAtOffset( + this: DoenetSourceObject, + offset: number | RowCol, +): { + node: DastElement | null; + cursorPosition: CursorPosition; +} { + if (typeof offset !== "number") { + offset = this.rowColToOffset(offset); + } + + let cursorPosition: CursorPosition = "unknown"; + const prevChar = this.source.charAt(offset - 1); + const exactNodeAtOffset = this.nodeAtOffset(offset); + let node = this.nodeAtOffset(offset, "element") as DastElement | null; + + if (exactNodeAtOffset && exactNodeAtOffset !== node) { + // If our exact node is not the same as our containing element, then we're a child of the containing + // element and so we're in the body. + cursorPosition = "body"; + } + + if (!node) { + cursorPosition = "unknown"; + } + if (node && cursorPosition === "unknown") { + // Try to guess where the cursor is + const cursor = this._lezerCursor(); + cursor.moveTo(offset, -1); + const leftNode = cursor.node; + cursor.moveTo(offset, 1); + const rightNode = cursor.node; + // XXX Fix this after the CodeMirror update + // @ts-ignore + const atNodeBoundary = leftNode.index !== rightNode.index; + // If we're at a node boundary, we pick the node to the left if the previous character + // is a word character. This should help with completion contexts, since the author + // is probably still typing a word, or is expecting completions from the word on the left. + let lezerNode = atNodeBoundary + ? prevChar.match(/\w/) + ? leftNode + : rightNode + : leftNode; + const rightNodeType = rightNode.type.name as LezerSyntaxNodeName; + if (atNodeBoundary && rightNodeType === "StartCloseTag") { + // If we're at the start of a close tag, then we're in the body of an element. + // We claim to be in the element to our left because that is what a user with + // auto-completion expects. + cursorPosition = "body"; + lezerNode = leftNode; + node = this.nodeAtOffset( + lezerNode.from, + "element", + ) as DastElement | null; + } + + const lezerNodeType = lezerNode.type.name as LezerSyntaxNodeName; + const lezerNodeParentType = lezerNode.parent?.type?.name as + | LezerSyntaxNodeName + | undefined; + switch (lezerNodeType) { + case "TagName": { + cursorPosition = + lezerNodeParentType === "OpenTag" || + lezerNodeParentType === "SelfClosingTag" + ? "openTagName" + : "closeTagName"; + break; + } + case "AttributeName": + cursorPosition = "attributeName"; + break; + case "AttributeValue": + cursorPosition = "attributeValue"; + break; + case "OpenTag": + case "SelfClosingTag": + cursorPosition = "openTag"; + break; + case "EndTag": + if ( + lezerNodeParentType === "OpenTag" || + lezerNodeParentType === "SelfClosingTag" + ) { + cursorPosition = "openTag"; + } else if (!prevChar.match(/(\s|\n)/)) { + cursorPosition = "closeTagName"; + } else { + cursorPosition = "unknown"; + } + break; + case "StartCloseTag": + cursorPosition = "body"; + break; + } + } + + // If we're not in an element and the previous character is a word character or `<`, then + // we might be part of an incomplete element. In this case, we return the element _before_ `offset`. + if (!node && prevChar.match(/(\w|<)/)) { + return this.elementAtOffset(offset - 1); + } + + const prevCharIsWhitespace = Boolean(prevChar.match(/(\s|\n)/)); + let prevNonWhitespaceCharOffset = offset - 1; + while (this.source.charAt(prevNonWhitespaceCharOffset).match(/(\s|\n)/)) { + prevNonWhitespaceCharOffset -= 1; + } + const prevNonWhitespaceChar = this.source.charAt( + prevNonWhitespaceCharOffset, + ); + + // If there is an incomplete element before the cursor position and the cursor + // is positioned right before the start of the close tag, we might misreport we're + // in the body of the parent element rather than in the incomplete preceding element. + // This can happen like + // 1. `
` where the cursor is a child of an element; OR + // 2. ``, even if they're self closing. + // We don't want to return the previous element if it's already closed. + if (prevNonWhitespaceChar !== ">") { + const precedingNode = this.nodeAtOffset( + prevNonWhitespaceCharOffset, + ); + if (precedingNode && precedingNode.type === "element") { + node = precedingNode; + } + } + } + + // If we're in an incomplete tag, our `cursorPosition` may be unknown. + if (node && cursorPosition === "unknown" && prevCharIsWhitespace) { + const cursor = this._lezerCursor(); + cursor.moveTo(prevNonWhitespaceCharOffset, 1); + const lezerNodeType = cursor.node.type.name as LezerSyntaxNodeName; + const lezerNodeParentType = cursor.node.parent?.type?.name as + | LezerSyntaxNodeName + | undefined; + switch (lezerNodeType) { + case "TagName": { + if (lezerNodeParentType === "CloseTag") { + break; + } + } + case "Attribute": + case "AttributeName": + case "AttributeValue": + cursorPosition = "openTag"; + break; + } + } + + // If `node.name === ""`, then there is some error. The user has probably typed `<` and nothing else. + // In this case, pretend we are the node before the cursor. + if (node && node.name === "") { + if (offset > 0) { + return this.elementAtOffset(offset - 1); + } + return { node: null, cursorPosition: "unknown" }; + } + + return { node, cursorPosition }; +} diff --git a/packages/lsp-tools/src/doenet-source-object/index.ts b/packages/lsp-tools/src/doenet-source-object/index.ts new file mode 100644 index 000000000..86311d620 --- /dev/null +++ b/packages/lsp-tools/src/doenet-source-object/index.ts @@ -0,0 +1,418 @@ +import { + DastElement, + DastFunctionMacro, + DastNodes, + DastRoot, + LezerSyntaxNodeName, + toXml, +} from "@doenet/parser"; +import { + initDast, + initLezer, + initLezerCursor, + initDescendentNamesMap, + initOffsetToNodeMap, + initOffsetToRowCache, + initParentMap, + initRowToOffsetCache, +} from "./initializers"; +import { LazyDataObject } from "./lazy-data"; +import { elementAtOffset } from "./element-at-offset"; +import { DastMacro } from "@doenet/parser"; + +/** + * A row/column position. All values are 1-indexed. This is compatible with UnifiedJs's + * position objects as well as Language Server Protocol's position objects. + */ +export type RowCol = + | { line: number; character: number } + | { line: number; column: number } + | { row: number; col: number }; + +export type CursorPosition = + | "unknown" + | "body" + | "openTagName" + | "closeTagName" + | "openTag" + | "attributeName" + | "attributeValue"; + +/** + * Keeps track of DoenetML source code, allowing you to run various queries. + */ +export class DoenetSourceObject extends LazyDataObject { + source: string = ""; + + // Set up the lazy data objects + // These will be initialized the first time they are used + _lezer = this._lazyDataGetter(initLezer); + _lezerCursor = this._lazyDataGetter(initLezerCursor); + _dast = this._lazyDataGetter(initDast); + _offsetToRowCache = this._lazyDataGetter(initOffsetToRowCache); + _rowToOffsetCache = this._lazyDataGetter(initRowToOffsetCache); + _parentMap = this._lazyDataGetter(initParentMap); + _offsetToNodeMap = this._lazyDataGetter(initOffsetToNodeMap); + _descendentNamesMap = this._lazyDataGetter(initDescendentNamesMap); + + constructor(source?: string) { + super(); + if (source != null) { + this.setSource(source); + } + } + + /** + * Set the DoenetML source string. All future queries will be run on this source. + */ + setSource(source: string) { + if (this.source === source) { + return this; + } + this._clearLazyData(); + this.source = source; + return this; + } + + /** + * Given a 0-index offset into the source string, return the 1-index line and column. + */ + offsetToRowCol(offset: number): { line: number; column: number } { + const offsetToRowCache = this._offsetToRowCache(); + return { + line: offsetToRowCache.rowMap[offset] + 1, + column: offsetToRowCache.columnMap[offset] + 1, + }; + } + + /** + * Given a 0-index offset into the source string, return an LSP position. + */ + offsetToLSPPosition(offset: number): { line: number; character: number } { + const offsetToRowCache = this._offsetToRowCache(); + return { + line: offsetToRowCache.rowMap[offset], + character: offsetToRowCache.columnMap[offset], + }; + } + + /** + * Given a 1-index line and column, return the 0-index offset into the source string. + */ + rowColToOffset(rowCol: RowCol): number { + const _rowToOffsetCache = this._rowToOffsetCache(); + // 0-indexed row and columns + let row = ("row" in rowCol ? rowCol.row : rowCol.line) - 1; + let col = + ("col" in rowCol + ? rowCol.col + : "column" in rowCol + ? rowCol.column + : rowCol.character) - 1; + // If `character` is in `rowCol`, then we are using the LSP format + // which is zero-indexed already. Apply an "unfix". + if ("character" in rowCol) { + row += 1; + col += 1; + } + + return _rowToOffsetCache[row] + col; + } + + /** + * Return the node that contains the current offset and is furthest down the tree. + * E.g. `x` at offset equal to the position of `x` return a text node. + * + * If `type` is passed in, then `nodeAtOffset` will walk up the parent tree until it finds + * a node of that type. It returns `null` if no such node can be found. + */ + nodeAtOffset( + offset: number | RowCol, + type?: DastNodes["type"], + ): DastNodes | null { + if (typeof offset !== "number") { + offset = this.rowColToOffset(offset); + } + if (offset < 0 || offset > this.source.length) { + return null; + } + if (offset > 0 && offset === this.source.length) { + // If we ask for a node at the "end" of the file, we probably want + // the last node, not null; walk back one character. + offset -= 1; + } + const offsetToNodeMap = this._offsetToNodeMap(); + let ret = offsetToNodeMap[offset] || null; + if (type != null) { + while (ret && ret.type !== type) { + ret = this.getParent(ret); + } + } + + return ret; + } + + /** + * Get the element containing the position `offset`. `null` is returned if the position is not + * contained in an element. + * + * Details about the `offset` position within the element are also returned, e.g., if `offset` is in + * the open tag, etc.. + */ + elementAtOffset = elementAtOffset; + + /** + * Get the element attribute at `offset`, if it exists. + */ + attributeAtOffset(offset: number | RowCol) { + if (typeof offset !== "number") { + offset = this.rowColToOffset(offset); + } + const _offset = offset; + const containingElm = this.elementAtOffset(offset); + if ( + !containingElm.node || + (containingElm.cursorPosition !== "attributeName" && + containingElm.cursorPosition !== "attributeValue") + ) { + return null; + } + + // Find the attribute whose range contains the cursor + const attribute = containingElm.node.attributes.find( + (a) => + a.position && + a.position.start.offset! <= _offset && + a.position.end.offset! >= _offset, + ); + return attribute || null; + } + + /** + * Returns whether `node` is a complete element (`true`) or + * partially complete (`false`). Complete elements are valid xml. + * Incomplete elements are ``. + */ + isCompleteElement(node: DastElement): { + tagComplete: boolean; + closed: boolean; + } { + if (node.type !== "element") { + throw new Error( + `Node ${toXml( + node, + )} is not an element. Only elements maybe passed to this function.`, + ); + } + if (!node.position || node.position.start.offset == null) { + throw new Error( + `Node ${JSON.stringify(node)} is missing position information`, + ); + } + const cursor = this._lezerCursor(); + cursor.moveTo(node.position.start.offset + 1, 0); + const lezerNode = cursor.node; + const lezerNodeParent = lezerNode.parent; + const nodeName = lezerNode.type.name as LezerSyntaxNodeName; + + let tagComplete = true; + let closed = true; + + switch (nodeName) { + case "OpenTag": { + // An open tag must have an EndTag (`>`) otherwise it is incomplete + if (!lezerNode.getChild("EndTag")) { + tagComplete = false; + } + if (!lezerNodeParent?.getChild("CloseTag")) { + closed = false; + } + break; + } + case "SelfClosingTag": { + // An self closing tag must have an SelfCloseEndTag (`/>`) otherwise it is incomplete + if (!lezerNode.getChild("SelfCloseEndTag")) { + tagComplete = false; + } + break; + } + default: + console.warn( + "Could not find OpenTag or SelfClosingTag for node", + node, + ); + } + + return { tagComplete, closed }; + } + + /** + * Get the offset ranges for the tag(s) of `node`. (I.e., just the part + * in the angle brackets without the children.) If the tag is incomplete or + * is a self-closing tag, only one range will be returned. + * + * Note: these values are given as **offsets**. + */ + getElementTagRanges(node: DastElement): { start: number; end: number }[] { + const start = node.position?.start?.offset || 0; + const end = node.position?.end?.offset || 0; + const childrenStart = node.children[0]?.position?.start?.offset; + const childrenEnd = + node.children[node.children.length - 1]?.position?.end?.offset; + if (childrenStart == null || childrenEnd == null) { + return [{ start, end }]; + } + return [ + { start, end: childrenStart }, + { start: childrenEnd, end }, + ]; + } + + /** + * Get the parent of `node`. Node must be in `this.dast`. + */ + getParent(node: DastNodes): DastElement | null { + const parentMap = this._parentMap(); + return parentMap.get(node) || null; + } + + /** + * Get the unique descendent of `node` with name `name`. + */ + getNamedChild( + node: DastElement | DastRoot | undefined | null, + name: string, + ) { + if (!node) { + return null; + } + const descendentNamesMap = this._descendentNamesMap(); + const accessibleNames = (descendentNamesMap.get(node) || []).filter( + (e) => e.name === name, + ); + if (accessibleNames.length === 1) { + return accessibleNames[0].element; + } + return null; + } + + /** + * Get the unique item with name `name` resolved from position `offset`. + */ + getReferentAtOffset(offset: number | RowCol, name: string) { + const { node } = this.elementAtOffset(offset); + let parent: DastElement | undefined | null = node; + let referent = this.getNamedChild(parent, name); + while (parent && !referent) { + parent = this._parentMap().get(parent); + referent = this.getNamedChild(parent, name); + } + if (!parent && !referent) { + // We need to search the root! + referent = this.getNamedChild(this.dast, name); + } + return referent || null; + } + + /** + * Get the element that `macro` is referring to at position `offset`. + * Because a macro may end in attribute access, the algorithm searches + * for the largest matching initial segment and returns any unmatched parts + * of the macro. + */ + getMacroReferentAtOffset(offset: number | RowCol, macro: DastMacro) { + if (isOldMacro(macro)) { + throw new Error( + `Cannot resolve v0.6 style macro "${toXml(macro)}"`, + ); + } + let pathPart = macro.path[0]; + if (pathPart.index.length > 0) { + throw new Error( + `The first part of a macro path must be just a name without an index. Failed to resolve "${toXml( + macro, + )}"`, + ); + } + // If we made it here, we are just a name, so proceed with the lookup! + let referent = this.getReferentAtOffset(offset, pathPart.name); + if (!referent) { + return null; + } + // If there are no ".foo" accesses, the referent gets returned. + if (!macro.accessedProp) { + return { + node: referent, + accessedProp: null, + }; + } + // Otherwise, we walk down the tree trying to + // resolve whatever `accessedProp` refers to until we find something + // that doesn't exist. + let prop: DastMacro | null = macro.accessedProp; + let propReferent: DastElement | null = referent; + while (prop) { + if (prop.path[0].index.length > 0) { + // Indexing can only be used on synthetic nodes. + return { + node: referent, + accessedProp: prop, + }; + } + propReferent = this.getNamedChild(referent, prop.path[0].name); + if (!propReferent) { + return { + node: referent, + accessedProp: prop, + }; + } + // Step down one level + referent = propReferent; + prop = prop.accessedProp; + } + return { + node: referent, + accessedProp: null, + }; + } + + /** + * The DAST representation of `source`. + */ + get dast(): DastRoot { + return this._dast(); + } + + /** + * The Lezer TreeCursor for the parsed version of `source`. + */ + get lezerCursor() { + return this._lezerCursor(); + } +} + +export type OffsetToPositionMap = { + rowMap: Uint32Array; + columnMap: Uint32Array; +}; + +/** + * Returns `true` if the macro is an "old-style" macro with slashes + * in its path. + */ +export function isOldMacro(macro: DastMacro | DastFunctionMacro): boolean { + switch (macro.type) { + case "macro": { + if (macro.path.length !== 1) { + return true; + } + if (macro.accessedProp) { + return isOldMacro(macro.accessedProp); + } + return false; + } + case "function": { + return isOldMacro(macro.macro); + } + } +} diff --git a/packages/lsp-tools/src/doenet-source-object/initializers.ts b/packages/lsp-tools/src/doenet-source-object/initializers.ts new file mode 100644 index 000000000..dae64f344 --- /dev/null +++ b/packages/lsp-tools/src/doenet-source-object/initializers.ts @@ -0,0 +1,141 @@ +import { + DastElement, + DastNodes, + DastRoot, + lezerToDast, + stringToLezer, + toXml, + visit, +} from "@doenet/parser"; +import type { TreeCursor } from "@lezer/common"; +import { DoenetSourceObject, OffsetToPositionMap } from "./index"; + +export function initOffsetToRowCache(this: DoenetSourceObject) { + return createOffsetToPositionMap(this.source); +} + +export function initRowToOffsetCache(this: DoenetSourceObject) { + const source = this.source || ""; + const numLines = (String(source).match(/\n/g) || "").length + 1; + const rowToOffset = new Uint32Array(numLines); + const len = source.length; + + let currentRow = 0; + rowToOffset[0] = 0; + for (let i = 0; i < len; i++) { + if (source.charAt(i) === "\n") { + currentRow += 1; + rowToOffset[currentRow] = i + 1; + } + } + return rowToOffset; +} + +export function initLezer(this: DoenetSourceObject) { + return stringToLezer(this.source || ""); +} + +export function initLezerCursor(this: DoenetSourceObject): TreeCursor { + const lezer = this._lezer(); + return lezer.cursor(); +} + +export function initDast(this: DoenetSourceObject) { + return lezerToDast(this._lezer(), this.source); +} + +export function initParentMap(this: DoenetSourceObject) { + const parentMap = new Map(); + visit(this.dast, (node) => { + if (node.type === "element") { + for (const child of node.children) { + parentMap.set(child, node); + } + } + }); + return parentMap; +} + +export function initOffsetToNodeMap(this: DoenetSourceObject) { + const dast = this.dast; + const offsetToNodeMap: (DastNodes | null)[] = Array.from(this.source).map( + () => null, + ); + visit(dast, (node) => { + if (node.type === "error") { + return; + } + if (!node.position) { + return; + } + const { start, end } = node.position; + if (start.offset == null || end.offset == null) { + return; + } + + for (let i = start.offset; i < end.offset; i++) { + offsetToNodeMap[i] = node; + } + }); + return offsetToNodeMap; +} + +export type AccessList = { name: string; element: DastElement }[]; +export function initDescendentNamesMap(this: DoenetSourceObject) { + const dast = this.dast; + const namesInScope: Map = new Map(); + const rootAccessList: AccessList = []; + namesInScope.set(dast, rootAccessList); + visit(dast, (node, info) => { + if (!(node.type === "element")) { + return; + } + const nameAttr = node.attributes.find((a) => a.name === "name"); + if (!nameAttr) { + return; + } + // We have a name. Push our name to all of our parents. + for (const parent of info.parents) { + let accessList = namesInScope.get(parent); + if (!accessList) { + accessList = []; + namesInScope.set(parent, accessList); + } + accessList.push({ name: toXml(nameAttr.children), element: node }); + } + // Make sure our name is also viewable from the root element. + rootAccessList.push({ name: toXml(nameAttr.children), element: node }); + }); + return namesInScope; +} + +/** + * Creates a map from source position to the row/column offset. To retrieve the row/col + * index at an offset `pos`, use `[ rowMap[pos], columnMap[pos] ]`. + */ +export function createOffsetToPositionMap( + source: string | null, +): OffsetToPositionMap { + if (!source) { + source = ""; + } + const rowMap = new Uint32Array(source.length + 1); + const columnMap = new Uint32Array(source.length + 1); + const len = source.length; + + let currentRow = 0; + let currentColumn = 0; + for (let i = 0; i < len; i++) { + rowMap[i] = currentRow; + columnMap[i] = currentColumn; + if (source.charAt(i) === "\n") { + currentRow += 1; + currentColumn = 0; + } else { + currentColumn += 1; + } + } + rowMap[len] = currentRow; + columnMap[len] = currentColumn; + return { rowMap, columnMap }; +} diff --git a/packages/lsp-tools/src/doenet-source-object/lazy-data.ts b/packages/lsp-tools/src/doenet-source-object/lazy-data.ts new file mode 100644 index 000000000..fd7b5145d --- /dev/null +++ b/packages/lsp-tools/src/doenet-source-object/lazy-data.ts @@ -0,0 +1,110 @@ +/** + * A lazy data object. This allows typescript to infer whether `data` exists based on the + * value of `init`. + */ +export type LazyData = + | { type: "lazy-data"; init: false; data?: null } + | { type: "lazy-data"; init: true; data: T }; + +/** + * Create an uninitialized lazy data object + */ +export function uninitializedLazyData(): LazyData { + return { type: "lazy-data", init: false, data: null }; +} + +/** + * Create a lazy data object initialized with `data` + */ +export function initializedLazyData(data: T): LazyData { + return { type: "lazy-data", init: true, data }; +} + +/** + * Clear the data in a lazy data object. + */ +export function resetLazyData(lazyData: LazyData) { + lazyData.init = false; + lazyData.data = null; +} + +export function isLazyData(obj: any): obj is LazyData { + return ( + typeof obj === "object" && + obj != null && + (obj as any).type === "lazy-data" + ); +} + +/** + * A class that allows you to create lazily computed data objects. + * If you inherit from this class, use `_lazyDataGetter` to create a getter function for + * lazily computed data. `_lazyDataGetter(initFunction)` will call `initFunction` the first + * time the getter is called, and cache the result. Subsequent calls will return the cached + * data. + */ +export class LazyDataObject { + _lazyData: Record> = {}; + + /** + * Clear all stale data to force a recompute next time it's used. + */ + _clearLazyData() { + for (const [name, val] of Object.entries(this._lazyData)) { + resetLazyData(val); + } + } + + /** + * Create a `getter` function for lazily computed data. You must pass in the name of the + */ + _lazyDataGetter(initFunction: (this: S) => T) { + // Create a new cache object for this lazy data. + const cacheName = generateNameFromInitializer( + initFunction, + this._lazyData, + ); + this._lazyData[cacheName] = uninitializedLazyData(); + + return function getter(this: S): T { + if (!(cacheName in this._lazyData)) { + throw new Error( + `Lazy data cache object named "${cacheName}" not found`, + ); + } + const lazyData = this._lazyData[cacheName]; + if (!isLazyData(lazyData)) { + throw new Error( + `Asked to treat "${cacheName}" as a lazy data but it appears not to be`, + ); + } + + if (!lazyData.init) { + this._lazyData[cacheName] = initializedLazyData( + initFunction.call(this), + ); + return getter.call(this); + } + return lazyData.data!; + }; + } +} + +/** + * Based on an initializer function, create a suitable (and unique) name for a lazy data object. + * Initializers are expected to start with `_init`. + */ +function generateNameFromInitializer( + fn: Function, + existingNames: Record, +) { + const fnSource = fn.toString(); + let name = ( + fnSource.replace("function ", "").replace(/\(.*/, "").split("\n")[0] || + "" + ).replace(/^(_?)init/, ""); + while (name in existingNames) { + name += "_"; + } + return name; +} diff --git a/packages/lsp-tools/src/index.ts b/packages/lsp-tools/src/index.ts new file mode 100644 index 000000000..bbbf99cee --- /dev/null +++ b/packages/lsp-tools/src/index.ts @@ -0,0 +1,2 @@ +export * from "./doenet-source-object"; +export * from "./auto-completer"; diff --git a/packages/lsp-tools/test/doenet-auto-complete.test.ts b/packages/lsp-tools/test/doenet-auto-complete.test.ts new file mode 100644 index 000000000..5abf7601d --- /dev/null +++ b/packages/lsp-tools/test/doenet-auto-complete.test.ts @@ -0,0 +1,169 @@ +import { describe, expect, it } from "vitest"; +import util from "util"; + +import { filterPositionInfo, DastMacro, DastElement } from "@doenet/parser"; +import { DoenetSourceObject, isOldMacro } from "../src/doenet-source-object"; +import { doenetSchema } from "@doenet/static-assets"; +import { AutoCompleter } from "../src"; + +const origLog = console.log; +console.log = (...args) => { + origLog(...args.map((x) => util.inspect(x, false, 10, true))); +}; + +const schema = { + elements: [ + { + name: "a", + children: ["b", "c", "d"], + attributes: [{ name: "x" }, { name: "y" }, { name: "xyx" }], + top: true, + acceptsStringChildren: false, + }, + { + name: "b", + children: ["www"], + attributes: [{ name: "foo", values: ["true", "false"] }], + top: false, + acceptsStringChildren: false, + }, + { + name: "c", + children: [], + attributes: [], + top: false, + acceptsStringChildren: true, + }, + ], +}; + +describe("AutoCompleter", () => { + it("Can suggest completions", () => { + let source: string; + let autoCompleter: AutoCompleter; + + source = ` < + + + hi + `; + autoCompleter = new AutoCompleter(source, schema.elements); + { + let offset = source.indexOf(" { + let source: string; + let autoCompleter: AutoCompleter; + + source = ` < `; + autoCompleter = new AutoCompleter(source, schema.elements); + { + let offset = source.indexOf("", + }, + ] + `); + } + source = ` ", + }, + ] + `); + } + }); +}); diff --git a/packages/lsp-tools/test/doenet-auto-schema-check.test.ts b/packages/lsp-tools/test/doenet-auto-schema-check.test.ts new file mode 100644 index 000000000..996649ea3 --- /dev/null +++ b/packages/lsp-tools/test/doenet-auto-schema-check.test.ts @@ -0,0 +1,366 @@ +import { describe, expect, it } from "vitest"; +import util from "util"; + +import { filterPositionInfo, DastMacro, DastElement } from "@doenet/parser"; +import { DoenetSourceObject, isOldMacro } from "../src/doenet-source-object"; +import { doenetSchema } from "@doenet/static-assets"; +import { AutoCompleter } from "../src"; + +const origLog = console.log; +console.log = (...args) => { + origLog(...args.map((x) => util.inspect(x, false, 10, true))); +}; + +const schema = { + elements: [ + { + name: "a", + children: ["b", "c", "d"], + attributes: [ + { name: "x" }, + { name: "y" }, + { name: "xyx", values: ["a", "B"] }, + ], + top: true, + acceptsStringChildren: false, + }, + { + name: "b", + children: ["www"], + attributes: [{ name: "foo", values: ["true", "false"] }], + top: true, + acceptsStringChildren: false, + }, + { + name: "c", + children: [], + attributes: [], + top: false, + acceptsStringChildren: true, + }, + ], +}; + +describe("AutoCompleter", () => { + it("Can detect schema violations for elements", () => { + let source: string; + let autoCompleter: AutoCompleter; + + source = ` + + + hi + `; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toHaveLength(0); + + source = ``; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toMatchInlineSnapshot(` + [ + { + "message": "Element \`\` is not allowed at the root of the document.", + "range": { + "end": { + "character": 7, + "line": 0, + }, + "start": { + "character": 0, + "line": 0, + }, + }, + "severity": 2, + }, + ] + `); + + source = `xxx`; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toMatchInlineSnapshot(` + [ + { + "message": "Element \`\` is not allowed at the root of the document.", + "range": { + "end": { + "character": 3, + "line": 0, + }, + "start": { + "character": 0, + "line": 0, + }, + }, + "severity": 2, + }, + ] + `); + + source = ``; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toMatchInlineSnapshot(` + [ + { + "message": "Element \`\` is not allowed inside of \`\`.", + "range": { + "end": { + "character": 10, + "line": 0, + }, + "start": { + "character": 3, + "line": 0, + }, + }, + "severity": 2, + }, + ] + `); + }); + + it("Can detect schema violations for elements not in the schema", () => { + let source: string; + let autoCompleter: AutoCompleter; + + source = `xxx`; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toMatchInlineSnapshot(` + [ + { + "message": "Element \`\` is not a recognized Doenet element.", + "range": { + "end": { + "character": 3, + "line": 0, + }, + "start": { + "character": 0, + "line": 0, + }, + }, + "severity": 2, + }, + ] + `); + }); + + it("Can detect schema violations for elements with differently capitalized names", () => { + let source: string; + let autoCompleter: AutoCompleter; + + source = ` + + + hi + `; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toHaveLength(0); + + source = ``; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toMatchInlineSnapshot(` + [ + { + "message": "Element \`\` is not allowed at the root of the document.", + "range": { + "end": { + "character": 7, + "line": 0, + }, + "start": { + "character": 0, + "line": 0, + }, + }, + "severity": 2, + }, + ] + `); + + source = ``; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toMatchInlineSnapshot(` + [ + { + "message": "Element \`\` is not allowed inside of \`\`.", + "range": { + "end": { + "character": 10, + "line": 0, + }, + "start": { + "character": 3, + "line": 0, + }, + }, + "severity": 2, + }, + ] + `); + }); + + it("Can detect schema violations for attributes", () => { + let source: string; + let autoCompleter: AutoCompleter; + + source = ` + + + hi + `; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toMatchInlineSnapshot(` + [ + { + "message": "Element \`\` doesn't have an attribute called \`food\`.", + "range": { + "end": { + "character": 27, + "line": 1, + }, + "start": { + "character": 16, + "line": 1, + }, + }, + "severity": 2, + }, + ] + `); + + source = ` + + + hi + `; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toMatchInlineSnapshot(` + [ + { + "message": "Element \`\` doesn't have an attribute called \`foo\`.", + "range": { + "end": { + "character": 13, + "line": 0, + }, + "start": { + "character": 3, + "line": 0, + }, + }, + "severity": 2, + }, + ] + `); + }); + + it("Can detect schema violations for attribute values", () => { + let source: string; + let autoCompleter: AutoCompleter; + + // No error for correct values + source = ` + + + hi + `; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toMatchInlineSnapshot("[]"); + + // No error if an explicit list of attribute values is NOT values is given + source = ` + + + hi + `; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toMatchInlineSnapshot("[]"); + + // No error if a function or macro is used in the attribute value + source = ``; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toMatchInlineSnapshot("[]"); + + source = ``; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toMatchInlineSnapshot("[]"); + + // Error if an explicit list is given and the attribute value is plain text and not on the list + source = ` + + + hi + `; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toMatchInlineSnapshot(` + [ + { + "message": "Attribute \`foo\` of element \`\` must be one of: \\"true\\", \\"false\\"", + "range": { + "end": { + "character": 25, + "line": 1, + }, + "start": { + "character": 20, + "line": 1, + }, + }, + "severity": 2, + }, + ] + `); + }); + + it( + "Can detect schema violations for attribute values while ignoring case " + + "but still suggests the correct case if a value is wrong", + () => { + let source: string; + let autoCompleter: AutoCompleter; + + // No error for correct values + source = ` + + + hi + `; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toMatchInlineSnapshot( + "[]", + ); + + // Error if an explicit list is given and the attribute value is plain text and not on the list + source = ``; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toMatchInlineSnapshot(` + [ + { + "message": "Attribute \`xyx\` of element \`\` must be one of: \\"a\\", \\"B\\"", + "range": { + "end": { + "character": 10, + "line": 0, + }, + "start": { + "character": 7, + "line": 0, + }, + }, + "severity": 2, + }, + ] + `); + }, + ); + + it("substitutes `true` in for the value of an attribute that is not specified", () => { + let source: string; + let autoCompleter: AutoCompleter; + + // No error for correct values + source = ``; + autoCompleter = new AutoCompleter(source, schema.elements); + expect(autoCompleter.getSchemaViolations()).toMatchInlineSnapshot("[]"); + }); +}); diff --git a/packages/lsp-tools/test/doenet-source-object.test.ts b/packages/lsp-tools/test/doenet-source-object.test.ts new file mode 100644 index 000000000..622ee8831 --- /dev/null +++ b/packages/lsp-tools/test/doenet-source-object.test.ts @@ -0,0 +1,377 @@ +import { describe, expect, it } from "vitest"; +import util from "util"; + +import { filterPositionInfo, DastMacro, DastElement } from "@doenet/parser"; +import { DoenetSourceObject, isOldMacro } from "../src/doenet-source-object"; + +const origLog = console.log; +console.log = (...args) => { + origLog(...args.map((x) => util.inspect(x, false, 10, true))); +}; + +describe("DoenetSourceObject", () => { + it("Can convert between offsets and positions", () => { + let source: string; + + source = "abc\nx\nq r s"; + let sourceObj = new DoenetSourceObject(source); + + expect(sourceObj.offsetToRowCol(0)).toEqual({ line: 1, column: 1 }); + expect( + Array.from(source).map((c, i) => sourceObj.offsetToRowCol(i)), + ).toEqual([ + { line: 1, column: 1 }, + { line: 1, column: 2 }, + { line: 1, column: 3 }, + { line: 1, column: 4 }, + { line: 2, column: 1 }, + { line: 2, column: 2 }, + { line: 3, column: 1 }, + { line: 3, column: 2 }, + { line: 3, column: 3 }, + { line: 3, column: 4 }, + { line: 3, column: 5 }, + ]); + + expect( + Array.from(source) + .map((c, i) => sourceObj.offsetToRowCol(i)) + .map((pos) => sourceObj.rowColToOffset(pos)), + ).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + }); + it("Can convert between LSP offsets and positions", () => { + let source: string; + + source = "abc\nx\nq r s"; + let sourceObj = new DoenetSourceObject(source); + + expect( + Array.from(source) + .map((c, i) => sourceObj.offsetToRowCol(i)) + // LSP positions are 0-indexed + .map((pos) => ({ + line: pos.line - 1, + character: pos.column - 1, + })) + .map((pos) => sourceObj.rowColToOffset(pos)), + ).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + }); + + it("Can get DAST", () => { + let source: string; + + source = "abc\nx\nq r s"; + let sourceObj = new DoenetSourceObject(source); + expect(filterPositionInfo(sourceObj.dast)).toEqual({ + children: [ + { + type: "text", + value: source, + }, + ], + type: "root", + }); + + // When the source changes, the DAST should change + source = "hi"; + sourceObj.setSource(source); + expect(filterPositionInfo(sourceObj.dast)).toEqual({ + children: [ + { + type: "text", + value: source, + }, + ], + type: "root", + }); + }); + + it("Can find what the containing node at a given offset", () => { + let source: string; + + source = "ahi there"; + let sourceObj = new DoenetSourceObject(source); + + expect(sourceObj.nodeAtOffset(0)).toMatchObject({ type: "text" }); + expect(sourceObj.nodeAtOffset(1)).toMatchObject({ + type: "element", + name: "x", + }); + expect(sourceObj.nodeAtOffset(4)).toMatchObject({ type: "text" }); + expect(sourceObj.nodeAtOffset(8)).toMatchObject({ + type: "element", + name: "b", + }); + expect(sourceObj.nodeAtOffset(23)).toMatchObject({ + type: "element", + name: "you", + }); + expect(sourceObj.nodeAtOffset(50)).toEqual(null); + }); + + it("Can get parent", () => { + let source: string; + + source = "hi"; + let sourceObj = new DoenetSourceObject(source); + const dast = sourceObj.dast; + const child = ( + (dast.children[0] as DastElement).children[0] as DastElement + ).children[0]; + const parent = (dast.children[0] as DastElement).children[0]; + + expect(sourceObj.getParent(child)).toEqual(parent); + }); + + it("Can get element", () => { + let source: string; + let sourceObj: DoenetSourceObject; + + source = ` hi`; + sourceObj = new DoenetSourceObject(source); + { + let { cursorPosition, node } = sourceObj.elementAtOffset(4); + expect(cursorPosition).toEqual("openTagName"); + expect(node).toMatchObject({ type: "element", name: "b" }); + } + { + let { cursorPosition, node } = sourceObj.elementAtOffset(6); + expect(cursorPosition).toEqual("attributeName"); + expect(node).toMatchObject({ type: "element", name: "b" }); + } + { + let { cursorPosition, node } = sourceObj.elementAtOffset(11); + expect(cursorPosition).toEqual("attributeValue"); + expect(node).toMatchObject({ type: "element", name: "b" }); + } + { + let { cursorPosition, node } = sourceObj.elementAtOffset(17); + expect(cursorPosition).toEqual("body"); + expect(node).toMatchObject({ type: "element", name: "b" }); + } + + source = ` `; + sourceObj = new DoenetSourceObject(source); + { + let { cursorPosition, node } = sourceObj.elementAtOffset(3); + expect(cursorPosition).toEqual("openTag"); + expect(node).toMatchObject({ type: "element", name: "a" }); + } + { + let { cursorPosition, node } = sourceObj.elementAtOffset(5); + expect(cursorPosition).toEqual("body"); + expect(node).toMatchObject({ type: "element", name: "a" }); + } + { + let { cursorPosition, node } = sourceObj.elementAtOffset(9); + expect(cursorPosition).toEqual("unknown"); + expect(node).toMatchObject({ type: "element", name: "a" }); + } + { + let { cursorPosition, node } = sourceObj.elementAtOffset(11); + expect(cursorPosition).toEqual("unknown"); + expect(node).toMatchObject({ type: "element", name: "a" }); + } + + source = ` `; + sourceObj = new DoenetSourceObject(source); + { + const offset = source.indexOf("") - 1; + let { cursorPosition, node } = sourceObj.elementAtOffset(offset); + expect(cursorPosition).toEqual("body"); + expect(node).toMatchObject({ type: "element", name: "b" }); + } + { + // Right at the boundary before the close tag of an element when there + // is a non-closed element inside, we should claim to be inside the body + // of the non-closed element. + const offset = source.indexOf(""); + let { cursorPosition, node } = sourceObj.elementAtOffset(offset); + expect(cursorPosition).toEqual("body"); + expect(node).toMatchObject({ type: "element", name: "b" }); + } + // The user may be in the middle of typing. A < probably indicates they're trying to + // type a tag. We want to assume that we're part of the unclosed tag for completion purposes. + source = ` <`; + sourceObj = new DoenetSourceObject(source); + { + const offset = source.indexOf(""); + let { cursorPosition, node } = sourceObj.elementAtOffset(offset); + expect(cursorPosition).toEqual("body"); + expect(node).toMatchObject({ type: "element", name: "b" }); + } + }); + + it("Can get cursor position when element contains macro", () => { + let source: string; + let sourceObj: DoenetSourceObject; + + source = `

$x zz zz

`; + sourceObj = new DoenetSourceObject(source); + { + let offset = source.indexOf("$x"); + let { cursorPosition, node } = sourceObj.elementAtOffset( + offset + 1, + ); + expect(cursorPosition).toEqual("body"); + expect(node).toMatchObject({ type: "element", name: "p" }); + } + }); + + it("Can find cursorPosition in incomplete element", () => { + let source: string; + let sourceObj: DoenetSourceObject; + + source = ``; + sourceObj = new DoenetSourceObject(source); + { + let { cursorPosition, node } = sourceObj.elementAtOffset(7); + expect(cursorPosition).toEqual("openTag"); + expect(node).toMatchObject({ type: "element", name: "a" }); + } + + source = `<`; + sourceObj = new DoenetSourceObject(source); + { + let { cursorPosition, node } = sourceObj.elementAtOffset(1); + expect(cursorPosition).toEqual("unknown"); + expect(node).toEqual(null); + } + }); + + it("Can find named referents", () => { + let source: string; + let sourceObj: DoenetSourceObject; + + source = ` + + + + + `; + sourceObj = new DoenetSourceObject(source); + { + let offset = source.indexOf(" { + let source: string; + let sourceObj: DoenetSourceObject; + let macro: DastMacro; + + source = ` + + + + + `; + sourceObj = new DoenetSourceObject(source); + { + let offset = source.indexOf(" { + let source: string; + let sourceObj: DoenetSourceObject; + let macro: DastMacro; + + source = `$foo.bar[2].baz`; + sourceObj = new DoenetSourceObject(source); + macro = sourceObj.dast.children[0] as DastMacro; + expect(isOldMacro(macro)).toEqual(false); + + source = `$(foo.bar[2].baz)`; + sourceObj = new DoenetSourceObject(source); + macro = sourceObj.dast.children[0] as DastMacro; + expect(isOldMacro(macro)).toEqual(false); + + source = `$(foo/x.bar[2].baz)`; + sourceObj = new DoenetSourceObject(source); + macro = sourceObj.dast.children[0] as DastMacro; + expect(isOldMacro(macro)).toEqual(true); + }); + + it("Can get element ranges", () => { + let source: string; + let sourceObj: DoenetSourceObject; + + source = ` hi`; + sourceObj = new DoenetSourceObject(source); + { + let { node } = sourceObj.elementAtOffset(1); + expect(node?.name).toEqual("a"); + expect(sourceObj.getElementTagRanges(node!)).toMatchInlineSnapshot(` + [ + { + "end": 3, + "start": 0, + }, + { + "end": 36, + "start": 32, + }, + ] + `); + } + { + let { node } = sourceObj.elementAtOffset(4); + expect(node?.name).toEqual("b"); + expect(sourceObj.getElementTagRanges(node!)).toMatchInlineSnapshot(` + [ + { + "end": 16, + "start": 3, + }, + { + "end": 32, + "start": 28, + }, + ] + `); + } + }); +}); diff --git a/packages/lsp-tools/test/tsconfig.json b/packages/lsp-tools/test/tsconfig.json new file mode 100644 index 000000000..7ff724db9 --- /dev/null +++ b/packages/lsp-tools/test/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../../tsconfig.build.json", + "compilerOptions": { + "rootDir": "../" + }, + "include": ["../**/*.ts", "../**/*.tsx"], + "exclude": [ + "node_modules", + "./vite.config.ts" + ], + "references": [] +} diff --git a/packages/lsp-tools/tsconfig.json b/packages/lsp-tools/tsconfig.json new file mode 100644 index 000000000..22a330066 --- /dev/null +++ b/packages/lsp-tools/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tsconfig.build.json", + "compilerOptions": { + "outDir": "./dist/", + "rootDir": "./src" + }, + "include": ["./**/*.ts", "./**/*.tsx"], + "exclude": [ + "./**/*.test.ts", + "./**/*.stub.ts", + "node_modules", + "**/tests/", + "**/dist/**/*", + "./vite.config.ts" + ], + "references": [] +} diff --git a/packages/lsp-tools/vite.config.ts b/packages/lsp-tools/vite.config.ts new file mode 100644 index 000000000..a89ce1914 --- /dev/null +++ b/packages/lsp-tools/vite.config.ts @@ -0,0 +1,20 @@ +import { defineConfig } from "vite"; +import dts from "vite-plugin-dts"; + +// https://vitejs.dev/config/ +export default defineConfig({ + base: "./", + plugins: [dts()], + build: { + minify: false, + sourcemap: true, + lib: { + entry: "./src/index.ts", + fileName: "index", + formats: ["es"], + }, + rollupOptions: { + external: ["@doenet/parser", "@doenet/static-assets"], + }, + }, +}); diff --git a/packages/parser/index.html b/packages/parser/index.html new file mode 100644 index 000000000..5659ecebf --- /dev/null +++ b/packages/parser/index.html @@ -0,0 +1,26 @@ + + + + + + + Parser Viewer + + + +
+ + + diff --git a/packages/parser/package.json b/packages/parser/package.json index 9a6198e1f..b6bf7ba2b 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -16,6 +16,7 @@ } }, "scripts": { + "dev": "vite", "watch": "vite build --watch", "build": "vite build", "test": "vitest", @@ -26,11 +27,16 @@ "@lezer/generator": "^1.5.0", "@lezer/lr": "^1.3.10", "@types/xast": "^2.0.0", + "peggy": "^3.0.2", + "prettier-plugin-pegjs": "^2.0.2", + "unified": "^11.0.2", "xast-util-to-xml": "^4.0.0" }, "devDependencies": { - "glob": "^10.3.3", - "vite": "^4.4.9", - "vite-plugin-dts": "^3.5.2" + "esbuild": "^0.19.5", + "glob": "^10.3.10", + "react18-json-view": "^0.2.6", + "vite": "^4.5.0", + "vite-plugin-dts": "^3.6.0" } } diff --git a/packages/parser/src/dast-to-xml/dast-util-to-xml.ts b/packages/parser/src/dast-to-xml/dast-util-to-xml.ts new file mode 100644 index 000000000..2a4b7cd3f --- /dev/null +++ b/packages/parser/src/dast-to-xml/dast-util-to-xml.ts @@ -0,0 +1,246 @@ +// Code modified from xast-util-to-xml MIT License https://github.com/syntax-tree/xast-util-to-xml +import { ccount } from "ccount"; +import { + DastAttribute, + DastElement, + DastNodes, + DastMacroFullPath, + DastFunctionMacro, + DastMacro, + DastMacroPathPart, + PrintOptions, +} from "../types"; +import { escape, mergeAdjacentTextInArray, name } from "./utils"; + +/** + * Serialize a xast tree to XML. + */ +export function toXml( + tree?: DastNodes[] | DastNodes | null, + options?: PrintOptions, +) { + options = options || {}; + if (!tree) { + return ""; + } + const node = ( + Array.isArray(tree) ? { type: "root", children: tree } : tree + ) as DastNodes; + + return nodesToXml(node, options); +} + +/** + * Serialize a node. + */ +export function nodesToXml( + node: DastNodes | DastNodes[], + options: PrintOptions, +): string { + if (Array.isArray(node)) { + return mergeAdjacentTextInArray(node) + .map((child) => nodesToXml(child, options)) + .join(""); + } + + const type = node && node.type; + switch (node?.type) { + case "root": + return nodesToXml(node.children, options); + case "cdata": { + const unsafe = /]]>/g; + const subset = [">"]; + return ""; + } + case "comment": + return ""; + case "doctype": { + const nodeName = name(node.name); + const pub = node.public; + const sys = node.system; + let result = ""; + } + case "element": { + const nodeName = name(node.name); + const content = nodesToXml(node.children, options); + const attributes = node.attributes || []; + + const attrs = attributes.map((attr) => attrToString(attr, options)); + const printedAttrs = + (attrs.length > 0 ? " " : "") + attrs.join(" "); + + if ( + node.children.length === 0 || + (!options.inlineErrors && + node.children.every((c) => c.type === "error")) + ) { + return `<${nodeName}${printedAttrs} />`; + } + return `<${nodeName}${printedAttrs}>${content}`; + } + case "instruction": { + const unsafe = /\?>/g; + const subset = [">"]; + const nodeName = name(node.name); + const result = escape(node.value, subset, unsafe); + return ""; + } + case "text": { + let escapedText = escape(node.value, ["&", "<"]); + if (options.doenetSyntax) { + // A < symbols that are followed by whitespace is safe + escapedText = escapedText.replace(/<(?=\s|=)/g, "<"); + + // We can replace & with & except in the case where it would + // accidentally make a character entity. For example `&amp;` or `&#x24;` + escapedText = escapedText.replace(/&(?!\S*;)/g, "&"); + } + return escapedText; + } + case "error": { + if (options.inlineErrors) { + const errorElement: DastElement = { + type: "element", + name: "_error", + attributes: [], + children: [{ type: "text", value: node.message }], + }; + return nodesToXml(errorElement, options); + } + return ""; + } + case "macro": { + const macro = unwrappedMacroToString(node, options); + + let start = "$"; + let end = ""; + if (macroNeedsParens(node)) { + start += "("; + end += ")"; + } + return start + macro + end; + } + case "function": { + const macro = unwrappedMacroToString(node.macro, options); + + let start = "$$"; + let end = ""; + if (macroNeedsParens(node)) { + start += "("; + end += ")"; + } + const args = node.input + ? `(${node.input + .map((a) => nodesToXml(a, options)) + .join(", ")})` + : ""; + return start + macro + end + args; + } + default: { + // Typescript exhaustiveness check + const unusedType: void = node; + } + } + + if (!type) { + throw new Error("Expected node, not `" + node + "`"); + } + + throw new Error("Cannot compile unknown node `" + type + "`"); +} + +/** + * Serialize an attribute value. + */ +export function quote(value: string) { + const result = String(value); + let quoteMark = '"'; + + const other = quoteMark === '"' ? "'" : '"'; + + if (ccount(result, quoteMark) > ccount(result, other)) { + quoteMark = other; + } + + return quoteMark + escape(result, ["<", quoteMark]) + quoteMark; +} + +/** + * Convert a macro to a string, but do not wrap it in parens or add a `$` prefix. + */ +function unwrappedMacroToString( + nodes: DastMacro, + options: PrintOptions, +): string { + const path = macroPathToString(nodes.path, options); + const attrs = (nodes.attributes || []) + .map((a) => attrToString(a, options)) + .join(" "); + let attrsStr = attrs.length > 0 ? `{${attrs}}` : ""; + let propAccess = ""; + if (nodes.accessedProp) { + propAccess = "." + unwrappedMacroToString(nodes.accessedProp, options); + } + return path + attrsStr + propAccess; +} + +function macroPathToString( + path: DastMacroFullPath, + options: PrintOptions, +): string { + return path.map((part) => macroPathPartToString(part, options)).join("/"); +} + +function macroPathPartToString( + pathPart: DastMacroPathPart, + options: PrintOptions, +): string { + return ( + pathPart.name + + pathPart.index + .map((part) => `[${nodesToXml(part.value, options)}]`) + .join("") + ); +} + +function attrToString(attr: DastAttribute, options: PrintOptions): string { + if (attr.children.length === 0) { + // Doenet syntax allows JSX style attributes without values assigned to them + if (options.doenetSyntax) { + return name(attr.name); + } + return `${name(attr.name)}="true"`; + } + return `${name(attr.name)}=${quote(nodesToXml(attr.children, options))}`; +} + +function macroNeedsParens(macro: DastMacro | DastFunctionMacro): boolean { + if (macro.type === "function") { + return macroNeedsParens(macro.macro); + } + // Paths are separated by slashes. They always need wrapping. + if (macro.path.length > 1) { + return true; + } + // We also might need wrapping if the path contains a `-` character + return ( + macro.path.some((part) => part.name.includes("-")) || + (macro.accessedProp != null && macroNeedsParens(macro.accessedProp)) + ); +} diff --git a/packages/parser/src/dast-to-xml/utils.ts b/packages/parser/src/dast-to-xml/utils.ts new file mode 100644 index 000000000..c8dd5a32e --- /dev/null +++ b/packages/parser/src/dast-to-xml/utils.ts @@ -0,0 +1,105 @@ +import { stringifyEntitiesLight } from "stringify-entities"; +import { DastNodes } from "../types"; + +/** + * Escape a string. + */ +export function escape( + value: string, + subset: string[], + unsafe?: RegExp | null | undefined, +): string { + const result = clean(value); + + return unsafe ? result.replace(unsafe, encode) : encode(result); + + /** + * Actually escape characters. + */ + function encode(value: string): string { + return ( + stringifyEntitiesLight(value, { subset }) + // We want fancy named versions of these two escaped characters + .replace(/</g, "<") + .replace(/&/g, "&") + ); + } +} + +const nonCharacter = /[\u0000-\u0008\u000B\u000C\u000E-\u001F]/g; +/** + * Remove non-characters. + */ +export function clean(value: string) { + return String(value || "").replace(nonCharacter, ""); +} + +/** + * Encode a node name. + */ +export function name(value: string) { + const subset = ["\t", "\n", " ", '"', "&", "'", "/", "<", "=", ">"]; + return escape(value, subset); +} + +/** + * Merge adjacent text nodes in an array + */ +export function mergeAdjacentTextInArray(nodes: DastNodes[]): DastNodes[] { + const needsMerging = nodes.some( + (n, i) => n.type === "text" && nodes[i + 1]?.type === "text", + ); + if (!needsMerging) { + return nodes; + } + const ret: DastNodes[] = []; + for (let i = 0; i < nodes.length; i++) { + let node = nodes[i]; + let nextNode = nodes[i + 1]; + if (!nextNode) { + ret.push(node); + continue; + } + if (node.type === "text" && nextNode.type === "text") { + node = { ...node }; + ret.push(node); + while (nextNode?.type === "text") { + node.value += nextNode.value; + if (node.position && nextNode.position) { + node.position.end = nextNode.position.end; + } + i++; + nextNode = nodes[i + 1]; + } + } else { + ret.push(node); + } + } + + return ret; +} + +/** + * Recursively remove position info from a DAST tree. + * + * **Note**: this mutates the tree. + */ +export function filterPositionInfo( + nodes: DastNodes | DastNodes[], +): DastNodes | DastNodes[] { + if (Array.isArray(nodes)) { + return nodes.flatMap(filterPositionInfo); + } + if (nodes && typeof nodes === "object" && "position" in nodes) { + delete nodes.position; + } + for (const value of Object.values(nodes)) { + if (Array.isArray(value)) { + filterPositionInfo(value); + } + if (value && typeof value === "object" && "position" in value) { + filterPositionInfo(value); + } + } + return nodes; +} diff --git a/packages/parser/src/dev-site.tsx b/packages/parser/src/dev-site.tsx new file mode 100644 index 000000000..71c6b11ea --- /dev/null +++ b/packages/parser/src/dev-site.tsx @@ -0,0 +1,106 @@ +/* + * This file is for running a dev test of the codemirror component. + * It does not show up in the bundled package. + */ + +import React from "react"; +import ReactDOM from "react-dom/client"; +import { CodeMirror } from "@doenet/codemirror"; +import { lezerToDast, parse } from "./parser"; +import JsonView from "react18-json-view"; +import "react18-json-view/src/style.css"; +import { filterPositionInfo } from "./dast-to-xml/utils"; + +const INITIAL_DOENET_SOURCE = ` +

Use this to test DoenetML

+ + + + + + + + + +`; + +ReactDOM.createRoot(document.getElementById("root")!).render(); + +function App() { + const [doenetSource, setDoenetSource] = React.useState( + INITIAL_DOENET_SOURCE, + ); + const [dast, setDast] = React.useState({}); + const [omitPosition, setOmitPosition] = React.useState(false); + const [rawJson, setRawJson] = React.useState(false); + + React.useEffect(() => { + let dast = lezerToDast(doenetSource); + if (omitPosition) { + dast = filterPositionInfo(dast) as any; + } + setDast(dast); + }, [doenetSource, omitPosition]); + + return ( +
+
+ { + setOmitPosition(e.target.checked); + }} + /> + + { + setRawJson(e.target.checked); + }} + /> + +
+
+
+ { + setDoenetSource(val); + }} + setInternalValueTo={INITIAL_DOENET_SOURCE} + /> +
+
+ {rawJson ? ( +
{JSON.stringify(dast, null, 2)}
+ ) : ( + { + if (node.indexOrName === "position") { + return true; + } + return false; + }} + /> + )} +
+
+
+ ); +} diff --git a/packages/parser/src/doenet.grammar b/packages/parser/src/doenet.grammar index 42b4029de..51c519ae4 100644 --- a/packages/parser/src/doenet.grammar +++ b/packages/parser/src/doenet.grammar @@ -1,9 +1,17 @@ -@top Document { topLevel+ } +/* + * Modified version of lezer-xml that accepts more html-like identifiers + */ +@top Document { (entity | DoctypeDecl)+ } entity { Text | + EntityReference | + CharacterReference | + Ampersand | + Cdata | Element | Comment | + ProcessingInst | MismatchedCloseTag | incompleteStartCloseTag } @@ -13,36 +21,38 @@ Element { SelfClosingTag } -topLevel { - Text | - Comment | - Element -} +@skip { space } { + OpenTag[closedBy="CloseTag MissingCloseTag"] { + StartTag TagName Attribute* EndTag + } -OpenTag[closedBy="CloseTag MissingCloseTag"] { - StartTag TagName ws* Attribute* endTag -} + SelfClosingTag { + StartTag TagName Attribute* SelfCloseEndTag + } -SelfClosingTag { - StartTag TagName ws* Attribute* selfCloseEndTag -} + CloseTag[openedBy=OpenTag] { + StartCloseTag TagName EndTag + } -CloseTag[openedBy=OpenTag] { - StartCloseTag ws* TagName ws* endTag -} + MismatchedCloseTag { + mismatchedStartCloseTag TagName EndTag + } -MismatchedCloseTag { - mismatchedStartCloseTag TagName endTag + Attribute { + AttributeName (Is AttributeValue)? + } } -Attribute { - AttributeName ws* | - AttributeName ws* Is ws* AttributeValue ws* +AttributeValue { + "\"" (doubleQuoteAttributeContent | EntityReference | CharacterReference | Ampersand)* "\"" | + "'" (singleQuoteAttributeContent | EntityReference | CharacterReference | Ampersand)* "'" } -AttributeValue {singleQuoteAttributeValue | doubleQuoteAttributeValue} +Comment { "" } + +ProcessingInst { "" } -Comment { beginComment commentContent* "-->" } +Cdata { cdataStart cdataContent* "]]>" } @context elementContext from "../tokens" @@ -55,36 +65,54 @@ Comment { beginComment commentContent* "-->" } } @external tokens commentContent from "../tokens" { commentContent } - -singleQuoteAttributeValue { "'" attributeContentSingleQuote* "'" } -doubleQuoteAttributeValue { "\"" attributeContentDoubleQuote* "\"" } +@external tokens piContent from "../tokens" { piContent } +@external tokens cdataContent from "../tokens" { cdataContent } +@external tokens textLessThan from "../tokens" { textLessThan } @tokens { - endTag { ">" } - - beginComment { ""]; + case "doctype": { + const nodeName = name(node.name); + const pub = node.public; + const sys = node.system; + let result = [""); + return result; + } + case "element": { + const nodeName = name(node.name); + const openingTag: Doc[] = ["<", nodeName]; + const closingTag: Doc[] = []; + const attributes = node.attributes || []; + const printedAttrs: Doc[] = []; + for (const attr of attributes) { + const attrName = name(attr.name); + // No fancy formatting goes on for quoted attributes + if (attr.children.length === 0) { + // Doenet syntax allows JSX style attributes without values assigned to them + if (options.doenetSyntax) { + printedAttrs.push(line, attrName); + } else { + printedAttrs.push(line, attrName, "=", '"true"'); + } + } else { + printedAttrs.push( + line, + attrName, + "=", + quote(nodesToXml(attr.children, options)), + ); + } + } + if (printedAttrs.length > 0) { + openingTag.push(indent(printedAttrs)); + } + if (node.children.length === 0) { + // Always self-closing if there are no children + // The closing slash will always be on the same line if there are no attributes + openingTag.push(printedAttrs.length > 0 ? line : " ", "/>"); + } else { + openingTag.push(printedAttrs.length > 0 ? softline : "", ">"); + closingTag.push(""); + } + + // Compute whether a break must be inserted before or after the node + const leadingBreak: Doc[] = []; + const closingBreak: Doc[] = []; + // Some elements always have breaks before or after. + // But we only add them if they won't be inserted from text nodes directly + if (BREAK_AROUND_ELEMENTS.has(node.name)) { + const prevSibling = nodeMap?.prevSiblingOf(node); + const nextSibling = nodeMap?.nextSiblingOf(node); + if ( + !nodeMap?.hasLineBreakBefore(node) && + prevSibling && + !( + isElement(prevSibling) && + BREAK_AROUND_ELEMENTS.has(prevSibling.name) + ) + ) { + leadingBreak.push(hardline); + } + if ( + nextSibling && + (!nodeMap?.hasLineBreakAfter(node) || + (isElement(nextSibling) && + BREAK_AROUND_ELEMENTS.has(nextSibling.name))) + ) { + closingBreak.push(hardline); + } + } + + // PRE elements have children printed verbatim. + if (PRE_ELEMENTS.has(node.name)) { + return [ + ...leadingBreak, + group(openingTag), + toXml(node.children, options), + group(closingTag), + ...closingBreak, + ]; + } + + let children = path + .map(print, "children") + .flat() + .filter((x) => !isEmptyGroup(x) && x !== ""); + if (node.children.length > 0) { + if (CHILDREN_ON_OWN_LINE_ELEMENTS.has(node.name)) { + children = [ + indent([softline, joinWithSoftline(children)]), + softline, + ]; + children.push(breakParent); + } else { + children = [indent([softline, fill(children)]), softline]; + } + if (ALWAYS_BREAK_ELEMENTS.has(node.name)) { + children.push(breakParent); + } + } + return [ + ...leadingBreak, + group([group(openingTag), group(children), group(closingTag)]), + ...closingBreak, + ]; + } + case "error": + return ""; + case "instruction": { + const unsafe = /\?>/g; + const subset = [">"]; + const nodeName = name(node.name); + const result = escape(node.value, subset, unsafe); + return [""]; + } + case "text": { + let escapedText = escape(node.value, ["&", "<"]); + if (options.doenetSyntax) { + // A < symbols that are followed by whitespace is safe + escapedText = escapedText.replace(/<(?=\s|=)/g, "<"); + + // We can replace & with & except in the case where it would + // accidentally make a character entity. For example `&amp;` or `&#x24;` + escapedText = escapedText.replace(/&(?!\S*;)/g, "&"); + } + // Double newlines are preserved + return join( + [hardline, hardline], + escapedText + .split(/\n\n+/) + .map((str) => join(line, str.split(/\s+/))), + ).flat(); + } + case "macro": + case "function": + return toXml(node, options); + + default: { + const unhandledType: never = node; + console.warn( + `Unhandled node type when pretty-printing: ${unhandledType}`, + ); + } + } + return ""; +}; + +class NodeMap { + _parents: Map; + _prevSiblings: Map; + _nextSiblings: Map; + constructor(root: DastNodes) { + this._parents = new Map(); + this._prevSiblings = new Map(); + this._nextSiblings = new Map(); + this._init(root); + } + /** + * Build a map of all parents/siblings. + */ + _init(node: DastNodes, parent: DastNodes | null = null) { + if (isElement(parent) || parent?.type === "root") { + this._parents.set(node, parent); + } + if (isElement(node) || node?.type === "root") { + const children = node.children; + let prevNode: DastNodes | null = null; + for (const n of children) { + this._prevSiblings.set(n, prevNode); + if (prevNode) { + this._nextSiblings.set(prevNode, n); + } + prevNode = n; + this._init(n, node); + } + } + } + parentOf(node: DastNodes): DastElement | DastRoot | null { + return this._parents.get(node) || null; + } + prevSiblingOf(node: DastNodes): DastNodes | null { + return this._prevSiblings.get(node) || null; + } + nextSiblingOf(node: DastNodes): DastNodes | null { + return this._nextSiblings.get(node) || null; + } + hasLineBreakBefore(node: DastNodes): boolean { + const prevSibling = this.prevSiblingOf(node); + if (prevSibling?.type === "text") { + return prevSibling.value.endsWith("\n"); + } + return false; + } + hasLineBreakAfter(node: DastNodes): boolean { + const nextSibling = this.nextSiblingOf(node); + if (nextSibling?.type === "text") { + return nextSibling.value.endsWith("\n"); + } + return false; + } +} + +/** + * Returns whether the object is `type === "group"` + */ +function isGroup(doc: Doc): doc is Doc & { type: "group" } { + if (typeof doc !== "object") { + return false; + } + if (Array.isArray(doc)) { + return false; + } + return doc.type === "group"; +} + +function isEmptyGroup(doc: Doc): boolean { + return ( + isGroup(doc) && Array.isArray(doc.contents) && doc.contents.length === 0 + ); +} + +/** + * Join with a softline between each element, but only if there isn't already a line between the elements. + */ +function joinWithSoftline(doc: Doc[]): Doc[] { + if (doc.length === 0) { + return doc; + } + const ret: Doc[] = []; + for (let i = 0; i < doc.length; i++) { + const curr = doc[i]; + const next = doc[i + 1]; + ret.push(curr); + if (next && !isLine(next) && !isLine(curr)) { + ret.push(softline); + } + } + return ret; +} + +function isLine(doc: Doc): boolean { + if (doc === line || doc === softline || doc === hardline) { + return true; + } + if (typeof doc !== "object") { + return false; + } + if (Array.isArray(doc)) { + // Could be an array containing a line and a break-parent + return isLine(doc[0]); + } else { + return doc.type === "line"; + } + return false; +} diff --git a/packages/parser/src/tokens.ts b/packages/parser/src/tokens.ts index ecb8e416c..27d0c5556 100644 --- a/packages/parser/src/tokens.ts +++ b/packages/parser/src/tokens.ts @@ -10,6 +10,9 @@ import { Element, OpenTag, commentContent as _commentContent, + piContent as _piContent, + cdataContent as _cdataContent, + Text, } from "./generated-assets/lezer-doenet.terms"; function nameChar(ch: number) { @@ -88,27 +91,44 @@ export const elementContext = new ContextTracker({ export const startTag = new ExternalTokenizer( (input, stack) => { - if (input.next != 60 /* '<' */) return; + if (input.next !== 60 /* '<' */) { + return; + } + const nextNext = input.peek(1); + if ( + nextNext === 61 /* '=' */ + // XXX We could avoid creating an error node here by ignoring `<` which is followed by a `<`. + // However, this would require a reworking of the `Text` node type to accept lone `<` characters + // (in a more robust way than currently implemented). + // || nextNext === 60 /* '<' */ + ) { + return; + } input.advance(); // @ts-ignore - if (input.next == 47 /* '/' */) { + if (input.next === 47 /* '/' */) { input.advance(); let name = tagNameAfter(input, 0); - if (!name) return input.acceptToken(incompleteStartCloseTag); + if (!name) { + return input.acceptToken(incompleteStartCloseTag); + } if ( stack.context && name.toLowerCase() == stack.context.name.toLowerCase() - ) + ) { return input.acceptToken(StartCloseTag); - for (let cx = stack.context; cx; cx = cx.parent) - if (cx.name == name) + } + for (let cx = stack.context; cx; cx = cx.parent) { + if (cx.name === name) { return input.acceptToken(MissingCloseTag, -2); + } + } input.acceptToken(mismatchedStartCloseTag); } else if ( // @ts-ignore - input.next != 33 /* '!' */ && + input.next !== 33 /* '!' */ && // @ts-ignore - input.next != 63 /* '?' */ && + input.next !== 63 /* '?' */ && !isSpace(input.next) ) { return input.acceptToken(StartTag); @@ -117,18 +137,35 @@ export const startTag = new ExternalTokenizer( { contextual: true }, ); +/** + * Match a `<` that is followed by another `<`, but only consume the first `<`. + * Such code is valid DoenetML, since `<` by itself should be interpreted as a less than sign. + */ +export const textLessThan = new ExternalTokenizer((input) => { + if (input.next !== 60 /* '<' */) { + return; + } + const nextNext = input.peek(1); + if (nextNext === 60 /* '<' */) { + return input.acceptToken(Text, 1); + } +}); + function scanTo(type: number, end: string) { return new ExternalTokenizer((input) => { for (let endPos = 0, len = 0; ; len++) { if (input.next < 0) { - if (len) input.acceptToken(type); + if (len) { + input.acceptToken(type); + } break; } if (input.next == end.charCodeAt(endPos)) { endPos++; if (endPos == end.length) { - if (len > end.length) + if (len > end.length) { input.acceptToken(type, 1 - end.length); + } break; } } else { @@ -140,3 +177,5 @@ function scanTo(type: number, end: string) { } export const commentContent = scanTo(_commentContent, "-->"); +export const piContent = scanTo(_piContent, "?>"); +export const cdataContent = scanTo(_cdataContent, "]]>"); diff --git a/packages/parser/src/types.ts b/packages/parser/src/types.ts new file mode 100644 index 000000000..05d6f79ab --- /dev/null +++ b/packages/parser/src/types.ts @@ -0,0 +1,408 @@ +import * as LezerTerms from "./generated-assets/lezer-doenet.terms"; + +type AllLezerTerms = keyof typeof LezerTerms; +// Only terms that start with a capital letter are exposed by Lezer +type LezerTerms = AllLezerTerms & Capitalize; + +export type LezerSyntaxNodeName = LezerTerms | "⚠"; + +// Dast stands for Doenet AST. It is closely based off of Xast with changes where needed. +// The following resources are from the Xast project: +// Project: https://github.com/syntax-tree/xast +// Definitions by: stefanprobst +// Titus Wormer +// Christian Murphy +// Junyoung Choi +// Remco Haszing +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +import type { + Data as UnistData, + Literal as UnistLiteral, + Node as UnistNode, + Parent as UnistParent, +} from "unist"; +import { + FunctionMacro as _FunctionMacro, + Macro as _Macro, + PathPart as _PathPart, + PropIndex as _PropIndex, +} from "./macros/types"; + +export type Position = UnistLiteral["position"] & {}; + +// ## Interfaces + +/** + * Info associated with an element. + */ +export interface DastAttribute extends DastAbstractNode { + type: "attribute"; + name: string; + children: (DastText | DastMacro | DastFunctionMacro)[]; +} + +/** + * Info associated with xast nodes by the ecosystem. + * + * This space is guaranteed to never be specified by unist or xast. + * But you can use it in utilities and plugins to store data. + * + * This type can be augmented to register custom data. + * For example: + * + * ```ts + * declare module 'xast' { + * interface Data { + * // `someNode.data.myId` is typed as `number | undefined` + * myId?: number | undefined + * } + * } + * ``` + */ +export interface Data extends UnistData {} + +// ## Content maps + +/** + * Union of registered xast nodes that can occur in {@link DastElement}. + * + * To register more custom xast nodes, add them to {@link ElementContentMap}. + * They will be automatically added here. + */ +export type DastElementContent = ElementContentMap[keyof ElementContentMap]; + +/** + * Registry of all xast nodes that can occur as children of {@link DastElement}. + * + * For a union of all {@link DastElement} children, see {@link DastElementContent}. + */ +export interface ElementContentMap { + cdata: DastCdata; + comment: DastComment; + element: DastElement; + instruction: DastInstruction; + text: DastText; + error: DastError; + macro: DastMacro; + function: DastFunctionMacro; +} + +/** + * Union of registered xast nodes that can occur in {@link DastRoot}. + * + * To register custom xast nodes, add them to {@link RootContentMap}. + * They will be automatically added here. + */ +export type DastRootContent = RootContentMap[keyof RootContentMap]; + +/** + * Registry of all xast nodes that can occur as children of {@link DastRoot}. + * + * > 👉 **Note**: {@link DastRoot} does not need to be an entire document. + * > it can also be a fragment. + * + * For a union of all {@link DastRoot} children, see {@link DastRootContent}. + */ +export interface RootContentMap { + cdata: DastCdata; + comment: DastComment; + doctype: DastDoctype; + element: DastElement; + instruction: DastInstruction; + text: DastText; + error: DastError; + macro: DastMacro; + function: DastFunctionMacro; +} + +// ### Special content types + +/** + * Union of registered xast literals. + * + * To register custom xast nodes, add them to {@link RootContentMap} and other + * places where relevant. + * They will be automatically added here. + */ +export type DastLiterals = Extract; + +/** + * Union of registered xast nodes. + * + * To register custom xast nodes, add them to {@link RootContentMap} and other + * places where relevant. + * They will be automatically added here. + */ +export type DastNodes = DastRoot | DastRootContent; + +/** + * Union of registered xast parents. + * + * To register custom xast nodes, add them to {@link RootContentMap} and other + * places where relevant. + * They will be automatically added here. + */ +export type DastParents = Extract; + +// ## Abstract nodes + +/** + * Abstract xast node that contains the smallest possible value. + * + * This interface is supposed to be extended if you make custom xast nodes. + * + * For a union of all registered xast literals, see {@link DastLiterals}. + */ +export interface DastLiteral extends DastAbstractNode { + /** + * Plain-text value. + */ + value: string; +} + +/** + * Abstract xast node. + * + * This interface is supposed to be extended. + * If you can use {@link DastLiteral} or {@link DastParent}, you should. + * But for example in XML, a `Doctype` is neither literal nor parent, but + * still a node. + * + * To register custom xast nodes, add them to {@link RootContentMap} and other + * places where relevant (such as {@link ElementContentMap}). + * + * For a union of all registered xast nodes, see {@link DastNodes}. + */ +export interface DastAbstractNode extends UnistNode { + /** + * Info from the ecosystem. + */ + data?: Data | undefined; +} + +/** + * Abstract xast node that contains other xast nodes (*children*). + * + * This interface is supposed to be extended if you make custom xast nodes. + * + * For a union of all registered xast parents, see {@link DastParents}. + */ +export interface DastParent extends DastAbstractNode { + /** + * List of children. + */ + children: DastRootContent[]; +} + +// ## Concrete nodes + +/** + * XML CDATA section. + */ +export interface DastCdata extends DastLiteral { + /** + * Node type of XML CDATA sections in xast. + */ + type: "cdata"; + /** + * Data associated with the cdata. + */ + data?: CdataData | undefined; +} + +/** + * Info associated with xast instructions by the ecosystem. + */ +export interface CdataData extends Data {} + +/** + * XML comment. + */ +export interface DastComment extends DastLiteral { + /** + * Node type of XML comments in xast. + */ + type: "comment"; + /** + * Data associated with the comment. + */ + data?: CommentData | undefined; +} + +/** + * Info associated with xast comments by the ecosystem. + */ +export interface CommentData extends Data {} + +/** + * XML document type. + */ +export interface DastDoctype extends DastAbstractNode { + /** + * Node type of XML document types in xast. + */ + type: "doctype"; + /** + * Name of the root element. + * + * To illustrate, for ``, `name` is `'html'`. + */ + name: string; + /** + * Public identifier of the document. + */ + public?: string | undefined; + /** + * System identifier of the document. + */ + system?: string | undefined; + /** + * Data associated with the doctype. + */ + data?: DoctypeData | undefined; +} + +/** + * Info associated with xast doctypes by the ecosystem. + */ +export interface DoctypeData extends Data {} + +/** + * XML processing instruction. + */ +export interface DastInstruction extends DastLiteral { + /** + * Node type of XML processing instructions in xast. + */ + type: "instruction"; + /** + * Name of the instruction. + * + * To illustrate, for ``, `name` is `'php'`. + */ + name: string; + /** + * Data associated with the instruction. + */ + data?: InstructionData | undefined; +} + +/** + * Info associated with xast instructions by the ecosystem. + */ +export interface InstructionData extends Data {} + +/** + * XML element. + */ +export interface DastElement extends DastParent { + /** + * Node type of elements. + */ + type: "element"; + /** + * Qualified name (such as `'artist'` or `'svg:rect'`) of the element. + */ + name: string; + /** + * Info associated with the element. + */ + attributes: DastAttribute[]; + /** + * Children of element. + */ + children: DastElementContent[]; + /** + * Data associated with the element. + */ + data?: ElementData | undefined; +} + +/** + * Info associated with xast elements by the ecosystem. + */ +export interface ElementData extends Data {} + +/** + * Document fragment or a whole document. + * + * Should be used as the root of a tree and must not be used as a child. + * + * XML specifies that documents should have exactly one element child, so a + * root should have exactly one element child when representing a whole + * document. + */ +export interface DastRoot extends DastParent { + /** + * Node type of xast root. + */ + type: "root"; + /** + * Data associated with the xast root. + */ + data?: RootData | undefined; +} + +/** + * Info associated with xast root nodes by the ecosystem. + */ +export interface RootData extends Data {} + +/** + * XML character data (plain text). + */ +export interface DastText extends DastLiteral { + /** + * Node type of XML character data (plain text) in xast. + */ + type: "text"; + /** + * Data associated with the text. + */ + data?: TextData | undefined; +} + +/** + * Info associated with xast texts by the ecosystem. + */ +export interface TextData extends Data {} + +export interface DastError extends DastAbstractNode { + type: "error"; + message: string; + data?: ErrorData; +} + +export interface ErrorData extends Data {} + +export type PrintOptions = { + /** + * Whether to render with the DoenetML syntax rather than true XML. + * That means `<` and `&` characters are allowed unescaped in the output. + */ + doenetSyntax?: boolean; + /** + * Whether to output XML error nodes when there are processing errors. + */ + inlineErrors?: boolean; +}; + +// +// Macros +// + +// We glue together the types of macros and regular DAST nodes +export type DastMacro = Omit<_Macro, "attributes" | "path"> & { + attributes: DastAttribute[]; + accessedProp: DastMacro | null; + path: DastMacroPathPart[]; +}; +export type DastMacroPathPart = Omit<_PathPart, "index"> & { + index: (Omit<_PropIndex, "value"> & { value: (DastText | DastMacro)[] })[]; +}; +export type DastMacroFullPath = DastMacroPathPart[]; +export type DastFunctionMacro = Omit<_FunctionMacro, "input" | "macro"> & { + input: DastElementContent[][] | null; + macro: DastMacro; +}; \ No newline at end of file diff --git a/packages/parser/test/__snapshots__/dast-basic.test.ts.snap b/packages/parser/test/__snapshots__/dast-basic.test.ts.snap new file mode 100644 index 000000000..438bf0091 --- /dev/null +++ b/packages/parser/test/__snapshots__/dast-basic.test.ts.snap @@ -0,0 +1,143 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`DAST > xml-1.doenet prints correctly in Xml format and Doenet format 1`] = `""`; + +exports[`DAST > xml-1.doenet prints correctly in Xml format and Doenet format 2`] = `""`; + +exports[`DAST > xml-2.doenet prints correctly in Xml format and Doenet format 1`] = `"bar"`; + +exports[`DAST > xml-2.doenet prints correctly in Xml format and Doenet format 2`] = `"bar"`; + +exports[`DAST > xml-3.doenet prints correctly in Xml format and Doenet format 1`] = `"c"`; + +exports[`DAST > xml-3.doenet prints correctly in Xml format and Doenet format 2`] = `"c"`; + +exports[`DAST > xml-4.doenet prints correctly in Xml format and Doenet format 1`] = `""`; + +exports[`DAST > xml-4.doenet prints correctly in Xml format and Doenet format 2`] = `""`; + +exports[`DAST > xml-5.doenet prints correctly in Xml format and Doenet format 1`] = `""`; + +exports[`DAST > xml-5.doenet prints correctly in Xml format and Doenet format 2`] = `""`; + +exports[`DAST > xml-6.doenet prints correctly in Xml format and Doenet format 1`] = `"&C"`; + +exports[`DAST > xml-6.doenet prints correctly in Xml format and Doenet format 2`] = `"&C"`; + +exports[`DAST > xml-7.doenet prints correctly in Xml format and Doenet format 1`] = ` +" +" +`; + +exports[`DAST > xml-7.doenet prints correctly in Xml format and Doenet format 2`] = ` +" +" +`; + +exports[`DAST > xml-8.doenet prints correctly in Xml format and Doenet format 1`] = `""`; + +exports[`DAST > xml-8.doenet prints correctly in Xml format and Doenet format 2`] = `""`; + +exports[`DAST > xml-8b.doenet prints correctly in Xml format and Doenet format 1`] = `""`; + +exports[`DAST > xml-8b.doenet prints correctly in Xml format and Doenet format 2`] = `""`; + +exports[`DAST > xml-9.doenet prints correctly in Xml format and Doenet format 1`] = ` +" + text +" +`; + +exports[`DAST > xml-9.doenet prints correctly in Xml format and Doenet format 2`] = ` +" + text +" +`; + +exports[`DAST > xml-10.doenet prints correctly in Xml format and Doenet format 1`] = `""`; + +exports[`DAST > xml-10.doenet prints correctly in Xml format and Doenet format 2`] = `""`; + +exports[`DAST > xml-12.doenet prints correctly in Xml format and Doenet format 1`] = `"yy"`; + +exports[`DAST > xml-12.doenet prints correctly in Xml format and Doenet format 2`] = `"yy"`; + +exports[`DAST > xml-doenet-ampersand-1.doenet prints correctly in Xml format and Doenet format 1`] = ` +"&lt; &#x25; &#x25 -- this one is okay. +(an amp followed by text with a semi colon should be an amp.)" +`; + +exports[`DAST > xml-doenet-ampersand-1.doenet prints correctly in Xml format and Doenet format 2`] = ` +"&lt; &#x25; % -- this one is okay. +(an amp followed by text with a semi colon should be an amp.)" +`; + +exports[`DAST > xml-doenet-ampersand-2.doenet prints correctly in Xml format and Doenet format 1`] = ` +"& +& +&amp" +`; + +exports[`DAST > xml-doenet-ampersand-2.doenet prints correctly in Xml format and Doenet format 2`] = ` +"& +& +&" +`; + +exports[`DAST > xml-doenet-ampersand-3.doenet prints correctly in Xml format and Doenet format 1`] = `"&"`; + +exports[`DAST > xml-doenet-ampersand-3.doenet prints correctly in Xml format and Doenet format 2`] = `"&"`; + +exports[`DAST > xml-doenet-attributes-1.doenet prints correctly in Xml format and Doenet format 1`] = `""`; + +exports[`DAST > xml-doenet-attributes-1.doenet prints correctly in Xml format and Doenet format 2`] = `""`; + +exports[`DAST > xml-doenet-attributes-2.doenet prints correctly in Xml format and Doenet format 1`] = `""`; + +exports[`DAST > xml-doenet-attributes-2.doenet prints correctly in Xml format and Doenet format 2`] = `""`; + +exports[`DAST > xml-doenet-lessthan-in-text-1.doenet prints correctly in Xml format and Doenet format 1`] = `"2 < 3"`; + +exports[`DAST > xml-doenet-lessthan-in-text-1.doenet prints correctly in Xml format and Doenet format 2`] = `"2 < 3"`; + +exports[`DAST > xml-doenet-lessthan-in-text-2.doenet prints correctly in Xml format and Doenet format 1`] = `"2 <= 3"`; + +exports[`DAST > xml-doenet-lessthan-in-text-2.doenet prints correctly in Xml format and Doenet format 2`] = `"2 <= 3"`; + +exports[`DAST > xml-doenet-lessthan-in-text-3.doenet prints correctly in Xml format and Doenet format 1`] = ` +" +2 +< +3 +" +`; + +exports[`DAST > xml-doenet-lessthan-in-text-3.doenet prints correctly in Xml format and Doenet format 2`] = ` +" +2 +< +3 +" +`; + +exports[`DAST > xml-doenet-lessthan-in-text-4.doenet prints correctly in Xml format and Doenet format 1`] = `" < "`; + +exports[`DAST > xml-doenet-lessthan-in-text-4.doenet prints correctly in Xml format and Doenet format 2`] = `" < "`; + +exports[`DAST > xml-doenet-lessthan-in-text-5.doenet prints correctly in Xml format and Doenet format 1`] = `"<="`; + +exports[`DAST > xml-doenet-lessthan-in-text-5.doenet prints correctly in Xml format and Doenet format 2`] = `"<="`; + +exports[`DAST > xml-doenet-no-root.doenet prints correctly in Xml format and Doenet format 1`] = ` +"hi + + +there" +`; + +exports[`DAST > xml-doenet-no-root.doenet prints correctly in Xml format and Doenet format 2`] = ` +"hi + + +there" +`; diff --git a/packages/parser/test/__snapshots__/macro-parse.test.ts.snap b/packages/parser/test/__snapshots__/macro-parse.test.ts.snap new file mode 100644 index 000000000..891d20316 --- /dev/null +++ b/packages/parser/test/__snapshots__/macro-parse.test.ts.snap @@ -0,0 +1,2304 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Macro parsing > should parse macro \`$(../t)\` 1`] = ` +[ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "..", + "position": { + "end": { + "column": 5, + "line": 1, + "offset": 4, + }, + "start": { + "column": 3, + "line": 1, + "offset": 2, + }, + }, + "type": "pathPart", + }, + { + "index": [], + "name": "t", + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 6, + "line": 1, + "offset": 5, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 8, + "line": 1, + "offset": 7, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$(/t)\` 1`] = ` +[ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "", + "position": { + "end": { + "column": 3, + "line": 1, + "offset": 2, + }, + "start": { + "column": 3, + "line": 1, + "offset": 2, + }, + }, + "type": "pathPart", + }, + { + "index": [], + "name": "t", + "position": { + "end": { + "column": 5, + "line": 1, + "offset": 4, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 6, + "line": 1, + "offset": 5, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$(t)\` 1`] = ` +[ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "t", + "position": { + "end": { + "column": 4, + "line": 1, + "offset": 3, + }, + "start": { + "column": 3, + "line": 1, + "offset": 2, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 5, + "line": 1, + "offset": 4, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$(t.x)\` 1`] = ` +[ + { + "accessedProp": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "x", + "position": { + "end": { + "column": 6, + "line": 1, + "offset": 5, + }, + "start": { + "column": 5, + "line": 1, + "offset": 4, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 6, + "line": 1, + "offset": 5, + }, + "start": { + "column": 5, + "line": 1, + "offset": 4, + }, + }, + "type": "macro", + }, + "attributes": [], + "path": [ + { + "index": [], + "name": "t", + "position": { + "end": { + "column": 4, + "line": 1, + "offset": 3, + }, + "start": { + "column": 3, + "line": 1, + "offset": 2, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$(t[1]/x)\` 1`] = ` +[ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [ + { + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "index", + "value": { + "position": { + "end": { + "column": 6, + "line": 1, + "offset": 5, + }, + "start": { + "column": 5, + "line": 1, + "offset": 4, + }, + }, + "type": "text", + "value": "1", + }, + }, + ], + "name": "t", + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 3, + "line": 1, + "offset": 2, + }, + }, + "type": "pathPart", + }, + { + "index": [], + "name": "x", + "position": { + "end": { + "column": 9, + "line": 1, + "offset": 8, + }, + "start": { + "column": 8, + "line": 1, + "offset": 7, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 10, + "line": 1, + "offset": 9, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$(t-x[1].y{a="b"})\` 1`] = ` +[ + { + "accessedProp": { + "accessedProp": null, + "attributes": [ + { + "children": [ + { + "position": { + "end": { + "column": 16, + "line": 1, + "offset": 15, + }, + "start": { + "column": 15, + "line": 1, + "offset": 14, + }, + }, + "type": "text", + "value": "b", + }, + ], + "name": "a", + "position": { + "end": { + "column": 17, + "line": 1, + "offset": 16, + }, + "start": { + "column": 12, + "line": 1, + "offset": 11, + }, + }, + "type": "attribute", + }, + ], + "path": [ + { + "index": [], + "name": "y", + "position": { + "end": { + "column": 11, + "line": 1, + "offset": 10, + }, + "start": { + "column": 10, + "line": 1, + "offset": 9, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 18, + "line": 1, + "offset": 17, + }, + "start": { + "column": 10, + "line": 1, + "offset": 9, + }, + }, + "type": "macro", + }, + "attributes": [], + "path": [ + { + "index": [ + { + "position": { + "end": { + "column": 9, + "line": 1, + "offset": 8, + }, + "start": { + "column": 6, + "line": 1, + "offset": 5, + }, + }, + "type": "index", + "value": { + "position": { + "end": { + "column": 8, + "line": 1, + "offset": 7, + }, + "start": { + "column": 7, + "line": 1, + "offset": 6, + }, + }, + "type": "text", + "value": "1", + }, + }, + ], + "name": "t-x", + "position": { + "end": { + "column": 9, + "line": 1, + "offset": 8, + }, + "start": { + "column": 3, + "line": 1, + "offset": 2, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 19, + "line": 1, + "offset": 18, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$(x-y)\` 1`] = ` +[ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "x-y", + "position": { + "end": { + "column": 6, + "line": 1, + "offset": 5, + }, + "start": { + "column": 3, + "line": 1, + "offset": 2, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$(x-y.a-b)\` 1`] = ` +[ + { + "accessedProp": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "a-b", + "position": { + "end": { + "column": 10, + "line": 1, + "offset": 9, + }, + "start": { + "column": 7, + "line": 1, + "offset": 6, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 10, + "line": 1, + "offset": 9, + }, + "start": { + "column": 7, + "line": 1, + "offset": 6, + }, + }, + "type": "macro", + }, + "attributes": [], + "path": [ + { + "index": [], + "name": "x-y", + "position": { + "end": { + "column": 6, + "line": 1, + "offset": 5, + }, + "start": { + "column": 3, + "line": 1, + "offset": 2, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 11, + "line": 1, + "offset": 10, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$(x-y/a-b)\` 1`] = ` +[ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "x-y", + "position": { + "end": { + "column": 6, + "line": 1, + "offset": 5, + }, + "start": { + "column": 3, + "line": 1, + "offset": 2, + }, + }, + "type": "pathPart", + }, + { + "index": [], + "name": "a-b", + "position": { + "end": { + "column": 10, + "line": 1, + "offset": 9, + }, + "start": { + "column": 7, + "line": 1, + "offset": 6, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 11, + "line": 1, + "offset": 10, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$_t\` 1`] = ` +[ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "_t", + "position": { + "end": { + "column": 4, + "line": 1, + "offset": 3, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 4, + "line": 1, + "offset": 3, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$t.x.y\` 1`] = ` +[ + { + "accessedProp": { + "accessedProp": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "y", + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 6, + "line": 1, + "offset": 5, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 6, + "line": 1, + "offset": 5, + }, + }, + "type": "macro", + }, + "attributes": [], + "path": [ + { + "index": [], + "name": "x", + "position": { + "end": { + "column": 5, + "line": 1, + "offset": 4, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "macro", + }, + "attributes": [], + "path": [ + { + "index": [], + "name": "t", + "position": { + "end": { + "column": 3, + "line": 1, + "offset": 2, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$t.x[1].y[2]\` 1`] = ` +[ + { + "accessedProp": { + "accessedProp": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [ + { + "position": { + "end": { + "column": 13, + "line": 1, + "offset": 12, + }, + "start": { + "column": 10, + "line": 1, + "offset": 9, + }, + }, + "type": "index", + "value": { + "position": { + "end": { + "column": 12, + "line": 1, + "offset": 11, + }, + "start": { + "column": 11, + "line": 1, + "offset": 10, + }, + }, + "type": "text", + "value": "2", + }, + }, + ], + "name": "y", + "position": { + "end": { + "column": 13, + "line": 1, + "offset": 12, + }, + "start": { + "column": 9, + "line": 1, + "offset": 8, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 13, + "line": 1, + "offset": 12, + }, + "start": { + "column": 9, + "line": 1, + "offset": 8, + }, + }, + "type": "macro", + }, + "attributes": [], + "path": [ + { + "index": [ + { + "position": { + "end": { + "column": 8, + "line": 1, + "offset": 7, + }, + "start": { + "column": 5, + "line": 1, + "offset": 4, + }, + }, + "type": "index", + "value": { + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 6, + "line": 1, + "offset": 5, + }, + }, + "type": "text", + "value": "1", + }, + }, + ], + "name": "x", + "position": { + "end": { + "column": 8, + "line": 1, + "offset": 7, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 13, + "line": 1, + "offset": 12, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "macro", + }, + "attributes": [], + "path": [ + { + "index": [], + "name": "t", + "position": { + "end": { + "column": 3, + "line": 1, + "offset": 2, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 13, + "line": 1, + "offset": 12, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$t.x[1].y\` 1`] = ` +[ + { + "accessedProp": { + "accessedProp": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "y", + "position": { + "end": { + "column": 10, + "line": 1, + "offset": 9, + }, + "start": { + "column": 9, + "line": 1, + "offset": 8, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 10, + "line": 1, + "offset": 9, + }, + "start": { + "column": 9, + "line": 1, + "offset": 8, + }, + }, + "type": "macro", + }, + "attributes": [], + "path": [ + { + "index": [ + { + "position": { + "end": { + "column": 8, + "line": 1, + "offset": 7, + }, + "start": { + "column": 5, + "line": 1, + "offset": 4, + }, + }, + "type": "index", + "value": { + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 6, + "line": 1, + "offset": 5, + }, + }, + "type": "text", + "value": "1", + }, + }, + ], + "name": "x", + "position": { + "end": { + "column": 8, + "line": 1, + "offset": 7, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 10, + "line": 1, + "offset": 9, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "macro", + }, + "attributes": [], + "path": [ + { + "index": [], + "name": "t", + "position": { + "end": { + "column": 3, + "line": 1, + "offset": 2, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 10, + "line": 1, + "offset": 9, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$t.x[1][2].y\` 1`] = ` +[ + { + "accessedProp": { + "accessedProp": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "y", + "position": { + "end": { + "column": 13, + "line": 1, + "offset": 12, + }, + "start": { + "column": 12, + "line": 1, + "offset": 11, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 13, + "line": 1, + "offset": 12, + }, + "start": { + "column": 12, + "line": 1, + "offset": 11, + }, + }, + "type": "macro", + }, + "attributes": [], + "path": [ + { + "index": [ + { + "position": { + "end": { + "column": 8, + "line": 1, + "offset": 7, + }, + "start": { + "column": 5, + "line": 1, + "offset": 4, + }, + }, + "type": "index", + "value": { + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 6, + "line": 1, + "offset": 5, + }, + }, + "type": "text", + "value": "1", + }, + }, + { + "position": { + "end": { + "column": 11, + "line": 1, + "offset": 10, + }, + "start": { + "column": 8, + "line": 1, + "offset": 7, + }, + }, + "type": "index", + "value": { + "position": { + "end": { + "column": 10, + "line": 1, + "offset": 9, + }, + "start": { + "column": 9, + "line": 1, + "offset": 8, + }, + }, + "type": "text", + "value": "2", + }, + }, + ], + "name": "x", + "position": { + "end": { + "column": 11, + "line": 1, + "offset": 10, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 13, + "line": 1, + "offset": 12, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "macro", + }, + "attributes": [], + "path": [ + { + "index": [], + "name": "t", + "position": { + "end": { + "column": 3, + "line": 1, + "offset": 2, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 13, + "line": 1, + "offset": 12, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$t.x[1]{a="b"}.y\` 1`] = ` +[ + { + "accessedProp": { + "accessedProp": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "y", + "position": { + "end": { + "column": 17, + "line": 1, + "offset": 16, + }, + "start": { + "column": 16, + "line": 1, + "offset": 15, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 17, + "line": 1, + "offset": 16, + }, + "start": { + "column": 16, + "line": 1, + "offset": 15, + }, + }, + "type": "macro", + }, + "attributes": [ + { + "children": [ + { + "position": { + "end": { + "column": 13, + "line": 1, + "offset": 12, + }, + "start": { + "column": 12, + "line": 1, + "offset": 11, + }, + }, + "type": "text", + "value": "b", + }, + ], + "name": "a", + "position": { + "end": { + "column": 14, + "line": 1, + "offset": 13, + }, + "start": { + "column": 9, + "line": 1, + "offset": 8, + }, + }, + "type": "attribute", + }, + ], + "path": [ + { + "index": [ + { + "position": { + "end": { + "column": 8, + "line": 1, + "offset": 7, + }, + "start": { + "column": 5, + "line": 1, + "offset": 4, + }, + }, + "type": "index", + "value": { + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 6, + "line": 1, + "offset": 5, + }, + }, + "type": "text", + "value": "1", + }, + }, + ], + "name": "x", + "position": { + "end": { + "column": 8, + "line": 1, + "offset": 7, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 17, + "line": 1, + "offset": 16, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "macro", + }, + "attributes": [], + "path": [ + { + "index": [], + "name": "t", + "position": { + "end": { + "column": 3, + "line": 1, + "offset": 2, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 17, + "line": 1, + "offset": 16, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$t.x\` 1`] = ` +[ + { + "accessedProp": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "x", + "position": { + "end": { + "column": 5, + "line": 1, + "offset": 4, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 5, + "line": 1, + "offset": 4, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "macro", + }, + "attributes": [], + "path": [ + { + "index": [], + "name": "t", + "position": { + "end": { + "column": 3, + "line": 1, + "offset": 2, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 5, + "line": 1, + "offset": 4, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$t[$x]\` 1`] = ` +[ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [ + { + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 3, + "line": 1, + "offset": 2, + }, + }, + "type": "index", + "value": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "x", + "position": { + "end": { + "column": 6, + "line": 1, + "offset": 5, + }, + "start": { + "column": 5, + "line": 1, + "offset": 4, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 6, + "line": 1, + "offset": 5, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "macro", + }, + }, + ], + "name": "t", + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$t[1.5]\` 1`] = ` +[ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [ + { + "position": { + "end": { + "column": 8, + "line": 1, + "offset": 7, + }, + "start": { + "column": 3, + "line": 1, + "offset": 2, + }, + }, + "type": "index", + "value": { + "position": { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "text", + "value": "1.5", + }, + }, + ], + "name": "t", + "position": { + "end": { + "column": 8, + "line": 1, + "offset": 7, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 8, + "line": 1, + "offset": 7, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$t[1]\` 1`] = ` +[ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [ + { + "position": { + "end": { + "column": 6, + "line": 1, + "offset": 5, + }, + "start": { + "column": 3, + "line": 1, + "offset": 2, + }, + }, + "type": "index", + "value": { + "position": { + "end": { + "column": 5, + "line": 1, + "offset": 4, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "text", + "value": "1", + }, + }, + ], + "name": "t", + "position": { + "end": { + "column": 6, + "line": 1, + "offset": 5, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 6, + "line": 1, + "offset": 5, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$t[1]{a="b"}\` 1`] = ` +[ + { + "accessedProp": null, + "attributes": [ + { + "children": [ + { + "position": { + "end": { + "column": 11, + "line": 1, + "offset": 10, + }, + "start": { + "column": 10, + "line": 1, + "offset": 9, + }, + }, + "type": "text", + "value": "b", + }, + ], + "name": "a", + "position": { + "end": { + "column": 12, + "line": 1, + "offset": 11, + }, + "start": { + "column": 7, + "line": 1, + "offset": 6, + }, + }, + "type": "attribute", + }, + ], + "path": [ + { + "index": [ + { + "position": { + "end": { + "column": 6, + "line": 1, + "offset": 5, + }, + "start": { + "column": 3, + "line": 1, + "offset": 2, + }, + }, + "type": "index", + "value": { + "position": { + "end": { + "column": 5, + "line": 1, + "offset": 4, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "text", + "value": "1", + }, + }, + ], + "name": "t", + "position": { + "end": { + "column": 6, + "line": 1, + "offset": 5, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 13, + "line": 1, + "offset": 12, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$t[a][b]\` 1`] = ` +[ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [ + { + "position": { + "end": { + "column": 6, + "line": 1, + "offset": 5, + }, + "start": { + "column": 3, + "line": 1, + "offset": 2, + }, + }, + "type": "index", + "value": { + "position": { + "end": { + "column": 5, + "line": 1, + "offset": 4, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "text", + "value": "a", + }, + }, + { + "position": { + "end": { + "column": 9, + "line": 1, + "offset": 8, + }, + "start": { + "column": 6, + "line": 1, + "offset": 5, + }, + }, + "type": "index", + "value": { + "position": { + "end": { + "column": 8, + "line": 1, + "offset": 7, + }, + "start": { + "column": 7, + "line": 1, + "offset": 6, + }, + }, + "type": "text", + "value": "b", + }, + }, + ], + "name": "t", + "position": { + "end": { + "column": 9, + "line": 1, + "offset": 8, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 9, + "line": 1, + "offset": 8, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$t\` 1`] = ` +[ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "t", + "position": { + "end": { + "column": 3, + "line": 1, + "offset": 2, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 3, + "line": 1, + "offset": 2, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$t{a="$b"}\` 1`] = ` +[ + { + "accessedProp": null, + "attributes": [ + { + "children": [ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "b", + "position": { + "end": { + "column": 9, + "line": 1, + "offset": 8, + }, + "start": { + "column": 8, + "line": 1, + "offset": 7, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 9, + "line": 1, + "offset": 8, + }, + "start": { + "column": 7, + "line": 1, + "offset": 6, + }, + }, + "type": "macro", + }, + ], + "name": "a", + "position": { + "end": { + "column": 10, + "line": 1, + "offset": 9, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "attribute", + }, + ], + "path": [ + { + "index": [], + "name": "t", + "position": { + "end": { + "column": 3, + "line": 1, + "offset": 2, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 11, + "line": 1, + "offset": 10, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$t{a="b"}\` 1`] = ` +[ + { + "accessedProp": null, + "attributes": [ + { + "children": [ + { + "position": { + "end": { + "column": 8, + "line": 1, + "offset": 7, + }, + "start": { + "column": 7, + "line": 1, + "offset": 6, + }, + }, + "type": "text", + "value": "b", + }, + ], + "name": "a", + "position": { + "end": { + "column": 9, + "line": 1, + "offset": 8, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "attribute", + }, + ], + "path": [ + { + "index": [], + "name": "t", + "position": { + "end": { + "column": 3, + "line": 1, + "offset": 2, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 10, + "line": 1, + "offset": 9, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$t{a}\` 1`] = ` +[ + { + "accessedProp": null, + "attributes": [ + { + "children": [], + "name": "a", + "position": { + "end": { + "column": 5, + "line": 1, + "offset": 4, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + }, + "type": "attribute", + }, + ], + "path": [ + { + "index": [], + "name": "t", + "position": { + "end": { + "column": 3, + "line": 1, + "offset": 2, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 6, + "line": 1, + "offset": 5, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; + +exports[`Macro parsing > should parse macro \`$t1\` 1`] = ` +[ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "t1", + "position": { + "end": { + "column": 4, + "line": 1, + "offset": 3, + }, + "start": { + "column": 2, + "line": 1, + "offset": 1, + }, + }, + "type": "pathPart", + }, + ], + "position": { + "end": { + "column": 4, + "line": 1, + "offset": 3, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "macro", + }, +] +`; diff --git a/packages/parser/test/__snapshots__/pretty-print.test.ts.snap b/packages/parser/test/__snapshots__/pretty-print.test.ts.snap new file mode 100644 index 000000000..d2ecefb0a --- /dev/null +++ b/packages/parser/test/__snapshots__/pretty-print.test.ts.snap @@ -0,0 +1,68 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Prettier > pretty-print-1.doenet pretty-prints correctly in Xml format and Doenet format 1`] = ` +"a +

a b c d e

+

+ +

Maximum number 2:

+

+ This is a really long sentence that is supposed to wrap eventually. Though, + it is not supposed to rap musically... +

+

another p

+ +

+ Maximum number 1: + +

+ + + yes + no + maybe + + +In document: $ci.choiceTexts $ci.choiceTexts +
$ci.choiceTexts
+$ci.choiceTexts + $ci.choiceTexts +$ci.choiceTexts +$ci.choiceTexts +$ci.choiceTexts$ci.choiceTexts +$ci.choiceTexts +$ci.choiceTexts + + A title + $ci.choiceTexts + +$ci.choiceTexts + +
    +
  • $ci.choiceTexts
  • +
+

$ci.choiceTexts

+
$ci.choiceTexts
+      x
+        y
+      
+

$ci.choiceTexts

+
+ Title: $ci.choiceTexts + Text: $ci.choiceTexts +
+
+ $ci.choiceTexts +
+$ci.choiceTexts +

$ci.choiceTexts

+ +$ci.choiceTexts + +
    +
  1. $ci.choiceTexts
  2. +
  3. $ci.choiceTexts
  4. + +
  5. $ci.choiceTexts
  6. +
" +`; diff --git a/packages/parser/test/__snapshots__/xml-compat.test.ts.snap b/packages/parser/test/__snapshots__/xml-compat.test.ts.snap new file mode 100644 index 000000000..369ab739a --- /dev/null +++ b/packages/parser/test/__snapshots__/xml-compat.test.ts.snap @@ -0,0 +1,47 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Xml files parse correctly > xml-1.doenet parses correctly 1`] = `"Document(Element(SelfClosingTag(StartTag,TagName,SelfCloseEndTag)))"`; + +exports[`Xml files parse correctly > xml-2.doenet parses correctly 1`] = `"Document(Element(OpenTag(StartTag,TagName,EndTag),Text,CloseTag(StartCloseTag,TagName,EndTag)))"`; + +exports[`Xml files parse correctly > xml-3.doenet parses correctly 1`] = `"Document(Element(OpenTag(StartTag,TagName,EndTag),Element(OpenTag(StartTag,TagName,EndTag),Text,CloseTag(StartCloseTag,TagName,EndTag)),Element(SelfClosingTag(StartTag,TagName,SelfCloseEndTag)),CloseTag(StartCloseTag,TagName,EndTag)))"`; + +exports[`Xml files parse correctly > xml-4.doenet parses correctly 1`] = `"Document(Element(SelfClosingTag(StartTag,TagName,Attribute(AttributeName,Is,AttributeValue),SelfCloseEndTag)))"`; + +exports[`Xml files parse correctly > xml-5.doenet parses correctly 1`] = `"Document(Element(OpenTag(StartTag,TagName,Attribute(AttributeName,Is,AttributeValue),Attribute(AttributeName,Is,AttributeValue),Attribute(AttributeName,Is,AttributeValue),EndTag),CloseTag(StartCloseTag,TagName,EndTag)))"`; + +exports[`Xml files parse correctly > xml-6.doenet parses correctly 1`] = `"Document(Element(OpenTag(StartTag,TagName,Attribute(AttributeName,Is,AttributeValue(EntityReference)),EndTag),EntityReference,CharacterReference,CloseTag(StartCloseTag,TagName,EndTag)))"`; + +exports[`Xml files parse correctly > xml-7.doenet parses correctly 1`] = `"Document(DoctypeDecl,Text,Element(SelfClosingTag(StartTag,TagName,SelfCloseEndTag)))"`; + +exports[`Xml files parse correctly > xml-8.doenet parses correctly 1`] = `"Document(ProcessingInst,Element(OpenTag(StartTag,TagName,EndTag),ProcessingInst,CloseTag(StartCloseTag,TagName,EndTag)))"`; + +exports[`Xml files parse correctly > xml-8b.doenet parses correctly 1`] = `"Document(ProcessingInst)"`; + +exports[`Xml files parse correctly > xml-9.doenet parses correctly 1`] = `"Document(Comment,Text,Element(OpenTag(StartTag,TagName,EndTag),Comment,Text,CloseTag(StartCloseTag,TagName,EndTag)),Text,Comment)"`; + +exports[`Xml files parse correctly > xml-10.doenet parses correctly 1`] = `"Document(Element(OpenTag(StartTag,TagName,EndTag),Cdata,CloseTag(StartCloseTag,TagName,EndTag)))"`; + +exports[`Xml files parse correctly > xml-12.doenet parses correctly 1`] = `"Document(Element(OpenTag(StartTag,TagName,Attribute(AttributeName,Is,AttributeValue),EndTag),Text,CloseTag(StartCloseTag,TagName,EndTag)))"`; + +exports[`Xml files parse correctly > xml-doenet-ampersand-1.doenet parses correctly 1`] = `"Document(EntityReference,Text,EntityReference,Text,EntityReference,Text)"`; + +exports[`Xml files parse correctly > xml-doenet-ampersand-2.doenet parses correctly 1`] = `"Document(Ampersand,Text,EntityReference,Text,Ampersand,Text)"`; + +exports[`Xml files parse correctly > xml-doenet-ampersand-3.doenet parses correctly 1`] = `"Document(Ampersand)"`; + +exports[`Xml files parse correctly > xml-doenet-attributes-1.doenet parses correctly 1`] = `"Document(Element(SelfClosingTag(StartTag,TagName,Attribute(AttributeName),Attribute(AttributeName,Is,AttributeValue),Attribute(AttributeName,Is,AttributeValue),SelfCloseEndTag)))"`; + +exports[`Xml files parse correctly > xml-doenet-attributes-2.doenet parses correctly 1`] = `"Document(Element(SelfClosingTag(StartTag,TagName,Attribute(AttributeName,Is,AttributeValue),Attribute(AttributeName,Is,AttributeValue(Ampersand)),SelfCloseEndTag)))"`; + +exports[`Xml files parse correctly > xml-doenet-lessthan-in-text-1.doenet parses correctly 1`] = `"Document(Element(OpenTag(StartTag,TagName,EndTag),Text,CloseTag(StartCloseTag,TagName,EndTag)))"`; + +exports[`Xml files parse correctly > xml-doenet-lessthan-in-text-2.doenet parses correctly 1`] = `"Document(Element(OpenTag(StartTag,TagName,EndTag),Text,CloseTag(StartCloseTag,TagName,EndTag)))"`; + +exports[`Xml files parse correctly > xml-doenet-lessthan-in-text-3.doenet parses correctly 1`] = `"Document(Element(OpenTag(StartTag,TagName,EndTag),Text,CloseTag(StartCloseTag,TagName,EndTag)))"`; + +exports[`Xml files parse correctly > xml-doenet-lessthan-in-text-4.doenet parses correctly 1`] = `"Document(Element(OpenTag(StartTag,TagName,EndTag),Text,CloseTag(StartCloseTag,TagName,EndTag)))"`; + +exports[`Xml files parse correctly > xml-doenet-lessthan-in-text-5.doenet parses correctly 1`] = `"Document(Element(OpenTag(StartTag,TagName,EndTag),Text,CloseTag(StartCloseTag,TagName,EndTag)))"`; + +exports[`Xml files parse correctly > xml-doenet-no-root.doenet parses correctly 1`] = `"Document(Text,Element(SelfClosingTag(StartTag,TagName,SelfCloseEndTag)),Text,Element(SelfClosingTag(StartTag,TagName,SelfCloseEndTag)),Text)"`; diff --git a/packages/parser/test/dast-advanced.test.ts b/packages/parser/test/dast-advanced.test.ts new file mode 100644 index 000000000..da6899c11 --- /dev/null +++ b/packages/parser/test/dast-advanced.test.ts @@ -0,0 +1,1017 @@ +import { describe, expect, it } from "vitest"; +import { lezerToDast } from "../src/lezer-to-dast"; +import util from "util"; +import { filterPositionInfo } from "../src/dast-to-xml/utils"; +import { DastElement, DastFunctionMacro, DastRootContent } from "../src/types"; +import { MacroParser } from "../src/macros/parser"; +import { gobbleFunctionArguments } from "../src/lezer-to-dast/gobble-function-arguments"; + +const origLog = console.log; +console.log = (...args) => { + origLog(...args.map((x) => util.inspect(x, false, 10, true))); +}; + +describe("DAST", async () => { + it("Can gobble function arguments", () => { + let nodes: DastRootContent[]; + let func: DastFunctionMacro; + + // Argument where text is already split up. + func = MacroParser.parse(`$$f`)[0] as DastFunctionMacro; + nodes = [ + func, + { type: "text", value: "(" }, + { type: "text", value: "foo" }, + { type: "text", value: ")" }, + { type: "text", value: "bar" }, + ]; + expect(filterPositionInfo(gobbleFunctionArguments(nodes))) + .toMatchInlineSnapshot(` + [ + { + "input": [ + [ + { + "type": "text", + "value": "foo", + }, + ], + ], + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "f", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + { + "type": "text", + "value": "bar", + }, + ] + `); + + // Argument where text is not split up. + func = MacroParser.parse(`$$f`)[0] as DastFunctionMacro; + nodes = [func, { type: "text", value: "(foo) bar" }]; + expect(filterPositionInfo(gobbleFunctionArguments(nodes))) + .toMatchInlineSnapshot(` + [ + { + "input": [ + [ + { + "type": "text", + "value": "foo", + }, + ], + ], + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "f", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + { + "type": "text", + "value": " bar", + }, + ] + `); + + // Multiple arguments + func = MacroParser.parse(`$$f`)[0] as DastFunctionMacro; + nodes = [func, { type: "text", value: "(foo, laz) bar" }]; + expect(filterPositionInfo(gobbleFunctionArguments(nodes))) + .toMatchInlineSnapshot(` + [ + { + "input": [ + [ + { + "type": "text", + "value": "foo", + }, + ], + [ + { + "type": "text", + "value": "laz", + }, + ], + ], + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "f", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + { + "type": "text", + "value": " bar", + }, + ] + `); + + // Argument with an element in it + func = MacroParser.parse(`$$f`)[0] as DastFunctionMacro; + nodes = [ + func, + { type: "text", value: "(foo" }, + { + type: "element", + name: "m", + attributes: [], + children: [{ type: "text", value: "alpha" }], + }, + { type: "text", value: ") bar" }, + ]; + expect(filterPositionInfo(gobbleFunctionArguments(nodes))) + .toMatchInlineSnapshot(` + [ + { + "input": [ + [ + { + "type": "text", + "value": "foo", + }, + { + "attributes": [], + "children": [ + { + "type": "text", + "value": "alpha", + }, + ], + "name": "m", + "type": "element", + }, + ], + ], + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "f", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + { + "type": "text", + "value": " bar", + }, + ] + `); + + // Missing closing paren. + func = MacroParser.parse(`$$f`)[0] as DastFunctionMacro; + nodes = [func, { type: "text", value: "(foo bar" }]; + expect(filterPositionInfo(gobbleFunctionArguments(nodes))) + .toMatchInlineSnapshot(` + [ + { + "input": null, + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "f", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + { + "type": "text", + "value": "(", + }, + { + "type": "text", + "value": "foo bar", + }, + ] + `); + + // Missing open paren. + func = MacroParser.parse(`$$f`)[0] as DastFunctionMacro; + nodes = [func, { type: "text", value: "foo bar)" }]; + expect(filterPositionInfo(gobbleFunctionArguments(nodes))) + .toMatchInlineSnapshot(` + [ + { + "input": null, + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "f", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + { + "type": "text", + "value": "foo bar", + }, + { + "type": "text", + "value": ")", + }, + ] + `); + + // Multiple functions + func = MacroParser.parse(`$$f`)[0] as DastFunctionMacro; + nodes = [ + { type: "text", value: "hi there" }, + MacroParser.parse(`$$f`)[0] as DastFunctionMacro, + { type: "text", value: "(foo)" }, + MacroParser.parse(`$$g`)[0] as DastFunctionMacro, + { type: "text", value: "(bar)" }, + ]; + expect(filterPositionInfo(gobbleFunctionArguments(nodes))) + .toMatchInlineSnapshot(` + [ + { + "type": "text", + "value": "hi there", + }, + { + "input": [ + [ + { + "type": "text", + "value": "foo", + }, + ], + ], + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "f", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + { + "input": [ + [ + { + "type": "text", + "value": "bar", + }, + ], + ], + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "g", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + ] + `); + + // Nested functions + func = MacroParser.parse(`$$f`)[0] as DastFunctionMacro; + nodes = [ + { type: "text", value: "hi there" }, + MacroParser.parse(`$$f`)[0] as DastFunctionMacro, + { type: "text", value: "(" }, + MacroParser.parse(`$$g`)[0] as DastFunctionMacro, + { type: "text", value: "(bar))" }, + ]; + expect(filterPositionInfo(gobbleFunctionArguments(nodes))) + .toMatchInlineSnapshot(` + [ + { + "type": "text", + "value": "hi there", + }, + { + "input": [ + [ + { + "input": [ + [ + { + "type": "text", + "value": "bar", + }, + ], + ], + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "g", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + ], + ], + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "f", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + ] + `); + }); + it("Produces DAST trees with macros in them", () => { + let source: string; + + source = `$x`; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "x", + "type": "pathPart", + }, + ], + "type": "macro", + }, + ], + "type": "root", + } + `); + + source = `$x`; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "attributes": [], + "children": [ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "x", + "type": "pathPart", + }, + ], + "type": "macro", + }, + ], + "name": "m", + "type": "element", + }, + ], + "type": "root", + } + `); + + source = `$x.`; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "x", + "type": "pathPart", + }, + ], + "type": "macro", + }, + { + "type": "text", + "value": ".", + }, + ], + "type": "root", + } + `); + + source = ``; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "attributes": [ + { + "children": [ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "x", + "type": "pathPart", + }, + ], + "type": "macro", + }, + ], + "name": "z", + "type": "attribute", + }, + ], + "children": [], + "name": "m", + "type": "element", + }, + ], + "type": "root", + } + `); + + source = `$x{y="$z"}`; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "accessedProp": null, + "attributes": [ + { + "children": [ + { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "z", + "type": "pathPart", + }, + ], + "type": "macro", + }, + ], + "name": "y", + "type": "attribute", + }, + ], + "path": [ + { + "index": [], + "name": "x", + "type": "pathPart", + }, + ], + "type": "macro", + }, + ], + "type": "root", + } + `); + + source = `$$f(x, y)`; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "input": [ + [ + { + "type": "text", + "value": "x", + }, + ], + [ + { + "type": "text", + "value": "y", + }, + ], + ], + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "f", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + ], + "type": "root", + } + `); + }); + + it("Produces DAST trees for function macros with element arguments", () => { + let source: string; + + source = `$$f(alpha)`; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "input": [ + [ + { + "attributes": [], + "children": [ + { + "type": "text", + "value": "alpha", + }, + ], + "name": "math", + "type": "element", + }, + ], + ], + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "f", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + ], + "type": "root", + } + `); + + source = `$$f(x, alpha)`; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "input": [ + [ + { + "type": "text", + "value": "x", + }, + ], + [ + { + "attributes": [], + "children": [ + { + "type": "text", + "value": "alpha", + }, + ], + "name": "math", + "type": "element", + }, + ], + ], + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "f", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + ], + "type": "root", + } + `); + + source = `

$$f(x, alpha)

`; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "attributes": [], + "children": [ + { + "input": [ + [ + { + "type": "text", + "value": "x", + }, + ], + [ + { + "attributes": [], + "children": [ + { + "type": "text", + "value": "alpha", + }, + ], + "name": "math", + "type": "element", + }, + ], + ], + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "f", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + ], + "name": "p", + "type": "element", + }, + ], + "type": "root", + } + `); + }); + it("Function macros can have balanced parens in their arguments", () => { + let source: string; + + source = `$$f((x-2), 7)`; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "input": [ + [ + { + "type": "text", + "value": "(", + }, + { + "type": "text", + "value": "x-2", + }, + { + "type": "text", + "value": ")", + }, + ], + [ + { + "type": "text", + "value": "7", + }, + ], + ], + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "f", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + ], + "type": "root", + } + `); + + source = `$$f((3,4), (5,6))`; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "input": [ + [ + { + "type": "text", + "value": "(", + }, + { + "type": "text", + "value": "3,4", + }, + { + "type": "text", + "value": ")", + }, + ], + [ + { + "type": "text", + "value": "(", + }, + { + "type": "text", + "value": "5,6", + }, + { + "type": "text", + "value": ")", + }, + ], + ], + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "f", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + ], + "type": "root", + } + `); + + source = `$$f(1,(alpha))`; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "input": [ + [ + { + "type": "text", + "value": "1", + }, + ], + [ + { + "type": "text", + "value": "(", + }, + { + "attributes": [], + "children": [ + { + "type": "text", + "value": "alpha", + }, + ], + "name": "math", + "type": "element", + }, + { + "type": "text", + "value": ")", + }, + ], + ], + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "f", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + ], + "type": "root", + } + `); + + source = `$$f(x, alpha)`; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "input": [ + [ + { + "type": "text", + "value": "x", + }, + ], + [ + { + "attributes": [], + "children": [ + { + "type": "text", + "value": "alpha", + }, + ], + "name": "math", + "type": "element", + }, + ], + ], + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "f", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + ], + "type": "root", + } + `); + + source = `$$f((x,y), alpha)`; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "input": [ + [ + { + "type": "text", + "value": "(", + }, + { + "type": "text", + "value": "x", + }, + { + "type": "text", + "value": ",", + }, + { + "type": "text", + "value": "y", + }, + { + "type": "text", + "value": ")", + }, + ], + [ + { + "attributes": [], + "children": [ + { + "type": "text", + "value": "alpha", + }, + ], + "name": "math", + "type": "element", + }, + ], + ], + "macro": { + "accessedProp": null, + "attributes": [], + "path": [ + { + "index": [], + "name": "f", + "type": "pathPart", + }, + ], + "type": "macro", + }, + "type": "function", + }, + ], + "type": "root", + } + `); + }); + it("DAST trees with macros in them have correct position information", () => { + let source: string; + + source = `$x`; + expect(lezerToDast(source).children[0].position).toMatchInlineSnapshot(` + { + "end": { + "column": 3, + "line": 1, + "offset": 2, + }, + "start": { + "column": 1, + "line": 1, + "offset": 0, + }, + } + `); + + source = `

$xx

`; + expect( + (lezerToDast(source).children[0] as DastElement).children[0] + .position, + ).toMatchInlineSnapshot(` + { + "end": { + "column": 7, + "line": 1, + "offset": 6, + }, + "start": { + "column": 4, + "line": 1, + "offset": 3, + }, + } + `); + }); +}); diff --git a/packages/parser/test/dast-basic.test.ts b/packages/parser/test/dast-basic.test.ts new file mode 100644 index 000000000..4adf8bfbc --- /dev/null +++ b/packages/parser/test/dast-basic.test.ts @@ -0,0 +1,449 @@ +import { glob } from "glob"; +import { describe, expect, it } from "vitest"; +import * as fs from "node:fs/promises"; +import { lezerToDast } from "../src/lezer-to-dast"; +import { toXml } from "../src/dast-to-xml/dast-util-to-xml"; +import util from "util"; +import { + filterPositionInfo, + mergeAdjacentTextInArray, +} from "../src/dast-to-xml/utils"; +import { DastRoot, DastText } from "../src/types"; +import { + splitTextAtSpecialChars, + splitTextNodeAt, +} from "../src/lezer-to-dast/gobble-function-arguments"; + +const origLog = console.log; +console.log = (...args) => { + origLog(...args.map((x) => util.inspect(x, false, 10, true))); +}; + +describe("DAST", async () => { + { + // Regular parsing tests + const files = glob + .sync(new URL("./fragments/xml-*.doenet", import.meta.url).pathname) + .filter((f) => !f.includes("-bad")); + const fileMap: Record = Object.fromEntries( + files.map((f) => [f.split("/").pop(), f]), + ); + + for (const [filename, filepath] of Object.entries(fileMap)) { + it(`${filename} prints correctly in Xml format and Doenet format`, async () => { + const source = await fs.readFile(filepath, "utf-8"); + const dast = lezerToDast(source); + const formattedXml = toXml(dast); + const formattedDoenet = toXml(dast, { doenetSyntax: true }); + expect(formattedXml).toMatchSnapshot(); + expect(formattedDoenet).toMatchSnapshot(); + }); + } + } + { + // Tests that identify parsing errors + const files = glob.sync( + new URL("./fragments/xml-bad*.doenet", import.meta.url).pathname, + ); + const fileMap: Record = Object.fromEntries( + files.map((f) => [f.split("/").pop(), f]), + ); + + for (const [filename, filepath] of Object.entries(fileMap)) { + it(`${filename} can parse badly formed Xml`, async () => { + const source = await fs.readFile(filepath, "utf-8"); + const dast = lezerToDast(source); + // We just don't want to throw any errors when printing + const formattedXml = toXml(dast); + const formattedDoenet = toXml(dast, { doenetSyntax: true }); + expect(formattedXml).toBeTypeOf("string"); + expect(formattedDoenet).toBeTypeOf("string"); + }); + } + } + + it("preserves ampersands", () => { + const cases = [ + { inStr: "a & b", outStrXml: "a & b", outStrDoenet: "a & b" }, + { + inStr: "a &b c", + outStrXml: "a &b c", + outStrDoenet: "a &b c", + }, + { inStr: "a &b", outStrXml: "a &b", outStrDoenet: "a &b" }, + { + inStr: "a &&", + outStrXml: "a &amp&", + outStrDoenet: "a &amp&", + }, + { + inStr: "&;", + outStrXml: "&amp;", + outStrDoenet: "&amp;", + }, + ]; + for (const { inStr, outStrXml, outStrDoenet } of cases) { + const dast = lezerToDast(inStr); + const formattedXml = toXml(dast); + const formattedDoenet = toXml(dast, { doenetSyntax: true }); + expect(formattedXml).toBe(outStrXml); + expect(formattedDoenet).toBe(outStrDoenet); + } + }); + + it("preserves ampersands 2", () => { + const dast: DastRoot = { + type: "root", + children: [ + { + type: "text", + value: "one&two", + }, + ], + }; + const formattedXml = toXml(dast); + const formattedDoenet = toXml(dast, { doenetSyntax: true }); + expect(formattedXml).toBe(`one&two`); + expect(formattedDoenet).toBe(`one&two`); + }); + + it("preserves ampersands in attributes", () => { + const dast: DastRoot = { + type: "root", + children: [ + { + type: "element", + name: "a", + attributes: [ + { + type: "attribute", + name: "attr", + children: [ + { + type: "text", + value: "one&two", + }, + ], + }, + ], + children: [], + }, + { + type: "text", + value: "\n", + }, + ], + }; + const formattedXml = toXml(dast).trim(); + const formattedDoenet = toXml(dast, { doenetSyntax: true }).trim(); + expect(formattedXml).toBe(``); + expect(formattedDoenet).toBe(``); + }); + + it("can merge adjacent text nodes", () => { + expect(mergeAdjacentTextInArray([])).toEqual([]); + expect( + mergeAdjacentTextInArray([{ type: "text", value: "foo" }]), + ).toEqual([{ type: "text", value: "foo" }]); + expect( + mergeAdjacentTextInArray([ + { type: "text", value: "foo" }, + { type: "text", value: "bar" }, + ]), + ).toEqual([{ type: "text", value: "foobar" }]); + expect( + mergeAdjacentTextInArray([ + { type: "text", value: "foo" }, + { type: "text", value: "bar" }, + { type: "text", value: "Baz" }, + ]), + ).toEqual([{ type: "text", value: "foobarBaz" }]); + expect( + mergeAdjacentTextInArray([ + { type: "text", value: "foo" }, + { type: "element", children: [], attributes: [], name: "m" }, + { type: "text", value: "bar" }, + { type: "text", value: "Foo" }, + { type: "element", children: [], attributes: [], name: "m" }, + { type: "text", value: "foo" }, + ]), + ).toEqual([ + { type: "text", value: "foo" }, + { type: "element", children: [], attributes: [], name: "m" }, + { type: "text", value: "barFoo" }, + { type: "element", children: [], attributes: [], name: "m" }, + { type: "text", value: "foo" }, + ]); + }); + it("Can split text nodes and preserve position information", () => { + let source: string; + let textNode: DastText; + + source = "hi there"; + textNode = lezerToDast(source).children[0] as DastText; + expect(splitTextNodeAt(textNode, 2)).toMatchObject([ + { + type: "text", + value: "hi", + position: { + start: { line: 1, column: 1, offset: 0 }, + end: { line: 1, column: 3, offset: 2 }, + }, + }, + { + type: "text", + value: " ", + position: { + start: { line: 1, column: 3, offset: 2 }, + end: { line: 1, column: 4, offset: 3 }, + }, + }, + { + type: "text", + value: "there", + position: { + start: { line: 1, column: 4, offset: 3 }, + end: { line: 1, column: 9, offset: 8 }, + }, + }, + ]); + + source = "hi there"; + textNode = lezerToDast(source).children[0] as DastText; + expect(splitTextNodeAt(textNode, 0)).toMatchObject([ + { + type: "text", + value: "", + position: { + start: { line: 1, column: 1, offset: 0 }, + end: { line: 1, column: 1, offset: 0 }, + }, + }, + { + type: "text", + value: "h", + position: { + start: { line: 1, column: 1, offset: 0 }, + end: { line: 1, column: 2, offset: 1 }, + }, + }, + { + type: "text", + value: "i there", + position: { + start: { line: 1, column: 2, offset: 1 }, + end: { line: 1, column: 9, offset: 8 }, + }, + }, + ]); + + source = "hi there\nhow are you"; + textNode = lezerToDast(source).children[0] as DastText; + expect(splitTextNodeAt(textNode, 12)).toMatchObject([ + { + type: "text", + value: "hi there\nhow", + position: { + start: { line: 1, column: 1, offset: 0 }, + end: { line: 2, column: 4, offset: 12 }, + }, + }, + { + type: "text", + value: " ", + position: { + start: { line: 2, column: 4, offset: 12 }, + end: { line: 2, column: 5, offset: 13 }, + }, + }, + { + type: "text", + value: "are you", + position: { + start: { line: 2, column: 5, offset: 13 }, + end: { line: 2, column: 12, offset: 20 }, + }, + }, + ]); + }); + it("Can split at /(),/ characters", () => { + let source: string; + let textNode: DastText; + + source = "hi (th, ere\n)"; + textNode = lezerToDast(source).children[0] as DastText; + expect( + filterPositionInfo(splitTextAtSpecialChars(textNode)), + ).toMatchObject([ + { type: "text", value: "hi " }, + { type: "text", value: "(" }, + { type: "text", value: "th" }, + { type: "text", value: "," }, + { type: "text", value: " ere\n" }, + { type: "text", value: ")" }, + ]); + }); + it("Produces DAST trees", () => { + let source: string; + + source = `foo`; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "attributes": [], + "children": [ + { + "type": "text", + "value": "foo", + }, + ], + "name": "m", + "type": "element", + }, + ], + "type": "root", + } + `); + + source = ``; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "attributes": [], + "children": [], + "name": "m", + "type": "element", + }, + ], + "type": "root", + } + `); + + source = ``; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "attributes": [ + { + "children": [], + "name": "foo", + "type": "attribute", + }, + ], + "children": [], + "name": "m", + "type": "element", + }, + ], + "type": "root", + } + `); + + source = ``; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "attributes": [ + { + "children": [], + "name": "foo", + "type": "attribute", + }, + { + "children": [ + { + "type": "text", + "value": "baz", + }, + ], + "name": "bar", + "type": "attribute", + }, + ], + "children": [], + "name": "m", + "type": "element", + }, + ], + "type": "root", + } + `); + + source = ``; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "attributes": [], + "children": [ + { + "attributes": [], + "children": [], + "name": "z", + "type": "element", + }, + ], + "name": "m", + "type": "element", + }, + ], + "type": "root", + } + `); + + source = ``; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "attributes": [], + "children": [ + { + "type": "cdata", + "value": "hi there", + }, + ], + "name": "m", + "type": "element", + }, + ], + "type": "root", + } + `); + + source = `\nfoo`; + expect(filterPositionInfo(lezerToDast(source))).toMatchInlineSnapshot(` + { + "children": [ + { + "name": "DoenetML", + "public": null, + "system": null, + "type": "doctype", + }, + { + "type": "text", + "value": " + ", + }, + { + "attributes": [], + "children": [ + { + "type": "text", + "value": "foo", + }, + ], + "name": "m", + "type": "element", + }, + ], + "type": "root", + } + `); + }); +}); diff --git a/packages/parser/test/dast-errors.test.ts b/packages/parser/test/dast-errors.test.ts new file mode 100644 index 000000000..3f82c5829 --- /dev/null +++ b/packages/parser/test/dast-errors.test.ts @@ -0,0 +1,136 @@ +import { describe, expect, it } from "vitest"; +import { lezerToDast } from "../src/lezer-to-dast"; +import util from "util"; +import { extractDastErrors } from "../src/extract-dast-errors"; + +const origLog = console.log; +console.log = (...args) => { + origLog(...args.map((x) => util.inspect(x, false, 10, true))); +}; + +describe("DAST", async () => { + it("Shows error for incomplete XML tag", () => { + let source: string; + let dast: ReturnType; + + source = ``; + dast = lezerToDast(source); + expect(extractDastErrors(dast)).toHaveLength(2); + + source = ``; + dast = lezerToDast(source); + expect(extractDastErrors(dast)).toHaveLength(1); + + source = ``; + dast = lezerToDast(source); + expect(extractDastErrors(dast)).toHaveLength(1); + }); + + it("Shows error for incomplete XML tag that is a child of another element", () => { + let source: string; + let dast: ReturnType; + + source = ``; + dast = lezerToDast(source); + expect(extractDastErrors(dast)).toHaveLength(1); + }); + + it("Shows error for incomplete XML closing tag", () => { + let source: string; + let dast: ReturnType; + + source = `` appears to be missing)."', + ); + + source = ``; + dast = lezerToDast(source); + expect(extractDastErrors(dast)).toHaveLength(1); + expect(extractDastErrors(dast)[0].message).toMatchInlineSnapshot( + '"Invalid DoenetML: Tag `` appears to be missing)."', + ); + }); + + it("Unmatched and incomplete XML closing tags prioritize incomplete error", () => { + let source: string; + let dast: ReturnType; + + source = `` appears to be missing)."', + ); + + source = ``; + dast = lezerToDast(source); + expect(extractDastErrors(dast)).toHaveLength(1); + expect(extractDastErrors(dast)[0].message).toMatchInlineSnapshot( + '"Invalid DoenetML: Tag `` appears to be missing)."', + ); + }); + + it("Errors for missing tags are shown at the location of the starting tag", () => { + let source: string; + let dast: ReturnType; + + source = ` `; + dast = lezerToDast(source); + expect(extractDastErrors(dast)[0].position).toMatchObject({ + start: { + offset: 0, + }, + end: { + offset: 8, + }, + }); + + source = ` `; + dast = lezerToDast(source); + expect(extractDastErrors(dast)[0].position).toMatchObject({ + start: { + offset: 0, + }, + end: { + offset: 4, + }, + }); + + source = `a + 1+1 + 1+1 + \ No newline at end of file diff --git a/packages/parser/test/fragments/math-2.doenet b/packages/parser/test/fragments/math-2.doenet new file mode 100644 index 000000000..af4eb8e9c --- /dev/null +++ b/packages/parser/test/fragments/math-2.doenet @@ -0,0 +1,5 @@ + + a + 3x+1+5 + 3x+1+5 + \ No newline at end of file diff --git a/packages/parser/test/fragments/math-3.doenet b/packages/parser/test/fragments/math-3.doenet new file mode 100644 index 000000000..abb2801e4 --- /dev/null +++ b/packages/parser/test/fragments/math-3.doenet @@ -0,0 +1,5 @@ + + a + x+1 + 3$_math1{name="m1a"} + 5 + \ No newline at end of file diff --git a/packages/parser/test/fragments/math-4.doenet b/packages/parser/test/fragments/math-4.doenet new file mode 100644 index 000000000..56eb8d79e --- /dev/null +++ b/packages/parser/test/fragments/math-4.doenet @@ -0,0 +1,4 @@ + + a + + \ No newline at end of file diff --git a/packages/parser/test/fragments/math-5.doenet b/packages/parser/test/fragments/math-5.doenet new file mode 100644 index 000000000..84d972405 --- /dev/null +++ b/packages/parser/test/fragments/math-5.doenet @@ -0,0 +1,4 @@ + + b + + \ No newline at end of file diff --git a/packages/parser/test/fragments/pretty-print-1.doenet b/packages/parser/test/fragments/pretty-print-1.doenet new file mode 100644 index 000000000..b93203900 --- /dev/null +++ b/packages/parser/test/fragments/pretty-print-1.doenet @@ -0,0 +1,56 @@ + a

a b c d e

+

+ + + +

Maximum number 2:

+

This is a really long sentence that is supposed to wrap eventually. Though, it is not supposed to rap musically...

another p

+ +

+ + Maximum number 1:

+ + + yes + no + maybe + + + In document: $ci.choiceTexts + $ci.choiceTexts +
$ci.choiceTexts
+ $ci.choiceTexts + $ci.choiceTexts + $ci.choiceTexts + $ci.choiceTexts + $ci.choiceTexts + $ci.choiceTexts + $ci.choiceTexts + $ci.choiceTexts + A title$ci.choiceTexts + $ci.choiceTexts + +
    +
  • $ci.choiceTexts
  • +
+

$ci.choiceTexts

+
$ci.choiceTexts
+      x
+        y
+      
+

$ci.choiceTexts

+
Title: $ci.choiceTextsText: $ci.choiceTexts
+
$ci.choiceTexts
+ $ci.choiceTexts +

$ci.choiceTexts

+ + $ci.choiceTexts + +
    + +
  1. $ci.choiceTexts
  2. +
  3. $ci.choiceTexts
  4. + +
  5. $ci.choiceTexts
  6. + +
diff --git a/packages/parser/test/fragments/xml-1.doenet b/packages/parser/test/fragments/xml-1.doenet new file mode 100644 index 000000000..d1bd00e34 --- /dev/null +++ b/packages/parser/test/fragments/xml-1.doenet @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-10.doenet b/packages/parser/test/fragments/xml-10.doenet new file mode 100644 index 000000000..35c26597f --- /dev/null +++ b/packages/parser/test/fragments/xml-10.doenet @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-12.doenet b/packages/parser/test/fragments/xml-12.doenet new file mode 100644 index 000000000..f3c789ddc --- /dev/null +++ b/packages/parser/test/fragments/xml-12.doenet @@ -0,0 +1 @@ +yy \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-2.doenet b/packages/parser/test/fragments/xml-2.doenet new file mode 100644 index 000000000..954791b5c --- /dev/null +++ b/packages/parser/test/fragments/xml-2.doenet @@ -0,0 +1 @@ +bar \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-3.doenet b/packages/parser/test/fragments/xml-3.doenet new file mode 100644 index 000000000..bacc263d6 --- /dev/null +++ b/packages/parser/test/fragments/xml-3.doenet @@ -0,0 +1 @@ +
c \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-4.doenet b/packages/parser/test/fragments/xml-4.doenet new file mode 100644 index 000000000..a085ea1bb --- /dev/null +++ b/packages/parser/test/fragments/xml-4.doenet @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-5.doenet b/packages/parser/test/fragments/xml-5.doenet new file mode 100644 index 000000000..b1a934c47 --- /dev/null +++ b/packages/parser/test/fragments/xml-5.doenet @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-6.doenet b/packages/parser/test/fragments/xml-6.doenet new file mode 100644 index 000000000..f3b38612b --- /dev/null +++ b/packages/parser/test/fragments/xml-6.doenet @@ -0,0 +1 @@ +&C \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-7.doenet b/packages/parser/test/fragments/xml-7.doenet new file mode 100644 index 000000000..2032772bd --- /dev/null +++ b/packages/parser/test/fragments/xml-7.doenet @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-8.doenet b/packages/parser/test/fragments/xml-8.doenet new file mode 100644 index 000000000..dd22b8856 --- /dev/null +++ b/packages/parser/test/fragments/xml-8.doenet @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-8b.doenet b/packages/parser/test/fragments/xml-8b.doenet new file mode 100644 index 000000000..0e723408f --- /dev/null +++ b/packages/parser/test/fragments/xml-8b.doenet @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-9.doenet b/packages/parser/test/fragments/xml-9.doenet new file mode 100644 index 000000000..935e84b60 --- /dev/null +++ b/packages/parser/test/fragments/xml-9.doenet @@ -0,0 +1,3 @@ + + text + \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-bad-1.doenet b/packages/parser/test/fragments/xml-bad-1.doenet new file mode 100644 index 000000000..a0b0dbabe --- /dev/null +++ b/packages/parser/test/fragments/xml-bad-1.doenet @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/packages/parser/test/fragments/xml-bad-2.doenet b/packages/parser/test/fragments/xml-bad-2.doenet new file mode 100644 index 000000000..cee42f818 --- /dev/null +++ b/packages/parser/test/fragments/xml-bad-2.doenet @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-bad-3.doenet b/packages/parser/test/fragments/xml-bad-3.doenet new file mode 100644 index 000000000..49236ee26 --- /dev/null +++ b/packages/parser/test/fragments/xml-bad-3.doenet @@ -0,0 +1 @@ + blah \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-bad-4.doenet b/packages/parser/test/fragments/xml-bad-4.doenet new file mode 100644 index 000000000..666628cc9 --- /dev/null +++ b/packages/parser/test/fragments/xml-bad-4.doenet @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-bad-5.doenet b/packages/parser/test/fragments/xml-bad-5.doenet new file mode 100644 index 000000000..9e20df031 --- /dev/null +++ b/packages/parser/test/fragments/xml-bad-5.doenet @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-bad-6.doenet b/packages/parser/test/fragments/xml-bad-6.doenet new file mode 100644 index 000000000..d8d2b8d61 --- /dev/null +++ b/packages/parser/test/fragments/xml-bad-6.doenet @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-bad-8.doenet b/packages/parser/test/fragments/xml-bad-8.doenet new file mode 100644 index 000000000..5579f93df --- /dev/null +++ b/packages/parser/test/fragments/xml-bad-8.doenet @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-doenet-ampersand-1.doenet b/packages/parser/test/fragments/xml-doenet-ampersand-1.doenet new file mode 100644 index 000000000..1583ed9de --- /dev/null +++ b/packages/parser/test/fragments/xml-doenet-ampersand-1.doenet @@ -0,0 +1,2 @@ +&lt; &#x25; &#x25 -- this one is okay. +(an amp followed by text with a semi colon should be an amp.) \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-doenet-ampersand-2.doenet b/packages/parser/test/fragments/xml-doenet-ampersand-2.doenet new file mode 100644 index 000000000..dbeab895c --- /dev/null +++ b/packages/parser/test/fragments/xml-doenet-ampersand-2.doenet @@ -0,0 +1,3 @@ +& +& +& \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-doenet-ampersand-3.doenet b/packages/parser/test/fragments/xml-doenet-ampersand-3.doenet new file mode 100644 index 000000000..00b15c0a3 --- /dev/null +++ b/packages/parser/test/fragments/xml-doenet-ampersand-3.doenet @@ -0,0 +1 @@ +& \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-doenet-attributes-1.doenet b/packages/parser/test/fragments/xml-doenet-attributes-1.doenet new file mode 100644 index 000000000..af827431a --- /dev/null +++ b/packages/parser/test/fragments/xml-doenet-attributes-1.doenet @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-doenet-attributes-2.doenet b/packages/parser/test/fragments/xml-doenet-attributes-2.doenet new file mode 100644 index 000000000..445e7fd3c --- /dev/null +++ b/packages/parser/test/fragments/xml-doenet-attributes-2.doenet @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-doenet-lessthan-in-text-1.doenet b/packages/parser/test/fragments/xml-doenet-lessthan-in-text-1.doenet new file mode 100644 index 000000000..cbbd5ff9c --- /dev/null +++ b/packages/parser/test/fragments/xml-doenet-lessthan-in-text-1.doenet @@ -0,0 +1 @@ +2 < 3 \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-doenet-lessthan-in-text-2.doenet b/packages/parser/test/fragments/xml-doenet-lessthan-in-text-2.doenet new file mode 100644 index 000000000..73d7b4373 --- /dev/null +++ b/packages/parser/test/fragments/xml-doenet-lessthan-in-text-2.doenet @@ -0,0 +1 @@ +2 <= 3 \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-doenet-lessthan-in-text-3.doenet b/packages/parser/test/fragments/xml-doenet-lessthan-in-text-3.doenet new file mode 100644 index 000000000..46d6cef5d --- /dev/null +++ b/packages/parser/test/fragments/xml-doenet-lessthan-in-text-3.doenet @@ -0,0 +1,5 @@ + +2 +< +3 + \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-doenet-lessthan-in-text-4.doenet b/packages/parser/test/fragments/xml-doenet-lessthan-in-text-4.doenet new file mode 100644 index 000000000..206906ab1 --- /dev/null +++ b/packages/parser/test/fragments/xml-doenet-lessthan-in-text-4.doenet @@ -0,0 +1 @@ + < \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-doenet-lessthan-in-text-5.doenet b/packages/parser/test/fragments/xml-doenet-lessthan-in-text-5.doenet new file mode 100644 index 000000000..5067e51b1 --- /dev/null +++ b/packages/parser/test/fragments/xml-doenet-lessthan-in-text-5.doenet @@ -0,0 +1 @@ +<= \ No newline at end of file diff --git a/packages/parser/test/fragments/xml-doenet-no-root.doenet b/packages/parser/test/fragments/xml-doenet-no-root.doenet new file mode 100644 index 000000000..b05eaed87 --- /dev/null +++ b/packages/parser/test/fragments/xml-doenet-no-root.doenet @@ -0,0 +1,4 @@ +hi + + +there \ No newline at end of file diff --git a/packages/parser/test/macro-parse.test.ts b/packages/parser/test/macro-parse.test.ts new file mode 100644 index 000000000..d17571d8b --- /dev/null +++ b/packages/parser/test/macro-parse.test.ts @@ -0,0 +1,114 @@ +import { describe, expect, it } from "vitest"; +import { mergeAdjacentTextInArray } from "../src/dast-to-xml/utils"; +import { MacroParser } from "../src/macros/parser"; +import { macroToString } from "../src/macros/macro-to-string"; +import { DastNodes } from "../src/types"; + +describe("Macro parsing", () => { + { + const validMacros = `$t + $t1 + $_t + $t[1] + $t[1.5] + $t[$x] + $t[a][b] + $t.x + $t.x.y + $t.x[1].y + $t.x[1][2].y + $t.x[1].y[2] + $t{a} + $t{a="b"} + $t{a="$b"} + $t[1]{a="b"} + $t.x[1]{a="b"}.y + $(t) + $(/t) + $(../t) + $(x-y) + $(x-y/a-b) + $(x-y.a-b) + $(t.x) + $(t-x[1].y{a="b"}) + $(t[1]/x)`.split(/\s+/g); + + for (const macroStr of validMacros) { + it(`should parse macro \`${macroStr}\``, () => { + expect(MacroParser.parse(macroStr)).toMatchSnapshot(); + }); + } + } + it("Parses `$x.` as a macro followed by a string", () => { + expect(MacroParser.parse("$x.")).toMatchObject([ + { type: "macro" }, + { type: "text", value: "." }, + ]); + }); + it("Parses `$x{z}[5]` as a macro followed by a string", () => { + expect(MacroParser.parse("$x{z}[5]")).toMatchObject([ + { type: "macro" }, + { type: "text", value: "[5]" }, + ]); + }); + it("Parses invalid macros as strings", () => { + expect( + mergeAdjacentTextInArray( + MacroParser.parse("$(x{z}[5])") as DastNodes[], + ), + ).toMatchObject([{ type: "text", value: "$(x{z}[5])" }]); + }); + { + const validMacros = `$t + $t1 + $_t + $t[1] + $t[1.5] + $t[$x] + $t[a][b] + $t.x + $t.x.y + $t.x[1].y + $t.x[1][2].y + $t.x[1].y[2] + $t{a} + $t{a="b"} + $t{a="$b"} + $t[1]{a="b"} + $t.x[1]{a="b"}.y + $(/t) + $(../t) + $(x-y) + $(x-y/a-b) + $(x-y.a-b) + $(t-x[1].y{a="b"}) + $(t[1]/x) + $(t.x-y)`.split(/\n\s+/g); + + for (const macroStr of validMacros) { + it(`should print macro \`${macroStr}\``, () => { + const parsed = MacroParser.parse(macroStr); + expect(macroToString(parsed)).toEqual(macroStr); + }); + } + } + { + const validFunctions = `$$f + $$f1(y) + $$f[1](y) + $$f[$x](y) + $$f[a][b](y) + $$(/f)(y) + $$(../f)(y) + $$f($x) + $$(x-y.z{t})(m) + $$f(x, y)`.split(/\n\s+/g); + + for (const macroStr of validFunctions) { + it(`should print macro \`${macroStr}\``, () => { + const parsed = MacroParser.parse(macroStr); + expect(macroToString(parsed)).toEqual(macroStr); + }); + } + } +}); diff --git a/packages/parser/test/parse.test.ts b/packages/parser/test/parse.test.ts index 974436bfa..dc38c7e61 100644 --- a/packages/parser/test/parse.test.ts +++ b/packages/parser/test/parse.test.ts @@ -10,15 +10,15 @@ describe("Lezer Parsing Tests", () => { }, { inStr: "hi there ", - outStr: "Document(Text,Element(SelfClosingTag(StartTag,TagName)))", + outStr: "Document(Text,Element(SelfClosingTag(StartTag,TagName,SelfCloseEndTag)))", }, { inStr: ``, - outStr: "Document(Element(SelfClosingTag(StartTag,TagName,Attribute(AttributeName),Attribute(AttributeName,Is,AttributeValue))))", + outStr: "Document(Element(SelfClosingTag(StartTag,TagName,Attribute(AttributeName),Attribute(AttributeName,Is,AttributeValue),SelfCloseEndTag)))", }, { inStr: "child", - outStr: "Document(Element(OpenTag(StartTag,TagName),Text,CloseTag(StartCloseTag,TagName)))", + outStr: "Document(Element(OpenTag(StartTag,TagName,EndTag),Text,CloseTag(StartCloseTag,TagName,EndTag)))", }, ]; for (const { inStr, outStr } of inputOutput) { diff --git a/packages/parser/test/pretty-print.test.ts b/packages/parser/test/pretty-print.test.ts new file mode 100644 index 000000000..49aaf2759 --- /dev/null +++ b/packages/parser/test/pretty-print.test.ts @@ -0,0 +1,143 @@ +import { glob } from "glob"; +import { describe, expect, it } from "vitest"; +import * as fs from "node:fs/promises"; +import { lezerToDast } from "../src/lezer-to-dast"; +import { toXml } from "../src/dast-to-xml/dast-util-to-xml"; +import { prettyPrint } from "../src/pretty-printer"; +import util from "util"; +import { normalizeWhitespace } from "../src/pretty-printer/normalize/plugin-merge-whitespace"; + +const origLog = console.log; +console.log = (...args) => { + origLog(...args.map((x) => util.inspect(x, false, 10, true))); +}; + +describe("Prettier", async () => { + it("Can normalize whitespace", () => { + expect(normalizeWhitespace("a\nb")).toEqual("a b"); + expect(normalizeWhitespace("a \n\tb")).toEqual("a b"); + expect(normalizeWhitespace("\n ")).toEqual(" "); + expect(normalizeWhitespace(" \n ")).toEqual(" "); + expect(normalizeWhitespace("a\n\nb")).toEqual("a\n\nb"); + expect(normalizeWhitespace("a \n \nb")).toEqual("a\n\nb"); + expect(normalizeWhitespace("a\n \n b")).toEqual("a\n\nb"); + expect(normalizeWhitespace("a\t\n \n b")).toEqual("a\n\nb"); + expect(normalizeWhitespace("a\t\n \n\n \n b")).toEqual("a\n\nb"); + expect(normalizeWhitespace("a b")).toEqual("a b"); + }); + it("Space is trimmed from paragraphs", async () => { + const cases = [ + { inStr: "

a

", outStr: "

a

" }, + { inStr: "

a

", outStr: "

a

" }, + { inStr: "

a\n

", outStr: "

a

" }, + { inStr: "

a\n \n

", outStr: "

a

" }, + ]; + for (const { inStr, outStr } of cases) { + const prettyPrinted = await prettyPrint(inStr, { + doenetSyntax: false, + printWidth: 30, + }); + expect(prettyPrinted).toEqual(outStr); + } + }); + it("Paragraphs show up on their own line", async () => { + const cases = [ + { inStr: "

a

b

", outStr: "

a

\n

b

" }, + ]; + for (const { inStr, outStr } of cases) { + const prettyPrinted = await prettyPrint(inStr, { + doenetSyntax: false, + printWidth: 30, + }); + expect(prettyPrinted).toEqual(outStr); + } + }); + it("Double newlines are preserved but single newlines are turned into a space", async () => { + const cases = [ + { inStr: "a\nb", outStr: "a b" }, + { inStr: "a\n b", outStr: "a b" }, + { inStr: "a \n b", outStr: "a b" }, + { inStr: "a \n \n b", outStr: "a\n\nb" }, + ]; + for (const { inStr, outStr } of cases) { + const prettyPrinted = await prettyPrint(inStr, { + doenetSyntax: false, + printWidth: 30, + }); + expect(prettyPrinted).toEqual(outStr); + } + }); + it("Prints function arguments", async () => { + const cases = [ + { inStr: "$$f(x)", outStr: "$$f(x)" }, + { inStr: "$$f(x,y)", outStr: "$$f(x, y)" }, + { inStr: "$$f(x,$y)", outStr: "$$f(x, $y)" }, + { inStr: "$$f(x,$y z)", outStr: "$$f(x, $y z)" }, + { inStr: "$$f((),())", outStr: "$$f((), ())" }, + { inStr: "$$f(x,$$g(y,z))", outStr: "$$f(x, $$g(y, z))" }, + { + inStr: "$$f(x,alpha)", + outStr: "$$f(x, alpha)", + }, + { + inStr: "$$f((x),alpha)", + outStr: "$$f((x), alpha)", + }, + { + inStr: "$$f(x, alpha)", + outStr: "$$f(x, alpha)", + }, + { + inStr: "

$$f(x, alpha)

", + outStr: "

\n $$f(x, alpha)\n

", + }, + ]; + for (const { inStr, outStr } of cases) { + const prettyPrinted = await prettyPrint(inStr, { + doenetSyntax: false, + printWidth: 30, + }); + expect(prettyPrinted).toEqual(outStr); + } + }); + { + // Regular parsing tests + const files = glob + .sync( + new URL("./fragments/*pretty*.doenet", import.meta.url) + .pathname, + ) + .filter((f) => !f.includes("-bad")); + const fileMap: Record = Object.fromEntries( + files.map((f) => [f.split("/").pop(), f]), + ); + + for (const [filename, filepath] of Object.entries(fileMap)) { + it(`${filename} pretty-prints correctly in Xml format and Doenet format`, async () => { + const source = await fs.readFile(filepath, "utf-8"); + const prettyPrinted = await prettyPrint(source, { + doenetSyntax: false, + printWidth: 80, + }); + //origLog(prettyPrinted); + expect(prettyPrinted).toMatchSnapshot(); + }); + } + } + + it("Always breaks children of BREAK_AROUND_ELEMENTS", async () => { + const cases = [ + { + inStr: "", + outStr: "\n \n \n", + }, + ]; + for (const { inStr, outStr } of cases) { + const prettyPrinted = await prettyPrint(inStr, { + doenetSyntax: false, + printWidth: 30, + }); + expect(prettyPrinted).toEqual(outStr); + } + }); +}); diff --git a/packages/parser/test/xml-compat.test.ts b/packages/parser/test/xml-compat.test.ts new file mode 100644 index 000000000..0ca76ed1a --- /dev/null +++ b/packages/parser/test/xml-compat.test.ts @@ -0,0 +1,21 @@ +import { glob } from "glob"; +import { describe, expect, it } from "vitest"; +import * as fs from "node:fs/promises"; +import { parse, showCursor } from "../src/parser"; + +describe("Xml files parse correctly", async () => { + const files = glob.sync( + new URL("./fragments/xml-*.doenet", import.meta.url).pathname, + ).filter((f) => !f.includes("-bad")); + const fileMap: Record = Object.fromEntries( + files.map((f) => [f.split("/").pop(), f]), + ); + + for (const [filename, filepath] of Object.entries(fileMap)) { + it(`${filename} parses correctly`, async () => { + const source = await fs.readFile(filepath, "utf-8"); + const parsed = parse(source); + expect(showCursor(parsed)).toMatchSnapshot(); + }); + } +}); diff --git a/packages/parser/tsconfig.json b/packages/parser/tsconfig.json index f89ffe262..22a330066 100644 --- a/packages/parser/tsconfig.json +++ b/packages/parser/tsconfig.json @@ -4,7 +4,7 @@ "outDir": "./dist/", "rootDir": "./src" }, - "include": ["./**/*.ts", "./**/*.tsx", "./src/generated-assets/*.js"], + "include": ["./**/*.ts", "./**/*.tsx"], "exclude": [ "./**/*.test.ts", "./**/*.stub.ts", diff --git a/packages/parser/vite.config.ts b/packages/parser/vite.config.ts index 31011e4ee..8a9736b15 100644 --- a/packages/parser/vite.config.ts +++ b/packages/parser/vite.config.ts @@ -1,17 +1,68 @@ -import { defineConfig } from "vite"; +import { defineConfig, Plugin } from "vite"; import dts from "vite-plugin-dts"; +import fs from "node:fs/promises"; +import path from "node:path"; +import peg from "peggy"; +import * as esbuild from "esbuild"; // https://vitejs.dev/config/ export default defineConfig({ base: "./", - plugins: [dts({ rollupTypes: true })], + plugins: [dts( + //{ rollupTypes: true } + ), pegjsLoader()], build: { minify: false, sourcemap: true, lib: { - entry: "./src/parser.ts", + entry: "./src/index.ts", fileName: "index", formats: ["es"], }, }, }); + +/** + * Plugin to allow importing peggy/pegjs files directly. + */ +function pegjsLoader(options = {}) { + const svgRegex = /\.peg(js|gy)$/; + + const ret: Plugin = { + name: "pegjs-loader", + enforce: "pre", + + async load(filePath) { + if (!filePath.match(svgRegex)) { + return; + } + const source = await fs.readFile(filePath, "utf-8"); + const filename = path.relative(process.cwd(), filePath); + + const defaultOptions: Record = { + output: "source", + format: "bare", + ...options, + }; + if (filename.match(/latex\.(pegjs|peggy)$/)) { + defaultOptions.allowedStartRules = ["document", "math"]; + } + if (filename.match(/tikz\.(pegjs|peggy)$/)) { + defaultOptions.allowedStartRules = [ + "path_spec", + "foreach_body", + ]; + } + + const contents = peg.generate(source, defaultOptions); + // contents might have some typescript in it, so we transpile the typescript + // away with esbuild. + const { code } = await esbuild.transform( + `export default ${contents}`, + { loader: "ts" }, + ); + return { code }; + }, + }; + return ret; +} diff --git a/packages/standalone/package.json b/packages/standalone/package.json index 903043834..9db7d0e91 100644 --- a/packages/standalone/package.json +++ b/packages/standalone/package.json @@ -24,6 +24,6 @@ }, "dependencies": {}, "devDependencies": { - "vite": "^4.3.9" + "vite": "^4.5.0" } } diff --git a/packages/static-assets/package.json b/packages/static-assets/package.json index 5ad194a5f..513ba08bd 100644 --- a/packages/static-assets/package.json +++ b/packages/static-assets/package.json @@ -13,6 +13,9 @@ "exports": { ".": { "import": "./dist/index.js" + }, + "./*json": { + "import": "./dist/generated/*json" } }, "scripts": { diff --git a/packages/test-viewer/package.json b/packages/test-viewer/package.json index e774e1034..3b2c921f6 100644 --- a/packages/test-viewer/package.json +++ b/packages/test-viewer/package.json @@ -21,8 +21,7 @@ "react-dom": "^18.2.0", "styled-components": "^5.3.11" }, - "dependencies": {}, "devDependencies": { - "vite": "^4.3.9" + "vite": "^4.5.0" } } diff --git a/packages/test-viewer/src/test/testCode.doenet b/packages/test-viewer/src/test/testCode.doenet index b5902c9fd..0ade7e4ad 100644 --- a/packages/test-viewer/src/test/testCode.doenet +++ b/packages/test-viewer/src/test/testCode.doenet @@ -1,11 +1,11 @@ -

Use this to test DoenetML

- + +

Use this to a < btest DoenetML

- - + + - - - - - + + + +
+ diff --git a/packages/virtual-keyboard/package.json b/packages/virtual-keyboard/package.json index da0f07b92..4729c4928 100644 --- a/packages/virtual-keyboard/package.json +++ b/packages/virtual-keyboard/package.json @@ -34,7 +34,7 @@ "react-icons": "^4.9.0" }, "devDependencies": { - "vite": "^4.4.9", - "vite-plugin-dts": "^3.5.2" + "vite": "^4.5.0", + "vite-plugin-dts": "^3.6.0" } }