diff --git a/builder/Cargo.lock b/builder/Cargo.lock index b1b18c6a..e4c9b0b5 100644 --- a/builder/Cargo.lock +++ b/builder/Cargo.lock @@ -81,9 +81,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.45" +version = "4.5.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318" +checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57" dependencies = [ "clap_builder", "clap_derive", @@ -91,9 +91,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.44" +version = "4.5.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8" +checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41" dependencies = [ "anstream", "anstyle", @@ -121,23 +121,22 @@ checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "cmd_lib" -version = "1.9.6" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1af0f9b65935ff457da75535a6b6ff117ac858f03f71191188b3b696f90aec5a" +checksum = "1e1ac603509ec7e9696f35e836365c53f305040b1080dabcde26e00e58b264a7" dependencies = [ "cmd_lib_macros", "env_logger", "faccess", - "lazy_static", "log", "os_pipe", ] [[package]] name = "cmd_lib_macros" -version = "1.9.6" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e69eee115667ccda8b9ed7010bcf13356ad45269fc92aa78534890b42809a64" +checksum = "2f213802401c6631f4ff5b3bfc40f07f01a431c53d736ab42a6d0d65be3e0266" dependencies = [ "proc-macro-error2", "proc-macro2", @@ -164,16 +163,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] -name = "env_logger" -version = "0.10.2" +name = "env_filter" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" dependencies = [ - "humantime", - "is-terminal", "log", "regex", - "termcolor", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", ] [[package]] @@ -194,39 +203,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - -[[package]] -name = "humantime" -version = "2.2.0" +name = "is_terminal_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] -name = "is-terminal" -version = "0.4.16" +name = "jiff" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.59.0", + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", ] [[package]] -name = "is_terminal_polyfill" -version = "1.70.1" +name = "jiff-static" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "libc" @@ -268,6 +272,21 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + [[package]] name = "proc-macro-error-attr2" version = "2.0.0" @@ -310,9 +329,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" dependencies = [ "aho-corasick", "memchr", @@ -322,9 +341,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" dependencies = [ "aho-corasick", "memchr", @@ -333,9 +352,29 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "strsim" @@ -354,15 +393,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - [[package]] name = "unicode-ident" version = "1.0.18" @@ -391,15 +421,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" -dependencies = [ - "windows-sys 0.60.2", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/builder/Cargo.toml b/builder/Cargo.toml index 46fd67b4..acfe4994 100644 --- a/builder/Cargo.toml +++ b/builder/Cargo.toml @@ -25,7 +25,7 @@ edition = "2024" [dependencies] clap = { version = "4.5.19", features = ["derive"] } -cmd_lib = "1.9.5" +cmd_lib = "2.0.0" current_platform = "0.2.0" dunce = "1.0.5" path-slash = "0.2.1" diff --git a/builder/src/main.rs b/builder/src/main.rs index 8d5d70b9..44db795c 100644 --- a/builder/src/main.rs +++ b/builder/src/main.rs @@ -313,7 +313,7 @@ fn patch_client_libs() -> io::Result<()> { // Copy across the parts of MathJax that are needed, since bundling it is // difficult. quick_copy_dir( - "../client/node_modules/@mathjax/src/bundle/", + "../client/node_modules/mathjax/", "../client/static/mathjax", None, )?; @@ -338,12 +338,7 @@ fn run_install(dev: bool) -> io::Result<()> { } // See [the client manifest](../../client/package.json5) for an explanation // of `--no-frozen-lockfile`. - run_script( - "pnpm", - &["install", "--no-frozen-lockfile"], - "../client", - true, - )?; + run_script("pnpm", &["install"], "../client", true)?; patch_client_libs()?; run_script("npm", &["install"], "../extensions/VSCode", true)?; run_cmd!( @@ -395,7 +390,10 @@ fn run_test() -> io::Result<()> { )?; run_build()?; // Verify that compiling for release produces no errors. - run_cmd!(dist build;)?; + run_cmd!( + cd ..; + dist build; + )?; run_cmd!( cargo test --manifest-path=../builder/Cargo.toml; cargo test; diff --git a/client/package.json5 b/client/package.json5 index 086b1d4f..94580c06 100644 --- a/client/package.json5 +++ b/client/package.json5 @@ -43,7 +43,7 @@ url: 'https://github.com/bjones1/CodeChat_editor', }, type: 'module', - version: '0.1.29', + version: '0.1.31', dependencies: { '@codemirror/lang-cpp': '^6.0.3', '@codemirror/lang-css': '^6.3.1', @@ -60,34 +60,12 @@ '@codemirror/state': '^6.5.2', '@codemirror/view': '^6.38.1', '@mathjax/mathjax-newcm-font': '4.0.0', - '@mathjax/src': '4.0.0', codemirror: '^6.0.2', 'graphviz-webcomponent': '^2.0.0', - mermaid: '^11.10.0', - 'npm-check-updates': '^18.0.2', - /* Per [this pdfjs-dist - issue](https://github.com/mozilla/pdf.js/issues/20127), avoid v5.4.54 - of this library. Per [this pnpm - issue](https://github.com/pnpm/pnpm/issues/6714), `pnpm` will - auto-rewrite this incorrectly, so manually revert changes after each - `pnpm update`. However, reverting these changes causes the following - error: - - ``` - ERR_PNPM_OUTDATED_LOCKFILE  Cannot install with "frozen-lockfile" because pnpm-lock. - yaml is not up to date with /package.json - - Note that in CI environments this setting is true by default. If you still need to - run install in such cases, use "pnpm install --no-frozen-lockfile" - - Failure reason: - specifiers in the lockfile don't match specifiers in package.json: - * 1 dependencies are mismatched: - - pdfjs-dist (lockfile: ^5.3.93, manifest: ~5 < 5.4.54 || ~5.4.55) - ``` - - So, installs in CI must have the `--no-frozen-lockfile` CLI flag. */ - 'pdfjs-dist': '~5 < 5.4.54 || ~5.4.55', + mathjax: '4.0.0', + mermaid: '^11.10.1', + 'npm-check-updates': '^18.0.3', + 'pdfjs-dist': '^5.4.149', tinymce: '^8.0.2', 'toastify-js': '^1.12.0', }, @@ -97,14 +75,16 @@ '@types/mocha': '^10.0.10', '@types/node': '^24.3.0', '@types/toastify-js': '^1.12.4', - '@typescript-eslint/eslint-plugin': '^8.40.0', - '@typescript-eslint/parser': '^8.40.0', - chai: '^5.3.1', + '@typescript-eslint/eslint-plugin': '^8.41.0', + '@typescript-eslint/parser': '^8.41.0', + chai: '^6.0.1', esbuild: '^0.25.9', - eslint: '^9.33.0', + eslint: '^9.34.0', 'eslint-config-prettier': '^10.1.8', 'eslint-plugin-import': '^2.32.0', 'eslint-plugin-prettier': '^5.5.4', + mocha: '^11.7.1', + prettier: '^3.6.2', typescript: '^5.9.2', }, scripts: { diff --git a/client/pnpm-lock.yaml b/client/pnpm-lock.yaml index 7bc509d3..ae8cf38d 100644 --- a/client/pnpm-lock.yaml +++ b/client/pnpm-lock.yaml @@ -53,24 +53,24 @@ importers: '@mathjax/mathjax-newcm-font': specifier: 4.0.0 version: 4.0.0 - '@mathjax/src': - specifier: 4.0.0 - version: 4.0.0 codemirror: specifier: ^6.0.2 version: 6.0.2 graphviz-webcomponent: specifier: ^2.0.0 version: 2.0.0 + mathjax: + specifier: 4.0.0 + version: 4.0.0 mermaid: - specifier: ^11.10.0 - version: 11.10.0 + specifier: ^11.10.1 + version: 11.10.1 npm-check-updates: - specifier: ^18.0.2 - version: 18.0.2 + specifier: ^18.0.3 + version: 18.0.3 pdfjs-dist: - specifier: ^5.3.93 - version: 5.3.93 + specifier: ^5.4.149 + version: 5.4.149 tinymce: specifier: ^8.0.2 version: 8.0.2 @@ -94,29 +94,35 @@ importers: specifier: ^1.12.4 version: 1.12.4 '@typescript-eslint/eslint-plugin': - specifier: ^8.40.0 - version: 8.40.0(@typescript-eslint/parser@8.40.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(typescript@5.9.2) + specifier: ^8.41.0 + version: 8.41.0(@typescript-eslint/parser@8.41.0(eslint@9.34.0)(typescript@5.9.2))(eslint@9.34.0)(typescript@5.9.2) '@typescript-eslint/parser': - specifier: ^8.40.0 - version: 8.40.0(eslint@9.33.0)(typescript@5.9.2) + specifier: ^8.41.0 + version: 8.41.0(eslint@9.34.0)(typescript@5.9.2) chai: - specifier: ^5.3.1 - version: 5.3.1 + specifier: ^6.0.1 + version: 6.0.1 esbuild: specifier: ^0.25.9 version: 0.25.9 eslint: - specifier: ^9.33.0 - version: 9.33.0 + specifier: ^9.34.0 + version: 9.34.0 eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@9.33.0) + version: 10.1.8(eslint@9.34.0) eslint-plugin-import: specifier: ^2.32.0 - version: 2.32.0(@typescript-eslint/parser@8.40.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0) + version: 2.32.0(@typescript-eslint/parser@8.41.0(eslint@9.34.0)(typescript@5.9.2))(eslint@9.34.0) eslint-plugin-prettier: specifier: ^5.5.4 - version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.33.0))(eslint@9.33.0)(prettier@3.6.2) + version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.34.0))(eslint@9.34.0)(prettier@3.6.2) + mocha: + specifier: ^11.7.1 + version: 11.7.1 + prettier: + specifier: ^3.6.2 + version: 3.6.2 typescript: specifier: ^5.9.2 version: 5.9.2 @@ -386,8 +392,8 @@ packages: resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.33.0': - resolution: {integrity: sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A==} + '@eslint/js@9.34.0': + resolution: {integrity: sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.6': @@ -424,6 +430,10 @@ packages: '@iconify/utils@2.3.0': resolution: {integrity: sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==} + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + '@lezer/common@1.2.3': resolution: {integrity: sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==} @@ -475,74 +485,71 @@ packages: '@mathjax/mathjax-newcm-font@4.0.0': resolution: {integrity: sha512-kpsJgIF4FpWiwIkFgOPmWwy5GXfL25spmJJNg27HQxPddmEL8Blx0jn2BuU/nlwjM/9SnYpEfDrWiAMgLPlB8Q==} - '@mathjax/src@4.0.0': - resolution: {integrity: sha512-i7oYVLkHTskfTqxBzrbvcJN8ptGChWb6bx2LZsCySk7QWf61JqaMYX5N7M0qr8tnYqRmN5DDedkRda7wDuTdBA==} - '@mermaid-js/parser@0.6.2': resolution: {integrity: sha512-+PO02uGF6L6Cs0Bw8RpGhikVvMWEysfAyl27qTlroUB8jSWr1lL0Sf6zi78ZxlSnmgSY2AMMKVgghnN9jTtwkQ==} - '@napi-rs/canvas-android-arm64@0.1.77': - resolution: {integrity: sha512-jC8YX0rbAnu9YrLK1A52KM2HX9EDjrJSCLVuBf9Dsov4IC6GgwMLS2pwL9GFLJnSZBFgdwnA84efBehHT9eshA==} + '@napi-rs/canvas-android-arm64@0.1.78': + resolution: {integrity: sha512-N1ikxztjrRmh8xxlG5kYm1RuNr8ZW1EINEDQsLhhuy7t0pWI/e7SH91uFVLZKCMDyjel1tyWV93b5fdCAi7ggw==} engines: {node: '>= 10'} cpu: [arm64] os: [android] - '@napi-rs/canvas-darwin-arm64@0.1.77': - resolution: {integrity: sha512-VFaCaCgAV0+hPwXajDIiHaaGx4fVCuUVYp/CxCGXmTGz699ngIEBx3Sa2oDp0uk3X+6RCRLueb7vD44BKBiPIg==} + '@napi-rs/canvas-darwin-arm64@0.1.78': + resolution: {integrity: sha512-FA3aCU3G5yGc74BSmnLJTObnZRV+HW+JBTrsU+0WVVaNyVKlb5nMvYAQuieQlRVemsAA2ek2c6nYtHh6u6bwFw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@napi-rs/canvas-darwin-x64@0.1.77': - resolution: {integrity: sha512-uD2NSkf6I4S3o0POJDwweK85FE4rfLNA2N714MgiEEMMw5AmupfSJGgpYzcyEXtPzdaca6rBfKcqNvzR1+EyLQ==} + '@napi-rs/canvas-darwin-x64@0.1.78': + resolution: {integrity: sha512-xVij69o9t/frixCDEoyWoVDKgE3ksLGdmE2nvBWVGmoLu94MWUlv2y4Qzf5oozBmydG5Dcm4pRHFBM7YWa1i6g==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@napi-rs/canvas-linux-arm-gnueabihf@0.1.77': - resolution: {integrity: sha512-03GxMMZGhHRQxiA4gyoKT6iQSz8xnA6T9PAfg/WNJnbkVMFZG782DwUJUb39QIZ1uE1euMCPnDgWAJ092MmgJQ==} + '@napi-rs/canvas-linux-arm-gnueabihf@0.1.78': + resolution: {integrity: sha512-aSEXrLcIpBtXpOSnLhTg4jPsjJEnK7Je9KqUdAWjc7T8O4iYlxWxrXFIF8rV8J79h5jNdScgZpAUWYnEcutR3g==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@napi-rs/canvas-linux-arm64-gnu@0.1.77': - resolution: {integrity: sha512-ZO+d2gRU9JU1Bb7SgJcJ1k9wtRMCpSWjJAJ+2phhu0Lw5As8jYXXXmLKmMTGs1bOya2dBMYDLzwp7KS/S/+aCA==} + '@napi-rs/canvas-linux-arm64-gnu@0.1.78': + resolution: {integrity: sha512-dlEPRX1hLGKaY3UtGa1dtkA1uGgFITn2mDnfI6YsLlYyLJQNqHx87D1YTACI4zFCUuLr/EzQDzuX+vnp9YveVg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@napi-rs/canvas-linux-arm64-musl@0.1.77': - resolution: {integrity: sha512-S1KtnP1+nWs2RApzNkdNf8X4trTLrHaY7FivV61ZRaL8NvuGOkSkKa+gWN2iedIGFEDz6gecpl/JAUSewwFXYg==} + '@napi-rs/canvas-linux-arm64-musl@0.1.78': + resolution: {integrity: sha512-TsCfjOPZtm5Q/NO1EZHR5pwDPSPjPEttvnv44GL32Zn1uvudssjTLbvaG1jHq81Qxm16GTXEiYLmx4jOLZQYlg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@napi-rs/canvas-linux-riscv64-gnu@0.1.77': - resolution: {integrity: sha512-A4YIKFYUwDtrSzCtdCAO5DYmRqlhCVKHdpq0+dBGPnIEhOQDFkPBTfoTAjO3pjlEnorlfKmNMOH21sKQg2esGA==} + '@napi-rs/canvas-linux-riscv64-gnu@0.1.78': + resolution: {integrity: sha512-+cpTTb0GDshEow/5Fy8TpNyzaPsYb3clQIjgWRmzRcuteLU+CHEU/vpYvAcSo7JxHYPJd8fjSr+qqh+nI5AtmA==} engines: {node: '>= 10'} cpu: [riscv64] os: [linux] - '@napi-rs/canvas-linux-x64-gnu@0.1.77': - resolution: {integrity: sha512-Lt6Sef5l0+5O1cSZ8ysO0JI+x+rSrqZyXs5f7+kVkCAOVq8X5WTcDVbvWvEs2aRhrWTp5y25Jf2Bn+3IcNHOuQ==} + '@napi-rs/canvas-linux-x64-gnu@0.1.78': + resolution: {integrity: sha512-wxRcvKfvYBgtrO0Uy8OmwvjlnTcHpY45LLwkwVNIWHPqHAsyoTyG/JBSfJ0p5tWRzMOPDCDqdhpIO4LOgXjeyg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@napi-rs/canvas-linux-x64-musl@0.1.77': - resolution: {integrity: sha512-NiNFvC+D+omVeJ3IjYlIbyt/igONSABVe9z0ZZph29epHgZYu4eHwV9osfpRt1BGGOAM8LkFrHk4LBdn2EDymA==} + '@napi-rs/canvas-linux-x64-musl@0.1.78': + resolution: {integrity: sha512-vQFOGwC9QDP0kXlhb2LU1QRw/humXgcbVp8mXlyBqzc/a0eijlLF9wzyarHC1EywpymtS63TAj8PHZnhTYN6hg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@napi-rs/canvas-win32-x64-msvc@0.1.77': - resolution: {integrity: sha512-fP6l0hZiWykyjvpZTS3sI46iib8QEflbPakNoUijtwyxRuOPTTBfzAWZUz5z2vKpJJ/8r305wnZeZ8lhsBHY5A==} + '@napi-rs/canvas-win32-x64-msvc@0.1.78': + resolution: {integrity: sha512-/eKlTZBtGUgpRKalzOzRr6h7KVSuziESWXgBcBnXggZmimwIJWPJlEcbrx5Tcwj8rPuZiANXQOG9pPgy9Q4LTQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@napi-rs/canvas@0.1.77': - resolution: {integrity: sha512-N9w2DkEKE1AXGp3q55GBOP6BEoFrqChDiFqJtKViTpQCWNOSVuMz7LkoGehbnpxtidppbsC36P0kCZNqJKs29w==} + '@napi-rs/canvas@0.1.78': + resolution: {integrity: sha512-YaBHJvT+T1DoP16puvWM6w46Lq3VhwKIJ8th5m1iEJyGh7mibk5dT7flBvMQ1EH1LYmMzXJ+OUhu+8wQ9I6u7g==} engines: {node: '>= 10'} '@nodelib/fs.scandir@2.1.5': @@ -557,6 +564,10 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + '@pkgr/core@0.2.9': resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} @@ -690,69 +701,65 @@ packages: '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - '@typescript-eslint/eslint-plugin@8.40.0': - resolution: {integrity: sha512-w/EboPlBwnmOBtRbiOvzjD+wdiZdgFeo17lkltrtn7X37vagKKWJABvyfsJXTlHe6XBzugmYgd4A4nW+k8Mixw==} + '@typescript-eslint/eslint-plugin@8.41.0': + resolution: {integrity: sha512-8fz6oa6wEKZrhXWro/S3n2eRJqlRcIa6SlDh59FXJ5Wp5XRZ8B9ixpJDcjadHq47hMx0u+HW6SNa6LjJQ6NLtw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.40.0 + '@typescript-eslint/parser': ^8.41.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.40.0': - resolution: {integrity: sha512-jCNyAuXx8dr5KJMkecGmZ8KI61KBUhkCob+SD+C+I5+Y1FWI2Y3QmY4/cxMCC5WAsZqoEtEETVhUiUMIGCf6Bw==} + '@typescript-eslint/parser@8.41.0': + resolution: {integrity: sha512-gTtSdWX9xiMPA/7MV9STjJOOYtWwIJIYxkQxnSV1U3xcE+mnJSH3f6zI0RYP+ew66WSlZ5ed+h0VCxsvdC1jJg==} 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.40.0': - resolution: {integrity: sha512-/A89vz7Wf5DEXsGVvcGdYKbVM9F7DyFXj52lNYUDS1L9yJfqjW/fIp5PgMuEJL/KeqVTe2QSbXAGUZljDUpArw==} + '@typescript-eslint/project-service@8.41.0': + resolution: {integrity: sha512-b8V9SdGBQzQdjJ/IO3eDifGpDBJfvrNTp2QD9P2BeqWTGrRibgfgIlBSw6z3b6R7dPzg752tOs4u/7yCLxksSQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.40.0': - resolution: {integrity: sha512-y9ObStCcdCiZKzwqsE8CcpyuVMwRouJbbSrNuThDpv16dFAj429IkM6LNb1dZ2m7hK5fHyzNcErZf7CEeKXR4w==} + '@typescript-eslint/scope-manager@8.41.0': + resolution: {integrity: sha512-n6m05bXn/Cd6DZDGyrpXrELCPVaTnLdPToyhBoFkLIMznRUQUEQdSp96s/pcWSQdqOhrgR1mzJ+yItK7T+WPMQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.40.0': - resolution: {integrity: sha512-jtMytmUaG9d/9kqSl/W3E3xaWESo4hFDxAIHGVW/WKKtQhesnRIJSAJO6XckluuJ6KDB5woD1EiqknriCtAmcw==} + '@typescript-eslint/tsconfig-utils@8.41.0': + resolution: {integrity: sha512-TDhxYFPUYRFxFhuU5hTIJk+auzM/wKvWgoNYOPcOf6i4ReYlOoYN8q1dV5kOTjNQNJgzWN3TUUQMtlLOcUgdUw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.40.0': - resolution: {integrity: sha512-eE60cK4KzAc6ZrzlJnflXdrMqOBaugeukWICO2rB0KNvwdIMaEaYiywwHMzA1qFpTxrLhN9Lp4E/00EgWcD3Ow==} + '@typescript-eslint/type-utils@8.41.0': + resolution: {integrity: sha512-63qt1h91vg3KsjVVonFJWjgSK7pZHSQFKH6uwqxAH9bBrsyRhO6ONoKyXxyVBzG1lJnFAJcKAcxLS54N1ee1OQ==} 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.40.0': - resolution: {integrity: sha512-ETdbFlgbAmXHyFPwqUIYrfc12ArvpBhEVgGAxVYSwli26dn8Ko+lIo4Su9vI9ykTZdJn+vJprs/0eZU0YMAEQg==} + '@typescript-eslint/types@8.41.0': + resolution: {integrity: sha512-9EwxsWdVqh42afLbHP90n2VdHaWU/oWgbH2P0CfcNfdKL7CuKpwMQGjwev56vWu9cSKU7FWSu6r9zck6CVfnag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.40.0': - resolution: {integrity: sha512-k1z9+GJReVVOkc1WfVKs1vBrR5MIKKbdAjDTPvIK3L8De6KbFfPFt6BKpdkdk7rZS2GtC/m6yI5MYX+UsuvVYQ==} + '@typescript-eslint/typescript-estree@8.41.0': + resolution: {integrity: sha512-D43UwUYJmGhuwHfY7MtNKRZMmfd8+p/eNSfFe6tH5mbVDto+VQCayeAt35rOx3Cs6wxD16DQtIKw/YXxt5E0UQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.40.0': - resolution: {integrity: sha512-Cgzi2MXSZyAUOY+BFwGs17s7ad/7L+gKt6Y8rAVVWS+7o6wrjeFN4nVfTpbE25MNcxyJ+iYUXflbs2xR9h4UBg==} + '@typescript-eslint/utils@8.41.0': + resolution: {integrity: sha512-udbCVstxZ5jiPIXrdH+BZWnPatjlYwJuJkDA4Tbo3WyYLh8NvB+h/bKeSZHDOFKfphsZYJQqaFtLeXEqurQn1A==} 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.40.0': - resolution: {integrity: sha512-8CZ47QwalyRjsypfwnbI3hKy5gJDPmrkLjkgMxhi0+DZZ2QNx2naS6/hWoVYUHU7LU2zleF68V9miaVZvhFfTA==} + '@typescript-eslint/visitor-keys@8.41.0': + resolution: {integrity: sha512-+GeGMebMCy0elMNg67LRNoVnUFPIm37iu5CmHESVx56/9Jsfdpsvbv605DQ81Pi/x11IdKUsS5nzgTYbCQU9fg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@xmldom/xmldom@0.9.8': - resolution: {integrity: sha512-p96FSY54r+WJ50FIOsCOjyj/wavs8921hG5+kVMmZgKcvIKxMXHTrjNJvRgWa/zuX3B6t2lijLNFaOyuxUH+2A==} - engines: {node: '>=14.6'} - acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -766,10 +773,22 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.0: + resolution: {integrity: sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==} + engines: {node: '>=12'} + ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -797,10 +816,6 @@ packages: resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} engines: {node: '>= 0.4'} - assertion-error@2.0.1: - resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} - engines: {node: '>=12'} - async-function@1.0.0: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} @@ -822,6 +837,9 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + browser-stdout@1.3.1: + resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} + call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -838,18 +856,18 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - chai@5.3.1: - resolution: {integrity: sha512-48af6xm9gQK8rhIcOxWwdGzIervm8BVTin+yRp9HEvU20BtVZ2lBywlIJBzwaDtvo0FvjeL7QdCADoUoqIbV3A==} + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + chai@6.0.1: + resolution: {integrity: sha512-/JOoU2//6p5vCXh00FpNgtlw0LjvhGttaWc+y7wpW9yjBm3ys0dI8tSKZxIOgNruz5J0RleccatSIC3uxEZP0g==} engines: {node: '>=18'} chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - check-error@2.1.1: - resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} - engines: {node: '>= 16'} - chevrotain-allstar@0.3.1: resolution: {integrity: sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==} peerDependencies: @@ -858,6 +876,14 @@ packages: chevrotain@11.0.3: resolution: {integrity: sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==} + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + codemirror@6.0.2: resolution: {integrity: sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==} @@ -868,10 +894,6 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - commander@14.0.0: - resolution: {integrity: sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==} - engines: {node: '>=20'} - commander@7.2.0: resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} engines: {node: '>= 10'} @@ -1070,8 +1092,8 @@ packages: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} - dayjs@1.11.13: - resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + dayjs@1.11.18: + resolution: {integrity: sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==} debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} @@ -1090,9 +1112,9 @@ packages: supports-color: optional: true - deep-eql@5.0.2: - resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} - engines: {node: '>=6'} + decamelize@4.0.0: + resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} + engines: {node: '>=10'} deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -1108,6 +1130,10 @@ packages: delaunator@5.0.1: resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} + diff@7.0.0: + resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==} + engines: {node: '>=0.3.1'} + doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} @@ -1119,6 +1145,15 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + es-abstract@1.24.0: resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} engines: {node: '>= 0.4'} @@ -1152,6 +1187,10 @@ packages: engines: {node: '>=18'} hasBin: true + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -1222,8 +1261,8 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.33.0: - resolution: {integrity: sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==} + eslint@9.34.0: + resolution: {integrity: sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -1290,6 +1329,10 @@ packages: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} + flat@5.0.2: + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + hasBin: true + flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} @@ -1297,6 +1340,10 @@ packages: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} @@ -1307,6 +1354,10 @@ packages: functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -1327,6 +1378,10 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -1380,6 +1435,10 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -1451,6 +1510,10 @@ packages: resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} engines: {node: '>= 0.4'} + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + is-generator-function@1.1.0: resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} engines: {node: '>= 0.4'} @@ -1475,6 +1538,10 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-plain-obj@2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -1499,6 +1566,10 @@ packages: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + is-weakmap@2.0.2: resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} engines: {node: '>= 0.4'} @@ -1517,6 +1588,9 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true @@ -1575,11 +1649,15 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - loupe@3.2.1: - resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - marked@16.2.0: - resolution: {integrity: sha512-LbbTuye+0dWRz2TS9KJ7wsnD4KAtpj0MVkWc90XvBa6AslXsT0hTBVH5k32pcSyHH1fst9XEFJunXHktVy0zlg==} + marked@16.2.1: + resolution: {integrity: sha512-r3UrXED9lMlHF97jJByry90cwrZBBvZmjG1L68oYfuPMW+uDTnuMbyJDymCWwbTE+f+3LhpNDKfpR3a3saFyjA==} engines: {node: '>= 20'} hasBin: true @@ -1587,15 +1665,15 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + mathjax@4.0.0: + resolution: {integrity: sha512-ThMPHiPl9ibZBInAmfoTCNq9MgCdH7ChIQ9YhKFc325noJ4DMzy9/Q14qdcuPzVJjEmC3kyXhwnERZWX3hbWzQ==} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - mermaid@11.10.0: - resolution: {integrity: sha512-oQsFzPBy9xlpnGxUqLbVY8pvknLlsNIJ0NWwi8SUJjhbP1IT0E0o1lfhU4iYV3ubpy+xkzkaOyDUQMn06vQElQ==} - - mhchemparser@4.2.1: - resolution: {integrity: sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ==} + mermaid@11.10.1: + resolution: {integrity: sha512-0PdeADVWURz7VMAX0+MiMcgfxFKY4aweSGsjgFihe3XlMKNqmai/cugMrqTd3WNHM93V+K+AZL6Wu6tB5HmxRw==} micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} @@ -1611,11 +1689,17 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - mj-context-menu@0.9.1: - resolution: {integrity: sha512-ECPcVXZFRfeYOxb1MWGzctAtnQcZ6nRucE3orfkKX7t/KE2mlXO2K/bq4BcCGOuhdz3Wg2BZDy2S8ECK73/iIw==} + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + mlly@1.8.0: + resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} - mlly@1.7.4: - resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} + mocha@11.7.1: + resolution: {integrity: sha512-5EK+Cty6KheMS/YLPPMJC64g5V61gIR25KsRItHw6x4hEKT6Njp1n9LOlH4gpevuwMVS66SXaBBpg+RWZkza4A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -1623,8 +1707,8 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - npm-check-updates@18.0.2: - resolution: {integrity: sha512-9uVFZUCg5oDOcbzdsrJ4BEvq2gikd23tXuF5mqpl4mxVl051lzB00Xmd7ZVjVWY3XNUF3BQKWlN/qmyD8/bwrA==} + npm-check-updates@18.0.3: + resolution: {integrity: sha512-IMZWxgAa5gpDVEle2KOZOMLfCu2/9FV+xsXQjPFt2OV0dyZixn0OJrZ9NxUcWgr/ZTGogmZtE0Cb8x2wlsVULg==} engines: {node: ^18.18.0 || >=20.0.0, npm: '>=8.12.1'} hasBin: true @@ -1668,6 +1752,9 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + package-manager-detector@1.3.0: resolution: {integrity: sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==} @@ -1689,17 +1776,20 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - pathval@2.0.1: - resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} - engines: {node: '>= 14.16'} - - pdfjs-dist@5.3.93: - resolution: {integrity: sha512-w3fQKVL1oGn8FRyx5JUG5tnbblggDqyx2XzA5brsJ5hSuS+I0NdnJANhmeWKLjotdbPQucLBug5t0MeWr0AAdg==} + pdfjs-dist@5.4.149: + resolution: {integrity: sha512-Xe8/1FMJEQPUVSti25AlDpwpUm2QAVmNOpFP0SIahaPIOKBKICaefbzogLdwey3XGGoaP4Lb9wqiw2e9Jqp0LA==} engines: {node: '>=20.16.0 || >=22.3.0'} + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} @@ -1743,6 +1833,13 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + reflect.getprototypeof@1.0.10: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} @@ -1751,6 +1848,10 @@ packages: resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -1780,6 +1881,9 @@ packages: resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} engines: {node: '>=0.4'} + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-push-apply@1.0.0: resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} engines: {node: '>= 0.4'} @@ -1800,6 +1904,9 @@ packages: engines: {node: '>=10'} hasBin: true + serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -1836,14 +1943,22 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} - speech-rule-engine@5.0.0-beta.1: - resolution: {integrity: sha512-arqcJpXEYRG9mQMxRCNd2xFERGvIvwvuhcnoXDw/SyeYNyJ5I9SUU5ft+BPw0M1rPpwl3Q+6ZeeYAcwGXTa6oQ==} - hasBin: true + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + string.prototype.trim@1.2.10: resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} engines: {node: '>= 0.4'} @@ -1856,6 +1971,14 @@ packages: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} @@ -1874,6 +1997,10 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -1994,13 +2121,37 @@ packages: engines: {node: '>= 8'} hasBin: true - wicked-good-xpath@1.3.0: - resolution: {integrity: sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw==} - word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + workerpool@9.3.3: + resolution: {integrity: sha512-slxCaKbYjEdFT/o2rH9xS1hf4uRDch1w7Uo+apxhZ+sf/1d9e0ZVkn42kPNGP2dgjIx6YFvSevj0zHvbWe2jdw==} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs-unparser@2.0.0: + resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} + engines: {node: '>=10'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -2250,9 +2401,9 @@ snapshots: '@esbuild/win32-x64@0.25.9': optional: true - '@eslint-community/eslint-utils@4.7.0(eslint@9.33.0)': + '@eslint-community/eslint-utils@4.7.0(eslint@9.34.0)': dependencies: - eslint: 9.33.0 + eslint: 9.34.0 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} @@ -2260,7 +2411,7 @@ snapshots: '@eslint/config-array@0.21.0': dependencies: '@eslint/object-schema': 2.1.6 - debug: 4.4.1 + debug: 4.4.1(supports-color@8.1.1) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -2274,7 +2425,7 @@ snapshots: '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 - debug: 4.4.1 + debug: 4.4.1(supports-color@8.1.1) espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 @@ -2285,7 +2436,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.33.0': {} + '@eslint/js@9.34.0': {} '@eslint/object-schema@2.1.6': {} @@ -2314,14 +2465,23 @@ snapshots: '@antfu/install-pkg': 1.1.0 '@antfu/utils': 8.1.1 '@iconify/types': 2.0.0 - debug: 4.4.1 + debug: 4.4.1(supports-color@8.1.1) globals: 15.15.0 kolorist: 1.8.0 local-pkg: 1.1.2 - mlly: 1.7.4 + mlly: 1.8.0 transitivePeerDependencies: - supports-color + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + '@lezer/common@1.2.3': {} '@lezer/cpp@1.1.3': @@ -2407,59 +2567,52 @@ snapshots: '@mathjax/mathjax-newcm-font@4.0.0': {} - '@mathjax/src@4.0.0': - dependencies: - '@mathjax/mathjax-newcm-font': 4.0.0 - mhchemparser: 4.2.1 - mj-context-menu: 0.9.1 - speech-rule-engine: 5.0.0-beta.1 - '@mermaid-js/parser@0.6.2': dependencies: langium: 3.3.1 - '@napi-rs/canvas-android-arm64@0.1.77': + '@napi-rs/canvas-android-arm64@0.1.78': optional: true - '@napi-rs/canvas-darwin-arm64@0.1.77': + '@napi-rs/canvas-darwin-arm64@0.1.78': optional: true - '@napi-rs/canvas-darwin-x64@0.1.77': + '@napi-rs/canvas-darwin-x64@0.1.78': optional: true - '@napi-rs/canvas-linux-arm-gnueabihf@0.1.77': + '@napi-rs/canvas-linux-arm-gnueabihf@0.1.78': optional: true - '@napi-rs/canvas-linux-arm64-gnu@0.1.77': + '@napi-rs/canvas-linux-arm64-gnu@0.1.78': optional: true - '@napi-rs/canvas-linux-arm64-musl@0.1.77': + '@napi-rs/canvas-linux-arm64-musl@0.1.78': optional: true - '@napi-rs/canvas-linux-riscv64-gnu@0.1.77': + '@napi-rs/canvas-linux-riscv64-gnu@0.1.78': optional: true - '@napi-rs/canvas-linux-x64-gnu@0.1.77': + '@napi-rs/canvas-linux-x64-gnu@0.1.78': optional: true - '@napi-rs/canvas-linux-x64-musl@0.1.77': + '@napi-rs/canvas-linux-x64-musl@0.1.78': optional: true - '@napi-rs/canvas-win32-x64-msvc@0.1.77': + '@napi-rs/canvas-win32-x64-msvc@0.1.78': optional: true - '@napi-rs/canvas@0.1.77': + '@napi-rs/canvas@0.1.78': optionalDependencies: - '@napi-rs/canvas-android-arm64': 0.1.77 - '@napi-rs/canvas-darwin-arm64': 0.1.77 - '@napi-rs/canvas-darwin-x64': 0.1.77 - '@napi-rs/canvas-linux-arm-gnueabihf': 0.1.77 - '@napi-rs/canvas-linux-arm64-gnu': 0.1.77 - '@napi-rs/canvas-linux-arm64-musl': 0.1.77 - '@napi-rs/canvas-linux-riscv64-gnu': 0.1.77 - '@napi-rs/canvas-linux-x64-gnu': 0.1.77 - '@napi-rs/canvas-linux-x64-musl': 0.1.77 - '@napi-rs/canvas-win32-x64-msvc': 0.1.77 + '@napi-rs/canvas-android-arm64': 0.1.78 + '@napi-rs/canvas-darwin-arm64': 0.1.78 + '@napi-rs/canvas-darwin-x64': 0.1.78 + '@napi-rs/canvas-linux-arm-gnueabihf': 0.1.78 + '@napi-rs/canvas-linux-arm64-gnu': 0.1.78 + '@napi-rs/canvas-linux-arm64-musl': 0.1.78 + '@napi-rs/canvas-linux-riscv64-gnu': 0.1.78 + '@napi-rs/canvas-linux-x64-gnu': 0.1.78 + '@napi-rs/canvas-linux-x64-musl': 0.1.78 + '@napi-rs/canvas-win32-x64-msvc': 0.1.78 optional: true '@nodelib/fs.scandir@2.1.5': @@ -2474,6 +2627,9 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.1 + '@pkgjs/parseargs@0.11.0': + optional: true + '@pkgr/core@0.2.9': {} '@rtsao/scc@1.1.0': {} @@ -2622,15 +2778,15 @@ snapshots: '@types/trusted-types@2.0.7': optional: true - '@typescript-eslint/eslint-plugin@8.40.0(@typescript-eslint/parser@8.40.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(typescript@5.9.2)': + '@typescript-eslint/eslint-plugin@8.41.0(@typescript-eslint/parser@8.41.0(eslint@9.34.0)(typescript@5.9.2))(eslint@9.34.0)(typescript@5.9.2)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.40.0(eslint@9.33.0)(typescript@5.9.2) - '@typescript-eslint/scope-manager': 8.40.0 - '@typescript-eslint/type-utils': 8.40.0(eslint@9.33.0)(typescript@5.9.2) - '@typescript-eslint/utils': 8.40.0(eslint@9.33.0)(typescript@5.9.2) - '@typescript-eslint/visitor-keys': 8.40.0 - eslint: 9.33.0 + '@typescript-eslint/parser': 8.41.0(eslint@9.34.0)(typescript@5.9.2) + '@typescript-eslint/scope-manager': 8.41.0 + '@typescript-eslint/type-utils': 8.41.0(eslint@9.34.0)(typescript@5.9.2) + '@typescript-eslint/utils': 8.41.0(eslint@9.34.0)(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.41.0 + eslint: 9.34.0 graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 @@ -2639,57 +2795,57 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.40.0(eslint@9.33.0)(typescript@5.9.2)': + '@typescript-eslint/parser@8.41.0(eslint@9.34.0)(typescript@5.9.2)': dependencies: - '@typescript-eslint/scope-manager': 8.40.0 - '@typescript-eslint/types': 8.40.0 - '@typescript-eslint/typescript-estree': 8.40.0(typescript@5.9.2) - '@typescript-eslint/visitor-keys': 8.40.0 - debug: 4.4.1 - eslint: 9.33.0 + '@typescript-eslint/scope-manager': 8.41.0 + '@typescript-eslint/types': 8.41.0 + '@typescript-eslint/typescript-estree': 8.41.0(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.41.0 + debug: 4.4.1(supports-color@8.1.1) + eslint: 9.34.0 typescript: 5.9.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.40.0(typescript@5.9.2)': + '@typescript-eslint/project-service@8.41.0(typescript@5.9.2)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.40.0(typescript@5.9.2) - '@typescript-eslint/types': 8.40.0 - debug: 4.4.1 + '@typescript-eslint/tsconfig-utils': 8.41.0(typescript@5.9.2) + '@typescript-eslint/types': 8.41.0 + debug: 4.4.1(supports-color@8.1.1) typescript: 5.9.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.40.0': + '@typescript-eslint/scope-manager@8.41.0': dependencies: - '@typescript-eslint/types': 8.40.0 - '@typescript-eslint/visitor-keys': 8.40.0 + '@typescript-eslint/types': 8.41.0 + '@typescript-eslint/visitor-keys': 8.41.0 - '@typescript-eslint/tsconfig-utils@8.40.0(typescript@5.9.2)': + '@typescript-eslint/tsconfig-utils@8.41.0(typescript@5.9.2)': dependencies: typescript: 5.9.2 - '@typescript-eslint/type-utils@8.40.0(eslint@9.33.0)(typescript@5.9.2)': + '@typescript-eslint/type-utils@8.41.0(eslint@9.34.0)(typescript@5.9.2)': dependencies: - '@typescript-eslint/types': 8.40.0 - '@typescript-eslint/typescript-estree': 8.40.0(typescript@5.9.2) - '@typescript-eslint/utils': 8.40.0(eslint@9.33.0)(typescript@5.9.2) - debug: 4.4.1 - eslint: 9.33.0 + '@typescript-eslint/types': 8.41.0 + '@typescript-eslint/typescript-estree': 8.41.0(typescript@5.9.2) + '@typescript-eslint/utils': 8.41.0(eslint@9.34.0)(typescript@5.9.2) + debug: 4.4.1(supports-color@8.1.1) + eslint: 9.34.0 ts-api-utils: 2.1.0(typescript@5.9.2) typescript: 5.9.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.40.0': {} + '@typescript-eslint/types@8.41.0': {} - '@typescript-eslint/typescript-estree@8.40.0(typescript@5.9.2)': + '@typescript-eslint/typescript-estree@8.41.0(typescript@5.9.2)': dependencies: - '@typescript-eslint/project-service': 8.40.0(typescript@5.9.2) - '@typescript-eslint/tsconfig-utils': 8.40.0(typescript@5.9.2) - '@typescript-eslint/types': 8.40.0 - '@typescript-eslint/visitor-keys': 8.40.0 - debug: 4.4.1 + '@typescript-eslint/project-service': 8.41.0(typescript@5.9.2) + '@typescript-eslint/tsconfig-utils': 8.41.0(typescript@5.9.2) + '@typescript-eslint/types': 8.41.0 + '@typescript-eslint/visitor-keys': 8.41.0 + debug: 4.4.1(supports-color@8.1.1) fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 @@ -2699,24 +2855,22 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.40.0(eslint@9.33.0)(typescript@5.9.2)': + '@typescript-eslint/utils@8.41.0(eslint@9.34.0)(typescript@5.9.2)': dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.33.0) - '@typescript-eslint/scope-manager': 8.40.0 - '@typescript-eslint/types': 8.40.0 - '@typescript-eslint/typescript-estree': 8.40.0(typescript@5.9.2) - eslint: 9.33.0 + '@eslint-community/eslint-utils': 4.7.0(eslint@9.34.0) + '@typescript-eslint/scope-manager': 8.41.0 + '@typescript-eslint/types': 8.41.0 + '@typescript-eslint/typescript-estree': 8.41.0(typescript@5.9.2) + eslint: 9.34.0 typescript: 5.9.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.40.0': + '@typescript-eslint/visitor-keys@8.41.0': dependencies: - '@typescript-eslint/types': 8.40.0 + '@typescript-eslint/types': 8.41.0 eslint-visitor-keys: 4.2.1 - '@xmldom/xmldom@0.9.8': {} - acorn-jsx@5.3.2(acorn@8.15.0): dependencies: acorn: 8.15.0 @@ -2730,10 +2884,16 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ansi-regex@5.0.1: {} + + ansi-regex@6.2.0: {} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 + ansi-styles@6.2.1: {} + argparse@2.0.1: {} array-buffer-byte-length@1.0.2: @@ -2786,8 +2946,6 @@ snapshots: get-intrinsic: 1.3.0 is-array-buffer: 3.0.5 - assertion-error@2.0.1: {} - async-function@1.0.0: {} available-typed-arrays@1.0.7: @@ -2809,6 +2967,8 @@ snapshots: dependencies: fill-range: 7.1.1 + browser-stdout@1.3.1: {} + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -2828,21 +2988,15 @@ snapshots: callsites@3.1.0: {} - chai@5.3.1: - dependencies: - assertion-error: 2.0.1 - check-error: 2.1.1 - deep-eql: 5.0.2 - loupe: 3.2.1 - pathval: 2.0.1 + camelcase@6.3.0: {} + + chai@6.0.1: {} chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - check-error@2.1.1: {} - chevrotain-allstar@0.3.1(chevrotain@11.0.3): dependencies: chevrotain: 11.0.3 @@ -2857,6 +3011,16 @@ snapshots: '@chevrotain/utils': 11.0.3 lodash-es: 4.17.21 + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + codemirror@6.0.2: dependencies: '@codemirror/autocomplete': 6.18.6 @@ -2873,8 +3037,6 @@ snapshots: color-name@1.1.4: {} - commander@14.0.0: {} - commander@7.2.0: {} commander@8.3.0: {} @@ -3103,17 +3265,19 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 - dayjs@1.11.13: {} + dayjs@1.11.18: {} debug@3.2.7: dependencies: ms: 2.1.3 - debug@4.4.1: + debug@4.4.1(supports-color@8.1.1): dependencies: ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 - deep-eql@5.0.2: {} + decamelize@4.0.0: {} deep-is@0.1.4: {} @@ -3133,6 +3297,8 @@ snapshots: dependencies: robust-predicates: 3.0.2 + diff@7.0.0: {} + doctrine@2.1.0: dependencies: esutils: 2.0.3 @@ -3147,6 +3313,12 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + eastasianwidth@0.2.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + es-abstract@1.24.0: dependencies: array-buffer-byte-length: 1.0.2 @@ -3258,11 +3430,13 @@ snapshots: '@esbuild/win32-ia32': 0.25.9 '@esbuild/win32-x64': 0.25.9 + escalade@3.2.0: {} + escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.8(eslint@9.33.0): + eslint-config-prettier@10.1.8(eslint@9.34.0): dependencies: - eslint: 9.33.0 + eslint: 9.34.0 eslint-import-resolver-node@0.3.9: dependencies: @@ -3272,17 +3446,17 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.40.0(eslint@9.33.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.33.0): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.41.0(eslint@9.34.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.34.0): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.40.0(eslint@9.33.0)(typescript@5.9.2) - eslint: 9.33.0 + '@typescript-eslint/parser': 8.41.0(eslint@9.34.0)(typescript@5.9.2) + eslint: 9.34.0 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.40.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.41.0(eslint@9.34.0)(typescript@5.9.2))(eslint@9.34.0): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -3291,9 +3465,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.33.0 + eslint: 9.34.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.40.0(eslint@9.33.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.33.0) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.41.0(eslint@9.34.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.34.0) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -3305,20 +3479,20 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.40.0(eslint@9.33.0)(typescript@5.9.2) + '@typescript-eslint/parser': 8.41.0(eslint@9.34.0)(typescript@5.9.2) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-prettier@5.5.4(eslint-config-prettier@10.1.8(eslint@9.33.0))(eslint@9.33.0)(prettier@3.6.2): + eslint-plugin-prettier@5.5.4(eslint-config-prettier@10.1.8(eslint@9.34.0))(eslint@9.34.0)(prettier@3.6.2): dependencies: - eslint: 9.33.0 + eslint: 9.34.0 prettier: 3.6.2 prettier-linter-helpers: 1.0.0 synckit: 0.11.11 optionalDependencies: - eslint-config-prettier: 10.1.8(eslint@9.33.0) + eslint-config-prettier: 10.1.8(eslint@9.34.0) eslint-scope@8.4.0: dependencies: @@ -3329,15 +3503,15 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.33.0: + eslint@9.34.0: dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.33.0) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.34.0) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.21.0 '@eslint/config-helpers': 0.3.1 '@eslint/core': 0.15.2 '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.33.0 + '@eslint/js': 9.34.0 '@eslint/plugin-kit': 0.3.5 '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 @@ -3347,7 +3521,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.1 + debug: 4.4.1(supports-color@8.1.1) escape-string-regexp: 4.0.0 eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -3427,12 +3601,19 @@ snapshots: flatted: 3.3.3 keyv: 4.5.4 + flat@5.0.2: {} + flatted@3.3.3: {} for-each@0.3.5: dependencies: is-callable: 1.2.7 + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + function-bind@1.1.2: {} function.prototype.name@1.1.8: @@ -3446,6 +3627,8 @@ snapshots: functions-have-names@1.2.3: {} + get-caller-file@2.0.5: {} + get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -3478,6 +3661,15 @@ snapshots: dependencies: is-glob: 4.0.3 + glob@10.4.5: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + globals@14.0.0: {} globals@15.15.0: {} @@ -3517,6 +3709,8 @@ snapshots: dependencies: function-bind: 1.1.2 + he@1.2.0: {} + iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 @@ -3588,6 +3782,8 @@ snapshots: dependencies: call-bound: 1.0.4 + is-fullwidth-code-point@3.0.0: {} + is-generator-function@1.1.0: dependencies: call-bound: 1.0.4 @@ -3610,6 +3806,8 @@ snapshots: is-number@7.0.0: {} + is-plain-obj@2.1.0: {} + is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -3638,6 +3836,8 @@ snapshots: dependencies: which-typed-array: 1.1.19 + is-unicode-supported@0.1.0: {} + is-weakmap@2.0.2: {} is-weakref@1.1.1: @@ -3653,6 +3853,12 @@ snapshots: isexe@2.0.0: {} + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + js-yaml@4.1.0: dependencies: argparse: 2.0.1 @@ -3698,7 +3904,7 @@ snapshots: local-pkg@1.1.2: dependencies: - mlly: 1.7.4 + mlly: 1.8.0 pkg-types: 2.3.0 quansync: 0.2.11 @@ -3710,15 +3916,24 @@ snapshots: lodash.merge@4.6.2: {} - loupe@3.2.1: {} + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + + lru-cache@10.4.3: {} - marked@16.2.0: {} + marked@16.2.1: {} math-intrinsics@1.1.0: {} + mathjax@4.0.0: + dependencies: + '@mathjax/mathjax-newcm-font': 4.0.0 + merge2@1.4.1: {} - mermaid@11.10.0: + mermaid@11.10.1: dependencies: '@braintree/sanitize-url': 7.1.1 '@iconify/utils': 2.3.0 @@ -3730,12 +3945,12 @@ snapshots: d3: 7.9.0 d3-sankey: 0.12.3 dagre-d3-es: 7.0.11 - dayjs: 1.11.13 + dayjs: 1.11.18 dompurify: 3.2.6 katex: 0.16.22 khroma: 2.1.0 lodash-es: 4.17.21 - marked: 16.2.0 + marked: 16.2.1 roughjs: 4.6.6 stylis: 4.3.6 ts-dedent: 2.2.0 @@ -3743,8 +3958,6 @@ snapshots: transitivePeerDependencies: - supports-color - mhchemparser@4.2.1: {} - micromatch@4.0.8: dependencies: braces: 3.0.3 @@ -3760,20 +3973,43 @@ snapshots: minimist@1.2.8: {} - mj-context-menu@0.9.1: {} + minipass@7.1.2: {} - mlly@1.7.4: + mlly@1.8.0: dependencies: acorn: 8.15.0 pathe: 2.0.3 pkg-types: 1.3.1 ufo: 1.6.1 + mocha@11.7.1: + dependencies: + browser-stdout: 1.3.1 + chokidar: 4.0.3 + debug: 4.4.1(supports-color@8.1.1) + diff: 7.0.0 + escape-string-regexp: 4.0.0 + find-up: 5.0.0 + glob: 10.4.5 + he: 1.2.0 + js-yaml: 4.1.0 + log-symbols: 4.1.0 + minimatch: 9.0.5 + ms: 2.1.3 + picocolors: 1.1.1 + serialize-javascript: 6.0.2 + strip-json-comments: 3.1.1 + supports-color: 8.1.1 + workerpool: 9.3.3 + yargs: 17.7.2 + yargs-parser: 21.1.1 + yargs-unparser: 2.0.0 + ms@2.1.3: {} natural-compare@1.4.0: {} - npm-check-updates@18.0.2: {} + npm-check-updates@18.0.3: {} object-inspect@1.13.4: {} @@ -3831,6 +4067,8 @@ snapshots: dependencies: p-limit: 3.1.0 + package-json-from-dist@1.0.1: {} + package-manager-detector@1.3.0: {} parent-module@1.0.1: @@ -3845,20 +4083,25 @@ snapshots: path-parse@1.0.7: {} - pathe@2.0.3: {} + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 - pathval@2.0.1: {} + pathe@2.0.3: {} - pdfjs-dist@5.3.93: + pdfjs-dist@5.4.149: optionalDependencies: - '@napi-rs/canvas': 0.1.77 + '@napi-rs/canvas': 0.1.78 + + picocolors@1.1.1: {} picomatch@2.3.1: {} pkg-types@1.3.1: dependencies: confbox: 0.1.8 - mlly: 1.7.4 + mlly: 1.8.0 pathe: 2.0.3 pkg-types@2.3.0: @@ -3890,6 +4133,12 @@ snapshots: queue-microtask@1.2.3: {} + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + readdirp@4.1.2: {} + reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.8 @@ -3910,6 +4159,8 @@ snapshots: gopd: 1.2.0 set-function-name: 2.0.2 + require-directory@2.1.1: {} + resolve-from@4.0.0: {} resolve@1.22.10: @@ -3943,6 +4194,8 @@ snapshots: has-symbols: 1.1.0 isarray: 2.0.5 + safe-buffer@5.2.1: {} + safe-push-apply@1.0.0: dependencies: es-errors: 1.3.0 @@ -3960,6 +4213,10 @@ snapshots: semver@7.7.2: {} + serialize-javascript@6.0.2: + dependencies: + randombytes: 2.1.0 + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -4016,17 +4273,25 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 - speech-rule-engine@5.0.0-beta.1: - dependencies: - '@xmldom/xmldom': 0.9.8 - commander: 14.0.0 - wicked-good-xpath: 1.3.0 + signal-exit@4.1.0: {} stop-iteration-iterator@1.1.0: dependencies: es-errors: 1.3.0 internal-slot: 1.1.0 + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + string.prototype.trim@1.2.10: dependencies: call-bind: 1.0.8 @@ -4050,6 +4315,14 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.2.0 + strip-bom@3.0.0: {} strip-json-comments@3.1.1: {} @@ -4062,6 +4335,10 @@ snapshots: dependencies: has-flag: 4.0.0 + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + supports-preserve-symlinks-flag@1.0.0: {} synckit@0.11.11: @@ -4211,8 +4488,41 @@ snapshots: dependencies: isexe: 2.0.0 - wicked-good-xpath@1.3.0: {} - word-wrap@1.2.5: {} + workerpool@9.3.3: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + y18n@5.0.8: {} + + yargs-parser@21.1.1: {} + + yargs-unparser@2.0.0: + dependencies: + camelcase: 6.3.0 + decamelize: 4.0.0 + flat: 5.0.2 + is-plain-obj: 2.1.0 + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + yocto-queue@0.1.0: {} diff --git a/client/pnpm-workspace.yaml b/client/pnpm-workspace.yaml index efc037aa..7cb5b88e 100644 --- a/client/pnpm-workspace.yaml +++ b/client/pnpm-workspace.yaml @@ -1,2 +1,2 @@ onlyBuiltDependencies: - - esbuild + - esbuild diff --git a/client/src/CodeChatEditor-test.mts b/client/src/CodeChatEditor-test.mts index 2c996115..ea9bbfc8 100644 --- a/client/src/CodeChatEditor-test.mts +++ b/client/src/CodeChatEditor-test.mts @@ -25,17 +25,13 @@ // // I can't get Mocha to work with ESBuild, so I import it using a script tag. import { assert } from "chai"; +import "mocha/mocha.js"; +import "mocha/mocha.css"; import { EditorView } from "@codemirror/view"; -import { - ChangeSpec, - EditorState, - EditorSelection, - MapMode, -} from "@codemirror/state"; -import { exportedForTesting, page_init } from "./CodeChatEditor.mjs"; +import { ChangeSpec, EditorState, EditorSelection } from "@codemirror/state"; +import { exportedForTesting } from "./CodeChatEditor.mjs"; import { CodeMirror, CodeMirrorDocBlockTuple } from "./shared_types.mjs"; import { - docBlockField, DocBlockPlugin, CodeMirror_JSON_fields, } from "./CodeMirror-integration.mjs"; @@ -44,7 +40,9 @@ import { // Otherwise, including [CodeChatEditor.mts](CodeChatEditor.mts) elsewhere would // double-define everything (producing complaints about two attempts to define // each web component). -export { page_init }; +// +// Nothing needed at present. +// // Provide convenient access to all functions tested here. const { codechat_html_to_markdown } = exportedForTesting; @@ -112,8 +110,8 @@ window.CodeChatEditor_test = () => { ]; codechat_html_to_markdown(db); assert.deepEqual(db, [ - [0, 0, "", "//", "# A\n\n\n"], - [2, 2, "", "//", "

Ax

\n"], + [0, 0, "", "//", "A\n===============\n"], + [2, 2, "", "//", "Ax\n--\n"], ]); }); }); @@ -137,7 +135,6 @@ window.CodeChatEditor_test = () => { [[1, 2, "", "#", "test"]], { from: 1, insert: "\n" }, ); - console.log(after_state); assert.deepEqual(after_state, { doc: "a\n\nbcd", doc_blocks: [[1, 3, "", "#", "test"]], @@ -176,8 +173,6 @@ const run_CodeMirror_test = ( // Run a transaction, then extract at the results. view.dispatch({ changes }); - console.log(view.state.field(docBlockField)); - console.log(MapMode.TrackBefore); const after_state = view.state.toJSON(CodeMirror_JSON_fields); delete after_state.selection; return after_state; diff --git a/client/src/CodeChatEditor.mts b/client/src/CodeChatEditor.mts index 50622984..8b647c7f 100644 --- a/client/src/CodeChatEditor.mts +++ b/client/src/CodeChatEditor.mts @@ -171,40 +171,13 @@ turndownService.use(gfm); // Page initialization // ------------------- -// -// Load the dynamic content into the static page. -export const page_init = () => { - on_dom_content_loaded(async () => { - // Intercept links in this document to save before following the link. - /// @ts-ignore - navigation.addEventListener("navigate", on_navigate); - const ccb = document.getElementById("CodeChat-sidebar") as - | HTMLIFrameElement - | undefined; - /// @ts-ignore - ccb?.contentWindow?.navigation.addEventListener( - "navigate", - on_navigate, - ); - document.addEventListener("click", on_click); - - window.CodeChatEditor = { - open_lp, - on_save, - scroll_to_line, - show_toast, - allow_navigation: false, - }; - }); -}; - export const set_is_dirty = (value: boolean = true) => { is_dirty = value; }; -// This is copied -// from[MDN](https://developer.mozilla.org/en-US/docs/Web/API/Document/DOMContentLoaded_event#checking_whether_loading_is_already_complete). -const on_dom_content_loaded = (on_load_func: () => void) => { +// 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) => { if (document.readyState === "loading") { // Loading hasn't finished yet. document.addEventListener("DOMContentLoaded", on_load_func); @@ -219,16 +192,22 @@ const on_dom_content_loaded = (on_load_func: () => void) => { // // True if this is a CodeChat Editor document (not a source file). const is_doc_only = () => { - // This might be called by the framework before a document is loaded. - // So, make sure `current_metadata` exists first. - return current_metadata !== undefined && current_metadata["mode"] === "markdown"; + // This might be called by the framework before a document is loaded. So, + // make sure `current_metadata` exists first. + return current_metadata?.["mode"] === "markdown"; }; // Wait for the DOM to load before opening the file. const open_lp = async ( codechat_for_web: CodeChatForWeb, cursor_position?: number, -) => on_dom_content_loaded(() => _open_lp(codechat_for_web, cursor_position)); +) => + await new Promise((resolve) => + on_dom_content_loaded(async () => { + await _open_lp(codechat_for_web, cursor_position); + resolve(); + }), + ); // Store the HTML sent for CodeChat Editor documents. We can't simply use // TinyMCE's @@ -363,8 +342,8 @@ const save_lp = (is_dirty: boolean) => { "CodeChat-body", ) as HTMLDivElement; mathJaxUnTypeset(codechat_body); - // To save a document only, simply get the HTML from the only Tiny MCE - // div. + // To save a document only, simply get the HTML from the only Tiny + // MCE div. tinymce.activeEditor!.save(); const html = tinymce.activeEditor!.getContent(); ( @@ -547,19 +526,61 @@ const save_then_navigate = (codeChatEditorUrl: URL) => { }); }; +// This can be called by the framework. Therefore, make no assumptions about +// variables being valid; it be called before a file is loaded, etc. const scroll_to_line = (line: number) => { if (is_doc_only()) { // TODO. } else { codemirror_scroll_to_line(line); } -} +}; export const console_log = (...args: any) => { if (DEBUG_ENABLED) { console.log(...args); } -} +}; + +// A global error handler: this is called on any uncaught exception. +export const on_error = (event: Event) => { + let err_str: string; + if (event instanceof ErrorEvent) { + err_str = `${event.filename}:${event.lineno}: ${event.message}`; + } else if (event instanceof PromiseRejectionEvent) { + err_str = `${event.promise} rejected: ${event.reason}`; + } else { + err_str = `Unexpected error ${typeof event}: ${event}`; + } + show_toast(`Error: ${err_str}`); + console.error(event); +}; + +// Load the dynamic content into the static page. Place this last, since we need +// functions above defined before assigning them to the `CodeChatEditor` +// namespace. +on_dom_content_loaded(async () => { + // Intercept links in this document to save before following the link. + /// @ts-ignore + navigation.addEventListener("navigate", on_navigate); + const ccb = document.getElementById("CodeChat-sidebar") as + | HTMLIFrameElement + | undefined; + /// @ts-ignore + ccb?.contentWindow?.navigation.addEventListener("navigate", on_navigate); + document.addEventListener("click", on_click); + // Provide basic error reporting for uncaught errors. + window.addEventListener("unhandledrejection", on_error); + window.addEventListener("error", on_error); + + window.CodeChatEditor = { + open_lp, + on_save, + scroll_to_line, + show_toast, + allow_navigation: false, + }; +}); // Testing // ------- diff --git a/client/src/CodeChatEditorFramework.mts b/client/src/CodeChatEditorFramework.mts index 1a7415fc..e58a7839 100644 --- a/client/src/CodeChatEditorFramework.mts +++ b/client/src/CodeChatEditorFramework.mts @@ -26,13 +26,11 @@ // Imports // ------- // -// ### JavaScript/TypeScript -// -// #### Third-party +// ### Third-party import ReconnectingWebSocket from "./third-party/ReconnectingWebSocket.cjs"; import { show_toast as show_toast_core } from "./show_toast.mjs"; -// #### Local +// ### Local import { assert } from "./assert.mjs"; import { CodeChatForWeb, @@ -41,7 +39,12 @@ import { MessageResult, UpdateMessageContents, } from "./shared_types.mjs"; -import { console_log } from "./CodeChatEditor.mjs"; +import { + console_log, + DEBUG_ENABLED, + on_error, + on_dom_content_loaded, +} from "./CodeChatEditor.mjs"; // Websocket // --------- @@ -51,8 +54,8 @@ import { console_log } from "./CodeChatEditor.mjs"; // // The max length of a message to show in the console. const MAX_MESSAGE_LENGTH = 200; -// The timeout for a websocket `Response`. -const RESPONSE_TIMEOUT = 15000; +// The timeout for a websocket `Response`, in ms. +const RESPONSE_TIMEOUT_MS = 1500000; // An instance of the websocket communication class. let webSocketComm: WebSocketComm; @@ -61,9 +64,11 @@ class WebSocketComm { // Use a unique ID for each websocket message sent. See the Implementation // section on Message IDs for more information. ws_id = -9007199254740988; + // The websocket used by this class. Really a `ReconnectingWebSocket`, but // that's not a type. ws: WebSocket; + // A map of message id to (timer id, callback) for all pending messages. pending_messages: Record< number, @@ -72,14 +77,22 @@ class WebSocketComm { callback: () => void; } > = {}; - // True when the iframe is loading, so that an `Update` should be postponed - // until the page load is finished. Otherwise, the page is fully loaded, so - // the `Update` may be applied immediately. - onloading = false; + // The current filename of the file being edited. This is provided by the // IDE and passed back to it, but not otherwise used by the Framework. current_filename: string | undefined = undefined; + // True when the iframe is loading, so that an `Update` should be postponed + // until the page load is finished. Otherwise, the page is fully loaded, so + // the `Update` may be applied immediately. + is_loading = false; + + // A promise to serialize calls to and from the Client. This is important: a + // `CurrentFile` requires the Client to save, then switch to a new web page. + // If an `Update` comes in, it should be applied after the `CurrentFile` has + // finished executing. + promise = Promise.resolve(); + constructor(ws_url: string) { // The `ReconnectingWebSocket` doesn't provide ALL the `WebSocket` // methods. Ignore this, since we can't use `ReconnectingWebSocket` as a @@ -92,28 +105,27 @@ class WebSocketComm { }; // Provide logging to help track down errors. - this.ws.onerror = (event: any) => { + this.ws.onerror = (event: Event) => { report_error( - `CodeChat Client: websocket error ${JSON.stringify(event)}.` + `CodeChat Client: websocket error.`, event ); }; - this.ws.onclose = (event: any) => { + this.ws.onclose = (event: CloseEvent) => { console_log( - `CodeChat Client: websocket closed by event type ${event.type}: ${event.detail}. This should only happen on shutdown.` + `CodeChat Client: websocket ${event.wasClean ? "" : "*NOT*"} cleanly closed ${event.reason}. This should only happen on shutdown.` ); + console_log(event); }; // Handle websocket messages. - this.ws.onmessage = (event: any) => { + this.ws.onmessage = (event: MessageEvent) => { // Parse the received message, which must be a single element of a - // dictionary representing a `JointMessage`. + // dictionary representing an `EditorMessage`. const joint_message = JSON.parse(event.data) as EditorMessage; - const { id: id, message: message } = joint_message; + const { id, message } = joint_message; console_log( - `Received data id = ${id}, message = ${JSON.stringify( - message - ).substring(0, MAX_MESSAGE_LENGTH)}` + `Received data id = ${id}, message = ${format_struct(message)}`, ); assert(id !== undefined); assert(message !== undefined); @@ -127,70 +139,91 @@ class WebSocketComm { case "Update": // Load this data in. const current_update = value as UpdateMessageContents; - // Check or update the `current_filename`. - if (this.current_filename === undefined) { - this.current_filename = current_update.file_path; - } else if ( - current_update.file_path !== this.current_filename - ) { - const msg = `Ignoring update for ${current_update.file_path} because it's not the current file ${this.current_filename}.`; - report_error(msg); - this.send_result(id, msg); - break; - } - const contents = current_update.contents; - const cursor_position = current_update.cursor_position; - if (contents !== undefined) { - // If the page is still loading, wait until the load - // completed before updating the editable contents. - if (this.onloading) { - root_iframe!.onload = () => { - set_content( + // The rest of this should run after all other messages have + // been processed. + this.promise = this.promise.finally(async () => { + // Check or update the `current_filename`. + if (this.current_filename === undefined) { + this.current_filename = current_update.file_path; + } else if ( + current_update.file_path !== this.current_filename + ) { + const msg = `Ignoring update for ${current_update.file_path} because it's not the current file ${this.current_filename}.`; + report_error(msg); + this.send_result(id, msg); + return; + } + const contents = current_update.contents; + const cursor_position = current_update.cursor_position; + if (contents !== undefined) { + // I'd prefer to use a system-maintained value to + // determine the ready state of the iframe, such as + // [readyState](https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState). + // However, this value only applies to the initial + // load of the iframe; it doesn't change when the + // iframe's `src` attribute is changed. So, we have + // to track this manually instead. + if (!this.is_loading) { + // Wait until after the DOM is ready, since we + // rely on content set in + // `on_dom_content_loaded` in the Client. + await set_content( contents, - current_update.cursor_position + current_update.cursor_position, ); - this.onloading = false; - }; - } else { - set_content( - contents, - current_update.cursor_position + } else { + // If the page is still loading, wait until the + // load completes before updating the editable + // contents. + // + // Construct the promise to use; this causes the + // `onload` callback to be set immediately. + await new Promise( + (resolve) => + (root_iframe!.onload = async () => { + this.is_loading = false; + await set_content( + contents, + current_update.cursor_position, + ); + resolve(); + }), + ); + } + } else if (cursor_position !== undefined) { + // We might receive a message while the Client is + // reloading; during this period, `scroll_to_line` + // isn't defined. + root_iframe!.contentWindow?.CodeChatEditor?.scroll_to_line?.( + cursor_position, ); } - } else if (cursor_position !== undefined) { - // We might receive a message while the Client is - // reloading; during this period, `scroll_to_line` isn't - // defined. - root_iframe!.contentWindow!.CodeChatEditor.scroll_to_line?.( - cursor_position - ); - } - this.send_result(id, null); + this.send_result(id, null); + }); break; case "CurrentFile": // Note that we can ignore `value[1]` (if the file is text // or binary); the server only sends text files here. const current_file = value[0] as string; - // If the page is still loading, then don't save. Otherwise, - // save the editor contents if necessary. - let cce = get_client(); - let promise = - cce !== undefined - ? cce.on_save(true) - : Promise.resolve(); - promise.then((_) => { - // Now, it's safe to load a new file. - const testSuffix = testMode - ? // Append the test parameter correctly, depending if - // there are already parameters or not. - current_file.indexOf("?") === -1 - ? "?test" - : "&test" - : ""; - // Tell the client to allow this navigation -- the - // document it contains has already been saved. + const testSuffix = testMode + ? // Append the test parameter correctly, depending if + // there are already parameters or not. + current_file.indexOf("?") === -1 + ? "?test" + : "&test" + : ""; + // Execute this after all other messages have been + // processed. + this.promise = this.promise.finally(async () => { + // If the page is still loading, then don't save. + // Otherwise, save the editor contents if necessary. + const cce = get_client(); + await cce?.on_save(true); + // Now, it's safe to load a new file. Tell the client to + // allow this navigation -- the document it contains has + // already been saved. if (cce !== undefined) { cce.allow_navigation = true; } @@ -221,15 +254,15 @@ class WebSocketComm { const result_contents = value as MessageResult; if ("Err" in result_contents) { report_error( - `Error in message ${id}: ${result_contents.Err}.` + `Error in message ${id}: ${result_contents.Err}.`, ); } break; default: - const msg = `Received unhandled message ${key}(${JSON.stringify( - value - ).substring(0, MAX_MESSAGE_LENGTH)})`; + const msg = `Received unhandled message ${key}(${format_struct( + value, + )})`; report_error(msg); this.send_result(id, msg); break; @@ -237,21 +270,20 @@ class WebSocketComm { }; } + send = (data: any) => this.ws.send(data); + close = (...args: any) => this.ws.close(...args); + set_root_iframe_src = (url: string) => { // Set the new src to (re)load content. At startup, the `srcdoc` // attribute shows some welcome text. Remove it so that we can now // assign the `src` attribute. root_iframe!.removeAttribute("srcdoc"); root_iframe!.src = url; - // There's no easy way to determine when the iframe's DOM is ready. This - // is a kludgy workaround -- set a flag. - this.onloading = true; - root_iframe!.onload = () => (this.onloading = false); + // Track the `is_loading` status. + this.is_loading = true; + root_iframe!.onload = () => (this.is_loading = false); }; - send = (data: any) => this.ws.send(data); - close = (...args: any) => this.ws.close(...args); - // Report an error from the server. report_server_timeout = (message_id: number) => { delete this.pending_messages[message_id]; @@ -261,21 +293,18 @@ class WebSocketComm { // Send a message expecting a result to the server. send_message = ( message: EditorMessageContents, - callback: () => void = () => 0 + callback: () => void = () => 0, ) => { const id = this.ws_id; + // The Client gets every third ID -- the IDE gets another third, while + // the Server gets the final third. this.ws_id += 3; // Add in the current filename to the message, if it's an `Update`. if (typeof message == "object" && "Update" in message) { assert(this.current_filename !== undefined); message.Update.file_path = this.current_filename!; } - console_log( - `Sent message ${id}, ${JSON.stringify(message).substring( - 0, - MAX_MESSAGE_LENGTH - )}` - ); + console_log(`Sent message ${id}, ${format_struct(message)}`); const jm: EditorMessage = { id: id, message: message, @@ -284,24 +313,35 @@ class WebSocketComm { this.pending_messages[id] = { timer_id: window.setTimeout( this.report_server_timeout, - RESPONSE_TIMEOUT, - id + RESPONSE_TIMEOUT_MS, + id, ), callback, }; }; + // This is called by the Client when the user navigates to another webpage. current_file = (url: URL) => { - // If this points to the Server, then tell the IDE to load a new file. - if (url.host === window.location.host) { - this.send_message({ CurrentFile: [url.toString(), null] }, () => { + // TODO: should we delay execution of user navigation until all previous + // actions have finished, or ignore them and immediately perform the + // user navigation? + this.promise = this.promise.finally(() => { + if (url.host === window.location.host) { + // If this points to the Server, then tell the IDE to load a new + // file. + this.send_message( + { CurrentFile: [url.toString(), null] }, + () => { + this.set_root_iframe_src(url.toString()); + }, + ); + } else { + // Otherwise, navigate to the provided page. this.set_root_iframe_src(url.toString()); - }); - } else { - this.set_root_iframe_src(url.toString()); - } - // Read the `current_filename` from the next `Update` message. - this.current_filename = undefined; + } + // Read the `current_filename` from the next `Update` message. + this.current_filename = undefined; + }); }; // Send a result (a response to a message from the server) back to the @@ -311,9 +351,7 @@ class WebSocketComm { Result: result === null ? { Ok: "Void" } : { Err: result }, }; console_log( - `Sending result id = ${id}, message = ${JSON.stringify( - message - ).substring(0, MAX_MESSAGE_LENGTH)}` + `Sending result id = ${id}, message = ${format_struct(message)}`, ); // We can't simply call `send_message` because that function expects a // result message back from the server. @@ -331,7 +369,10 @@ const get_client = () => root_iframe?.contentWindow?.CodeChatEditor; // Assign content to either the Client (if it's loaded) or the webpage (if not) // in the `root_iframe`. -const set_content = (contents: CodeChatForWeb, cursor_position?: number) => { +const set_content = async ( + contents: CodeChatForWeb, + cursor_position?: number, +) => { let client = get_client(); if (client === undefined) { // See if this is the [simple viewer](#Client-simple-viewer). Otherwise, @@ -339,7 +380,7 @@ const set_content = (contents: CodeChatForWeb, cursor_position?: number) => { const cw = ( root_iframe!.contentDocument?.getElementById( - "CodeChat-contents" + "CodeChat-contents", ) as HTMLIFrameElement | undefined )?.contentWindow ?? root_iframe!.contentWindow!; cw.document.open(); @@ -347,9 +388,9 @@ const set_content = (contents: CodeChatForWeb, cursor_position?: number) => { cw.document.write(contents.source.Plain.doc); cw.document.close(); } else { - root_iframe!.contentWindow!.CodeChatEditor.open_lp( + await root_iframe!.contentWindow!.CodeChatEditor.open_lp( contents, - cursor_position + cursor_position, ); } }; @@ -368,19 +409,23 @@ export const page_init = ( // nice, interactive definition of the components of a URL. ws_pathname: string, // Test mode flag - testMode_: boolean + testMode_: boolean, ) => { testMode = testMode_; - on_dom_content_loaded(async () => { + on_dom_content_loaded(() => { + // Provide basic error reporting for uncaught errors. + window.addEventListener("unhandledrejection", on_error); + window.addEventListener("error", on_error); + // If the hosting page uses HTTPS, then use a secure websocket (WSS // protocol); otherwise, use an insecure websocket (WS). const protocol = window.location.protocol === "http:" ? "ws:" : "wss:"; // Build a websocket address based on the URL of the current page. webSocketComm = new WebSocketComm( - `${protocol}//${window.location.host}/${ws_pathname}` + `${protocol}//${window.location.host}/${ws_pathname}`, ); root_iframe = document.getElementById( - "CodeChat-iframe" + "CodeChat-iframe", )! as HTMLIFrameElement; window.CodeChatEditorFramework = { webSocketComm, @@ -388,18 +433,6 @@ export const page_init = ( }); }; -// This is copied from -// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Document/DOMContentLoaded_event#checking_whether_loading_is_already_complete). -const on_dom_content_loaded = (on_load_func: () => void) => { - if (document.readyState === "loading") { - // Loading hasn't finished yet. - document.addEventListener("DOMContentLoaded", on_load_func); - } else { - // `DOMContentLoaded` has already fired. - on_load_func(); - } -}; - // Tell TypeScript about the global namespace this program defines. declare global { interface Window { @@ -418,7 +451,19 @@ const show_toast = (text: string) => { } }; -const report_error = (text: string) => { +// Format a complex data structure as a string when in debug mode. +export const format_struct = (complex_data_structure: any): string => + DEBUG_ENABLED + ? JSON.stringify(complex_data_structure).substring( + 0, + MAX_MESSAGE_LENGTH, + ) + : ""; + +const report_error = (text: string, ...objs: any) => { console.error(text); + if (objs !== undefined) { + console.log(...objs); + } show_toast(text); }; diff --git a/client/src/CodeMirror-integration.mts b/client/src/CodeMirror-integration.mts index cbf8a974..288a54db 100644 --- a/client/src/CodeMirror-integration.mts +++ b/client/src/CodeMirror-integration.mts @@ -1080,8 +1080,8 @@ export const CodeMirror_load = async ( export const scroll_to_line = (line: number) => { ignore_selection_change = true; - const line_range = current_view.state.doc.line(line); - current_view.dispatch({ + const line_range = current_view?.state.doc.line(line); + current_view?.dispatch({ selection: EditorSelection.cursor(line_range.from), scrollIntoView: true, }); diff --git a/client/src/assert.mts b/client/src/assert.mts index f3ea5671..27be8f1e 100644 --- a/client/src/assert.mts +++ b/client/src/assert.mts @@ -1,7 +1,11 @@ // `assert.mts` // ============ -// Provide a simple `assert` function to check conditions at runtime. Using things like [assert](https://nodejs.org/api/assert.html) causes problems -- somehow, this indicates that the code in running in a development environment (see [this](https://github.com/micromark/micromark/issues/87#issuecomment-908924233)). -// +//// +// Provide a simple `assert` function to check conditions at runtime. Using +// things like [assert](https://nodejs.org/api/assert.html) causes problems -- +// somehow, this indicates that the code is running in a development environment +// (see +// [this](https://github.com/micromark/micromark/issues/87#issuecomment-908924233)). // Taken from the TypeScript // [docs](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#assertion-functions). export function assert(condition: any, msg?: string): asserts condition { diff --git a/docs/changelog.md b/docs/changelog.md index f4b2d697..6364dd01 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -22,6 +22,16 @@ Changelog [Github master](https://github.com/bjones1/CodeChat_Editor) ----------------------------------------------------------- +* Correct EOL handling on Windows which caused data corruption. + +Version 0.1.30 -- 2025-30-Aug +----------------------------- + +* Correct ordering of messages sent to and from the Framework to the Client. +* Fix and improve test framework and error reporting. +* Improve MathJax bundling. +* Update PDF viewer. + Version 0.1.29 -- 2025-23-Aug ----------------------------- diff --git a/docs/design.md b/docs/design.md index e668c375..d8dbd9d8 100644 --- a/docs/design.md +++ b/docs/design.md @@ -10,7 +10,7 @@ To build from source 3. [Install NPM](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) (the Node.js package manager). -4. In the `server/` directory: +4. In the `server/` directory: 1. Run `./bt install --dev`. 2. Run `./bt build`. 3. Run `cargo run -- start ../README.md`. @@ -26,20 +26,27 @@ These form a set of high-level requirements to guide the project. * View source code as [code blocks and doc blocks](index.md#code-blocks-and-doc-blocks). Doc blocks are lines of source which contain only correctly-formatted comments. + * Provide support for a [wide variety of programming languages](index.md#programming-language-support). + * Provide integration with a [wide variety of IDEs/text editors](index.md#ide-integration). -* Load a document from source code, allow edits in a GUI, then save it - back to source code. + +* Load a document from source code, allow edits in a GUI, then save it back to + source code. + * Provide word processor GUI tools (insert hyperlink, images, headings, change font, etc.) for doc blocks. * Provide text editor/IDE tools (syntax highlighting, line numbers, show linter feedback) for code blocks. * Zero build: eliminate the traditional project build process -- make it almost instantaneous. + * Doc block markup should be readable and well-known: markdown. + * Support both a single-file mode and a project mode. + * A project is a specific directory tree, identified by the presence of a TOC. A TOC is just a plain Markdown file with a specific name. A better term: not a TOC, but a navigation pane, since the TOC can contain @@ -50,8 +57,9 @@ These form a set of high-level requirements to guide the project. * Numbering comes from the current page's location within the TOC. Pages not in the TOC aren't numbered. * Provide [authoring - support](index.md#authoring-support), which allows authors to easily - create book/project-like features. In particular: + support](index.md#authoring-support), which allows authors to easily create + book/project-like features. In particular: + * Counters for numbering figures, tables, equations, etc. All counters are page-local (no global counters). * Auto-titled links: the link text is automatically derived from the @@ -108,9 +116,9 @@ These form a set of high-level requirements to guide the project. all anchors to be globally unique. HTML allows upper/lowercase ASCII plus the hyphen and underscore for IDs, meaning that a 5-character string provides >250 million unique anchors. - * Make picking a file/anchor easy: provide a searchable, expanded TOC listing every anchor. + * Provide edit and view options. (Rely on an IDE to edit raw source.) ### Nice to have features diff --git a/docs/style_guide.cpp b/docs/style_guide.cpp index fc364119..e2497fe2 100644 --- a/docs/style_guide.cpp +++ b/docs/style_guide.cpp @@ -183,17 +183,12 @@ double accurate_g( // Properly configuring the text editor used with the CodeChat Editor // significantly improves the authoring process. Recommended settings: // -// * Enable word wrap: -// [vscode](https://learn.microsoft.com/en-us/visualstudio/ide/reference/how-to-manage-word-wrap-in-the-editor?view=vs-2022) -// * Use spaces, not tabs​, for indentation: -// [vscode](https://code.visualstudio.com/docs/editor/codebasics#_indentation) -// * Enable auto-save: -// [vscode](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save) +// * Enable word wrap: [vscode](https://learn.microsoft.com/en-us/visualstudio/ide/reference/how-to-manage-word-wrap-in-the-editor?view=vs-2022) +// * Use spaces, not tabs​, for indentation: [vscode](https://code.visualstudio.com/docs/editor/codebasics#_indentation) +// * Enable auto-save: [vscode](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save) // * Auto-reload enabled​: default in vscode -// * On save, remove trailing whitespace​: -// [vscode](https://stackoverflow.com/a/53663494/16038919) -// * Use a spell checker: -// [vscode](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker) +// * On save, remove trailing whitespace​: [vscode](https://stackoverflow.com/a/53663494/16038919) +// * Use a spell checker: [vscode](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker) // * On a big monitor, place your IDE side by side with the CodeChat Editor. // // Common problems diff --git a/extensions/VSCode/package-lock.json b/extensions/VSCode/package-lock.json index 506f1c7b..e27709d2 100644 --- a/extensions/VSCode/package-lock.json +++ b/extensions/VSCode/package-lock.json @@ -1,12 +1,12 @@ { "name": "codechat-editor-client", - "version": "0.1.29", + "version": "0.1.31", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codechat-editor-client", - "version": "0.1.29", + "version": "0.1.31", "license": "GPL-3.0-only", "dependencies": { "escape-html": "^1", @@ -24,6 +24,7 @@ "eslint-plugin-import": "^2", "eslint-plugin-node": "^11", "ovsx": "^0.10", + "prettier": "^3.6.2", "typescript": "^5" }, "engines": { @@ -182,9 +183,9 @@ } }, "node_modules/@azure/msal-browser": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-4.21.0.tgz", - "integrity": "sha512-vgzhz1F3DIB8qcjeJ3DLxMAha4iEaV2BDd1nxPP0ovTjIrpFUGlbhI+Z0pnK+GXctf2UmCwujH2L8xd8CdlMvw==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-4.21.1.tgz", + "integrity": "sha512-qGtzX3HJfJsOVeDcVrFZAYZoxLRjrW2lXzXqijgiBA5EtM9ud7F/EYgKKQ9TJU/WtE46szuZtQZx5vD4pEiknA==", "dev": true, "license": "MIT", "dependencies": { @@ -205,9 +206,9 @@ } }, "node_modules/@azure/msal-node": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-3.7.2.tgz", - "integrity": "sha512-pZ4GdPL9sBqgbdlQOIBDOrcqoFtCHkOVvvDYdhZOGHzpXp/nEwcL0PZt+qCHyy21fnK2GavvnFA4PeNb1ZGpDg==", + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-3.7.3.tgz", + "integrity": "sha512-MoJxkKM/YpChfq4g2o36tElyzNUMG8mfD6u8NbuaPAsqfGpaw249khAcJYNoIOigUzRw45OjXCOrexE6ImdUxg==", "dev": true, "license": "MIT", "dependencies": { @@ -245,21 +246,21 @@ } }, "node_modules/@emnapi/core": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz", - "integrity": "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz", + "integrity": "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==", "dev": true, "license": "MIT", "optional": true, "dependencies": { - "@emnapi/wasi-threads": "1.0.4", + "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", - "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz", + "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==", "dev": true, "license": "MIT", "optional": true, @@ -268,9 +269,9 @@ } }, "node_modules/@emnapi/wasi-threads": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz", - "integrity": "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", "dev": true, "license": "MIT", "optional": true, @@ -472,9 +473,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.33.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.33.0.tgz", - "integrity": "sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A==", + "version": "9.34.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.34.0.tgz", + "integrity": "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==", "dev": true, "license": "MIT", "engines": { @@ -1318,17 +1319,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.40.0.tgz", - "integrity": "sha512-w/EboPlBwnmOBtRbiOvzjD+wdiZdgFeo17lkltrtn7X37vagKKWJABvyfsJXTlHe6XBzugmYgd4A4nW+k8Mixw==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.41.0.tgz", + "integrity": "sha512-8fz6oa6wEKZrhXWro/S3n2eRJqlRcIa6SlDh59FXJ5Wp5XRZ8B9ixpJDcjadHq47hMx0u+HW6SNa6LjJQ6NLtw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.40.0", - "@typescript-eslint/type-utils": "8.40.0", - "@typescript-eslint/utils": "8.40.0", - "@typescript-eslint/visitor-keys": "8.40.0", + "@typescript-eslint/scope-manager": "8.41.0", + "@typescript-eslint/type-utils": "8.41.0", + "@typescript-eslint/utils": "8.41.0", + "@typescript-eslint/visitor-keys": "8.41.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -1342,22 +1343,22 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.40.0", + "@typescript-eslint/parser": "^8.41.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.40.0.tgz", - "integrity": "sha512-jCNyAuXx8dr5KJMkecGmZ8KI61KBUhkCob+SD+C+I5+Y1FWI2Y3QmY4/cxMCC5WAsZqoEtEETVhUiUMIGCf6Bw==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.41.0.tgz", + "integrity": "sha512-gTtSdWX9xiMPA/7MV9STjJOOYtWwIJIYxkQxnSV1U3xcE+mnJSH3f6zI0RYP+ew66WSlZ5ed+h0VCxsvdC1jJg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.40.0", - "@typescript-eslint/types": "8.40.0", - "@typescript-eslint/typescript-estree": "8.40.0", - "@typescript-eslint/visitor-keys": "8.40.0", + "@typescript-eslint/scope-manager": "8.41.0", + "@typescript-eslint/types": "8.41.0", + "@typescript-eslint/typescript-estree": "8.41.0", + "@typescript-eslint/visitor-keys": "8.41.0", "debug": "^4.3.4" }, "engines": { @@ -1373,14 +1374,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.40.0.tgz", - "integrity": "sha512-/A89vz7Wf5DEXsGVvcGdYKbVM9F7DyFXj52lNYUDS1L9yJfqjW/fIp5PgMuEJL/KeqVTe2QSbXAGUZljDUpArw==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.41.0.tgz", + "integrity": "sha512-b8V9SdGBQzQdjJ/IO3eDifGpDBJfvrNTp2QD9P2BeqWTGrRibgfgIlBSw6z3b6R7dPzg752tOs4u/7yCLxksSQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.40.0", - "@typescript-eslint/types": "^8.40.0", + "@typescript-eslint/tsconfig-utils": "^8.41.0", + "@typescript-eslint/types": "^8.41.0", "debug": "^4.3.4" }, "engines": { @@ -1395,14 +1396,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.40.0.tgz", - "integrity": "sha512-y9ObStCcdCiZKzwqsE8CcpyuVMwRouJbbSrNuThDpv16dFAj429IkM6LNb1dZ2m7hK5fHyzNcErZf7CEeKXR4w==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.41.0.tgz", + "integrity": "sha512-n6m05bXn/Cd6DZDGyrpXrELCPVaTnLdPToyhBoFkLIMznRUQUEQdSp96s/pcWSQdqOhrgR1mzJ+yItK7T+WPMQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.40.0", - "@typescript-eslint/visitor-keys": "8.40.0" + "@typescript-eslint/types": "8.41.0", + "@typescript-eslint/visitor-keys": "8.41.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1413,9 +1414,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.40.0.tgz", - "integrity": "sha512-jtMytmUaG9d/9kqSl/W3E3xaWESo4hFDxAIHGVW/WKKtQhesnRIJSAJO6XckluuJ6KDB5woD1EiqknriCtAmcw==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.41.0.tgz", + "integrity": "sha512-TDhxYFPUYRFxFhuU5hTIJk+auzM/wKvWgoNYOPcOf6i4ReYlOoYN8q1dV5kOTjNQNJgzWN3TUUQMtlLOcUgdUw==", "dev": true, "license": "MIT", "engines": { @@ -1430,15 +1431,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.40.0.tgz", - "integrity": "sha512-eE60cK4KzAc6ZrzlJnflXdrMqOBaugeukWICO2rB0KNvwdIMaEaYiywwHMzA1qFpTxrLhN9Lp4E/00EgWcD3Ow==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.41.0.tgz", + "integrity": "sha512-63qt1h91vg3KsjVVonFJWjgSK7pZHSQFKH6uwqxAH9bBrsyRhO6ONoKyXxyVBzG1lJnFAJcKAcxLS54N1ee1OQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.40.0", - "@typescript-eslint/typescript-estree": "8.40.0", - "@typescript-eslint/utils": "8.40.0", + "@typescript-eslint/types": "8.41.0", + "@typescript-eslint/typescript-estree": "8.41.0", + "@typescript-eslint/utils": "8.41.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -1455,9 +1456,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.40.0.tgz", - "integrity": "sha512-ETdbFlgbAmXHyFPwqUIYrfc12ArvpBhEVgGAxVYSwli26dn8Ko+lIo4Su9vI9ykTZdJn+vJprs/0eZU0YMAEQg==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.41.0.tgz", + "integrity": "sha512-9EwxsWdVqh42afLbHP90n2VdHaWU/oWgbH2P0CfcNfdKL7CuKpwMQGjwev56vWu9cSKU7FWSu6r9zck6CVfnag==", "dev": true, "license": "MIT", "engines": { @@ -1469,16 +1470,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.40.0.tgz", - "integrity": "sha512-k1z9+GJReVVOkc1WfVKs1vBrR5MIKKbdAjDTPvIK3L8De6KbFfPFt6BKpdkdk7rZS2GtC/m6yI5MYX+UsuvVYQ==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.41.0.tgz", + "integrity": "sha512-D43UwUYJmGhuwHfY7MtNKRZMmfd8+p/eNSfFe6tH5mbVDto+VQCayeAt35rOx3Cs6wxD16DQtIKw/YXxt5E0UQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.40.0", - "@typescript-eslint/tsconfig-utils": "8.40.0", - "@typescript-eslint/types": "8.40.0", - "@typescript-eslint/visitor-keys": "8.40.0", + "@typescript-eslint/project-service": "8.41.0", + "@typescript-eslint/tsconfig-utils": "8.41.0", + "@typescript-eslint/types": "8.41.0", + "@typescript-eslint/visitor-keys": "8.41.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1498,16 +1499,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.40.0.tgz", - "integrity": "sha512-Cgzi2MXSZyAUOY+BFwGs17s7ad/7L+gKt6Y8rAVVWS+7o6wrjeFN4nVfTpbE25MNcxyJ+iYUXflbs2xR9h4UBg==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.41.0.tgz", + "integrity": "sha512-udbCVstxZ5jiPIXrdH+BZWnPatjlYwJuJkDA4Tbo3WyYLh8NvB+h/bKeSZHDOFKfphsZYJQqaFtLeXEqurQn1A==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.40.0", - "@typescript-eslint/types": "8.40.0", - "@typescript-eslint/typescript-estree": "8.40.0" + "@typescript-eslint/scope-manager": "8.41.0", + "@typescript-eslint/types": "8.41.0", + "@typescript-eslint/typescript-estree": "8.41.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1522,13 +1523,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.40.0.tgz", - "integrity": "sha512-8CZ47QwalyRjsypfwnbI3hKy5gJDPmrkLjkgMxhi0+DZZ2QNx2naS6/hWoVYUHU7LU2zleF68V9miaVZvhFfTA==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.41.0.tgz", + "integrity": "sha512-+GeGMebMCy0elMNg67LRNoVnUFPIm37iu5CmHESVx56/9Jsfdpsvbv605DQ81Pi/x11IdKUsS5nzgTYbCQU9fg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.40.0", + "@typescript-eslint/types": "8.41.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -3028,9 +3029,9 @@ } }, "node_modules/eslint": { - "version": "9.33.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.33.0.tgz", - "integrity": "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==", + "version": "9.34.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.34.0.tgz", + "integrity": "sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg==", "dev": true, "license": "MIT", "dependencies": { @@ -3040,7 +3041,7 @@ "@eslint/config-helpers": "^0.3.1", "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.33.0", + "@eslint/js": "9.34.0", "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -3598,9 +3599,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", "dev": true, "funding": [ { @@ -5905,6 +5906,22 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pump": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", @@ -7308,9 +7325,9 @@ "license": "MIT" }, "node_modules/undici": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.14.0.tgz", - "integrity": "sha512-Vqs8HTzjpQXZeXdpsfChQTlafcMQaaIwnGwLam1wudSSjlJeQ3bw1j+TLPePgrCnCpUXx7Ba5Pdpf5OBih62NQ==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.15.0.tgz", + "integrity": "sha512-7oZJCPvvMvTd0OlqWsIxTuItTpJBpU1tcbVl24FMn3xt3+VSunwUasmfPJRE57oNO1KsZ4PgA1xTdAX4hq8NyQ==", "dev": true, "license": "MIT", "engines": { diff --git a/extensions/VSCode/package.json b/extensions/VSCode/package.json index b340782f..4c785a8b 100644 --- a/extensions/VSCode/package.json +++ b/extensions/VSCode/package.json @@ -30,7 +30,7 @@ "type": "git", "url": "https://github.com/bjones1/CodeChat_Editor" }, - "version": "0.1.29", + "version": "0.1.31", "activationEvents": [ "onCommand:extension.codeChatEditorActivate", "onCommand:extension.codeChatEditorDeactivate" @@ -83,8 +83,8 @@ }, "devDependencies": { "@types/escape-html": "^1", - "@types/ws": "^8", "@types/vscode": "^1.51.0", + "@types/ws": "^8", "@typescript-eslint/eslint-plugin": "^8", "@typescript-eslint/parser": "^8", "@vscode/vsce": "^3", @@ -93,6 +93,7 @@ "eslint-plugin-import": "^2", "eslint-plugin-node": "^11", "ovsx": "^0.10", + "prettier": "^3.6.2", "typescript": "^5" }, "optionalDependencies": { diff --git a/extensions/VSCode/pnpm-workspace.yaml b/extensions/VSCode/pnpm-workspace.yaml deleted file mode 100644 index 964a1923..00000000 --- a/extensions/VSCode/pnpm-workspace.yaml +++ /dev/null @@ -1,4 +0,0 @@ -onlyBuiltDependencies: - - '@vscode/vsce-sign' - - bufferutil - - keytar diff --git a/extensions/VSCode/src/extension.ts b/extensions/VSCode/src/extension.ts index 63d402ea..29750806 100644 --- a/extensions/VSCode/src/extension.ts +++ b/extensions/VSCode/src/extension.ts @@ -49,8 +49,8 @@ enum CodeChatEditorClientLocation { } // The max length of a message to show in the console. const MAX_MESSAGE_LENGTH = 200; -// The timeout for a websocket `Response`. -const RESPONSE_TIMEOUT = 15000; +// The timeout for a websocket `Response`, in ms. +const RESPONSE_TIMEOUT_MS = 15000; // True to enable additional debug logging. const DEBUG_ENABLED = false; @@ -112,7 +112,7 @@ export const activate = (context: vscode.ExtensionContext) => { context.subscriptions.push( vscode.commands.registerCommand( "extension.codeChatEditorDeactivate", - deactivate + deactivate, ), vscode.commands.registerCommand( "extension.codeChatEditorActivate", @@ -134,10 +134,10 @@ export const activate = (context: vscode.ExtensionContext) => { console_log( `CodeChat Editor extension: text changed - ${ event.reason - }, ${format_struct(event.contentChanges)}.` + }, ${format_struct(event.contentChanges)}.`, ); send_update(true); - }) + }), ); // Render when the active editor changes. @@ -148,7 +148,7 @@ export const activate = (context: vscode.ExtensionContext) => { return; } current_file(); - }) + }), ); context.subscriptions.push( @@ -159,8 +159,8 @@ export const activate = (context: vscode.ExtensionContext) => { return; } send_update(false); - } - ) + }, + ), ); } @@ -228,13 +228,13 @@ export const activate = (context: vscode.ExtensionContext) => { // Without this, the websocket connection is // dropped when the panel is hidden. retainContextWhenHidden: true, - } + }, ); webview_panel.onDidDispose(async () => { // Shut down the render client when the webview // panel closes. console_log( - "CodeChat Editor extension: shut down webview." + "CodeChat Editor extension: shut down webview.", ); // Closing the webview abruptly closes the Client, // which produces an error. Don't report it. @@ -246,14 +246,14 @@ export const activate = (context: vscode.ExtensionContext) => { // Render when the webview panel is shown. webview_panel.onDidChangeViewState( ( - _event: vscode.WebviewPanelOnDidChangeViewStateEvent + _event: vscode.WebviewPanelOnDidChangeViewStateEvent, ) => { // Only render if the webview was activated; // this event also occurs when it's deactivated. if (webview_panel?.active) { send_update(true); } - } + }, ); } } @@ -267,7 +267,7 @@ export const activate = (context: vscode.ExtensionContext) => { "

CodeChat Editor

Loading...

"; } else { vscode.window.showInformationMessage( - "The CodeChat Editor is loading in an external browser..." + "The CodeChat Editor is loading in an external browser...", ); } @@ -283,12 +283,12 @@ export const activate = (context: vscode.ExtensionContext) => { if (websocket === undefined) { console_log( - "CodeChat Editor extension: opening websocket." + "CodeChat Editor extension: opening websocket.", ); // Connect to the CodeChat Editor Server. websocket = new WebSocket( - `ws://localhost:${get_port()}/vsc/ws-ide/${Math.random()}` + `ws://localhost:${get_port()}/vsc/ws-ide/${Math.random()}`, ); let was_error: boolean = false; @@ -296,7 +296,7 @@ export const activate = (context: vscode.ExtensionContext) => { websocket.on("error", (err: ErrorEvent) => { was_error = true; show_error( - `Error communicating with the CodeChat Editor Server: ${err.message}. Re-run the CodeChat Editor extension to restart it.` + `Error communicating with the CodeChat Editor Server: ${err.message}. Re-run the CodeChat Editor extension to restart it.`, ); // The close event will be [emitted // next](https://nodejs.org/api/net.html#net_event_error_1); @@ -305,7 +305,7 @@ export const activate = (context: vscode.ExtensionContext) => { websocket.on("close", (hadError: CloseEvent) => { console_log( - "CodeChat Editor extension: closing websocket connection." + "CodeChat Editor extension: closing websocket connection.", ); // If there was an error, the event handler above // already provided the message. Note: the [parameter @@ -316,7 +316,7 @@ export const activate = (context: vscode.ExtensionContext) => { // non-transmission errors. if (!was_error && hadError) { show_error( - "The connection to the CodeChat Editor Server was closed due to a transmission error. Re-run the CodeChat Editor extension to restart it." + "The connection to the CodeChat Editor Server was closed due to a transmission error. Re-run the CodeChat Editor extension to restart it.", ); } websocket = undefined; @@ -325,7 +325,7 @@ export const activate = (context: vscode.ExtensionContext) => { websocket.on("open", () => { console_log( - "CodeChat Editor extension: connected to server." + "CodeChat Editor extension: connected to server.", ); assert(websocket !== undefined); send_message({ @@ -350,12 +350,12 @@ export const activate = (context: vscode.ExtensionContext) => { websocket.on("message", (data) => { // Parse the data into a message. const { id, message } = JSON.parse( - data.toString() + data.toString(), ) as EditorMessage; console_log( `CodeChat Editor extension: Received data id = ${id}, message = ${format_struct( - message - )}.` + message, + )}.`, ); assert(id !== undefined); assert(message !== undefined); @@ -370,7 +370,7 @@ export const activate = (context: vscode.ExtensionContext) => { const current_update = value as UpdateMessageContents; const doc = get_document( - current_update.file_path + current_update.file_path, ); if (doc === undefined) { send_result(id, { @@ -397,10 +397,10 @@ export const activate = (context: vscode.ExtensionContext) => { 0, 0, doc.lineCount, - 0 - ) + 0, + ), ), - source.Plain.doc + source.Plain.doc, ); } else { assert("Diff" in source); @@ -411,24 +411,24 @@ export const activate = (context: vscode.ExtensionContext) => { // `Position` (line, then offset on that // line) needed by VSCode. const from = doc.positionAt( - diff.from + diff.from, ); if (diff.to === undefined) { // This is an insert. wse.insert( doc.uri, from, - diff.insert + diff.insert, ); } else { // This is a replace or delete. const to = doc.positionAt( - diff.to + diff.to, ); wse.replace( doc.uri, new Range(from, to), - diff.insert + diff.insert, ); } } @@ -437,8 +437,7 @@ export const activate = (context: vscode.ExtensionContext) => { .applyEdit(wse) .then( () => - (ignore_text_document_change = - false) + (ignore_text_document_change = false), ); } // Update the cursor position if provided. @@ -453,16 +452,19 @@ export const activate = (context: vscode.ExtensionContext) => { console_log(`Moving to line ${line}.`); const position = new vscode.Position( line, - line + line, ); editor.selections = [ new vscode.Selection( position, - position + position, ), ]; editor.revealRange( - new vscode.Range(position, position) + new vscode.Range( + position, + position, + ), ); } } @@ -478,18 +480,17 @@ export const activate = (context: vscode.ExtensionContext) => { .openTextDocument(current_file) .then( (document) => { - ignore_active_editor_change = - true; + ignore_active_editor_change = true; vscode.window.showTextDocument( document, - current_editor?.viewColumn + current_editor?.viewColumn, ); send_result(id); }, (reason) => send_result(id, { Err: `Error: unable to open file ${current_file}: ${reason}`, - }) + }), ); } else { // TODO: open using a custom document @@ -509,14 +510,14 @@ export const activate = (context: vscode.ExtensionContext) => { { viewColumn: current_editor?.viewColumn, - } + }, ) .then( () => send_result(id), (reason) => send_result(id, { Err: `Error: unable to open file ${current_file}: ${reason}`, - }) + }), ); } send_result(id); @@ -542,7 +543,7 @@ export const activate = (context: vscode.ExtensionContext) => { const result_contents = value as MessageResult; if ("Err" in result_contents) { show_error( - `Error in message ${id}: ${result_contents.Err}` + `Error in message ${id}: ${result_contents.Err}`, ); } break; @@ -577,19 +578,19 @@ export const activate = (context: vscode.ExtensionContext) => { default: console.error( `Unhandled message ${key}(${format_struct( - value - )}` + value, + )}`, ); break; } }); } else { console_log( - "CodeChat Editor extension: connection already pending, so a new client wasn't created." + "CodeChat Editor extension: connection already pending, so a new client wasn't created.", ); } - } - ) + }, + ), ); }; @@ -607,7 +608,7 @@ export const deactivate = async () => { // Send a message expecting a result to the server. const send_message = ( message: EditorMessageContents, - callback: (succeeded: boolean) => void = (_) => 0 + callback: (succeeded: boolean) => void = (_) => 0, ) => { const id = message_id; message_id += 3; @@ -617,11 +618,11 @@ const send_message = ( }; assert(websocket); console_log( - `CodeChat Editor extension: sending message ${format_struct(jm)}.` + `CodeChat Editor extension: sending message ${format_struct(jm)}.`, ); websocket.send(JSON.stringify(jm)); pending_messages[id] = { - timer_id: setTimeout(report_server_timeout, RESPONSE_TIMEOUT, id), + timer_id: setTimeout(report_server_timeout, RESPONSE_TIMEOUT_MS, id), callback, }; }; @@ -631,7 +632,7 @@ const format_struct = (complex_data_structure: any): string => DEBUG_ENABLED ? JSON.stringify(complex_data_structure).substring( 0, - MAX_MESSAGE_LENGTH + MAX_MESSAGE_LENGTH, ) : ""; @@ -658,8 +659,8 @@ const send_result = (id: number, result: MessageResult = { Ok: "Void" }) => { assert(websocket); console_log( `CodeChat Editor extension: sending result ${JSON.stringify( - jm - ).substring(0, MAX_MESSAGE_LENGTH)}.` + jm, + ).substring(0, MAX_MESSAGE_LENGTH)}.`, ); websocket.send(JSON.stringify(jm)); }; @@ -744,7 +745,7 @@ const stop_client = async () => { } catch (err) { assert(err instanceof Error); console.error( - `CodeChat Editor Client: error on server shutdown - ${err.message}` + `CodeChat Editor Client: error on server shutdown - ${err.message}`, ); } current_editor = undefined; @@ -765,11 +766,11 @@ const show_error = (message: string) => { webview_panel.webview.html = "

CodeChat Editor

"; } webview_panel.webview.html += `

${escape( - message + message, )}

See the docs.

`; } else { vscode.window.showErrorMessage( - message + "\nSee https://github.com/bjones1/CodeChat_Editor." + message + "\nSee https://github.com/bjones1/CodeChat_Editor.", ); } }; @@ -838,7 +839,7 @@ const run_server = (args: string[]) => { // If not specified, use the packaged binary. if (codechat_editor_server_command === "") { const ext = vscode.extensions.getExtension( - "CodeChat.codechat-editor-client" + "CodeChat.codechat-editor-client", ); assert(ext !== undefined); codechat_editor_server_command = @@ -850,7 +851,7 @@ const run_server = (args: string[]) => { return new Promise((resolve, reject) => { const server_process = child_process.spawn( codechat_editor_server_command as string, - ["--port", get_port().toString()].concat(args) + ["--port", get_port().toString()].concat(args), ); server_process.on("error", (err: NodeJS.ErrnoException) => { const msg = @@ -858,7 +859,7 @@ const run_server = (args: string[]) => { ? `Error - cannot find the file ${err.path}` : err; reject( - new Error(`While starting the CodeChat Editor Server: ${msg}.`) + new Error(`While starting the CodeChat Editor Server: ${msg}.`), ); }); @@ -869,8 +870,8 @@ const run_server = (args: string[]) => { } else { reject( new Error( - `${stdout}\n${stderr}\n\nCodeChat Editor Server exited with ${exit_str}.\n` - ) + `${stdout}\n${stderr}\n\nCodeChat Editor Server exited with ${exit_str}.\n`, + ), ); } }); diff --git a/server/Cargo.lock b/server/Cargo.lock index 78944678..e68a2846 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -8,7 +8,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "bytes", "futures-core", "futures-sink", @@ -21,17 +21,17 @@ dependencies = [ [[package]] name = "actix-files" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0773d59061dedb49a8aed04c67291b9d8cf2fe0b60130a381aab53c6dd86e9be" +checksum = "22c8b5536deb14cd9c3e505bd0e3366e1a12383b659c92f2b4fa4d323d583599" dependencies = [ "actix-http", "actix-service", "actix-utils", "actix-web", - "bitflags 2.9.2", + "bitflags 2.9.3", "bytes", - "derive_more 0.99.20", + "derive_more", "futures-core", "http-range", "log", @@ -44,20 +44,20 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.11.0" +version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44dfe5c9e0004c623edc65391dfd51daa201e7e30ebd9c9bedf873048ec32bc2" +checksum = "44cceded2fb55f3c4b67068fa64962e2ca59614edc5b03167de9ff82ae803da0" dependencies = [ "actix-codec", "actix-rt", "actix-service", "actix-utils", "base64", - "bitflags 2.9.2", + "bitflags 2.9.3", "brotli", "bytes", "bytestring", - "derive_more 2.0.1", + "derive_more", "encoding_rs", "flate2", "foldhash", @@ -108,9 +108,9 @@ dependencies = [ [[package]] name = "actix-rt" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" +checksum = "92589714878ca59a7626ea19734f0e07a6a875197eec751bb5d3f99e64998c63" dependencies = [ "actix-macros", "futures-core", @@ -173,7 +173,7 @@ dependencies = [ "bytestring", "cfg-if", "cookie", - "derive_more 2.0.1", + "derive_more", "encoding_rs", "foldhash", "futures-core", @@ -437,9 +437,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.2" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29" +checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" [[package]] name = "block-buffer" @@ -514,9 +514,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.33" +version = "1.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f" +checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" dependencies = [ "jobserver", "libc", @@ -551,9 +551,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.45" +version = "4.5.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318" +checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57" dependencies = [ "clap_builder", "clap_derive", @@ -561,9 +561,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.44" +version = "4.5.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8" +checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41" dependencies = [ "anstream", "anstyle", @@ -591,7 +591,7 @@ checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "codechat-editor-server" -version = "0.1.29" +version = "0.1.31" dependencies = [ "actix-files", "actix-http", @@ -659,12 +659,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb58b6451e8c2a812ad979ed1d83378caa5e927eef2622017a45f251457c2c9d" -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - [[package]] name = "cookie" version = "0.16.2" @@ -753,9 +747,9 @@ checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" [[package]] name = "deranged" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "75d7cc94194b4dd0fa12845ef8c911101b7f37633cda14997a6e82099aa0b693" dependencies = [ "powerfmt", ] @@ -771,19 +765,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive_more" -version = "0.99.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn 2.0.106", -] - [[package]] name = "derive_more" version = "2.0.1" @@ -1036,7 +1017,7 @@ dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasi 0.14.3+wasi-0.2.4", ] [[package]] @@ -1064,7 +1045,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "ignore", "walkdir", ] @@ -1323,9 +1304,9 @@ checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2" [[package]] name = "indexmap" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" dependencies = [ "equivalent", "hashbrown", @@ -1343,7 +1324,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "inotify-sys", "libc", ] @@ -1359,11 +1340,11 @@ dependencies = [ [[package]] name = "io-uring" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" +checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "cfg-if", "libc", ] @@ -1404,9 +1385,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ "getrandom 0.3.3", "libc", @@ -1466,7 +1447,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "libc", "redox_syscall", ] @@ -1633,7 +1614,7 @@ version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "fsevent-sys", "inotify", "kqueue", @@ -1700,7 +1681,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "objc2", ] @@ -1881,9 +1862,9 @@ dependencies = [ [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" dependencies = [ "zerovec", ] @@ -1958,7 +1939,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "memchr", "pulldown-cmark-escape", "unicase", @@ -2050,14 +2031,14 @@ version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" dependencies = [ "aho-corasick", "memchr", @@ -2067,9 +2048,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" dependencies = [ "aho-corasick", "memchr", @@ -2078,15 +2059,15 @@ dependencies = [ [[package]] name = "regex-lite" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" +checksum = "943f41321c63ef1c92fd763bfe054d2668f7f225a5c29f0105903dc2fc04ba30" [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" [[package]] name = "rustc-demangle" @@ -2094,22 +2075,13 @@ version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - [[package]] name = "rustix" version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ - "bitflags 2.9.2", + "bitflags 2.9.3", "errno", "libc", "linux-raw-sys", @@ -2143,12 +2115,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "semver" -version = "1.0.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" - [[package]] name = "serde" version = "1.0.219" @@ -2433,12 +2399,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.41" +version = "0.3.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +checksum = "8ca967379f9d8eb8058d86ed467d81d03e81acd45757e4ca341c24affbe8e8e3" dependencies = [ "deranged", - "itoa", "num-conv", "powerfmt", "serde", @@ -2448,15 +2413,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "a9108bb380861b07264b950ded55a44a14a4adc68b9f5efd85aafc3aa4d40a68" [[package]] name = "time-macros" -version = "0.2.22" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +checksum = "7182799245a7264ce590b349d90338f1c1affad93d2639aed5f8f69c090b334c" dependencies = [ "num-conv", "time-core", @@ -2717,13 +2682,14 @@ checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "url" -version = "2.5.6" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "137a3c834eaf7139b73688502f3f1141a0337c5d8e4d9b536f9b8c796e26a7c4" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -2789,11 +2755,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.14.2+wasi-0.2.4" +version = "0.14.3+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "6a51ae83037bdd272a9e28ce236db8c07016dd0d50c27038b3f407533c030c95" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] @@ -3246,13 +3212,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.2", -] +checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814" [[package]] name = "writeable" diff --git a/server/Cargo.toml b/server/Cargo.toml index 34361919..a587ec0b 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -32,7 +32,7 @@ license = "GPL-3.0-only" name = "codechat-editor-server" readme = "../README.md" repository = "https://github.com/bjones1/CodeChat_Editor" -version = "0.1.29" +version = "0.1.31" # This library allows other packages to use core CodeChat Editor features. [lib] diff --git a/server/dist.toml b/server/dist.toml index 231ff583..d7a71954 100644 --- a/server/dist.toml +++ b/server/dist.toml @@ -26,4 +26,4 @@ include = ["log4rs.yml", "hashLocations.json", "../client/static"] [package] -changelog = "../docs/changelog.md" +changelog = "docs/changelog.md" diff --git a/server/src/ide/filewatcher.rs b/server/src/ide/filewatcher.rs index 06b130a4..0a6c3198 100644 --- a/server/src/ide/filewatcher.rs +++ b/server/src/ide/filewatcher.rs @@ -1057,17 +1057,17 @@ mod tests { (20.0, Ok(ResultOkTypes::Void)) ); - // Check that the requested file is written. + // Check that the requested file was written. let mut s = fs::read_to_string(&file_path).unwrap(); assert_eq!(s, "testing()"); - // Wait for the filewatcher to debounce this file write. - sleep(Duration::from_secs(1)).await; // 8. Change this file and verify that this produces an update. // // Message ids: IDE - 6->9, Server - 10, Client - 23. s.push_str("123"); fs::write(&file_path, s).unwrap(); + // Wait for the filewatcher to debounce this file write. + sleep(Duration::from_secs(2)).await; assert_eq!( get_message_as!(to_client_rx, EditorMessageContents::Update), ( diff --git a/server/src/ide/vscode/tests.rs b/server/src/ide/vscode/tests.rs index 310f91df..aa182143 100644 --- a/server/src/ide/vscode/tests.rs +++ b/server/src/ide/vscode/tests.rs @@ -18,6 +18,7 @@ // Imports // ------- use std::{ + env, fs::{self, File}, io::{Error, Read}, net::SocketAddr, @@ -264,6 +265,14 @@ async fn test_vscode_ide_websocket1() { // Test opening the Client in an external browser. #[actix_web::test] async fn test_vscode_ide_websocket2() { + // Running this in CI on Windows causes the test suite to never exit. Avoid this. + // See the [docs](https://docs.github.com/en/actions/reference/workflows-and-actions/variables) + // on GitHub Actions environment variables. + if env::var("RUNNER_OS") == Ok("Windows".to_string()) { + // TODO: call a function here which tells the test running we're skipping this test. + return; + } + let connection_id = "test-connection-id2"; let (_, _, mut ws_ide, _) = prep_test!(connection_id).await; diff --git a/server/src/lexer/pest/parser_design.md b/server/src/lexer/pest/parser_design.md index 3b10ac41..25802881 100644 --- a/server/src/lexer/pest/parser_design.md +++ b/server/src/lexer/pest/parser_design.md @@ -18,7 +18,9 @@ In particular, a language-specific grammar must provide: inline_comment | block_comment }`. However, languages which lack an inline comment (such as CSS) or a block comment (such as Python) would contain only the appropriate comment type. + * Inline comment definitions: + * Opening inline delimiter(s) supported by the language. Three inline comment delimiters must be defined for a language. For C, this is: diff --git a/server/src/translation.rs b/server/src/translation.rs index 1734fc45..70af8e8a 100644 --- a/server/src/translation.rs +++ b/server/src/translation.rs @@ -415,6 +415,8 @@ pub async fn translation_task( // Leave space for a server message during the init phase. let mut id: f64 = INITIAL_MESSAGE_ID + MESSAGE_ID_INCREMENT; + // The source code, provided by the IDE. It will use whatever + // the IDE provides for EOLs, which is stored in `eol` below. let mut source_code = String::new(); let mut code_mirror_doc = String::new(); // The initial state will be overwritten by the first `Update` @@ -530,45 +532,40 @@ pub async fn translation_task( // this is a PDF file. (TODO: look at the // magic number also -- "%PDF"). let use_pdf_js = http_request.file_path.extension() == Some(OsStr::new("pdf")); - let (simple_http_response, option_update, file_contents) = match file_contents_option { + let ((simple_http_response, option_update), file_contents) = match file_contents_option { Some(file_contents) => { // If there are Windows newlines, replace // with Unix; this is reversed when the // file is sent back to the IDE. - eol = find_eol_type(&file_contents); - let file_contents = if use_pdf_js { file_contents } else { file_contents.replace("\r\n", "\n") }; - file_to_response(&http_request, ¤t_file, Some(file_contents), use_pdf_js).await + (file_to_response(&http_request, ¤t_file, Some(&file_contents), use_pdf_js).await, file_contents) }, None => { // The file wasn't available in the IDE. // Look for it in the filesystem. match File::open(&http_request.file_path).await { Err(err) => ( - SimpleHttpResponse::Err(SimpleHttpResponseError::Io(err)), - None, - None + ( + SimpleHttpResponse::Err(SimpleHttpResponseError::Io(err)), + None, + ), + // There's no file, so return empty + // contents, which will be ignored. + "".to_string() ), Ok(mut fc) => { let option_file_contents = try_read_as_text(&mut fc).await; - let option_file_contents = if let Some(file_contents) = option_file_contents { - eol = find_eol_type(&file_contents); - let file_contents = if use_pdf_js { file_contents } else { file_contents.replace("\r\n", "\n") }; - Some(file_contents) - } else { - None - }; - // If this - // is a binary file (meaning we can't read - // the contents as UTF-8), send the - // contents as none to signal this isn't a - // text file. - file_to_response( - &http_request, - ¤t_file, - option_file_contents, - use_pdf_js, + ( + file_to_response( + &http_request, + ¤t_file, + option_file_contents.as_ref(), + use_pdf_js, + ) + .await, + // If the file is binary, return empty + // contents, which will be ignored. + option_file_contents.unwrap_or("".to_string()) ) - .await } } } @@ -582,9 +579,10 @@ pub async fn translation_task( error!("Not plain!"); break; }; + source_code = file_contents; + eol = find_eol_type(&source_code); // We must clone here, since the original // is placed in the TX queue. - source_code = file_contents.unwrap(); code_mirror_doc = plain.doc.clone(); code_mirror_doc_blocks = Some(plain.doc_blocks.clone()); sync_state = SyncState::Pending(id); @@ -841,7 +839,10 @@ pub async fn translation_task( Some(cfw) => match codechat_for_web_to_source( &cfw) { - Ok(result) => { + Ok(new_source_code) => { + // Correct EOL endings for use with the + // IDE. + let new_source_code_eol = eol_convert(new_source_code, &eol); let ccfw = if sync_state == SyncState::InSync && allow_source_diffs { Some(CodeChatForWeb { metadata: cfw.metadata, @@ -849,7 +850,7 @@ pub async fn translation_task( // Diff with correct EOLs, so that (for // CRLF files as well as LF files) offsets // are correct. - doc: diff_str(&eol_convert(source_code, &eol), &eol_convert(result.clone(), &eol)), + doc: diff_str(&source_code, &new_source_code_eol), doc_blocks: vec![], }), }) @@ -859,14 +860,12 @@ pub async fn translation_task( source: CodeMirrorDiffable::Plain(CodeMirror { // We must clone here, so that it can be // placed in the TX queue. - doc: eol_convert(result.clone(), &eol), + doc: new_source_code_eol.clone(), doc_blocks: vec![], }), }) }; - // Store the document with Unix-style EOLs - // (LFs). - source_code = result; + source_code = new_source_code_eol; let CodeMirrorDiffable::Plain(cmd) = cfw.source else { // TODO: support diffable! error!("No diff!"); diff --git a/server/src/webserver.rs b/server/src/webserver.rs index 6281433e..8d649cd4 100644 --- a/server/src/webserver.rs +++ b/server/src/webserver.rs @@ -49,7 +49,7 @@ use actix_ws::AggregatedMessage; use bytes::Bytes; use dunce::simplified; use futures_util::StreamExt; -use indoc::{formatdoc, indoc}; +use indoc::{concatdoc, formatdoc}; use lazy_static::lazy_static; use log::{LevelFilter, error, info, warn}; use log4rs::{self, config::load_config_file}; @@ -341,9 +341,9 @@ macro_rules! queue_send { /// Globals /// ------- -// The timeout for a reply from a websocket. Use a short timeout to speed up -// unit tests. -const REPLY_TIMEOUT: Duration = if cfg!(test) { +// The timeout for a reply from a websocket, in ms. Use a short timeout to speed +// up unit tests. +const REPLY_TIMEOUT_MS: Duration = if cfg!(test) { Duration::from_millis(500) } else { Duration::from_millis(15000) @@ -353,7 +353,8 @@ const REPLY_TIMEOUT: Duration = if cfg!(test) { /// this server. const WEBSOCKET_PING_DELAY: Duration = Duration::from_secs(2); -/// A message ID which won't be used by anything but a `Result` produced by an error not produced in response to a message. +/// A message ID which won't be used by anything but a `Result` produced by an +/// error not produced in response to a message. pub const RESERVED_MESSAGE_ID: f64 = if cfg!(test) { // A simpler value when testing. 0.0 @@ -388,11 +389,13 @@ pub enum SyncState { OutOfSync, } -const MATHJAX_TAGS: &str = indoc!( +const MATHJAX_TAGS: &str = concatdoc!( r#" - - "# + "#, + // Per the [MathJax + // docs](https://docs.mathjax.org/en/latest/web/components/combined.html#tex-chtml), + // enable tex input and HTML output. + r#" + "# ); lazy_static! { @@ -660,44 +666,6 @@ pub async fn filesystem_endpoint( } } -// Use the provided HTTP request to look for the requested file, returning it as -// an HTTP response. This should be called from within a processing task. -pub async fn make_simple_http_response( - // The HTTP request presented to the processing task. - http_request: &ProcessingTaskHttpRequest, - // Path to the file currently being edited. - current_filepath: &Path, - // True to use the PDF.js viewer for this file. - use_pdf_js: bool, -) -> ( - // The response to send back to the HTTP endpoint. - SimpleHttpResponse, - // If this file is currently being edited, this is the body of an `Update` - // message to send. - Option, - // The resulting file contents, if this is a CodeChat Editor file - Option, -) { - // Convert the provided URL back into a file name. - let file_path = &http_request.file_path; - - // Read the file - match File::open(file_path).await { - Err(err) => ( - SimpleHttpResponse::Err(SimpleHttpResponseError::Io(err)), - None, - None, - ), - Ok(mut fc) => { - let file_contents = try_read_as_text(&mut fc).await; - // If this is a binary file (meaning - // we can't read the contents as UTF-8), send the contents as none - // to signal this isn't a text file. - file_to_response(http_request, current_filepath, file_contents, use_pdf_js).await - } - } -} - // Determine if the provided file is text or binary. If text, return it as a // Unicode string. If binary, return None. pub async fn try_read_as_text(file: &mut File) -> Option { @@ -726,7 +694,7 @@ pub async fn file_to_response( // `try_canonicalize`. current_filepath: &Path, // Contents of this file, if it's text; None if it was binary data. - file_contents: Option, + file_contents: Option<&String>, // True to use the PDF.js viewer for this file. use_pdf_js: bool, ) -> ( @@ -736,8 +704,6 @@ pub async fn file_to_response( // populate the Client with the parsed `file_contents`. In all other cases, // return None. Option, - // The `file_contents` if this is a - Option, ) { // Use a lossy conversion, since this is UI display, not filesystem access. let file_path = &http_request.file_path; @@ -747,7 +713,6 @@ pub async fn file_to_response( file_path.to_path_buf(), )), None, - None, ); }; let name = escape_html(&file_name.to_string_lossy()); @@ -765,7 +730,6 @@ pub async fn file_to_response( codechat_editor_js_name, )), None, - None, ); }; let codechat_editor_css_name = format!("CodeChatEditor{js_test_suffix}.css"); @@ -775,7 +739,6 @@ pub async fn file_to_response( codechat_editor_css_name, )), None, - file_contents, ); }; @@ -783,20 +746,26 @@ pub async fn file_to_response( // `try_canonical`. let is_current_file = file_path == current_filepath; let is_toc = http_request.flags == ProcessingTaskHttpRequestFlags::Toc; - let (translation_results_string, path_to_toc) = - if let Some(ref file_contents_text) = file_contents { - if is_current_file || is_toc { - source_to_codechat_for_web_string(file_contents_text, file_path, is_toc) - } else { - // If this isn't the current file, then don't parse it. - (TranslationResultsString::Unknown, None) - } - } else { - ( - TranslationResultsString::Binary, - find_path_to_toc(file_path), + let (translation_results_string, path_to_toc) = if let Some(file_contents_text) = file_contents + { + if is_current_file || is_toc { + source_to_codechat_for_web_string( + // Ensure we work with Unix-style (LF only) files, since other + // line endings break the translation process. + &file_contents_text.replace("\r\n", "\n"), + file_path, + is_toc, ) - }; + } else { + // If this isn't the current file, then don't parse it. + (TranslationResultsString::Unknown, None) + } + } else { + ( + TranslationResultsString::Binary, + find_path_to_toc(file_path), + ) + }; let is_project = path_to_toc.is_some(); // For project files, add in the sidebar. Convert this from a Windows path // to a Posix path if necessary. @@ -828,7 +797,6 @@ pub async fn file_to_response( file_name, ))), None, - None, ); }; return ( @@ -848,14 +816,13 @@ pub async fn file_to_response( }, ), None, - None, ); } let codechat_for_web = match translation_results_string { // The file type is binary. Ask the HTTP server to serve it raw. TranslationResultsString::Binary => return - (SimpleHttpResponse::Bin(file_path.to_path_buf()), None, None) + (SimpleHttpResponse::Bin(file_path.to_path_buf()), None) , // The file type is unknown. Serve it raw. TranslationResultsString::Unknown => { @@ -865,12 +832,11 @@ pub async fn file_to_response( mime_guess::from_path(file_path).first_or_text_plain(), ), None, - None ); } // Report a lexer error. TranslationResultsString::Err(err_string) => { - return (SimpleHttpResponse::Err(SimpleHttpResponseError::LexerError(err_string)), None, None); + return (SimpleHttpResponse::Err(SimpleHttpResponseError::LexerError(err_string)), None); } // This is a CodeChat file. The following code wraps the CodeChat for // web results in a CodeChat Editor Client webpage. @@ -898,21 +864,10 @@ pub async fn file_to_response( "#, )), None, - None ); } }; - // Add testing mode scripts if requested. - let testing_src = if http_request.is_test_mode { - r#" - - - "# - } else { - "" - }; - // Provided info from the HTTP request, determine the following parameters. let Some(raw_dir) = file_path.parent() else { return ( @@ -920,7 +875,6 @@ pub async fn file_to_response( file_path.to_path_buf(), )), None, - None, ); }; let dir = path_display(raw_dir); @@ -930,7 +884,6 @@ pub async fn file_to_response( file_path.to_path_buf(), )), None, - None, ); }; // Build and return the webpage. @@ -944,12 +897,8 @@ pub async fn file_to_response( {name} - The CodeChat Editor {MATHJAX_TAGS} - + - {testing_src} {sidebar_css} @@ -978,7 +927,6 @@ pub async fn file_to_response( cursor_position: None, scroll_position: None, }), - file_contents, ) } @@ -1255,7 +1203,7 @@ pub async fn client_websocket( _ => { let timeout_tx = from_websocket_tx.clone(); let waiting_task = actix_rt::spawn(async move { - sleep(REPLY_TIMEOUT).await; + sleep(REPLY_TIMEOUT_MS).await; let msg = format!("Timeout: message id {} unacknowledged.", m.id); error!("{msg}"); // Since the websocket failed to send a diff --git a/server/src/webserver/tests.rs b/server/src/webserver/tests.rs index 356e6e46..cd0677dc 100644 --- a/server/src/webserver/tests.rs +++ b/server/src/webserver/tests.rs @@ -128,7 +128,7 @@ fn test_other_path() { .success(); }); // The server waits for up to 3 seconds for a ping to work. Add some extra time for starting the process. - sleep(Duration::from_millis(4000)); + sleep(Duration::from_millis(5000)); get_server() .args(["--port", "8083", "stop"]) .current_dir(&test_dir)