diff --git a/builder/Cargo.lock b/builder/Cargo.lock index dde4e734..71b05e93 100644 --- a/builder/Cargo.lock +++ b/builder/Cargo.lock @@ -324,9 +324,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.93" +version = "2.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058" +checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" dependencies = [ "proc-macro2", "quote", diff --git a/client/package-lock.json b/client/package-lock.json index 54e95078..724d767b 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1,12 +1,12 @@ { "name": "codechat-editor-client", - "version": "0.1.6", + "version": "0.1.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codechat-editor-client", - "version": "0.1.6", + "version": "0.1.7", "license": "GPL-3.0-or-later", "dependencies": { "@codemirror/lang-cpp": "^6", @@ -1480,9 +1480,9 @@ "license": "MIT" }, "node_modules/@types/d3-shape": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", - "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", "license": "MIT", "dependencies": { "@types/d3-path": "*" @@ -1574,9 +1574,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "version": "22.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.5.tgz", + "integrity": "sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1591,21 +1591,21 @@ "optional": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.2.tgz", - "integrity": "sha512-adig4SzPLjeQ0Tm+jvsozSGiCliI2ajeURDGHjZ2llnA+A67HihCQ+a3amtPhUakd1GlwHxSRvzOZktbEvhPPg==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.1.tgz", + "integrity": "sha512-tJzcVyvvb9h/PB96g30MpxACd9IrunT7GF9wfA9/0TJ1LxGOJx1TdPzSbBBnNED7K9Ka8ybJsnEpiXPktolTLg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.18.2", - "@typescript-eslint/type-utils": "8.18.2", - "@typescript-eslint/utils": "8.18.2", - "@typescript-eslint/visitor-keys": "8.18.2", + "@typescript-eslint/scope-manager": "8.19.1", + "@typescript-eslint/type-utils": "8.19.1", + "@typescript-eslint/utils": "8.19.1", + "@typescript-eslint/visitor-keys": "8.19.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1621,16 +1621,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.18.2.tgz", - "integrity": "sha512-y7tcq4StgxQD4mDr9+Jb26dZ+HTZ/SkfqpXSiqeUXZHxOUyjWDKsmwKhJ0/tApR08DgOhrFAoAhyB80/p3ViuA==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.19.1.tgz", + "integrity": "sha512-67gbfv8rAwawjYx3fYArwldTQKoYfezNUT4D5ioWetr/xCrxXxvleo3uuiFuKfejipvq+og7mjz3b0G2bVyUCw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.18.2", - "@typescript-eslint/types": "8.18.2", - "@typescript-eslint/typescript-estree": "8.18.2", - "@typescript-eslint/visitor-keys": "8.18.2", + "@typescript-eslint/scope-manager": "8.19.1", + "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/typescript-estree": "8.19.1", + "@typescript-eslint/visitor-keys": "8.19.1", "debug": "^4.3.4" }, "engines": { @@ -1646,14 +1646,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.2.tgz", - "integrity": "sha512-YJFSfbd0CJjy14r/EvWapYgV4R5CHzptssoag2M7y3Ra7XNta6GPAJPPP5KGB9j14viYXyrzRO5GkX7CRfo8/g==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.19.1.tgz", + "integrity": "sha512-60L9KIuN/xgmsINzonOcMDSB8p82h95hoBfSBtXuO4jlR1R9L1xSkmVZKgCPVfavDlXihh4ARNjXhh1gGnLC7Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.2", - "@typescript-eslint/visitor-keys": "8.18.2" + "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/visitor-keys": "8.19.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1664,16 +1664,16 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.2.tgz", - "integrity": "sha512-AB/Wr1Lz31bzHfGm/jgbFR0VB0SML/hd2P1yxzKDM48YmP7vbyJNHRExUE/wZsQj2wUCvbWH8poNHFuxLqCTnA==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.19.1.tgz", + "integrity": "sha512-Rp7k9lhDKBMRJB/nM9Ksp1zs4796wVNyihG9/TU9R6KCJDNkQbc2EOKjrBtLYh3396ZdpXLtr/MkaSEmNMtykw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.18.2", - "@typescript-eslint/utils": "8.18.2", + "@typescript-eslint/typescript-estree": "8.19.1", + "@typescript-eslint/utils": "8.19.1", "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1688,9 +1688,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.2.tgz", - "integrity": "sha512-Z/zblEPp8cIvmEn6+tPDIHUbRu/0z5lqZ+NvolL5SvXWT5rQy7+Nch83M0++XzO0XrWRFWECgOAyE8bsJTl1GQ==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.1.tgz", + "integrity": "sha512-JBVHMLj7B1K1v1051ZaMMgLW4Q/jre5qGK0Ew6UgXz1Rqh+/xPzV1aW581OM00X6iOfyr1be+QyW8LOUf19BbA==", "dev": true, "license": "MIT", "engines": { @@ -1702,20 +1702,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.2.tgz", - "integrity": "sha512-WXAVt595HjpmlfH4crSdM/1bcsqh+1weFRWIa9XMTx/XHZ9TCKMcr725tLYqWOgzKdeDrqVHxFotrvWcEsk2Tg==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.1.tgz", + "integrity": "sha512-jk/TZwSMJlxlNnqhy0Eod1PNEvCkpY6MXOXE/WLlblZ6ibb32i2We4uByoKPv1d0OD2xebDv4hbs3fm11SMw8Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.2", - "@typescript-eslint/visitor-keys": "8.18.2", + "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/visitor-keys": "8.19.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1729,16 +1729,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.2.tgz", - "integrity": "sha512-Cr4A0H7DtVIPkauj4sTSXVl+VBWewE9/o40KcF3TV9aqDEOWoXF3/+oRXNby3DYzZeCATvbdksYsGZzplwnK/Q==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.19.1.tgz", + "integrity": "sha512-IxG5gLO0Ne+KaUc8iW1A+XuKLd63o4wlbI1Zp692n1xojCl/THvgIKXJXBZixTh5dd5+yTJ/VXH7GJaaw21qXA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.18.2", - "@typescript-eslint/types": "8.18.2", - "@typescript-eslint/typescript-estree": "8.18.2" + "@typescript-eslint/scope-manager": "8.19.1", + "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/typescript-estree": "8.19.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1753,13 +1753,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.2.tgz", - "integrity": "sha512-zORcwn4C3trOWiCqFQP1x6G3xTRyZ1LYydnj51cRnJ6hxBlr/cKPckk+PKPUw/fXmvfKTcw7bwY3w9izgx5jZw==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.1.tgz", + "integrity": "sha512-fzmjU8CHK853V/avYZAvuVut3ZTfwN5YtMaoi+X9Y9MA9keaWNHC3zEQ9zvyX/7Hj+5JkNyK1l7TOR2hevHB6Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.2", + "@typescript-eslint/types": "8.19.1", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -2922,9 +2922,9 @@ } }, "node_modules/es-abstract": { - "version": "1.23.8", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.8.tgz", - "integrity": "sha512-lfab8IzDn6EpI1ibZakcgS6WsfEBiB+43cuJo+wgylx1xKXf+Sp+YR3vFuQwC/u3sxYwV8Cxe3B0DpVUu/WiJQ==", + "version": "1.23.9", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", + "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", "dev": true, "license": "MIT", "dependencies": { @@ -2939,10 +2939,11 @@ "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", + "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.2.6", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.0", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", @@ -2963,11 +2964,12 @@ "object-inspect": "^1.13.3", "object-keys": "^1.1.1", "object.assign": "^4.1.7", - "own-keys": "^1.0.0", + "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.3", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", @@ -3019,15 +3021,16 @@ } }, "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.4", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -3506,9 +3509,9 @@ "license": "Apache-2.0" }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "license": "MIT", "dependencies": { @@ -3516,7 +3519,7 @@ "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -3675,22 +3678,22 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", - "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", - "dunder-proto": "^1.0.0", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", + "get-proto": "^1.0.0", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "math-intrinsics": "^1.0.0" + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -3699,6 +3702,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-symbol-description": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", @@ -3981,13 +3998,16 @@ } }, "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.0.tgz", + "integrity": "sha512-GExz9MtyhlZyXYLxzlJRj5WUCE661zhDa1Yna52CN57AJsymh+DvXXjyveSioqSRdxvUrdKdvqB1b5cVKsNpWQ==", "dev": true, "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -4120,13 +4140,16 @@ } }, "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", "dev": true, "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -4786,9 +4809,9 @@ } }, "node_modules/own-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.0.tgz", - "integrity": "sha512-HcuIjzpjrUbqZPGzWHVg95Bc2Y37KoY5n66QQyEGMzrIWVKHsgHcv8/Aq5Cu3qFUQJzMSPVP8MD3oaFoaME1lg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", "dev": true, "license": "MIT", "dependencies": { @@ -5024,19 +5047,19 @@ "license": "MIT" }, "node_modules/reflect.getprototypeof": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.9.tgz", - "integrity": "sha512-r0Ay04Snci87djAsI4U+WNRcSw5S4pOH7qFjd/veA5gC7TbqESR3tcj28ia95L/fYUDw11JKP7uqUKUAfVvV5Q==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "dunder-proto": "^1.0.1", - "es-abstract": "^1.23.6", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "gopd": "^1.2.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" }, "engines": { @@ -5047,15 +5070,17 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", - "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", "set-function-name": "^2.0.2" }, "engines": { @@ -5274,6 +5299,21 @@ "node": ">= 0.4" } }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5536,16 +5576,16 @@ } }, "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", + "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/ts-dedent": { diff --git a/client/package.json b/client/package.json index 7b047c37..3cbb71e7 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "codechat-editor-client", - "version": "0.1.6", + "version": "0.1.7", "description": "The CodeChat Editor Client, part of a web-based literate programming editor (the CodeChat Editor).", "homepage": "https://github.com/bjones1/CodeChat_Editor", "type": "module", diff --git a/docs/changelog.md b/docs/changelog.md index 533f8385..e97a2fe2 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -19,7 +19,8 @@ CodeChat Editor. If not, see # Changelog - [Github master](https://github.com/bjones1/CodeChat_Editor): - - No changes. + - Fixed hyperlink navigation. + - Fixed case-insensitive filename handling bugs. - v0.1.6, 2024-Dec-29: - Improvements to the build tool. - Corrections to the C parser. diff --git a/extensions/VSCode/package-lock.json b/extensions/VSCode/package-lock.json index 3e720dfd..d0cae9af 100644 --- a/extensions/VSCode/package-lock.json +++ b/extensions/VSCode/package-lock.json @@ -1,12 +1,12 @@ { "name": "codechat-editor-client", - "version": "0.1.6", + "version": "0.1.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codechat-editor-client", - "version": "0.1.6", + "version": "0.1.7", "license": "GPL-3.0-only", "dependencies": { "escape-html": "^1", @@ -461,9 +461,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "version": "22.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.5.tgz", + "integrity": "sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==", "dev": true, "license": "MIT", "dependencies": { @@ -488,21 +488,21 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.2.tgz", - "integrity": "sha512-adig4SzPLjeQ0Tm+jvsozSGiCliI2ajeURDGHjZ2llnA+A67HihCQ+a3amtPhUakd1GlwHxSRvzOZktbEvhPPg==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.1.tgz", + "integrity": "sha512-tJzcVyvvb9h/PB96g30MpxACd9IrunT7GF9wfA9/0TJ1LxGOJx1TdPzSbBBnNED7K9Ka8ybJsnEpiXPktolTLg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.18.2", - "@typescript-eslint/type-utils": "8.18.2", - "@typescript-eslint/utils": "8.18.2", - "@typescript-eslint/visitor-keys": "8.18.2", + "@typescript-eslint/scope-manager": "8.19.1", + "@typescript-eslint/type-utils": "8.19.1", + "@typescript-eslint/utils": "8.19.1", + "@typescript-eslint/visitor-keys": "8.19.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -518,16 +518,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.18.2.tgz", - "integrity": "sha512-y7tcq4StgxQD4mDr9+Jb26dZ+HTZ/SkfqpXSiqeUXZHxOUyjWDKsmwKhJ0/tApR08DgOhrFAoAhyB80/p3ViuA==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.19.1.tgz", + "integrity": "sha512-67gbfv8rAwawjYx3fYArwldTQKoYfezNUT4D5ioWetr/xCrxXxvleo3uuiFuKfejipvq+og7mjz3b0G2bVyUCw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.18.2", - "@typescript-eslint/types": "8.18.2", - "@typescript-eslint/typescript-estree": "8.18.2", - "@typescript-eslint/visitor-keys": "8.18.2", + "@typescript-eslint/scope-manager": "8.19.1", + "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/typescript-estree": "8.19.1", + "@typescript-eslint/visitor-keys": "8.19.1", "debug": "^4.3.4" }, "engines": { @@ -543,14 +543,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.2.tgz", - "integrity": "sha512-YJFSfbd0CJjy14r/EvWapYgV4R5CHzptssoag2M7y3Ra7XNta6GPAJPPP5KGB9j14viYXyrzRO5GkX7CRfo8/g==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.19.1.tgz", + "integrity": "sha512-60L9KIuN/xgmsINzonOcMDSB8p82h95hoBfSBtXuO4jlR1R9L1xSkmVZKgCPVfavDlXihh4ARNjXhh1gGnLC7Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.2", - "@typescript-eslint/visitor-keys": "8.18.2" + "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/visitor-keys": "8.19.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -561,16 +561,16 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.2.tgz", - "integrity": "sha512-AB/Wr1Lz31bzHfGm/jgbFR0VB0SML/hd2P1yxzKDM48YmP7vbyJNHRExUE/wZsQj2wUCvbWH8poNHFuxLqCTnA==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.19.1.tgz", + "integrity": "sha512-Rp7k9lhDKBMRJB/nM9Ksp1zs4796wVNyihG9/TU9R6KCJDNkQbc2EOKjrBtLYh3396ZdpXLtr/MkaSEmNMtykw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.18.2", - "@typescript-eslint/utils": "8.18.2", + "@typescript-eslint/typescript-estree": "8.19.1", + "@typescript-eslint/utils": "8.19.1", "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -585,9 +585,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.2.tgz", - "integrity": "sha512-Z/zblEPp8cIvmEn6+tPDIHUbRu/0z5lqZ+NvolL5SvXWT5rQy7+Nch83M0++XzO0XrWRFWECgOAyE8bsJTl1GQ==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.1.tgz", + "integrity": "sha512-JBVHMLj7B1K1v1051ZaMMgLW4Q/jre5qGK0Ew6UgXz1Rqh+/xPzV1aW581OM00X6iOfyr1be+QyW8LOUf19BbA==", "dev": true, "license": "MIT", "engines": { @@ -599,20 +599,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.2.tgz", - "integrity": "sha512-WXAVt595HjpmlfH4crSdM/1bcsqh+1weFRWIa9XMTx/XHZ9TCKMcr725tLYqWOgzKdeDrqVHxFotrvWcEsk2Tg==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.1.tgz", + "integrity": "sha512-jk/TZwSMJlxlNnqhy0Eod1PNEvCkpY6MXOXE/WLlblZ6ibb32i2We4uByoKPv1d0OD2xebDv4hbs3fm11SMw8Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.2", - "@typescript-eslint/visitor-keys": "8.18.2", + "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/visitor-keys": "8.19.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -626,16 +626,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.2.tgz", - "integrity": "sha512-Cr4A0H7DtVIPkauj4sTSXVl+VBWewE9/o40KcF3TV9aqDEOWoXF3/+oRXNby3DYzZeCATvbdksYsGZzplwnK/Q==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.19.1.tgz", + "integrity": "sha512-IxG5gLO0Ne+KaUc8iW1A+XuKLd63o4wlbI1Zp692n1xojCl/THvgIKXJXBZixTh5dd5+yTJ/VXH7GJaaw21qXA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.18.2", - "@typescript-eslint/types": "8.18.2", - "@typescript-eslint/typescript-estree": "8.18.2" + "@typescript-eslint/scope-manager": "8.19.1", + "@typescript-eslint/types": "8.19.1", + "@typescript-eslint/typescript-estree": "8.19.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -650,13 +650,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.18.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.2.tgz", - "integrity": "sha512-zORcwn4C3trOWiCqFQP1x6G3xTRyZ1LYydnj51cRnJ6hxBlr/cKPckk+PKPUw/fXmvfKTcw7bwY3w9izgx5jZw==", + "version": "8.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.1.tgz", + "integrity": "sha512-fzmjU8CHK853V/avYZAvuVut3ZTfwN5YtMaoi+X9Y9MA9keaWNHC3zEQ9zvyX/7Hj+5JkNyK1l7TOR2hevHB6Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.2", + "@typescript-eslint/types": "8.19.1", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -1753,9 +1753,9 @@ } }, "node_modules/domutils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.1.tgz", - "integrity": "sha512-xWXmuRnN9OMP6ptPd2+H0cCbcYBULa5YDTbMm/2lvkWvNA3O4wcW+GvzooqBuNM8yy6pl3VIAeJTUUWUbfI5Fw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -1845,9 +1845,9 @@ } }, "node_modules/es-abstract": { - "version": "1.23.8", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.8.tgz", - "integrity": "sha512-lfab8IzDn6EpI1ibZakcgS6WsfEBiB+43cuJo+wgylx1xKXf+Sp+YR3vFuQwC/u3sxYwV8Cxe3B0DpVUu/WiJQ==", + "version": "1.23.9", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", + "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", "dev": true, "license": "MIT", "dependencies": { @@ -1862,10 +1862,11 @@ "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", + "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.2.6", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.0", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", @@ -1886,11 +1887,12 @@ "object-inspect": "^1.13.3", "object-keys": "^1.1.1", "object.assign": "^4.1.7", - "own-keys": "^1.0.0", + "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.3", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", @@ -1942,15 +1944,16 @@ } }, "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.4", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -2691,9 +2694,9 @@ "license": "MIT" }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "license": "MIT", "dependencies": { @@ -2701,7 +2704,7 @@ "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -2939,22 +2942,22 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", - "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", - "dunder-proto": "^1.0.0", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", + "get-proto": "^1.0.0", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "math-intrinsics": "^1.0.0" + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -2963,6 +2966,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-symbol-description": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", @@ -3397,13 +3414,16 @@ } }, "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.0.tgz", + "integrity": "sha512-GExz9MtyhlZyXYLxzlJRj5WUCE661zhDa1Yna52CN57AJsymh+DvXXjyveSioqSRdxvUrdKdvqB1b5cVKsNpWQ==", "dev": true, "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -3592,13 +3612,16 @@ } }, "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", "dev": true, "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -4533,9 +4556,9 @@ } }, "node_modules/own-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.0.tgz", - "integrity": "sha512-HcuIjzpjrUbqZPGzWHVg95Bc2Y37KoY5n66QQyEGMzrIWVKHsgHcv8/Aq5Cu3qFUQJzMSPVP8MD3oaFoaME1lg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", "dev": true, "license": "MIT", "dependencies": { @@ -4921,19 +4944,19 @@ } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.9.tgz", - "integrity": "sha512-r0Ay04Snci87djAsI4U+WNRcSw5S4pOH7qFjd/veA5gC7TbqESR3tcj28ia95L/fYUDw11JKP7uqUKUAfVvV5Q==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "dunder-proto": "^1.0.1", - "es-abstract": "^1.23.6", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "gopd": "^1.2.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" }, "engines": { @@ -4944,15 +4967,17 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", - "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", "set-function-name": "^2.0.2" }, "engines": { @@ -5252,6 +5277,21 @@ "node": ">= 0.4" } }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5703,16 +5743,16 @@ } }, "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz", + "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/tsconfig-paths": { diff --git a/extensions/VSCode/package.json b/extensions/VSCode/package.json index 752f0415..9470f12c 100644 --- a/extensions/VSCode/package.json +++ b/extensions/VSCode/package.json @@ -1,6 +1,6 @@ { "name": "codechat-editor-client", - "version": "0.1.6", + "version": "0.1.7", "publisher": "CodeChat", "engines": { "vscode": "^1.61.0" diff --git a/extensions/VSCode/src/extension.ts b/extensions/VSCode/src/extension.ts index b76c0656..3913d19b 100644 --- a/extensions/VSCode/src/extension.ts +++ b/extensions/VSCode/src/extension.ts @@ -25,6 +25,7 @@ // ### Node.js packages import assert from "assert"; import child_process from "node:child_process"; +import process from "node:process"; // ### Third-party packages import escape from "escape-html"; @@ -45,6 +46,9 @@ const MAX_MESSAGE_LENGTH = 200; // The timeout for a websocket `Response`. const RESPONSE_TIMEOUT = 15000; +// True on Windows, false on OS X / Linux. +const is_windows = process.platform === "win32"; + // These globals are truly global: only one is needed for this entire plugin. let websocket: WebSocket | undefined; // Where the webclient resides: `html` for a webview panel embedded in VSCode; @@ -395,7 +399,9 @@ export const activate = (context: vscode.ExtensionContext) => { case "Update": { const current_update = value as UpdateMessageContents; - const doc = get_document(current_update.file_path); + const doc = get_document( + current_update.file_path + ); if (doc === undefined) { send_result(id, { Err: "No open document for this file.", @@ -457,7 +463,7 @@ export const activate = (context: vscode.ExtensionContext) => { // Report if this was an error. const result_contents = value as MessageResult; if ("Err" in result_contents) { - const msg = `Error in message ${id}: ${result_contents.Err}.`; + const msg = `Error in message ${id}: ${result_contents.Err}`; console.log(msg); // Warning: Calling `show_error` shuts down // the client. Do this deliberately, since @@ -473,7 +479,8 @@ export const activate = (context: vscode.ExtensionContext) => { // Look through all open documents to see if we // have the requested file. const doc = get_document(load_file); - const load_file_result = doc === undefined ? null : doc.getText(); + const load_file_result = + doc === undefined ? null : doc.getText(); send_result(id, { Ok: { LoadFile: load_file_result, @@ -511,7 +518,7 @@ export const activate = (context: vscode.ExtensionContext) => { } ) ); -} +}; // On deactivation, close everything down. export const deactivate = async () => { @@ -519,7 +526,7 @@ export const deactivate = async () => { await stop_client(); webview_panel?.dispose(); console.log("CodeChat extension: deactivated."); -} +}; // ## Supporting functions // @@ -606,18 +613,16 @@ const start_render = () => { } }, 300); } -} +}; const current_file = () => { // Only send a new current file is there's a change. const ate = vscode.window.activeTextEditor; if (can_render() && ate !== current_editor) { current_editor = ate; - send_message( - { - CurrentFile: ate!.document.fileName, - }, - ); + send_message({ + CurrentFile: ate!.document.fileName, + }); } }; @@ -648,7 +653,7 @@ const stop_client = async () => { ); } current_editor = undefined; -} +}; // Provide an error message in the panel if possible. const show_error = (message: string) => { @@ -667,7 +672,7 @@ const show_error = (message: string) => { message + "\nSee https://github.com/bjones1/CodeChat_Editor." ); } -} +}; // Only render if the window and editor are active, we have a valid render // client, and the webview is visible. @@ -676,14 +681,33 @@ const can_render = () => { vscode.window.activeTextEditor !== undefined && websocket !== undefined && (codechat_client_location === CodeChatEditorClientLocation.browser || - (webview_panel !== undefined)) + webview_panel !== undefined) ); -} +}; const get_document = (file_path: string) => { // Look through all open documents to see if we have the requested file. for (const doc of vscode.workspace.textDocuments) { - if (doc.fileName === file_path) { + // Make the possibly incorrect assumption that only Windows filesystems + // are case-insensitive; I don't know how to easily determine the + // case-sensitivity of the current filesystem without extra probing code + // (write a file in mixed case, try to open it in another mixed case.) + // Per + // [How to Work with Different Filesystems](https://nodejs.org/en/learn/manipulating-files/working-with-different-filesystems#filesystem-behavior), + // "Be wary of inferring filesystem behavior from `process.platform`. + // For example, do not assume that because your program is running on + // Darwin that you are therefore working on a case-insensitive + // filesystem (HFS+), as the user may be using a case-sensitive + // filesystem (HFSX)." + // + // The same article + // [recommends](https://nodejs.org/en/learn/manipulating-files/working-with-different-filesystems#be-prepared-for-slight-differences-in-comparison-functions) + // using `toUpperCase` for case-insensitive filename comparisons. + if ( + (!is_windows && doc.fileName === file_path) || + (is_windows && + doc.fileName.toUpperCase() === file_path.toUpperCase()) + ) { return doc; } } @@ -755,4 +779,4 @@ const run_server = (args: string[]) => { stderr += chunk.toString(); }); }); -} +}; diff --git a/server/Cargo.lock b/server/Cargo.lock index 1942e90c..9c15993e 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -88,7 +88,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.93", + "syn 2.0.95", ] [[package]] @@ -206,7 +206,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", ] [[package]] @@ -390,13 +390,13 @@ checksum = "0082388b8564898f945b04215e800e800a164af15307d8dfe714b02cc69356e9" [[package]] name = "async-trait" -version = "0.1.83" +version = "0.1.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", ] [[package]] @@ -470,9 +470,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.11.1" +version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786a307d683a5bf92e6fd5fd69a7eb613751668d1d8d67d802846dfe367c62c8" +checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" dependencies = [ "memchr", "regex-automata", @@ -511,9 +511,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.6" +version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333" +checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" dependencies = [ "jobserver", "libc", @@ -571,7 +571,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", ] [[package]] @@ -582,7 +582,7 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "codechat-editor-server" -version = "0.1.6" +version = "0.1.7" dependencies = [ "actix-files", "actix-http", @@ -747,7 +747,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.93", + "syn 2.0.95", ] [[package]] @@ -781,7 +781,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", ] [[package]] @@ -921,7 +921,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", ] [[package]] @@ -1226,7 +1226,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", ] [[package]] @@ -1639,9 +1639,9 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "open" -version = "5.3.1" +version = "5.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ecd52f0b8d15c40ce4820aa251ed5de032e5d91fab27f7db2f40d42a8bdf69c" +checksum = "e2483562e62ea94312f3576a7aca397306df7990b8d89033e18766744377ef95" dependencies = [ "is-wsl", "libc", @@ -1735,7 +1735,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", ] [[package]] @@ -1751,27 +1751,27 @@ dependencies = [ [[package]] name = "phf" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_shared", ] [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", ] [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -2052,14 +2052,14 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", ] [[package]] name = "serde_json" -version = "1.0.134" +version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ "itoa", "memchr", @@ -2131,9 +2131,9 @@ dependencies = [ [[package]] name = "siphasher" -version = "0.3.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" @@ -2202,9 +2202,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.93" +version = "2.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058" +checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" dependencies = [ "proc-macro2", "quote", @@ -2219,17 +2219,18 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", ] [[package]] name = "tempfile" -version = "3.14.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" dependencies = [ "cfg-if", "fastrand", + "getrandom", "once_cell", "rustix", "windows-sys 0.59.0", @@ -2267,7 +2268,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", ] [[package]] @@ -2278,7 +2279,7 @@ checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", ] [[package]] @@ -2373,7 +2374,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", ] [[package]] @@ -2639,7 +2640,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", "wasm-bindgen-shared", ] @@ -2661,7 +2662,7 @@ checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2883,7 +2884,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", "synstructure", ] @@ -2905,7 +2906,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", ] [[package]] @@ -2925,7 +2926,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", "synstructure", ] @@ -2948,7 +2949,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.93", + "syn 2.0.95", ] [[package]] diff --git a/server/Cargo.toml b/server/Cargo.toml index a39c2049..9657819c 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -29,7 +29,7 @@ license = "GPL-3.0-only" name = "codechat-editor-server" readme = "../README.md" repository = "https://github.com/bjones1/CodeChat_Editor" -version = "0.1.6" +version = "0.1.7" # This library allows other packages to use core CodeChat Editor features. [lib] diff --git a/server/src/main.rs b/server/src/main.rs index f68394b9..c7bd3e00 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -20,7 +20,7 @@ use std::{ env, io::Read, - process::{Command, Stdio}, + process::{Child, Command, Stdio}, time::SystemTime, }; @@ -93,41 +93,8 @@ impl Cli { webserver::main(self.port).unwrap(); } Commands::Start => { - println!("Starting server in background..."); - let current_exe = match env::current_exe() { - Ok(exe) => exe, - Err(e) => return Err(format!("Failed to get current executable: {e}").into()), - }; - #[cfg(not(debug_assertions))] - let mut cmd = Command::new(¤t_exe); - #[cfg(debug_assertions)] - let mut cmd; - #[cfg(debug_assertions)] - match self.test_mode { - None => cmd = Command::new(¤t_exe), - Some(TestMode::NotFound) => cmd = Command::new("nonexistent-command"), - Some(TestMode::Sleep) => { - cmd = Command::new(¤t_exe); - cmd.args(["--test-mode", "sleep"]); - } - } - let mut process = match cmd - .args(["--port", &self.port.to_string(), "serve", "--log", "off"]) - // Subtle: the default of `stdout(Stdio::inherit())` causes - // a parent process to block, since the child process - // inherits the parent's stdout. So, use the pipes to avoid - // blocking. - .stdin(Stdio::null()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn() - { - Ok(process) => process, - Err(e) => { - return Err(format!("Failed to start server: {e}").into()); - } - }; // Poll the server to ensure it starts. + let mut process: Option = None; let now = SystemTime::now(); loop { // Look for a ping/pong response from the server. @@ -152,22 +119,68 @@ impl Cli { } } - // Check if the server has exited or failed to start. - match process.try_wait() { - Ok(Some(status)) => { - let mut stdout_buf = String::new(); - let mut stderr_buf = String::new(); - let stdout = process.stdout.as_mut().unwrap(); - let stderr = process.stderr.as_mut().unwrap(); - stdout.read_to_string(&mut stdout_buf).unwrap(); - stderr.read_to_string(&mut stderr_buf).unwrap(); - return Err(format!( - "Server failed to start: {status:?}\n{stdout_buf}\n{stderr_buf}" - ) - .into()); + match process { + // If the process isn't started, then do so. We wait to here to start the process, in case the server was already running; in this case, the ping above will see the running server then exit. + None => { + println!("Starting server in background..."); + let current_exe = match env::current_exe() { + Ok(exe) => exe, + Err(e) => { + return Err( + format!("Failed to get current executable: {e}").into() + ) + } + }; + #[cfg(not(debug_assertions))] + let mut cmd = Command::new(¤t_exe); + #[cfg(debug_assertions)] + let mut cmd; + #[cfg(debug_assertions)] + match self.test_mode { + None => cmd = Command::new(¤t_exe), + Some(TestMode::NotFound) => { + cmd = Command::new("nonexistent-command") + } + Some(TestMode::Sleep) => { + cmd = Command::new(¤t_exe); + cmd.args(["--test-mode", "sleep"]); + } + } + process = match cmd + .args(["--port", &self.port.to_string(), "serve", "--log", "off"]) + // Subtle: the default of `stdout(Stdio::inherit())` causes + // a parent process to block, since the child process + // inherits the parent's stdout. So, use the pipes to avoid + // blocking. + .stdin(Stdio::null()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + { + Ok(process) => Some(process), + Err(e) => { + return Err(format!("Failed to start server: {e}").into()); + } + }; } - Ok(None) => {} - Err(e) => return Err(format!("Error starting server: {e}").into()), + + // Check if the server has exited or failed to start. + Some(ref mut child) => match child.try_wait() { + Ok(Some(status)) => { + let mut stdout_buf = String::new(); + let mut stderr_buf = String::new(); + let stdout = child.stdout.as_mut().unwrap(); + let stderr = child.stderr.as_mut().unwrap(); + stdout.read_to_string(&mut stdout_buf).unwrap(); + stderr.read_to_string(&mut stderr_buf).unwrap(); + return Err(format!( + "Server failed to start: {status:?}\n{stdout_buf}\n{stderr_buf}" + ) + .into()); + } + Ok(None) => {} + Err(e) => return Err(format!("Error starting server: {e}").into()), + }, } // Wait a bit before trying again. std::thread::sleep(std::time::Duration::from_millis(50)); diff --git a/server/src/webserver.rs b/server/src/webserver.rs index bf6ba49f..56023321 100644 --- a/server/src/webserver.rs +++ b/server/src/webserver.rs @@ -487,16 +487,8 @@ pub async fn filesystem_endpoint( app_state: &web::Data, ) -> HttpResponse { let (connection_id, file_path) = request_path.into_inner(); - let file_path = match PathBuf::from_str(&file_path) { - // For Windows, use `absolute` to switch to Windows path separators. - Ok(v) => match path::absolute(&v) { - Ok(v) => v, - Err(err) => { - let msg = format!("Error: unable to resolve absolute path {file_path}: {err}."); - error!("{msg}"); - return html_not_found(&msg); - } - }, + let file_path = match try_canonicalize(&file_path) { + Ok(v) => v, Err(err) => { let msg = format!("Error: unable to convert path {file_path}: {err}."); error!("{msg}"); @@ -1214,27 +1206,7 @@ fn url_to_path(url_string: &str, expected_prefix: &[&str]) -> Result Err(format!( - "Error: unable to parse file path {path_str_encoded}: {err}." - )), - Ok(path_buf) => match path_buf.canonicalize() { - // [Canonicalize](https://doc.rust-lang.org/stable/std/fs/fn.canonicalize.html#errors) - // fails if the path doesn't exist. For - // unsaved files, this is expected; - // therefore, use - // [absolute](https://doc.rust-lang.org/stable/std/path/fn.absolute.html) - // on error, since it doesn't require the - // path to exist. - Err(_) => match path::absolute(&*path_buf) { - Err(err) => Err(format!( - "Unable to make {path_buf:?} absolute: {err}" - )), - Ok(p) => Ok(p), - }, - Ok(p) => Ok(PathBuf::from(simplified(&p))), - }, - } + try_canonicalize(&path_str) } } } @@ -1243,6 +1215,32 @@ fn url_to_path(url_string: &str, expected_prefix: &[&str]) -> Result Result { + match PathBuf::from_str(file_path) { + Err(err) => Err(format!( + "Error: unable to parse file path {file_path}: {err}." + )), + Ok(path_buf) => match path_buf.canonicalize() { + // [Canonicalize](https://doc.rust-lang.org/stable/std/fs/fn.canonicalize.html#errors) + // fails if the path doesn't exist. For + // unsaved files, this is expected; + // therefore, use + // [absolute](https://doc.rust-lang.org/stable/std/path/fn.absolute.html) + // on error, since it doesn't require the + // path to exist. + Err(_) => match path::absolute(&path_buf) { + Err(err) => Err(format!("Unable to make {path_buf:?} absolute: {err}")), + Ok(p) => Ok(p), + }, + Ok(p) => Ok(PathBuf::from(simplified(&p))), + }, + } +} + // Given a file path, convert it to a URL, encoding as necessary. fn path_to_url(prefix: &str, connection_id: &str, file_path: &Path) -> String { // First, convert the path to use forward slashes. diff --git a/server/src/webserver/vscode.rs b/server/src/webserver/vscode.rs index 1596f66c..687427cf 100644 --- a/server/src/webserver/vscode.rs +++ b/server/src/webserver/vscode.rs @@ -18,11 +18,7 @@ // ## Imports // // ### Standard library -use std::{ - cmp::min, - collections::HashMap, - path::{Path, PathBuf}, -}; +use std::{cmp::min, collections::HashMap, path::PathBuf}; // ### Third-party use actix_web::{ @@ -48,8 +44,8 @@ use crate::{ queue_send, webserver::{ escape_html, filesystem_endpoint, html_wrapper, make_simple_http_response, path_to_url, - text_file_to_response, url_to_path, ProcessingTaskHttpRequest, ResultOkTypes, - UpdateMessageContents, INITIAL_MESSAGE_ID, MESSAGE_ID_INCREMENT, + text_file_to_response, try_canonicalize, url_to_path, ProcessingTaskHttpRequest, + ResultOkTypes, UpdateMessageContents, INITIAL_MESSAGE_ID, MESSAGE_ID_INCREMENT, }, }; @@ -159,16 +155,17 @@ pub async fn vscode_ide_websocket( debug!("VSCode processing task started."); // Get the first message sent by the IDE. - let Some(message): std::option::Option = from_ide_rx.recv().await else { + let Some(first_message): std::option::Option = from_ide_rx.recv().await + else { error!("{}", "IDE websocket received no data."); break 'task; }; // Make sure it's the `Opened` message. - let EditorMessageContents::Opened(ide_type) = message.message else { - let msg = format!("Unexpected message {message:?}"); + let EditorMessageContents::Opened(ide_type) = first_message.message else { + let msg = format!("Unexpected message {first_message:?}"); error!("{msg}"); - send_response(&to_ide_tx, message.id, Err(msg)).await; + send_response(&to_ide_tx, first_message.id, Err(msg)).await; // Send a `Closed` message to shut down the websocket. queue_send!(to_ide_tx.send(EditorMessage { id: 0.0, message: EditorMessageContents::Closed}), 'task); @@ -183,9 +180,9 @@ pub async fn vscode_ide_websocket( // Send a response (successful) to the `Opened` message. debug!( "Sending response = OK to IDE Opened message, id {}.", - message.id + first_message.id ); - send_response(&to_ide_tx, message.id, Ok(ResultOkTypes::Void)).await; + send_response(&to_ide_tx, first_message.id, Ok(ResultOkTypes::Void)).await; // Send the HTML for the internal browser. let port = app_state_task.port; @@ -250,7 +247,7 @@ pub async fn vscode_ide_websocket( )) { let msg = format!("Unable to open web browser: {err}"); error!("{msg}"); - send_response(&to_ide_tx, message.id, Err(msg)).await; + send_response(&to_ide_tx, first_message.id, Err(msg)).await; // Send a `Closed` message. queue_send!(to_ide_tx.send(EditorMessage{ @@ -260,14 +257,14 @@ pub async fn vscode_ide_websocket( break 'task; } // Send a response (successful) to the `Opened` message. - send_response(&to_ide_tx, message.id, Ok(ResultOkTypes::Void)).await; + send_response(&to_ide_tx, first_message.id, Ok(ResultOkTypes::Void)).await; } } _ => { // This is the wrong IDE type. Report then error. let msg = format!("Invalid IDE type: {ide_type:?}"); error!("{msg}"); - send_response(&to_ide_tx, message.id, Err(msg)).await; + send_response(&to_ide_tx, first_message.id, Err(msg)).await; // Close the connection. queue_send!(to_ide_tx.send(EditorMessage { id: 0.0, message: EditorMessageContents::Closed}), 'task); @@ -371,25 +368,40 @@ pub async fn vscode_ide_websocket( // Handle the `Update` message. EditorMessageContents::Update(update) => { - if let Some(contents) = &update.contents { - // Translate the file. - let (translation_results_string, _path_to_toc) = - source_to_codechat_for_web_string(&contents.source.doc, ¤t_file, false); - if let TranslationResultsString::CodeChat(cc) = translation_results_string { - // Send the new contents - debug!("Sending translated contents to Client."); - queue_send!(to_client_tx.send(EditorMessage { - id: ide_message.id, - message: EditorMessageContents::Update(UpdateMessageContents { - file_path: update.file_path, - contents: Some(cc), - cursor_position: None, - scroll_position: None, - }), - })); - } else { - error!("Error translating source to CodeChat."); + // Normalize the provided file name. + let result = match try_canonicalize(&update.file_path) { + Err(err) => Err(err), + Ok(clean_file_path) => { + match &update.contents { + None => Err("TODO: support for updates without contents.".to_string()), + Some(contents) => { + // Translate the file. + let (translation_results_string, _path_to_toc) = + source_to_codechat_for_web_string(&contents.source.doc, ¤t_file, false); + if let TranslationResultsString::CodeChat(cc) = translation_results_string { + // Send the new contents + debug!("Sending translated contents to Client."); + queue_send!(to_client_tx.send(EditorMessage { + id: ide_message.id, + message: EditorMessageContents::Update(UpdateMessageContents { + file_path: clean_file_path.to_str().expect("Since the path started as a string, assume it losslessly translates back to a string.").to_string(), + contents: Some(cc), + cursor_position: None, + scroll_position: None, + }), + })); + Ok(ResultOkTypes::Void) + } else { + Err("Error translating source to CodeChat.".to_string()) + } + } + } } + }; + // If there's an error, then report it; otherwise, the message is passed to the Client, which will provide the result. + if let Err(err) = &result { + error!("{err}"); + send_response(&to_ide_tx, ide_message.id, result).await; } } @@ -397,13 +409,24 @@ pub async fn vscode_ide_websocket( // then pass it to the Client. EditorMessageContents::CurrentFile(file_path) => { debug!("Translating and forwarding it to the Client."); - queue_send!(to_client_tx.send(EditorMessage { - id: ide_message.id, - message: EditorMessageContents::CurrentFile( - path_to_url("/vsc/fs", &connection_id_task, Path::new(&file_path)) - ) - })); - current_file = file_path.into(); + match try_canonicalize(&file_path) { + Ok(clean_file_path) => { + queue_send!(to_client_tx.send(EditorMessage { + id: ide_message.id, + message: EditorMessageContents::CurrentFile( + path_to_url("/vsc/fs", &connection_id_task, &clean_file_path) + ) + })); + current_file = file_path.into(); + } + Err(err) => { + let msg = format!( + "Unable to canonicalize file name {}: {err}", &file_path + ); + error!("{msg}"); + send_response(&to_client_tx, ide_message.id, Err(msg)).await; + } + } } } }, @@ -449,9 +472,9 @@ pub async fn vscode_ide_websocket( if let Err(err) = open::that_detached(&url) { let msg = format!("Unable to open web browser to URL {url}: {err}"); error!("{msg}"); - send_response(&to_client_tx, message.id, Err(msg)).await; + send_response(&to_client_tx, client_message.id, Err(msg)).await; } else { - send_response(&to_client_tx, message.id, Ok(ResultOkTypes::Void)).await; + send_response(&to_client_tx, client_message.id, Ok(ResultOkTypes::Void)).await; } }, @@ -480,15 +503,27 @@ pub async fn vscode_ide_websocket( } }, }; - queue_send!(to_ide_tx.send(EditorMessage { - id: client_message.id, - message: EditorMessageContents::Update(UpdateMessageContents { - file_path: update_message_contents.file_path, - contents: codechat_for_web, - cursor_position: update_message_contents.cursor_position, - scroll_position: update_message_contents.scroll_position, - }) - })); + match try_canonicalize(&update_message_contents.file_path) { + Err(err) => { + let msg = format!( + "Unable to canonicalize file name {}: {err}", &update_message_contents.file_path + ); + error!("{msg}"); + send_response(&to_client_tx, client_message.id, Err(msg)).await; + continue; + } + Ok(clean_file_path) => { + queue_send!(to_ide_tx.send(EditorMessage { + id: client_message.id, + message: EditorMessageContents::Update(UpdateMessageContents { + file_path: clean_file_path.to_str().expect("Since the path started as a string, assume it losslessly translates back to a string.").to_string(), + contents: codechat_for_web, + cursor_position: update_message_contents.cursor_position, + scroll_position: update_message_contents.scroll_position, + }) + })); + } + } }, // Update the current file; translate it to a URL @@ -630,7 +665,7 @@ mod test { use std::{ fs, io::Error, - path::{self, Path, PathBuf, MAIN_SEPARATOR_STR}, + path::{self, Path, PathBuf}, thread, time::{Duration, SystemTime}, }; @@ -638,9 +673,11 @@ mod test { use actix_rt::task::JoinHandle; use assert_fs::TempDir; use assertables::{assert_ends_with, assert_starts_with}; + use dunce::simplified; use futures_util::{SinkExt, StreamExt}; use lazy_static::lazy_static; use minreq; + use path_slash::PathExt; use tokio::{ io::{AsyncRead, AsyncWrite}, net::TcpStream, @@ -892,14 +929,17 @@ mod test { let (temp_dir, test_dir, mut ws_ide, _) = prep_test!(connection_id).await; open_client(&mut ws_ide).await; + let file_path = test_dir.join("none.py"); + let file_path_str = file_path.to_slash().unwrap().to_string(); + // Do this is a thread, since the request generates a message that // requires a response in order to complete. - let test_dir_thread = test_dir.clone(); + let file_path_str_thread = file_path_str.clone(); let join_handle = thread::spawn(move || { assert_eq!( minreq::get(format!( - "http://localhost:8080/vsc/fs/{connection_id}/{}/none.py", - test_dir_thread.to_str().unwrap() + "http://localhost:8080/vsc/fs/{connection_id}/{}", + file_path_str_thread )) .send() .unwrap() @@ -915,10 +955,7 @@ mod test { let msg = cast!(em.message, EditorMessageContents::LoadFile); // Compare these as strings -- we want to ensure the path separator is // correct for the current platform. - assert_eq!( - format!("{}{MAIN_SEPARATOR_STR}none.py", test_dir.to_str().unwrap()), - msg.to_string_lossy() - ); + assert_eq!(file_path.to_string_lossy(), msg.to_string_lossy()); assert_eq!(em.id, 3.0); // Reply to the `LoadFile` message -- the file isn't present. @@ -949,15 +986,13 @@ mod test { open_client(&mut ws_ide).await; // Message ids: IDE - 4->7, Server - 3, Client - 2. - let file_path = format!( - "{}{MAIN_SEPARATOR_STR}only-in-ide.py", - test_dir.to_str().unwrap() - ); + let file_path = test_dir.join("only-in-ide.py"); + let file_path_str = file_path.to_str().unwrap().to_string(); send_message( &mut ws_ide, &EditorMessage { id: 4.0, - message: EditorMessageContents::CurrentFile(file_path.clone()), + message: EditorMessageContents::CurrentFile(file_path_str.clone()), }, ) .await; @@ -990,12 +1025,12 @@ mod test { ); // The Client should send a GET request for this file. - let test_dir_thread = test_dir.clone(); + let file_path_thread = file_path.clone(); let join_handle = thread::spawn(move || { assert_eq!( minreq::get(format!( - "http://localhost:8080/vsc/fs/{connection_id}/{}/only-in-ide.py", - test_dir_thread.to_str().unwrap() + "http://localhost:8080/vsc/fs/{connection_id}/{}", + file_path_thread.to_slash().unwrap() )) .send() .unwrap() @@ -1036,7 +1071,7 @@ mod test { EditorMessage { id: 6.0, message: EditorMessageContents::Update(UpdateMessageContents { - file_path, + file_path: file_path_str.clone(), contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -1092,28 +1127,22 @@ mod test { // translated. // // Message ids: IDE - 4, Server - 3, Client - 2->5. - let file_path = format!("{}/test.py", test_dir.to_str().unwrap()); + let file_path = test_dir.join("test.py"); + let file_path_str = file_path.to_str().unwrap().to_string(); send_message( &mut ws_client, &EditorMessage { id: 2.0, message: EditorMessageContents::CurrentFile(format!( "http://localhost:8080/vsc/fs/{connection_id}/{}", - &file_path + &file_path.to_slash().unwrap() )), }, ) .await; let em = read_message(&mut ws_ide).await; let cf = cast!(em.message, EditorMessageContents::CurrentFile); - assert_eq!( - path::absolute(Path::new(&cf)).unwrap(), - path::absolute(Path::new(&format!( - "{}/test.py", - test_dir.to_str().unwrap() - ))) - .unwrap() - ); + assert_eq!(path::absolute(Path::new(&cf)).unwrap(), file_path); assert_eq!(em.id, 2.0); send_message( @@ -1140,7 +1169,7 @@ mod test { &EditorMessage { id: 4.0, message: EditorMessageContents::Update(UpdateMessageContents { - file_path: file_path.clone(), + file_path: file_path_str.clone(), contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -1161,7 +1190,7 @@ mod test { EditorMessage { id: 4.0, message: EditorMessageContents::Update(UpdateMessageContents { - file_path, + file_path: file_path_str.clone(), contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -1207,11 +1236,11 @@ mod test { #[actix_web::test] async fn test_vscode_ide_websocket6() { let connection_id = "test-connection-id6"; - let (temp_dir, _, mut ws_ide, mut ws_client) = prep_test!(connection_id).await; + let (temp_dir, test_dir, mut ws_ide, mut ws_client) = prep_test!(connection_id).await; open_client(&mut ws_ide).await; // Message ids: IDE - 4, Server - 3, Client - 2->5. - let file_path = "foo.py".to_string(); + let file_path = test_dir.join("foo.py").to_string_lossy().to_string(); send_message( &mut ws_client, &EditorMessage { @@ -1289,14 +1318,15 @@ mod test { open_client(&mut ws_ide).await; // Message ids: IDE - 4, Server - 3, Client - 2->5. - let file_path = format!("{}{MAIN_SEPARATOR_STR}test.py", test_dir.to_str().unwrap()); + let file_path_temp = fs::canonicalize(test_dir.join("test.py")).unwrap(); + let file_path = simplified(&file_path_temp); send_message( &mut ws_client, &EditorMessage { id: 2.0, message: EditorMessageContents::CurrentFile(format!( "http://localhost:8080/vsc/fs/{connection_id}/{}", - &file_path + &file_path.to_slash().unwrap() )), }, ) @@ -1304,14 +1334,7 @@ mod test { let em = read_message(&mut ws_ide).await; let cf = cast!(em.message, EditorMessageContents::CurrentFile); - assert_eq!( - fs::canonicalize(Path::new(&cf)).unwrap(), - fs::canonicalize(Path::new(&format!( - "{}/test.py", - test_dir.to_str().unwrap() - ))) - .unwrap() - ); + assert_eq!(cf, file_path.to_str().unwrap().to_string()); assert_eq!(em.id, 2.0); send_message( @@ -1335,8 +1358,10 @@ mod test { let join_handle = thread::spawn(move || { assert_eq!( minreq::get(format!( - "http://localhost:8080/vsc/fs/{connection_id}/{}/test.py", - test_dir_thread.to_str().unwrap() + "http://localhost:8080/vsc/fs/{connection_id}/{}/{}", + test_dir_thread.to_slash().unwrap(), + // On Windows, send incorrect case for this file; the server should correct it. + if cfg!(windows) { "Test.py" } else { "test.py" } )) .send() .unwrap() @@ -1350,10 +1375,7 @@ mod test { // Message ids: IDE - 4, Server - 3->6, Client - 5. let em = read_message(&mut ws_ide).await; let msg = cast!(em.message, EditorMessageContents::LoadFile); - assert_eq!( - path::absolute(Path::new(&msg)).unwrap(), - path::absolute(format!("{}/test.py", test_dir.to_str().unwrap())).unwrap() - ); + assert_eq!(fs::canonicalize(&msg).unwrap(), file_path_temp); assert_eq!(em.id, 3.0); // Reply to the `LoadFile` message: the IDE doesn't have the file. @@ -1375,7 +1397,7 @@ mod test { EditorMessage { id: 6.0, message: EditorMessageContents::Update(UpdateMessageContents { - file_path, + file_path: file_path.to_str().unwrap().to_string(), contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(),