diff --git a/CHANGELOG.md b/CHANGELOG.md index 39d32d1..6a9197b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,14 @@ Changelog [Github master](https://github.com/bjones1/CodeChat_Editor) -------------------------------------------------------------------------------- -* No changes. +* Re-translate Markdown documents as necessary. This causes math written in the + Client to immediately be rendered, instead of needing to switch to the IDE and + perform an edit. +* Ignore re-translations if the Client contents is dirty; overwrite Client + contents when dirty when an IDE update arrives. This prevents data corruption. +* Correctly mark Client contents as clean after sending an update to the IDE, + instead of waiting until the IDE's response arrives. This prevents cases where + the Client edits didn't update IDE text. Version 0.1.47 -- 2025-Dec-19 -------------------------------------------------------------------------------- @@ -37,7 +44,8 @@ Version 0.1.47 -- 2025-Dec-19 * Prevent editing the `` that wraps math expressions. * Automatically re-sync Client with IDE when out of sync. * Update to latest release of MathJax. -* Add support for [Loci](https://github.com/EdwardALuke/loci) files. +* Add support for + [Loci](https://www.simcenter.msstate.edu/software/luke/loci/index.html) files. Version 0.1.46 -- 2025-Dec-15 -------------------------------------------------------------------------------- diff --git a/builder/Cargo.lock b/builder/Cargo.lock index 7f60f02..92dfebd 100644 --- a/builder/Cargo.lock +++ b/builder/Cargo.lock @@ -274,9 +274,9 @@ checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "f59e70c4aef1e55797c2e8fd94a4f2a973fc972cfde0e0b05f683667b0cd39dd" [[package]] name = "portable-atomic-util" diff --git a/client/package.json5 b/client/package.json5 index 90b2382..8370d08 100644 --- a/client/package.json5 +++ b/client/package.json5 @@ -60,7 +60,7 @@ '@codemirror/lang-sql': '^6.10.0', '@codemirror/lang-xml': '^6.1.0', '@codemirror/lang-yaml': '^6.1.2', - '@codemirror/state': '^6.5.2', + '@codemirror/state': '^6.5.3', '@codemirror/view': '6.38.8', '@hpcc-js/wasm-graphviz': '^1.17.0', '@mathjax/mathjax-newcm-font': '^4.1.0', @@ -80,9 +80,9 @@ '@types/mocha': '^10.0.10', '@types/node': '^24.10.4', '@types/toastify-js': '^1.12.4', - '@typescript-eslint/eslint-plugin': '^8.50.0', - '@typescript-eslint/parser': '^8.50.0', - chai: '^6.2.1', + '@typescript-eslint/eslint-plugin': '^8.50.1', + '@typescript-eslint/parser': '^8.50.1', + chai: '^6.2.2', esbuild: '^0.27.2', eslint: '^9.39.2', 'eslint-config-prettier': '^10.1.8', @@ -91,7 +91,7 @@ mocha: '^11.7.5', prettier: '^3.7.4', typescript: '^5.9.3', - 'typescript-eslint': '^8.50.0', + 'typescript-eslint': '^8.50.1', }, scripts: { test: 'echo "Error: no test specified" && exit 1', diff --git a/client/pnpm-lock.yaml b/client/pnpm-lock.yaml index a447b9c..4fc0a11 100644 --- a/client/pnpm-lock.yaml +++ b/client/pnpm-lock.yaml @@ -54,8 +54,8 @@ importers: specifier: ^6.1.2 version: 6.1.2 '@codemirror/state': - specifier: ^6.5.2 - version: 6.5.2 + specifier: ^6.5.3 + version: 6.5.3 '@codemirror/view': specifier: 6.38.8 version: 6.38.8 @@ -109,14 +109,14 @@ importers: specifier: ^1.12.4 version: 1.12.4 '@typescript-eslint/eslint-plugin': - specifier: ^8.50.0 - version: 8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) + specifier: ^8.50.1 + version: 8.50.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) '@typescript-eslint/parser': - specifier: ^8.50.0 - version: 8.50.0(eslint@9.39.2)(typescript@5.9.3) + specifier: ^8.50.1 + version: 8.50.1(eslint@9.39.2)(typescript@5.9.3) chai: - specifier: ^6.2.1 - version: 6.2.1 + specifier: ^6.2.2 + version: 6.2.2 esbuild: specifier: ^0.27.2 version: 0.27.2 @@ -128,7 +128,7 @@ importers: version: 10.1.8(eslint@9.39.2) eslint-plugin-import: specifier: ^2.32.0 - version: 2.32.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2) + version: 2.32.0(@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2) eslint-plugin-prettier: specifier: ^5.5.4 version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.39.2))(eslint@9.39.2)(prettier@3.7.4) @@ -142,8 +142,8 @@ importers: specifier: ^5.9.3 version: 5.9.3 typescript-eslint: - specifier: ^8.50.0 - version: 8.50.0(eslint@9.39.2)(typescript@5.9.3) + specifier: ^8.50.1 + version: 8.50.1(eslint@9.39.2)(typescript@5.9.3) packages: @@ -216,8 +216,8 @@ packages: '@codemirror/lang-yaml@6.1.2': resolution: {integrity: sha512-dxrfG8w5Ce/QbT7YID7mWZFKhdhsaTNOYjOkSIMt1qmC4VQnXSDSYVHHHn8k6kJUfIhtLo8t1JJgltlxWdsITw==} - '@codemirror/language@6.11.3': - resolution: {integrity: sha512-9HBM2XnwDj7fnu0551HkGdrUrrqmYq/WC5iv6nbY2WdicXdGbhR/gfbZOH73Aqj4351alY1+aoG9rCNfiwS1RA==} + '@codemirror/language@6.12.1': + resolution: {integrity: sha512-Fa6xkSiuGKc8XC8Cn96T+TQHYj4ZZ7RdFmXA3i9xe/3hLHfwPZdM+dqfX0Cp0zQklBKhVD8Yzc8LS45rkqcwpQ==} '@codemirror/lint@6.9.2': resolution: {integrity: sha512-sv3DylBiIyi+xKwRCJAAsBZZZWo82shJ/RTMymLabAdtbkV5cSKwWDeCgtUq3v8flTaXS2y1kKkICuRYtUswyQ==} @@ -225,8 +225,8 @@ packages: '@codemirror/search@6.5.11': resolution: {integrity: sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA==} - '@codemirror/state@6.5.2': - resolution: {integrity: sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==} + '@codemirror/state@6.5.3': + resolution: {integrity: sha512-MerMzJzlXogk2fxWFU1nKp36bY5orBG59HnPiz0G9nLRebWa0zXuv2siH6PLIHBvv5TH8CkQRqjBs0MlxCZu+A==} '@codemirror/view@6.38.8': resolution: {integrity: sha512-XcE9fcnkHCbWkjeKyi0lllwXmBLtyYb5dt89dJyx23I9+LSh5vZDIuk7OLG4VM1lgrXZQcY6cxyZyk5WVPRv/A==} @@ -454,8 +454,8 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} - '@lezer/common@1.4.0': - resolution: {integrity: sha512-DVeMRoGrgn/k45oQNu189BoW4SZwgZFzJ1+1TV5j2NJ/KFC83oa/enRqZSGshyeMk5cPWMhsKs9nx+8o0unwGg==} + '@lezer/common@1.5.0': + resolution: {integrity: sha512-PNGcolp9hr4PJdXR4ix7XtixDrClScvtSCYW3rQG106oVMOOI+jFb+0+J3mbeL/53g1Zd6s0kJzaw6Ri68GmAA==} '@lezer/cpp@1.1.4': resolution: {integrity: sha512-aYSdZyUueeTgnfXQntiGUqKNW5WujlAsIbbHzkfJDneSZoyjPg8ObmWG3bzDPVYMC/Kf4l43WJLCunPnYFfQ0g==} @@ -469,8 +469,8 @@ packages: '@lezer/highlight@1.2.3': resolution: {integrity: sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==} - '@lezer/html@1.3.12': - resolution: {integrity: sha512-RJ7eRWdaJe3bsiiLLHjCFT1JMk8m1YP9kaUbvu2rMLEoOnke9mcTVDyfOslsln0LtujdWespjJ39w6zo+RsQYw==} + '@lezer/html@1.3.13': + resolution: {integrity: sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg==} '@lezer/java@1.1.3': resolution: {integrity: sha512-yHquUfujwg6Yu4Fd1GNHCvidIvJwi/1Xu2DaKl/pfWIA2c1oXkVvawH3NyXhCaFx4OdlYBVX5wvz2f7Aoa/4Xw==} @@ -484,8 +484,8 @@ packages: '@lezer/lr@1.4.5': resolution: {integrity: sha512-/YTRKP5yPPSo1xImYQk7AZZMAgap0kegzqCSYHjAL9x1AZ0ZQW+IpcEzMKagCsbTsLnVeWkxYrCNeXG8xEPrjg==} - '@lezer/markdown@1.6.1': - resolution: {integrity: sha512-72ah+Sml7lD8Wn7lnz9vwYmZBo9aQT+I2gjK/0epI+gjdwUbWw3MJ/ZBGEqG1UfrIauRqH37/c5mVHXeCTGXtA==} + '@lezer/markdown@1.6.2': + resolution: {integrity: sha512-iNSdKrIK0FfOjVPVpV0fu7OykdncYpEzf4vkG9szFf60ql/ObZShoVbM9u1tgkogDOmubms1CyoNS2/unOXWNw==} '@lezer/php@1.0.5': resolution: {integrity: sha512-W7asp9DhM6q0W6DYNwIkLSKOvxlXRrif+UXBMxzsJUuqmhE7oVU+gS3THO4S/Puh7Xzgm858UNaFi6dxTP8dJA==} @@ -511,68 +511,74 @@ packages: '@mermaid-js/parser@0.6.3': resolution: {integrity: sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==} - '@napi-rs/canvas-android-arm64@0.1.84': - resolution: {integrity: sha512-pdvuqvj3qtwVryqgpAGornJLV6Ezpk39V6wT4JCnRVGy8I3Tk1au8qOalFGrx/r0Ig87hWslysPpHBxVpBMIww==} + '@napi-rs/canvas-android-arm64@0.1.86': + resolution: {integrity: sha512-IjkZFKUr6GzMzzrawJaN3v+yY3Fvpa71e0DcbePfxWelFKnESIir+XUcdAbim29JOd0JE0/hQJdfUCb5t/Fjrw==} engines: {node: '>= 10'} cpu: [arm64] os: [android] - '@napi-rs/canvas-darwin-arm64@0.1.84': - resolution: {integrity: sha512-A8IND3Hnv0R6abc6qCcCaOCujTLMmGxtucMTZ5vbQUrEN/scxi378MyTLtyWg+MRr6bwQJ6v/orqMS9datIcww==} + '@napi-rs/canvas-darwin-arm64@0.1.86': + resolution: {integrity: sha512-PUCxDq0wSSJbtaOqoKj3+t5tyDbtxWumziOTykdn3T839hu6koMaBFpGk9lXpsGaPNgyFpPqjxhtsPljBGnDHg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@napi-rs/canvas-darwin-x64@0.1.84': - resolution: {integrity: sha512-AUW45lJhYWwnA74LaNeqhvqYKK/2hNnBBBl03KRdqeCD4tKneUSrxUqIv8d22CBweOvrAASyKN3W87WO2zEr/A==} + '@napi-rs/canvas-darwin-x64@0.1.86': + resolution: {integrity: sha512-rlCFLv4Rrg45qFZq7mysrKnsUbMhwdNg3YPuVfo9u4RkOqm7ooAJvdyDFxiqfSsJJTqupYqa9VQCUt8WKxKhNQ==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@napi-rs/canvas-linux-arm-gnueabihf@0.1.84': - resolution: {integrity: sha512-8zs5ZqOrdgs4FioTxSBrkl/wHZB56bJNBqaIsfPL4ZkEQCinOkrFF7xIcXiHiKp93J3wUtbIzeVrhTIaWwqk+A==} + '@napi-rs/canvas-linux-arm-gnueabihf@0.1.86': + resolution: {integrity: sha512-6xWwyMc9BlDBt+9XHN/GzUo3MozHta/2fxQHMb80x0K2zpZuAdDKUYHmYzx9dFWDY3SbPYnx6iRlQl6wxnwS1w==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@napi-rs/canvas-linux-arm64-gnu@0.1.84': - resolution: {integrity: sha512-i204vtowOglJUpbAFWU5mqsJgH0lVpNk/Ml4mQtB4Lndd86oF+Otr6Mr5KQnZHqYGhlSIKiU2SYnUbhO28zGQA==} + '@napi-rs/canvas-linux-arm64-gnu@0.1.86': + resolution: {integrity: sha512-r2OX3w50xHxrToTovOSQWwkVfSq752CUzH9dzlVXyr8UDKFV8dMjfa9hePXvAJhN3NBp4TkHcGx15QCdaCIwnA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@napi-rs/canvas-linux-arm64-musl@0.1.84': - resolution: {integrity: sha512-VyZq0EEw+OILnWk7G3ZgLLPaz1ERaPP++jLjeyLMbFOF+Tr4zHzWKiKDsEV/cT7btLPZbVoR3VX+T9/QubnURQ==} + '@napi-rs/canvas-linux-arm64-musl@0.1.86': + resolution: {integrity: sha512-jbXuh8zVFUPw6a9SGpgc6EC+fRbGGyP1NFfeQiVqGLs6bN93ROtPLPL6MH9Bp6yt0CXUFallk2vgKdWDbmW+bw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@napi-rs/canvas-linux-riscv64-gnu@0.1.84': - resolution: {integrity: sha512-PSMTh8DiThvLRsbtc/a065I/ceZk17EXAATv9uNvHgkgo7wdEfTh2C3aveNkBMGByVO3tvnvD5v/YFtZL07cIg==} + '@napi-rs/canvas-linux-riscv64-gnu@0.1.86': + resolution: {integrity: sha512-9IwHR2qbq2HceM9fgwyL7x37Jy3ptt1uxvikQEuWR0FisIx9QEdt7F3huljCky76aoouF2vSd0R2fHo3ESRoPw==} engines: {node: '>= 10'} cpu: [riscv64] os: [linux] - '@napi-rs/canvas-linux-x64-gnu@0.1.84': - resolution: {integrity: sha512-N1GY3noO1oqgEo3rYQIwY44kfM11vA0lDbN0orTOHfCSUZTUyiYCY0nZ197QMahZBm1aR/vYgsWpV74MMMDuNA==} + '@napi-rs/canvas-linux-x64-gnu@0.1.86': + resolution: {integrity: sha512-Jor+rhRN6ubix+D2QkNn9XlPPVAYl+2qFrkZ4oZN9UgtqIUZ+n+HljxhlkkDFRaX1mlxXOXPQjxaZg17zDSFcQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@napi-rs/canvas-linux-x64-musl@0.1.84': - resolution: {integrity: sha512-vUZmua6ADqTWyHyei81aXIt9wp0yjeNwTH0KdhdeoBb6azHmFR8uKTukZMXfLCC3bnsW0t4lW7K78KNMknmtjg==} + '@napi-rs/canvas-linux-x64-musl@0.1.86': + resolution: {integrity: sha512-A28VTy91DbclopSGZ2tIon3p8hcVI1JhnNpDpJ5N9rYlUnVz1WQo4waEMh+FICTZF07O3coxBNZc4Vu4doFw7A==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@napi-rs/canvas-win32-x64-msvc@0.1.84': - resolution: {integrity: sha512-YSs8ncurc1xzegUMNnQUTYrdrAuaXdPMOa+iYYyAxydOtg0ppV386hyYMsy00Yip1NlTgLCseRG4sHSnjQx6og==} + '@napi-rs/canvas-win32-arm64-msvc@0.1.86': + resolution: {integrity: sha512-q6G1YXUt3gBCAS2bcDMCaBL4y20di8eVVBi1XhjUqZSVyZZxxwIuRQHy31NlPJUCMiyNiMuc6zeI0uqgkWwAmA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@napi-rs/canvas-win32-x64-msvc@0.1.86': + resolution: {integrity: sha512-X0g46uRVgnvCM1cOjRXAOSFSG63ktUFIf/TIfbKCUc7QpmYUcHmSP9iR6DGOYfk+SggLsXoJCIhPTotYeZEAmg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@napi-rs/canvas@0.1.84': - resolution: {integrity: sha512-88FTNFs4uuiFKP0tUrPsEXhpe9dg7za9ILZJE08pGdUveMIDeana1zwfVkqRHJDPJFAmGY3dXmJ99dzsy57YnA==} + '@napi-rs/canvas@0.1.86': + resolution: {integrity: sha512-hOkywnrkdFdVpsuaNsZWfEY7kc96eROV2DuMTTvGF15AZfwobzdG2w0eDlU5UBx3Lg/XlWUnqVT5zLUWyo5h6A==} engines: {node: '>= 10'} '@pkgjs/parseargs@0.11.0': @@ -715,63 +721,63 @@ packages: '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - '@typescript-eslint/eslint-plugin@8.50.0': - resolution: {integrity: sha512-O7QnmOXYKVtPrfYzMolrCTfkezCJS9+ljLdKW/+DCvRsc3UAz+sbH6Xcsv7p30+0OwUbeWfUDAQE0vpabZ3QLg==} + '@typescript-eslint/eslint-plugin@8.50.1': + resolution: {integrity: sha512-PKhLGDq3JAg0Jk/aK890knnqduuI/Qj+udH7wCf0217IGi4gt+acgCyPVe79qoT+qKUvHMDQkwJeKW9fwl8Cyw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.50.0 + '@typescript-eslint/parser': ^8.50.1 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.50.0': - resolution: {integrity: sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==} + '@typescript-eslint/parser@8.50.1': + resolution: {integrity: sha512-hM5faZwg7aVNa819m/5r7D0h0c9yC4DUlWAOvHAtISdFTc8xB86VmX5Xqabrama3wIPJ/q9RbGS1worb6JfnMg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.50.0': - resolution: {integrity: sha512-Cg/nQcL1BcoTijEWyx4mkVC56r8dj44bFDvBdygifuS20f3OZCHmFbjF34DPSi07kwlFvqfv/xOLnJ5DquxSGQ==} + '@typescript-eslint/project-service@8.50.1': + resolution: {integrity: sha512-E1ur1MCVf+YiP89+o4Les/oBAVzmSbeRB0MQLfSlYtbWU17HPxZ6Bhs5iYmKZRALvEuBoXIZMOIRRc/P++Ortg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.50.0': - resolution: {integrity: sha512-xCwfuCZjhIqy7+HKxBLrDVT5q/iq7XBVBXLn57RTIIpelLtEIZHXAF/Upa3+gaCpeV1NNS5Z9A+ID6jn50VD4A==} + '@typescript-eslint/scope-manager@8.50.1': + resolution: {integrity: sha512-mfRx06Myt3T4vuoHaKi8ZWNTPdzKPNBhiblze5N50//TSHOAQQevl/aolqA/BcqqbJ88GUnLqjjcBc8EWdBcVw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.50.0': - resolution: {integrity: sha512-vxd3G/ybKTSlm31MOA96gqvrRGv9RJ7LGtZCn2Vrc5htA0zCDvcMqUkifcjrWNNKXHUU3WCkYOzzVSFBd0wa2w==} + '@typescript-eslint/tsconfig-utils@8.50.1': + resolution: {integrity: sha512-ooHmotT/lCWLXi55G4mvaUF60aJa012QzvLK0Y+Mp4WdSt17QhMhWOaBWeGTFVkb2gDgBe19Cxy1elPXylslDw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.50.0': - resolution: {integrity: sha512-7OciHT2lKCewR0mFoBrvZJ4AXTMe/sYOe87289WAViOocEmDjjv8MvIOT2XESuKj9jp8u3SZYUSh89QA4S1kQw==} + '@typescript-eslint/type-utils@8.50.1': + resolution: {integrity: sha512-7J3bf022QZE42tYMO6SL+6lTPKFk/WphhRPe9Tw/el+cEwzLz1Jjz2PX3GtGQVxooLDKeMVmMt7fWpYRdG5Etg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.50.0': - resolution: {integrity: sha512-iX1mgmGrXdANhhITbpp2QQM2fGehBse9LbTf0sidWK6yg/NE+uhV5dfU1g6EYPlcReYmkE9QLPq/2irKAmtS9w==} + '@typescript-eslint/types@8.50.1': + resolution: {integrity: sha512-v5lFIS2feTkNyMhd7AucE/9j/4V9v5iIbpVRncjk/K0sQ6Sb+Np9fgYS/63n6nwqahHQvbmujeBL7mp07Q9mlA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.50.0': - resolution: {integrity: sha512-W7SVAGBR/IX7zm1t70Yujpbk+zdPq/u4soeFSknWFdXIFuWsBGBOUu/Tn/I6KHSKvSh91OiMuaSnYp3mtPt5IQ==} + '@typescript-eslint/typescript-estree@8.50.1': + resolution: {integrity: sha512-woHPdW+0gj53aM+cxchymJCrh0cyS7BTIdcDxWUNsclr9VDkOSbqC13juHzxOmQ22dDkMZEpZB+3X1WpUvzgVQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.50.0': - resolution: {integrity: sha512-87KgUXET09CRjGCi2Ejxy3PULXna63/bMYv72tCAlDJC3Yqwln0HiFJ3VJMst2+mEtNtZu5oFvX4qJGjKsnAgg==} + '@typescript-eslint/utils@8.50.1': + resolution: {integrity: sha512-lCLp8H1T9T7gPbEuJSnHwnSuO9mDf8mfK/Nion5mZmiEaQD9sWf9W4dfeFqRyqRjF06/kBuTmAqcs9sewM2NbQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.50.0': - resolution: {integrity: sha512-Xzmnb58+Db78gT/CCj/PVCvK+zxbnsw6F+O1oheYszJbBSdEjVhQi3C/Xttzxgi/GLmpvOggRs1RFpiJ8+c34Q==} + '@typescript-eslint/visitor-keys@8.50.1': + resolution: {integrity: sha512-IrDKrw7pCRUR94zeuCSUWQ+w8JEf5ZX5jl/e6AHGSLi1/zIr0lgutfn/7JpfCey+urpgQEdrZVYzCaVVKiTwhQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} acorn-jsx@5.3.2: @@ -874,8 +880,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - chai@6.2.1: - resolution: {integrity: sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} chalk@4.1.2: @@ -2023,8 +2029,8 @@ packages: resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} engines: {node: '>= 0.4'} - typescript-eslint@8.50.0: - resolution: {integrity: sha512-Q1/6yNUmCpH94fbgMUMg2/BSAr/6U7GBk61kZTv1/asghQOWOjTlp9K8mixS5NcJmm2creY+UFfGeW/+OcA64A==} + typescript-eslint@8.50.1: + resolution: {integrity: sha512-ytTHO+SoYSbhAH9CrYnMhiLx8To6PSSvqnvXyPUgPETCvB6eBKmTI9w6XMPS3HsBRGkwTVBX+urA8dYQx6bHfQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -2159,37 +2165,37 @@ snapshots: '@codemirror/autocomplete@6.20.0': dependencies: - '@codemirror/language': 6.11.3 - '@codemirror/state': 6.5.2 + '@codemirror/language': 6.12.1 + '@codemirror/state': 6.5.3 '@codemirror/view': 6.38.8 - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@codemirror/commands@6.10.1': dependencies: - '@codemirror/language': 6.11.3 - '@codemirror/state': 6.5.2 + '@codemirror/language': 6.12.1 + '@codemirror/state': 6.5.3 '@codemirror/view': 6.38.8 - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@codemirror/lang-cpp@6.0.3': dependencies: - '@codemirror/language': 6.11.3 + '@codemirror/language': 6.12.1 '@lezer/cpp': 1.1.4 '@codemirror/lang-css@6.3.1': dependencies: '@codemirror/autocomplete': 6.20.0 - '@codemirror/language': 6.11.3 - '@codemirror/state': 6.5.2 - '@lezer/common': 1.4.0 + '@codemirror/language': 6.12.1 + '@codemirror/state': 6.5.3 + '@lezer/common': 1.5.0 '@lezer/css': 1.3.0 '@codemirror/lang-go@6.0.1': dependencies: '@codemirror/autocomplete': 6.20.0 - '@codemirror/language': 6.11.3 - '@codemirror/state': 6.5.2 - '@lezer/common': 1.4.0 + '@codemirror/language': 6.12.1 + '@codemirror/state': 6.5.3 + '@lezer/common': 1.5.0 '@lezer/go': 1.0.1 '@codemirror/lang-html@6.4.11': @@ -2197,120 +2203,120 @@ snapshots: '@codemirror/autocomplete': 6.20.0 '@codemirror/lang-css': 6.3.1 '@codemirror/lang-javascript': 6.2.4 - '@codemirror/language': 6.11.3 - '@codemirror/state': 6.5.2 + '@codemirror/language': 6.12.1 + '@codemirror/state': 6.5.3 '@codemirror/view': 6.38.8 - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@lezer/css': 1.3.0 - '@lezer/html': 1.3.12 + '@lezer/html': 1.3.13 '@codemirror/lang-java@6.0.2': dependencies: - '@codemirror/language': 6.11.3 + '@codemirror/language': 6.12.1 '@lezer/java': 1.1.3 '@codemirror/lang-javascript@6.2.4': dependencies: '@codemirror/autocomplete': 6.20.0 - '@codemirror/language': 6.11.3 + '@codemirror/language': 6.12.1 '@codemirror/lint': 6.9.2 - '@codemirror/state': 6.5.2 + '@codemirror/state': 6.5.3 '@codemirror/view': 6.38.8 - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@lezer/javascript': 1.5.4 '@codemirror/lang-json@6.0.2': dependencies: - '@codemirror/language': 6.11.3 + '@codemirror/language': 6.12.1 '@lezer/json': 1.0.3 '@codemirror/lang-markdown@6.5.0': dependencies: '@codemirror/autocomplete': 6.20.0 '@codemirror/lang-html': 6.4.11 - '@codemirror/language': 6.11.3 - '@codemirror/state': 6.5.2 + '@codemirror/language': 6.12.1 + '@codemirror/state': 6.5.3 '@codemirror/view': 6.38.8 - '@lezer/common': 1.4.0 - '@lezer/markdown': 1.6.1 + '@lezer/common': 1.5.0 + '@lezer/markdown': 1.6.2 '@codemirror/lang-php@6.0.2': dependencies: '@codemirror/lang-html': 6.4.11 - '@codemirror/language': 6.11.3 - '@codemirror/state': 6.5.2 - '@lezer/common': 1.4.0 + '@codemirror/language': 6.12.1 + '@codemirror/state': 6.5.3 + '@lezer/common': 1.5.0 '@lezer/php': 1.0.5 '@codemirror/lang-python@6.2.1': dependencies: '@codemirror/autocomplete': 6.20.0 - '@codemirror/language': 6.11.3 - '@codemirror/state': 6.5.2 - '@lezer/common': 1.4.0 + '@codemirror/language': 6.12.1 + '@codemirror/state': 6.5.3 + '@lezer/common': 1.5.0 '@lezer/python': 1.1.18 '@codemirror/lang-rust@6.0.2': dependencies: - '@codemirror/language': 6.11.3 + '@codemirror/language': 6.12.1 '@lezer/rust': 1.0.2 '@codemirror/lang-sql@6.10.0': dependencies: '@codemirror/autocomplete': 6.20.0 - '@codemirror/language': 6.11.3 - '@codemirror/state': 6.5.2 - '@lezer/common': 1.4.0 + '@codemirror/language': 6.12.1 + '@codemirror/state': 6.5.3 + '@lezer/common': 1.5.0 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.5 '@codemirror/lang-xml@6.1.0': dependencies: '@codemirror/autocomplete': 6.20.0 - '@codemirror/language': 6.11.3 - '@codemirror/state': 6.5.2 + '@codemirror/language': 6.12.1 + '@codemirror/state': 6.5.3 '@codemirror/view': 6.38.8 - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@lezer/xml': 1.0.6 '@codemirror/lang-yaml@6.1.2': dependencies: '@codemirror/autocomplete': 6.20.0 - '@codemirror/language': 6.11.3 - '@codemirror/state': 6.5.2 - '@lezer/common': 1.4.0 + '@codemirror/language': 6.12.1 + '@codemirror/state': 6.5.3 + '@lezer/common': 1.5.0 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.5 '@lezer/yaml': 1.0.3 - '@codemirror/language@6.11.3': + '@codemirror/language@6.12.1': dependencies: - '@codemirror/state': 6.5.2 + '@codemirror/state': 6.5.3 '@codemirror/view': 6.38.8 - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.5 style-mod: 4.1.3 '@codemirror/lint@6.9.2': dependencies: - '@codemirror/state': 6.5.2 + '@codemirror/state': 6.5.3 '@codemirror/view': 6.38.8 crelt: 1.0.6 '@codemirror/search@6.5.11': dependencies: - '@codemirror/state': 6.5.2 + '@codemirror/state': 6.5.3 '@codemirror/view': 6.38.8 crelt: 1.0.6 - '@codemirror/state@6.5.2': + '@codemirror/state@6.5.3': dependencies: '@marijn/find-cluster-break': 1.0.2 '@codemirror/view@6.38.8': dependencies: - '@codemirror/state': 6.5.2 + '@codemirror/state': 6.5.3 crelt: 1.0.6 style-mod: 4.1.3 w3c-keyname: 2.2.8 @@ -2469,90 +2475,90 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 - '@lezer/common@1.4.0': {} + '@lezer/common@1.5.0': {} '@lezer/cpp@1.1.4': dependencies: - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.5 '@lezer/css@1.3.0': dependencies: - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.5 '@lezer/go@1.0.1': dependencies: - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.5 '@lezer/highlight@1.2.3': dependencies: - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 - '@lezer/html@1.3.12': + '@lezer/html@1.3.13': dependencies: - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.5 '@lezer/java@1.1.3': dependencies: - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.5 '@lezer/javascript@1.5.4': dependencies: - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.5 '@lezer/json@1.0.3': dependencies: - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.5 '@lezer/lr@1.4.5': dependencies: - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 - '@lezer/markdown@1.6.1': + '@lezer/markdown@1.6.2': dependencies: - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@lezer/highlight': 1.2.3 '@lezer/php@1.0.5': dependencies: - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.5 '@lezer/python@1.1.18': dependencies: - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.5 '@lezer/rust@1.0.2': dependencies: - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.5 '@lezer/xml@1.0.6': dependencies: - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.5 '@lezer/yaml@1.0.3': dependencies: - '@lezer/common': 1.4.0 + '@lezer/common': 1.5.0 '@lezer/highlight': 1.2.3 '@lezer/lr': 1.4.5 @@ -2564,48 +2570,52 @@ snapshots: dependencies: langium: 3.3.1 - '@napi-rs/canvas-android-arm64@0.1.84': + '@napi-rs/canvas-android-arm64@0.1.86': + optional: true + + '@napi-rs/canvas-darwin-arm64@0.1.86': optional: true - '@napi-rs/canvas-darwin-arm64@0.1.84': + '@napi-rs/canvas-darwin-x64@0.1.86': optional: true - '@napi-rs/canvas-darwin-x64@0.1.84': + '@napi-rs/canvas-linux-arm-gnueabihf@0.1.86': optional: true - '@napi-rs/canvas-linux-arm-gnueabihf@0.1.84': + '@napi-rs/canvas-linux-arm64-gnu@0.1.86': optional: true - '@napi-rs/canvas-linux-arm64-gnu@0.1.84': + '@napi-rs/canvas-linux-arm64-musl@0.1.86': optional: true - '@napi-rs/canvas-linux-arm64-musl@0.1.84': + '@napi-rs/canvas-linux-riscv64-gnu@0.1.86': optional: true - '@napi-rs/canvas-linux-riscv64-gnu@0.1.84': + '@napi-rs/canvas-linux-x64-gnu@0.1.86': optional: true - '@napi-rs/canvas-linux-x64-gnu@0.1.84': + '@napi-rs/canvas-linux-x64-musl@0.1.86': optional: true - '@napi-rs/canvas-linux-x64-musl@0.1.84': + '@napi-rs/canvas-win32-arm64-msvc@0.1.86': optional: true - '@napi-rs/canvas-win32-x64-msvc@0.1.84': + '@napi-rs/canvas-win32-x64-msvc@0.1.86': optional: true - '@napi-rs/canvas@0.1.84': + '@napi-rs/canvas@0.1.86': optionalDependencies: - '@napi-rs/canvas-android-arm64': 0.1.84 - '@napi-rs/canvas-darwin-arm64': 0.1.84 - '@napi-rs/canvas-darwin-x64': 0.1.84 - '@napi-rs/canvas-linux-arm-gnueabihf': 0.1.84 - '@napi-rs/canvas-linux-arm64-gnu': 0.1.84 - '@napi-rs/canvas-linux-arm64-musl': 0.1.84 - '@napi-rs/canvas-linux-riscv64-gnu': 0.1.84 - '@napi-rs/canvas-linux-x64-gnu': 0.1.84 - '@napi-rs/canvas-linux-x64-musl': 0.1.84 - '@napi-rs/canvas-win32-x64-msvc': 0.1.84 + '@napi-rs/canvas-android-arm64': 0.1.86 + '@napi-rs/canvas-darwin-arm64': 0.1.86 + '@napi-rs/canvas-darwin-x64': 0.1.86 + '@napi-rs/canvas-linux-arm-gnueabihf': 0.1.86 + '@napi-rs/canvas-linux-arm64-gnu': 0.1.86 + '@napi-rs/canvas-linux-arm64-musl': 0.1.86 + '@napi-rs/canvas-linux-riscv64-gnu': 0.1.86 + '@napi-rs/canvas-linux-x64-gnu': 0.1.86 + '@napi-rs/canvas-linux-x64-musl': 0.1.86 + '@napi-rs/canvas-win32-arm64-msvc': 0.1.86 + '@napi-rs/canvas-win32-x64-msvc': 0.1.86 optional: true '@pkgjs/parseargs@0.11.0': @@ -2762,14 +2772,14 @@ snapshots: '@types/trusted-types@2.0.7': optional: true - '@typescript-eslint/eslint-plugin@8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.50.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.50.0 - '@typescript-eslint/type-utils': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.50.0 + '@typescript-eslint/parser': 8.50.1(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.50.1 + '@typescript-eslint/type-utils': 8.50.1(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/utils': 8.50.1(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.50.1 eslint: 9.39.2 ignore: 7.0.5 natural-compare: 1.4.0 @@ -2778,41 +2788,41 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.50.0 - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.50.0 + '@typescript-eslint/scope-manager': 8.50.1 + '@typescript-eslint/types': 8.50.1 + '@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.50.1 debug: 4.4.3(supports-color@8.1.1) eslint: 9.39.2 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.50.0(typescript@5.9.3)': + '@typescript-eslint/project-service@8.50.1(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.50.0(typescript@5.9.3) - '@typescript-eslint/types': 8.50.0 + '@typescript-eslint/tsconfig-utils': 8.50.1(typescript@5.9.3) + '@typescript-eslint/types': 8.50.1 debug: 4.4.3(supports-color@8.1.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.50.0': + '@typescript-eslint/scope-manager@8.50.1': dependencies: - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/visitor-keys': 8.50.0 + '@typescript-eslint/types': 8.50.1 + '@typescript-eslint/visitor-keys': 8.50.1 - '@typescript-eslint/tsconfig-utils@8.50.0(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.50.1(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.50.0(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.50.1(eslint@9.39.2)(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/types': 8.50.1 + '@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.50.1(eslint@9.39.2)(typescript@5.9.3) debug: 4.4.3(supports-color@8.1.1) eslint: 9.39.2 ts-api-utils: 2.1.0(typescript@5.9.3) @@ -2820,14 +2830,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.50.0': {} + '@typescript-eslint/types@8.50.1': {} - '@typescript-eslint/typescript-estree@8.50.0(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.50.1(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.50.0(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.50.0(typescript@5.9.3) - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/visitor-keys': 8.50.0 + '@typescript-eslint/project-service': 8.50.1(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.50.1(typescript@5.9.3) + '@typescript-eslint/types': 8.50.1 + '@typescript-eslint/visitor-keys': 8.50.1 debug: 4.4.3(supports-color@8.1.1) minimatch: 9.0.5 semver: 7.7.3 @@ -2837,20 +2847,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.50.0(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/utils@8.50.1(eslint@9.39.2)(typescript@5.9.3)': dependencies: '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2) - '@typescript-eslint/scope-manager': 8.50.0 - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.50.1 + '@typescript-eslint/types': 8.50.1 + '@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3) eslint: 9.39.2 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.50.0': + '@typescript-eslint/visitor-keys@8.50.1': dependencies: - '@typescript-eslint/types': 8.50.0 + '@typescript-eslint/types': 8.50.1 eslint-visitor-keys: 4.2.1 acorn-jsx@5.3.2(acorn@8.15.0): @@ -2970,7 +2980,7 @@ snapshots: camelcase@6.3.0: {} - chai@6.2.1: {} + chai@6.2.2: {} chalk@4.1.2: dependencies: @@ -3005,10 +3015,10 @@ snapshots: dependencies: '@codemirror/autocomplete': 6.20.0 '@codemirror/commands': 6.10.1 - '@codemirror/language': 6.11.3 + '@codemirror/language': 6.12.1 '@codemirror/lint': 6.9.2 '@codemirror/search': 6.5.11 - '@codemirror/state': 6.5.2 + '@codemirror/state': 6.5.3 '@codemirror/view': 6.38.8 color-convert@2.0.1: @@ -3424,17 +3434,17 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.50.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/parser': 8.50.1(eslint@9.39.2)(typescript@5.9.3) eslint: 9.39.2 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -3445,7 +3455,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.39.2 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -3457,7 +3467,7 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.50.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/parser': 8.50.1(eslint@9.39.2)(typescript@5.9.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -4034,7 +4044,7 @@ snapshots: pdfjs-dist@5.4.449: optionalDependencies: - '@napi-rs/canvas': 0.1.84 + '@napi-rs/canvas': 0.1.86 picocolors@1.1.1: {} @@ -4332,12 +4342,12 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typescript-eslint@8.50.0(eslint@9.39.2)(typescript@5.9.3): + typescript-eslint@8.50.1(eslint@9.39.2)(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/parser': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.50.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/parser': 8.50.1(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.50.1(eslint@9.39.2)(typescript@5.9.3) eslint: 9.39.2 typescript: 5.9.3 transitivePeerDependencies: diff --git a/client/src/CodeChatEditor.mts b/client/src/CodeChatEditor.mts index eaa52ff..d7f6de8 100644 --- a/client/src/CodeChatEditor.mts +++ b/client/src/CodeChatEditor.mts @@ -102,6 +102,7 @@ declare global { // Called by the Client Framework. open_lp: ( codechat_for_web: CodeChatForWeb, + is_re_translation: boolean, cursor_line?: number, scroll_line?: number, ) => Promise; @@ -124,9 +125,6 @@ declare global { // autosaved. let autosaveTimeoutId: null | number = null; -// True to enable autosave. -let autosaveEnabled = true; - // Store the lexer info for the currently-loaded language. // // This mirrors the data provided by the server -- @@ -135,15 +133,20 @@ let current_metadata: { mode: string; }; +const webSocketComm = () => parent.window.CodeChatEditorFramework.webSocketComm; + // True if the document is dirty (needs saving). let is_dirty = false; -// Page initialization -// ----------------------------------------------------------------------------- export const set_is_dirty = (value: boolean = true) => { is_dirty = value; }; +export const get_is_dirty = () => is_dirty; + +// Page initialization +// ----------------------------------------------------------------------------- + // This is copied from // [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Document/DOMContentLoaded_event#checking_whether_loading_is_already_complete). export const on_dom_content_loaded = (on_load_func: () => void) => { @@ -169,12 +172,18 @@ const is_doc_only = () => { // Wait for the DOM to load before opening the file. const open_lp = async ( codechat_for_web: CodeChatForWeb, + is_re_translation: boolean, cursor_line?: number, scroll_line?: number, ) => await new Promise((resolve) => on_dom_content_loaded(async () => { - await _open_lp(codechat_for_web, cursor_line, scroll_line); + await _open_lp( + codechat_for_web, + is_re_translation, + cursor_line, + scroll_line, + ); resolve(); }), ); @@ -195,108 +204,165 @@ const _open_lp = async ( // A data structure provided by the server, containing the source and // associated metadata. See [`AllSource`](#AllSource). codechat_for_web: CodeChatForWeb, + is_re_translation: boolean, cursor_line?: number, scroll_line?: number, ) => { - // Use - // [URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) - // to parse out the search parameters of this window's URL. - const urlParams = new URLSearchParams(window.location.search); - // Get the mode from the page's query parameters. Default to edit using the - // [nullish coalescing operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator). - // This works, but TypeScript marks it as an error. Ignore this error by - // including the - // [@ts-ignore directive](https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html#ts-check). - /// @ts-expect-error("See above.") - const _editorMode = EditorMode[urlParams.get("mode") ?? "edit"]; - - // Get the [current_metadata](#current_metadata) from the - // provided `code_chat_for_web` struct and store it as a global variable. - current_metadata = codechat_for_web["metadata"]; - const source = codechat_for_web["source"]; - const codechat_body = document.getElementById( - "CodeChat-body", - ) as HTMLDivElement; - // Disable autosave when updating the document. - autosaveEnabled = false; - clearAutosaveTimer(); + // Note that globals, such as `is_dirty` and document contents, may change + // between `await` calls. Therefore, try to perform processing which relies + // on these values between `await` calls. For example, evaluate this first: + // // Before calling any MathJax, make sure it's fully loaded and the initial // render is finished. await window.MathJax.startup.promise; - // Per the - // [docs](https://docs.mathjax.org/en/latest/web/typeset.html#updating-previously-typeset-content), - // "If you modify the page to remove content that contains typeset - // mathematics, you will need to tell MathJax about that so that it knows - // the typeset math that you are removing is no longer on the page." - window.MathJax.typesetClear(codechat_body); - if (is_doc_only()) { - if (tinymce.activeEditor === null) { - // We shouldn't have a diff if the editor hasn't been initialized. - assert("Plain" in source); - // Special case: a CodeChat Editor document's HTML is stored - // in`source.doc`. We don't need the CodeMirror editor at all; - // instead, treat it like a single doc block contents div. - doc_content = source.Plain.doc; - codechat_body.innerHTML = `
${doc_content}
`; - await init({ - selector: ".CodeChat-doc-contents", - // In the doc-only mode, add autosave functionality. While there - // is an - // [autosave plugin](https://www.tiny.cloud/docs/tinymce/6/autosave/), - // this autosave functionality is completely different from the - // autosave provided here. Per - // [handling editor events](https://www.tiny.cloud/docs/tinymce/6/events/#handling-editor-events), - // this is how to create a TinyMCE event handler. - setup: (editor: Editor) => { - editor.on( - "dirty", - ( - event: EditorEvent, - ) => { - // Sometimes, `tinymce.activeEditor` is null - // (perhaps when it's not focused). Use the `event` - // data instead. - event.target.setDirty(false); - is_dirty = true; - startAutosaveTimer(); - }, - ); - }, - }); - tinymce.activeEditor!.focus(); + + // The only the `await` is based on TinyMCE init, which should only cause an + // async delay on its first execution. (Even then, I'm not sure it does, + // since all resources are statically imported). So, we should be OK for the + // rest of this function. + // + // Now, make all decisions about `is_dirty`: if the text is dirty, do some + // special processing; simply applying the update could cause either data + // loss (overwriting edits made since the last autosave) or data corruption + // (applying a diff to updated text, causing the diff to be mis-applied). + // Specifically: + // + // 1. If this is a re-translation, then ignore the update, since it's only + // changes due to re-translation, not due to updates to IDE content. + // 2. If this is the full text, discard changes made in the Client since the + // last autosave, overwriting them with the provided update. + // 3. If this is a diff: + // 1. In document-only mode, we have a backup copy of the full text + // before it was modified by the Client. Apply the diff to this, + // overwriting changes made in the Client. + // 2. In normal mode, we don't have a backup copy of the full text. + // Report an `OutOfSync` error, which causes the IDE to send the full + // text which will then overwrite changes made in the Client. + if (is_dirty && is_re_translation) { + console_log(`Ignoring re-translation because Client is dirty.`); + return; + } + + try { + // Use + // [URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) + // to parse out the search parameters of this window's URL. + const urlParams = new URLSearchParams(window.location.search); + // Get the mode from the page's query parameters. Default to edit using + // the + // [nullish coalescing operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator). + // TODO: this isn't typesafe, since the `mode` might not be a key of + // `EditorMode`. + /// @ts-expect-error("See above.") + const _editorMode = EditorMode[urlParams.get("mode") ?? "edit"]; + + // Get the [current_metadata](#current_metadata) from the + // provided `code_chat_for_web` struct and store it as a global + // variable. + current_metadata = codechat_for_web["metadata"]; + const source = codechat_for_web["source"]; + const codechat_body = document.getElementById( + "CodeChat-body", + ) as HTMLDivElement; + // Per the + // [docs](https://docs.mathjax.org/en/latest/web/typeset.html#updating-previously-typeset-content), + // "If you modify the page to remove content that contains typeset + // mathematics, you will need to tell MathJax about that so that it + // knows the typeset math that you are removing is no longer on the + // page." + window.MathJax.typesetClear(codechat_body); + if (is_doc_only()) { + if (tinymce.activeEditor === null) { + // We shouldn't have a diff if the editor hasn't been + // initialized. + assert("Plain" in source); + // Special case: a CodeChat Editor document's HTML is stored + // in`source.doc`. We don't need the CodeMirror editor at all; + // instead, treat it like a single doc block contents div. + doc_content = source.Plain.doc; + codechat_body.innerHTML = `
${doc_content}
`; + await init({ + selector: ".CodeChat-doc-contents", + // In the doc-only mode, add autosave functionality. While + // there is an + // [autosave plugin](https://www.tiny.cloud/docs/tinymce/6/autosave/), + // this autosave functionality is completely different from + // the autosave provided here. Per + // [handling editor events](https://www.tiny.cloud/docs/tinymce/6/events/#handling-editor-events), + // this is how to create a TinyMCE event handler. + setup: (editor: Editor) => { + editor.on( + "dirty", + ( + event: EditorEvent< + Events.EditorEventMap["dirty"] + >, + ) => { + // Sometimes, `tinymce.activeEditor` is null + // (perhaps when it's not focused). Use the + // `event` data instead. + event.target.setDirty(false); + is_dirty = true; + startAutosaveTimer(); + }, + ); + }, + }); + tinymce.activeEditor!.focus(); + } else { + // Save the cursor location before the update, then restore it + // afterwards, if TinyMCE has focus. + const sel = tinymce.activeEditor!.hasFocus() + ? saveSelection() + : undefined; + doc_content = + "Plain" in source + ? source.Plain.doc + : apply_diff_str(doc_content, source.Diff.doc); + tinymce.activeEditor!.setContent(doc_content); + if (sel !== undefined) { + restoreSelection(sel); + } + } + mathJaxTypeset(codechat_body); + scroll_to_line(cursor_line, scroll_line); } else { - // Save the cursor location before the update, then restore it - // afterwards, if TinyMCE has focus. - const sel = tinymce.activeEditor!.hasFocus() - ? saveSelection() - : undefined; - doc_content = - "Plain" in source - ? source.Plain.doc - : apply_diff_str(doc_content, source.Diff.doc); - tinymce.activeEditor!.setContent(doc_content); - if (sel !== undefined) { - restoreSelection(sel); + if (is_dirty && "Diff" in source) { + // Send an `OutOfSync` response, so that the IDE will send the + // full text to overwrite these changes with. + webSocketComm().send_result( + // Pick a rarely-used ID, since we're not responding to a + // specific message. + 0, + // There's not a version that matters. TODO: replace this + // with a more suitable error. + { OutOfSync: [0, 0] }, + ); + } else { + await CodeMirror_load( + codechat_body, + codechat_for_web, + [], + cursor_line, + scroll_line, + ); } } - mathJaxTypeset(codechat_body); - scroll_to_line(cursor_line, scroll_line); - } else { - await CodeMirror_load( - codechat_body, - codechat_for_web, - [], - cursor_line, - scroll_line, - ); - } - autosaveEnabled = true; - - // If tests should be run, then the - // [following global variable](CodeChatEditor-test.mts#CodeChatEditor_test) - // is function that runs them. - if (typeof window.CodeChatEditor_test === "function") { - window.CodeChatEditor_test(); + } finally { + // Use a `finally` block to ensure the cleanup code always run. + // + // Per the discussion at the beginning of this function, the dirty + // contents have been overwritten by contents from the IDE. By the same + // reasoning, restart the autosave timer. + clearAutosaveTimer(); + is_dirty = false; + + // If tests should be run, then the + // [following global variable](CodeChatEditor-test.mts#CodeChatEditor_test) + // is function that runs them. + if (typeof window.CodeChatEditor_test === "function") { + window.CodeChatEditor_test(); + } } }; @@ -304,6 +370,7 @@ const save_lp = (is_dirty: boolean) => { const update: UpdateMessageContents = { // The Framework will fill in this value. file_path: "", + is_re_translation: false, }; if (is_doc_only()) { // TODO: set cursor/scroll position. @@ -463,15 +530,11 @@ const on_save = async (only_if_dirty: boolean = false) => { // Save the provided contents back to the filesystem, by // sending an update message over the websocket. - const webSocketComm = parent.window.CodeChatEditorFramework.webSocketComm; console_log( "CodeChat Editor Client: sent Update - saving document/updating cursor location.", ); - await new Promise((resolve) => { - webSocketComm.send_message({ Update: save_lp(is_dirty) }, () => - resolve(0), - ); - }); + // Don't wait for a response to change `is_dirty`; this boogers up logic. + webSocketComm().send_message({ Update: save_lp(is_dirty) }); is_dirty = false; }; @@ -479,9 +542,6 @@ const on_save = async (only_if_dirty: boolean = false) => { // // Schedule an autosave; call this whenever the document is modified. export const startAutosaveTimer = () => { - if (!autosaveEnabled) { - return; - } // When the document is changed, perform an autosave after no changes have // occurred for a little while. To do this, first cancel any current // timeout... @@ -496,6 +556,7 @@ export const startAutosaveTimer = () => { const clearAutosaveTimer = () => { if (autosaveTimeoutId !== null) { clearTimeout(autosaveTimeoutId); + autosaveTimeoutId = null; } }; diff --git a/client/src/CodeChatEditorFramework.mts b/client/src/CodeChatEditorFramework.mts index ee30ddc..14150c2 100644 --- a/client/src/CodeChatEditorFramework.mts +++ b/client/src/CodeChatEditorFramework.mts @@ -167,21 +167,27 @@ class WebSocketComm { if (contents !== undefined) { // Check and update the version. If this is a diff, // ensure the diff was made against the version of - // the file we have. + // the file we have. Ignore re-translation version errors, instead ignoring the update. if ("Diff" in contents.source) { if ( contents.source.Diff.version !== this.version ) { - report_error( - `Out of sync: Client version ${this.version} !== incoming version ${contents.source.Diff.version}.`, - ); - this.send_result(id, { - OutOfSync: [ - this.version, - contents.source.Diff.version, - ], - }); + if (current_update.is_re_translation) { + console_log( + `Ignoring out-of-sync re-translation update.`, + ); + } else { + report_error( + `Out of sync: Client version ${this.version} !== incoming version ${contents.source.Diff.version}.`, + ); + this.send_result(id, { + OutOfSync: [ + this.version, + contents.source.Diff.version, + ], + }); + } return; } } @@ -199,6 +205,7 @@ class WebSocketComm { // `on_dom_content_loaded` in the Client. await set_content( contents, + current_update.is_re_translation, current_update.cursor_position, ); } else { @@ -214,6 +221,7 @@ class WebSocketComm { this.is_loading = false; await set_content( contents, + current_update.is_re_translation, current_update.cursor_position, current_update.scroll_position, ); @@ -418,6 +426,7 @@ const get_client = () => root_iframe?.contentWindow?.CodeChatEditor; // in the `root_iframe`. const set_content = async ( contents: CodeChatForWeb, + is_re_translation: boolean, cursor_line?: number, scroll_line?: number, ) => { @@ -438,6 +447,7 @@ const set_content = async ( } else { await root_iframe!.contentWindow!.CodeChatEditor.open_lp( contents, + is_re_translation, cursor_line, scroll_line, ); diff --git a/client/src/tinymce-config.mts b/client/src/tinymce-config.mts index 2b64624..4672316 100644 --- a/client/src/tinymce-config.mts +++ b/client/src/tinymce-config.mts @@ -174,5 +174,5 @@ export const init = async ( // Use these combined options to // [init](https://www.tiny.cloud/docs/tinymce/6/apis/tinymce.root/#init) // TinyMCE. - return tinymce.init(combinedOptions); + return await tinymce.init(combinedOptions); }; diff --git a/extensions/VSCode/Cargo.lock b/extensions/VSCode/Cargo.lock index 29c6783..4ce80fb 100644 --- a/extensions/VSCode/Cargo.lock +++ b/extensions/VSCode/Cargo.lock @@ -753,18 +753,18 @@ dependencies = [ [[package]] name = "derive_more" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b768e943bed7bf2cab53df09f4bc34bfd217cdb57d971e769874c9a6710618" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d286bfdaf75e988b4a78e013ecd79c581e06399ab53fbacd2d916c2f904f30b" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ "convert_case", "proc-macro2", @@ -1424,9 +1424,9 @@ checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "7ee5b5339afb4c41626dde77b7a611bd4f2c202b897852b4bcf5d03eddc61010" [[package]] name = "jni" @@ -2293,9 +2293,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "62049b2877bf12821e8f9ad256ee38fdc31db7387ec2d3b3f403024de2034aea" [[package]] name = "same-file" @@ -2360,9 +2360,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.146" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "217ca874ae0207aac254aa02c957ded05585a90892cc8d87f9e5fa49669dadd8" dependencies = [ "itoa", "memchr", diff --git a/extensions/VSCode/package.json b/extensions/VSCode/package.json index fc22eef..09461c7 100644 --- a/extensions/VSCode/package.json +++ b/extensions/VSCode/package.json @@ -88,8 +88,8 @@ "@types/escape-html": "^1.0.4", "@types/node": "^24.10.4", "@types/vscode": "1.61.0", - "@typescript-eslint/eslint-plugin": "^8.50.0", - "@typescript-eslint/parser": "^8.50.0", + "@typescript-eslint/eslint-plugin": "^8.50.1", + "@typescript-eslint/parser": "^8.50.1", "@vscode/vsce": "^3.7.1", "chalk": "^5.6.2", "esbuild": "^0.27.2", @@ -102,7 +102,7 @@ "ovsx": "^0.10.7", "prettier": "^3.7.4", "typescript": "^5.9.3", - "typescript-eslint": "^8.50.0" + "typescript-eslint": "^8.50.1" }, "optionalDependencies": { "bufferutil": "^4.1.0" diff --git a/extensions/VSCode/pnpm-lock.yaml b/extensions/VSCode/pnpm-lock.yaml index cf32b11..e643f3f 100644 --- a/extensions/VSCode/pnpm-lock.yaml +++ b/extensions/VSCode/pnpm-lock.yaml @@ -37,11 +37,11 @@ importers: specifier: 1.61.0 version: 1.61.0 '@typescript-eslint/eslint-plugin': - specifier: ^8.50.0 - version: 8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) + specifier: ^8.50.1 + version: 8.50.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) '@typescript-eslint/parser': - specifier: ^8.50.0 - version: 8.50.0(eslint@9.39.2)(typescript@5.9.3) + specifier: ^8.50.1 + version: 8.50.1(eslint@9.39.2)(typescript@5.9.3) '@vscode/vsce': specifier: ^3.7.1 version: 3.7.1 @@ -59,7 +59,7 @@ importers: version: 10.1.8(eslint@9.39.2) eslint-plugin-import: specifier: ^2.32.0 - version: 2.32.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2) + version: 2.32.0(@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2) eslint-plugin-node: specifier: ^11.1.0 version: 11.1.0(eslint@9.39.2) @@ -79,8 +79,8 @@ importers: specifier: ^5.9.3 version: 5.9.3 typescript-eslint: - specifier: ^8.50.0 - version: 8.50.0(eslint@9.39.2)(typescript@5.9.3) + specifier: ^8.50.1 + version: 8.50.1(eslint@9.39.2)(typescript@5.9.3) optionalDependencies: bufferutil: specifier: ^4.1.0 @@ -1096,63 +1096,63 @@ packages: '@types/vscode@1.61.0': resolution: {integrity: sha512-9k5Nwq45hkRwdfCFY+eKXeQQSbPoA114mF7U/4uJXRBJeGIO7MuJdhF1PnaDN+lllL9iKGQtd6FFXShBXMNaFg==} - '@typescript-eslint/eslint-plugin@8.50.0': - resolution: {integrity: sha512-O7QnmOXYKVtPrfYzMolrCTfkezCJS9+ljLdKW/+DCvRsc3UAz+sbH6Xcsv7p30+0OwUbeWfUDAQE0vpabZ3QLg==} + '@typescript-eslint/eslint-plugin@8.50.1': + resolution: {integrity: sha512-PKhLGDq3JAg0Jk/aK890knnqduuI/Qj+udH7wCf0217IGi4gt+acgCyPVe79qoT+qKUvHMDQkwJeKW9fwl8Cyw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.50.0 + '@typescript-eslint/parser': ^8.50.1 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.50.0': - resolution: {integrity: sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==} + '@typescript-eslint/parser@8.50.1': + resolution: {integrity: sha512-hM5faZwg7aVNa819m/5r7D0h0c9yC4DUlWAOvHAtISdFTc8xB86VmX5Xqabrama3wIPJ/q9RbGS1worb6JfnMg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.50.0': - resolution: {integrity: sha512-Cg/nQcL1BcoTijEWyx4mkVC56r8dj44bFDvBdygifuS20f3OZCHmFbjF34DPSi07kwlFvqfv/xOLnJ5DquxSGQ==} + '@typescript-eslint/project-service@8.50.1': + resolution: {integrity: sha512-E1ur1MCVf+YiP89+o4Les/oBAVzmSbeRB0MQLfSlYtbWU17HPxZ6Bhs5iYmKZRALvEuBoXIZMOIRRc/P++Ortg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.50.0': - resolution: {integrity: sha512-xCwfuCZjhIqy7+HKxBLrDVT5q/iq7XBVBXLn57RTIIpelLtEIZHXAF/Upa3+gaCpeV1NNS5Z9A+ID6jn50VD4A==} + '@typescript-eslint/scope-manager@8.50.1': + resolution: {integrity: sha512-mfRx06Myt3T4vuoHaKi8ZWNTPdzKPNBhiblze5N50//TSHOAQQevl/aolqA/BcqqbJ88GUnLqjjcBc8EWdBcVw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.50.0': - resolution: {integrity: sha512-vxd3G/ybKTSlm31MOA96gqvrRGv9RJ7LGtZCn2Vrc5htA0zCDvcMqUkifcjrWNNKXHUU3WCkYOzzVSFBd0wa2w==} + '@typescript-eslint/tsconfig-utils@8.50.1': + resolution: {integrity: sha512-ooHmotT/lCWLXi55G4mvaUF60aJa012QzvLK0Y+Mp4WdSt17QhMhWOaBWeGTFVkb2gDgBe19Cxy1elPXylslDw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.50.0': - resolution: {integrity: sha512-7OciHT2lKCewR0mFoBrvZJ4AXTMe/sYOe87289WAViOocEmDjjv8MvIOT2XESuKj9jp8u3SZYUSh89QA4S1kQw==} + '@typescript-eslint/type-utils@8.50.1': + resolution: {integrity: sha512-7J3bf022QZE42tYMO6SL+6lTPKFk/WphhRPe9Tw/el+cEwzLz1Jjz2PX3GtGQVxooLDKeMVmMt7fWpYRdG5Etg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.50.0': - resolution: {integrity: sha512-iX1mgmGrXdANhhITbpp2QQM2fGehBse9LbTf0sidWK6yg/NE+uhV5dfU1g6EYPlcReYmkE9QLPq/2irKAmtS9w==} + '@typescript-eslint/types@8.50.1': + resolution: {integrity: sha512-v5lFIS2feTkNyMhd7AucE/9j/4V9v5iIbpVRncjk/K0sQ6Sb+Np9fgYS/63n6nwqahHQvbmujeBL7mp07Q9mlA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.50.0': - resolution: {integrity: sha512-W7SVAGBR/IX7zm1t70Yujpbk+zdPq/u4soeFSknWFdXIFuWsBGBOUu/Tn/I6KHSKvSh91OiMuaSnYp3mtPt5IQ==} + '@typescript-eslint/typescript-estree@8.50.1': + resolution: {integrity: sha512-woHPdW+0gj53aM+cxchymJCrh0cyS7BTIdcDxWUNsclr9VDkOSbqC13juHzxOmQ22dDkMZEpZB+3X1WpUvzgVQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.50.0': - resolution: {integrity: sha512-87KgUXET09CRjGCi2Ejxy3PULXna63/bMYv72tCAlDJC3Yqwln0HiFJ3VJMst2+mEtNtZu5oFvX4qJGjKsnAgg==} + '@typescript-eslint/utils@8.50.1': + resolution: {integrity: sha512-lCLp8H1T9T7gPbEuJSnHwnSuO9mDf8mfK/Nion5mZmiEaQD9sWf9W4dfeFqRyqRjF06/kBuTmAqcs9sewM2NbQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.50.0': - resolution: {integrity: sha512-Xzmnb58+Db78gT/CCj/PVCvK+zxbnsw6F+O1oheYszJbBSdEjVhQi3C/Xttzxgi/GLmpvOggRs1RFpiJ8+c34Q==} + '@typescript-eslint/visitor-keys@8.50.1': + resolution: {integrity: sha512-IrDKrw7pCRUR94zeuCSUWQ+w8JEf5ZX5jl/e6AHGSLi1/zIr0lgutfn/7JpfCey+urpgQEdrZVYzCaVVKiTwhQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@typespec/ts-http-runtime@0.3.2': @@ -2822,8 +2822,8 @@ packages: typed-rest-client@1.8.11: resolution: {integrity: sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==} - typescript-eslint@8.50.0: - resolution: {integrity: sha512-Q1/6yNUmCpH94fbgMUMg2/BSAr/6U7GBk61kZTv1/asghQOWOjTlp9K8mixS5NcJmm2creY+UFfGeW/+OcA64A==} + typescript-eslint@8.50.1: + resolution: {integrity: sha512-ytTHO+SoYSbhAH9CrYnMhiLx8To6PSSvqnvXyPUgPETCvB6eBKmTI9w6XMPS3HsBRGkwTVBX+urA8dYQx6bHfQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -3867,14 +3867,14 @@ snapshots: '@types/vscode@1.61.0': {} - '@typescript-eslint/eslint-plugin@8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.50.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.50.0 - '@typescript-eslint/type-utils': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.50.0 + '@typescript-eslint/parser': 8.50.1(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.50.1 + '@typescript-eslint/type-utils': 8.50.1(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/utils': 8.50.1(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.50.1 eslint: 9.39.2 ignore: 7.0.5 natural-compare: 1.4.0 @@ -3883,41 +3883,41 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.50.0 - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.50.0 + '@typescript-eslint/scope-manager': 8.50.1 + '@typescript-eslint/types': 8.50.1 + '@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.50.1 debug: 4.4.3 eslint: 9.39.2 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.50.0(typescript@5.9.3)': + '@typescript-eslint/project-service@8.50.1(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.50.0(typescript@5.9.3) - '@typescript-eslint/types': 8.50.0 + '@typescript-eslint/tsconfig-utils': 8.50.1(typescript@5.9.3) + '@typescript-eslint/types': 8.50.1 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.50.0': + '@typescript-eslint/scope-manager@8.50.1': dependencies: - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/visitor-keys': 8.50.0 + '@typescript-eslint/types': 8.50.1 + '@typescript-eslint/visitor-keys': 8.50.1 - '@typescript-eslint/tsconfig-utils@8.50.0(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.50.1(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.50.0(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.50.1(eslint@9.39.2)(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/types': 8.50.1 + '@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.50.1(eslint@9.39.2)(typescript@5.9.3) debug: 4.4.3 eslint: 9.39.2 ts-api-utils: 2.1.0(typescript@5.9.3) @@ -3925,14 +3925,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.50.0': {} + '@typescript-eslint/types@8.50.1': {} - '@typescript-eslint/typescript-estree@8.50.0(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.50.1(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.50.0(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.50.0(typescript@5.9.3) - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/visitor-keys': 8.50.0 + '@typescript-eslint/project-service': 8.50.1(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.50.1(typescript@5.9.3) + '@typescript-eslint/types': 8.50.1 + '@typescript-eslint/visitor-keys': 8.50.1 debug: 4.4.3 minimatch: 9.0.5 semver: 7.7.3 @@ -3942,20 +3942,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.50.0(eslint@9.39.2)(typescript@5.9.3)': + '@typescript-eslint/utils@8.50.1(eslint@9.39.2)(typescript@5.9.3)': dependencies: '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2) - '@typescript-eslint/scope-manager': 8.50.0 - '@typescript-eslint/types': 8.50.0 - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.50.1 + '@typescript-eslint/types': 8.50.1 + '@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3) eslint: 9.39.2 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.50.0': + '@typescript-eslint/visitor-keys@8.50.1': dependencies: - '@typescript-eslint/types': 8.50.0 + '@typescript-eslint/types': 8.50.1 eslint-visitor-keys: 4.2.1 '@typespec/ts-http-runtime@0.3.2': @@ -4549,11 +4549,11 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.50.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/parser': 8.50.1(eslint@9.39.2)(typescript@5.9.3) eslint: 9.39.2 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: @@ -4565,7 +4565,7 @@ snapshots: eslint-utils: 2.1.0 regexpp: 3.2.0 - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -4576,7 +4576,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.39.2 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@9.39.2) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -4588,7 +4588,7 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.50.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/parser': 8.50.1(eslint@9.39.2)(typescript@5.9.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -5890,12 +5890,12 @@ snapshots: tunnel: 0.0.6 underscore: 1.13.7 - typescript-eslint@8.50.0(eslint@9.39.2)(typescript@5.9.3): + typescript-eslint@8.50.1(eslint@9.39.2)(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/parser': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.50.1(@typescript-eslint/parser@8.50.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/parser': 8.50.1(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.50.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.50.1(eslint@9.39.2)(typescript@5.9.3) eslint: 9.39.2 typescript: 5.9.3 transitivePeerDependencies: diff --git a/server/Cargo.lock b/server/Cargo.lock index 14feccf..fb0ecf1 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -1041,18 +1041,18 @@ dependencies = [ [[package]] name = "derive_more" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b768e943bed7bf2cab53df09f4bc34bfd217cdb57d971e769874c9a6710618" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d286bfdaf75e988b4a78e013ecd79c581e06399ab53fbacd2d916c2f904f30b" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ "convert_case", "proc-macro2", @@ -1989,9 +1989,9 @@ checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "7ee5b5339afb4c41626dde77b7a611bd4f2c202b897852b4bcf5d03eddc61010" [[package]] name = "jiff" @@ -2116,9 +2116,9 @@ dependencies = [ [[package]] name = "libz-rs-sys" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15413ef615ad868d4d65dce091cb233b229419c7c0c4bcaa746c0901c49ff39c" +checksum = "c10501e7805cee23da17c7790e59df2870c0d4043ec6d03f67d31e2b53e77415" dependencies = [ "zlib-rs", ] @@ -2634,9 +2634,9 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "f59e70c4aef1e55797c2e8fd94a4f2a973fc972cfde0e0b05f683667b0cd39dd" [[package]] name = "portable-atomic-util" @@ -2980,9 +2980,9 @@ checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "reqwest" -version = "0.12.26" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b4c14b2d9afca6a60277086b0cc6a6ae0b568f6f7916c943a8cdc79f8be240f" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64", "bytes", @@ -3109,9 +3109,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "62049b2877bf12821e8f9ad256ee38fdc31db7387ec2d3b3f403024de2034aea" [[package]] name = "same-file" @@ -3242,9 +3242,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.146" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "217ca874ae0207aac254aa02c957ded05585a90892cc8d87f9e5fa49669dadd8" dependencies = [ "indexmap 2.12.1", "itoa", @@ -4898,9 +4898,9 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f936044d677be1a1168fae1d03b583a285a5dd9d8cbf7b24c23aa1fc775235" +checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" [[package]] name = "zopfli" diff --git a/server/src/ide.rs b/server/src/ide.rs index 7492bcc..21037d9 100644 --- a/server/src/ide.rs +++ b/server/src/ide.rs @@ -257,6 +257,9 @@ impl CodeChatEditorServer { ) -> std::io::Result { self.send_message_timeout(EditorMessageContents::Update(UpdateMessageContents { file_path, + cursor_position, + scroll_position: scroll_position.map(|x| x as f32), + is_re_translation: false, contents: option_contents.map(|contents| CodeChatForWeb { metadata: SourceFileMetadata { mode: "".to_string(), @@ -267,8 +270,6 @@ impl CodeChatEditorServer { }), version: contents.1, }), - cursor_position, - scroll_position: scroll_position.map(|x| x as f32), })) .await } diff --git a/server/src/ide/filewatcher.rs b/server/src/ide/filewatcher.rs index ecd3b27..57d7e0d 100644 --- a/server/src/ide/filewatcher.rs +++ b/server/src/ide/filewatcher.rs @@ -527,6 +527,9 @@ async fn processing_task( id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: current_filepath_str.to_string(), + cursor_position: None, + scroll_position: None, + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { // The IDE doesn't need to provide this. @@ -544,8 +547,6 @@ async fn processing_task( // difference with fractional values. version: random::() as f64, }), - cursor_position: None, - scroll_position: None, }), })); id += MESSAGE_ID_INCREMENT; @@ -927,9 +928,10 @@ mod tests { id: INITIAL_CLIENT_MESSAGE_ID, message: EditorMessageContents::Update(UpdateMessageContents { file_path: file_path.clone(), - contents: None, cursor_position: None, scroll_position: None, + is_re_translation: false, + contents: None, }), }) .await @@ -975,6 +977,9 @@ mod tests { id: INITIAL_CLIENT_MESSAGE_ID + 4.0 * MESSAGE_ID_INCREMENT, message: EditorMessageContents::Update(UpdateMessageContents { file_path: "".to_string(), + cursor_position: None, + scroll_position: None, + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "".to_string(), @@ -985,8 +990,6 @@ mod tests { }), version: 0.0, }), - cursor_position: None, - scroll_position: None, }), }) .await @@ -1010,6 +1013,9 @@ mod tests { id: INITIAL_CLIENT_MESSAGE_ID + 5.0 * MESSAGE_ID_INCREMENT, message: EditorMessageContents::Update(UpdateMessageContents { file_path: file_path.clone(), + cursor_position: None, + scroll_position: None, + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "nope".to_string(), @@ -1020,8 +1026,6 @@ mod tests { }), version: 1.0, }), - cursor_position: None, - scroll_position: None, }), }) .await @@ -1046,6 +1050,9 @@ mod tests { id: INITIAL_CLIENT_MESSAGE_ID + 6.0 * MESSAGE_ID_INCREMENT, message: EditorMessageContents::Update(UpdateMessageContents { file_path: file_path.clone(), + cursor_position: None, + scroll_position: None, + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -1056,8 +1063,6 @@ mod tests { }), version: 2.0, }), - cursor_position: None, - scroll_position: None, }), }) .await @@ -1097,6 +1102,9 @@ mod tests { INITIAL_IDE_MESSAGE_ID + MESSAGE_ID_INCREMENT, UpdateMessageContents { file_path: file_path.clone(), + cursor_position: None, + scroll_position: None, + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -1107,8 +1115,6 @@ mod tests { }), version: msg.1.contents.as_ref().unwrap().version, }), - cursor_position: None, - scroll_position: None, } ) ); diff --git a/server/src/ide/vscode/tests.rs b/server/src/ide/vscode/tests.rs index 9676747..d9919b3 100644 --- a/server/src/ide/vscode/tests.rs +++ b/server/src/ide/vscode/tests.rs @@ -262,9 +262,10 @@ async fn test_vscode_ide_websocket1() { id: INITIAL_IDE_MESSAGE_ID, message: EditorMessageContents::Update(UpdateMessageContents { file_path: "".to_string(), - contents: None, cursor_position: None, scroll_position: None, + is_re_translation: false, + contents: None, }), }, ) @@ -542,6 +543,9 @@ async fn test_vscode_ide_websocket8() { id: INITIAL_MESSAGE_ID + 2.0 * MESSAGE_ID_INCREMENT, message: EditorMessageContents::Update(UpdateMessageContents { file_path: file_path_str.clone(), + cursor_position: None, + scroll_position: None, + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -558,8 +562,6 @@ async fn test_vscode_ide_websocket8() { }), version: 0.0, }), - cursor_position: None, - scroll_position: None, }) } ); @@ -650,6 +652,9 @@ async fn test_vscode_ide_websocket7() { id: INITIAL_IDE_MESSAGE_ID, message: EditorMessageContents::Update(UpdateMessageContents { file_path: file_path_str.clone(), + cursor_position: None, + scroll_position: None, + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -660,8 +665,6 @@ async fn test_vscode_ide_websocket7() { }), version: 0.0, }), - cursor_position: None, - scroll_position: None, }), }, ) @@ -672,6 +675,9 @@ async fn test_vscode_ide_websocket7() { id: INITIAL_IDE_MESSAGE_ID, message: EditorMessageContents::Update(UpdateMessageContents { file_path: file_path_str.clone(), + cursor_position: None, + scroll_position: None, + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -688,8 +694,6 @@ async fn test_vscode_ide_websocket7() { }), version: 0.0, }), - cursor_position: None, - scroll_position: None, }) } ); @@ -718,6 +722,9 @@ async fn test_vscode_ide_websocket7() { id: INITIAL_IDE_MESSAGE_ID + 2.0 * MESSAGE_ID_INCREMENT, message: EditorMessageContents::Update(UpdateMessageContents { file_path: file_path_str.clone(), + cursor_position: None, + scroll_position: None, + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -734,8 +741,6 @@ async fn test_vscode_ide_websocket7() { }), version: 1.0, }), - cursor_position: None, - scroll_position: None, }), }, ) @@ -746,6 +751,9 @@ async fn test_vscode_ide_websocket7() { id: INITIAL_IDE_MESSAGE_ID + 2.0 * MESSAGE_ID_INCREMENT, message: EditorMessageContents::Update(UpdateMessageContents { file_path: file_path_str.clone(), + cursor_position: None, + scroll_position: None, + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -767,8 +775,6 @@ async fn test_vscode_ide_websocket7() { }), version: 1.0, }), - cursor_position: None, - scroll_position: None, }) } ); @@ -808,6 +814,9 @@ async fn test_vscode_ide_websocket6() { id: INITIAL_CLIENT_MESSAGE_ID, message: EditorMessageContents::Update(UpdateMessageContents { file_path: file_path.clone(), + cursor_position: None, + scroll_position: None, + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -824,8 +833,6 @@ async fn test_vscode_ide_websocket6() { }), version: 0.0, }), - cursor_position: None, - scroll_position: None, }), }, ) @@ -836,6 +843,9 @@ async fn test_vscode_ide_websocket6() { id: INITIAL_CLIENT_MESSAGE_ID, message: EditorMessageContents::Update(UpdateMessageContents { file_path, + cursor_position: None, + scroll_position: None, + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -846,8 +856,6 @@ async fn test_vscode_ide_websocket6() { }), version: 0.0, }), - cursor_position: None, - scroll_position: None, }) } ); @@ -973,6 +981,9 @@ async fn test_vscode_ide_websocket4() { id: INITIAL_MESSAGE_ID + 2.0 * MESSAGE_ID_INCREMENT, message: EditorMessageContents::Update(UpdateMessageContents { file_path: file_path_str.clone(), + cursor_position: None, + scroll_position: None, + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -993,8 +1004,6 @@ async fn test_vscode_ide_websocket4() { .unwrap() .version, }), - cursor_position: None, - scroll_position: None, }) } ); diff --git a/server/src/processing.rs b/server/src/processing.rs index a85f26c..4b6e806 100644 --- a/server/src/processing.rs +++ b/server/src/processing.rs @@ -1063,7 +1063,7 @@ fn html_to_tree(html: &str) -> io::Result> { // A framework to transform HTML by parsing it to a DOM tree, walking the tree, // then serializing the tree back to an HTML string. -fn transform_html)>(html: &str, transform: T) -> io::Result { +pub fn transform_html)>(html: &str, transform: T) -> io::Result { let tree = html_to_tree(html)?; transform(tree.clone()); diff --git a/server/src/translation.rs b/server/src/translation.rs index 3583c44..dbd7659 100644 --- a/server/src/translation.rs +++ b/server/src/translation.rs @@ -226,7 +226,7 @@ use crate::{ CodeChatForWeb, CodeMirror, CodeMirrorDiff, CodeMirrorDiffable, CodeMirrorDocBlock, CodeMirrorDocBlockVec, SourceFileMetadata, TranslationResultsString, codechat_for_web_to_source, diff_code_mirror_doc_blocks, diff_str, - source_to_codechat_for_web_string, + source_to_codechat_for_web_string, transform_html, }, queue_send, queue_send_func, webserver::{ @@ -853,9 +853,10 @@ impl TranslationTask { 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: None, cursor_position: update.cursor_position, scroll_position: update.scroll_position, + is_re_translation: false, + contents: None, }), })); Ok(ResultOkTypes::Void) @@ -907,9 +908,10 @@ impl TranslationTask { 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(client_contents), cursor_position: update.cursor_position, scroll_position: update.scroll_position, + is_re_translation: false, + contents: Some(client_contents), }), })); // Update to the latest code after @@ -941,6 +943,9 @@ impl TranslationTask { 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(), + cursor_position: update.cursor_position, + scroll_position: update.scroll_position, + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { // Since this is raw data, `mode` doesn't @@ -953,8 +958,6 @@ impl TranslationTask { }), version: contents.version }), - cursor_position: update.cursor_position, - scroll_position: update.scroll_position, }), })); Ok(ResultOkTypes::Void) @@ -1052,14 +1055,12 @@ impl TranslationTask { // Translate back to the Client to see if there are // any changes after this conversion. Only check // CodeChat documents, not Markdown docs. - if cfw.metadata.mode != MARKDOWN_MODE - && let Ok(ccfws) = source_to_codechat_for_web_string( - &new_source_code, - &clean_file_path, - cfw.version, - false, - ) - && let TranslationResultsString::CodeChat(ccfw) = ccfws.0 + if let Ok(ccfws) = source_to_codechat_for_web_string( + &new_source_code, + &clean_file_path, + cfw.version, + false, + ) && let TranslationResultsString::CodeChat(ccfw) = ccfws.0 && let CodeMirrorDiffable::Plain(code_mirror_translated) = ccfw.source && self.sent_full @@ -1068,27 +1069,40 @@ impl TranslationTask { // changes (such as line wrapping in doc blocks // which changes line numbering, creation of a // new doc block from previous code block text, - // or updates from future document intelligence - // such as renamed headings, etc.) For doc - // blocks that haven't been edited by TinyMCE, - // this is easy; equality is sufficient. Doc - // blocks that have been edited are a different - // case: TinyMCE removes newlines, causing a lot - // of "changes" to re-insert these. Therefore, - // use the following approach: + // insertion of math, or updates from future + // document intelligence such as renamed + // headings, etc.). Note that strict HTML + // comparison fails, since TinyMCE modifies + // whitespace and some characters; for example, + // `👨‍👦` becomes `👨‍👦` after processing by + // TinyMCE. Therefore, HTML processed by TinyMCE + // needs to be normalized before it can be + // compared. // - // 1. Compare the `doc` values. If they differ, - // then the the Client needs an update. - // 2. Compare each code block using simple - // equality. If this fails, compare the doc - // block text excluding newlines. If still - // different, then the Client needs an - // update. - if code_mirror_translated.doc != self.code_mirror_doc - || !doc_block_compare( - &code_mirror_translated.doc_blocks, - self.code_mirror_doc_blocks.as_ref().unwrap(), - ) + // 1. Document-only: HTML is stored in `.doc`; + // ignore `.doc_blocks`. + // 2. Normal mode: HTML is stored in + // `.doc_blocks`; perform a binary compare of + // `.doc`, then an HTML comparison of + // `.doc_blocks`. + // + // It looks like comparing HTML is risky, since + // TinyMCE (or something) store emojis + // differently. Perhaps we need to compare + // Markdown instead of HTML? Or HTML after + // processing? The second seems easier. + let is_markdown_mode = cfw.metadata.mode == MARKDOWN_MODE; + if (is_markdown_mode + && !compare_html( + &code_mirror_translated.doc, + &self.code_mirror_doc, + )) + || (!is_markdown_mode + && (code_mirror_translated.doc != self.code_mirror_doc + || !doc_block_compare( + &code_mirror_translated.doc_blocks, + self.code_mirror_doc_blocks.as_ref().unwrap(), + ))) { // Use a whole number to avoid encoding // differences with fractional values. @@ -1109,12 +1123,13 @@ impl TranslationTask { message: EditorMessageContents::Update( UpdateMessageContents { file_path: update_message_contents.file_path, - contents: Some(client_contents), // Don't change the current position, since // the Client editing position should be // left undisturbed. cursor_position: None, - scroll_position: None + scroll_position: None, + is_re_translation: true, + contents: Some(client_contents), } ) })); @@ -1170,9 +1185,10 @@ impl TranslationTask { 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, + is_re_translation: false, + contents: codechat_for_web, }) })); } @@ -1192,6 +1208,38 @@ fn eol_convert(s: String, eol_type: &EolType) -> String { } } +// TinyMCE replaces newlines inside paragraphs with a space and (I think) avoids +// surrogate pairs by breaking them into a series of UTF-16 characters. +// Therefore, to compare HTML, normalize HTML touched by TinyMCE first. +fn compare_html( + // A string containing HTML that's been normalized by html5ever. + normalized_html: &str, + // A string containing HTML that's not normalized; for example, data after + // processing by TinyMCE. + raw_html: &str, +) -> bool { + // The normalized HTML is word-wrapped, while the raw HTML is not. Use this + // to ignore the differences between newlines and spaces, in order to ignore + // these differences. + fn map_newlines_to_spaces<'a>( + s: &'a str, + ) -> std::iter::Map, impl FnMut(char) -> char> { + s.trim() + .chars() + .map(|c: char| if c == '\n' { ' ' } else { c }) + } + + // Transforming the HTML with an empty transform normalizes it but leave it + // otherwise unchanged. + if let Ok(normalized_raw_html) = transform_html(raw_html, |_node| {}) { + // Ignore word wrapping and leading/trailing whitespace in the + // comparison. + map_newlines_to_spaces(normalized_html).eq(map_newlines_to_spaces(&normalized_raw_html)) + } else { + false + } +} + // Given a vector of two doc blocks, compare them, ignoring newlines. fn doc_block_compare(a: &CodeMirrorDocBlockVec, b: &CodeMirrorDocBlockVec) -> bool { if a.len() != b.len() { @@ -1205,22 +1253,13 @@ fn doc_block_compare(a: &CodeMirrorDocBlockVec, b: &CodeMirrorDocBlockVec) -> bo && a.to == b.to && a.indent == b.indent && a.delimiter == b.delimiter - && (a.contents == b.contents - // TinyMCE replaces newlines inside paragraphs with a space; for - // a crude comparison, translate all newlines back to spaces, - // then ignore leading/trailing newlines. - || map_newlines_to_spaces(&a.contents).eq(map_newlines_to_spaces(&b.contents))) + // Most doc blocks haven't been touched by TinyMCE. Try a fast + // binary compare first. + && (a.contents == b.contents || + compare_html(&a.contents, &b.contents)) }) } -fn map_newlines_to_spaces<'a>( - s: &'a str, -) -> std::iter::Map, impl FnMut(char) -> char> { - s.trim() - .chars() - .map(|c: char| if c == '\n' { ' ' } else { c }) -} - // Provide a simple debug function that prints only the first // `MAX_MESSAGE_LENGTH` characters of the provided value. fn debug_shorten(val: T) -> String { diff --git a/server/src/webserver.rs b/server/src/webserver.rs index 724de16..7e5df7f 100644 --- a/server/src/webserver.rs +++ b/server/src/webserver.rs @@ -340,9 +340,6 @@ pub struct UpdateMessageContents { /// transition times when the IDE and Client have different files loaded, /// guaranteeing to updates are still applied to the correct file. pub file_path: String, - /// The contents of this file. - #[serde(skip_serializing_if = "Option::is_none")] - pub contents: Option, /// The line in the file where the cursor is located. TODO: Selections are /// not yet supported. #[serde(skip_serializing_if = "Option::is_none")] @@ -350,6 +347,12 @@ pub struct UpdateMessageContents { /// The line at the top of the screen. #[serde(skip_serializing_if = "Option::is_none")] pub scroll_position: Option, + /// True if this is a re-translation, which can be ignored if the receiver's + /// document is dirty. Therefore, this is written by the IDE and read by the Client and IDE; conversely, it's ignored by the Server. The IDE and Client should set this value to false. + pub is_re_translation: bool, + /// The contents of this file. + #[serde(skip_serializing_if = "Option::is_none")] + pub contents: Option, } /// ### Data structures used by the webserver @@ -1017,9 +1020,10 @@ pub async fn file_to_response( // `simple_http_response` contains the Client. Some(UpdateMessageContents { file_path: file_path.to_string(), - contents: Some(codechat_for_web), cursor_position: None, scroll_position: None, + is_re_translation: false, + contents: Some(codechat_for_web), }), ) } diff --git a/server/tests/overall_1.rs b/server/tests/overall_1.rs index 9db3321..178e444 100644 --- a/server/tests/overall_1.rs +++ b/server/tests/overall_1.rs @@ -123,9 +123,10 @@ async fn test_server_core( id: client_id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: path_str.clone(), - contents: None, cursor_position: Some(1), - scroll_position: Some(1.0) + scroll_position: Some(1.0), + is_re_translation: false, + contents: None, }) } ); @@ -148,6 +149,9 @@ async fn test_server_core( id: client_id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: path_str.clone(), + cursor_position: Some(1), + scroll_position: Some(1.0), + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -163,8 +167,6 @@ async fn test_server_core( }), version: client_version, }), - cursor_position: Some(1), - scroll_position: Some(1.0) }) } ); @@ -183,6 +185,9 @@ async fn test_server_core( id: client_id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: path_str.clone(), + cursor_position: Some(1), + scroll_position: Some(1.0), + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -198,8 +203,6 @@ async fn test_server_core( }), version: client_version, }), - cursor_position: Some(1), - scroll_position: Some(1.0), }), } ); @@ -222,9 +225,10 @@ async fn test_server_core( id: client_id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: path_str.clone(), - contents: None, cursor_position: Some(2), - scroll_position: Some(1.0) + scroll_position: Some(1.0), + is_re_translation: false, + contents: None, }) } ); @@ -242,9 +246,10 @@ async fn test_server_core( id: client_id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: path_str.clone(), - contents: None, cursor_position: Some(1), - scroll_position: Some(1.0) + scroll_position: Some(1.0), + is_re_translation: false, + contents: None, }) } ); @@ -263,6 +268,9 @@ async fn test_server_core( id: client_id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: path_str.clone(), + cursor_position: Some(2), + scroll_position: Some(1.0), + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -278,8 +286,6 @@ async fn test_server_core( }), version: client_version, }), - cursor_position: Some(2), - scroll_position: Some(1.0) }) } ); @@ -379,6 +385,9 @@ async fn test_server_core( id: client_id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: md_path_str.clone(), + cursor_position: None, + scroll_position: None, + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: MARKDOWN_MODE.to_string() @@ -397,8 +406,24 @@ async fn test_server_core( }), version: client_version, }), + }) + } + ); + codechat_server.send_result(client_id, None).await.unwrap(); + client_id += MESSAGE_ID_INCREMENT; + + // Get the resulting cursor position update after the edit. + let msg = codechat_server.get_message_timeout(TIMEOUT).await.unwrap(); + assert_eq!( + msg, + EditorMessage { + id: client_id, + message: EditorMessageContents::Update(UpdateMessageContents { + file_path: md_path_str.clone(), cursor_position: None, - scroll_position: None + scroll_position: None, + is_re_translation: false, + contents: None, }) } ); @@ -744,6 +769,9 @@ async fn test_client_updates_core( id: client_id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: path_str.clone(), + cursor_position: Some(1), + scroll_position: Some(1.0), + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -759,8 +787,6 @@ async fn test_client_updates_core( }), version: client_version, }), - cursor_position: Some(1), - scroll_position: Some(1.0) }) } ); @@ -796,6 +822,9 @@ async fn test_client_updates_core( id: client_id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: path_str.clone(), + cursor_position: Some(4), + scroll_position: Some(1.0), + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -811,8 +840,6 @@ async fn test_client_updates_core( }), version: new_client_version, }), - cursor_position: Some(4), - scroll_position: Some(1.0) }) } ); @@ -861,6 +888,9 @@ async fn test_client_updates_core( id: client_id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: path_str.clone(), + cursor_position: Some(2), + scroll_position: Some(1.0), + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -876,8 +906,6 @@ async fn test_client_updates_core( }), version: new_client_version, }), - cursor_position: Some(2), - scroll_position: Some(1.0) }) } ); diff --git a/server/tests/overall_2.rs b/server/tests/overall_2.rs index f264c4c..82b7ea3 100644 --- a/server/tests/overall_2.rs +++ b/server/tests/overall_2.rs @@ -112,9 +112,10 @@ async fn test_4_core( id: client_id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: path_str.clone(), - contents: None, cursor_position: Some(1), - scroll_position: Some(1.0) + scroll_position: Some(1.0), + is_re_translation: false, + contents: None, }) } ); @@ -205,9 +206,10 @@ async fn test_5_core( id: client_id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: path_str.clone(), - contents: None, cursor_position: Some(1), - scroll_position: Some(1.0) + scroll_position: Some(1.0), + is_re_translation: false, + contents: None, }) } ); @@ -230,6 +232,9 @@ async fn test_5_core( id: client_id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: path_str.clone(), + cursor_position: Some(1), + scroll_position: Some(1.0), + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -245,8 +250,6 @@ async fn test_5_core( }), version: client_version, }), - cursor_position: Some(1), - scroll_position: Some(1.0) }) } ); @@ -292,6 +295,9 @@ async fn test_5_core( id: client_id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: path_str.clone(), + cursor_position: Some(1), + scroll_position: Some(1.0), + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "python".to_string(), @@ -307,8 +313,6 @@ async fn test_5_core( }), version: client_version, }), - cursor_position: Some(1), - scroll_position: Some(1.0) }) } ); @@ -379,6 +383,9 @@ async fn test_6_core( id: client_id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: path_str.clone(), + cursor_position: None, + scroll_position: None, + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: "markdown".to_string(), @@ -394,8 +401,6 @@ async fn test_6_core( }), version: client_version, }), - cursor_position: None, - scroll_position: None }) } ); diff --git a/server/tests/overall_common/mod.rs b/server/tests/overall_common/mod.rs index acc056d..b6df159 100644 --- a/server/tests/overall_common/mod.rs +++ b/server/tests/overall_common/mod.rs @@ -307,9 +307,10 @@ pub async fn goto_line( id: *client_id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: path_str.to_string(), - contents: None, cursor_position: Some(line), - scroll_position: Some(1.0) + scroll_position: Some(1.0), + is_re_translation: false, + contents: None, }) } ); @@ -430,6 +431,9 @@ pub async fn get_empty_client_update( id: *client_id, message: EditorMessageContents::Update(UpdateMessageContents { file_path: path_str.to_owned(), + cursor_position, + scroll_position, + is_re_translation: false, contents: Some(CodeChatForWeb { metadata: SourceFileMetadata { mode: mode.to_string() @@ -441,8 +445,6 @@ pub async fn get_empty_client_update( }), version: *client_version }), - cursor_position, - scroll_position }) } ); diff --git a/test_utils/Cargo.lock b/test_utils/Cargo.lock new file mode 100644 index 0000000..32b8f1a --- /dev/null +++ b/test_utils/Cargo.lock @@ -0,0 +1,409 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "assert_fs" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652f6cb1f516886fcfee5e7a5c078b9ade62cfcb889524efe5a64d682dd27a9" +dependencies = [ + "anstyle", + "doc-comment", + "globwalk", + "predicates", + "predicates-core", + "predicates-tree", + "tempfile", +] + +[[package]] +name = "assertables" +version = "9.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbada39b42413d4db3d9460f6e791702490c40f72924378a1b6fc1a4181188fd" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "bstr" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "doc-comment" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "780955b8b195a21ab8e4ac6b60dd1dbdcec1dc6c51c0617964b08c81785e12c9" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "globset" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "globwalk" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" +dependencies = [ + "bitflags", + "ignore", + "walkdir", +] + +[[package]] +name = "ignore" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata", + "same-file", + "walkdir", + "winapi-util", +] + +[[package]] +name = "libc" +version = "0.2.178" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "predicates" +version = "3.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" +dependencies = [ + "anstyle", + "difflib", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" + +[[package]] +name = "predicates-tree" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "rustix" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "termtree" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" + +[[package]] +name = "test_utils" +version = "0.1.0" +dependencies = [ + "assert_fs", + "assertables", + "log", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"