>(src: P, dest: P, files: Option) -> io::Res
}
#[cfg(not(windows))]
{
- // Create the dest directory, since old CI OSes don't support
- // `rsync --mkpath`.
+ // Create the dest directory, since old CI OSes don't support `rsync
+ // --mkpath`.
run_script(
"mkdir",
&["-p", dest.as_ref().to_str().unwrap()],
@@ -209,8 +213,8 @@ fn quick_copy_dir>(src: P, dest: P, files: Option) -> io::Res
.status()?
.code()
.expect("Copy process terminated by signal");
- // Per
- // [these docs](https://learn.microsoft.com/en-us/troubleshoot/windows-server/backup-and-storage/return-codes-used-robocopy-utility),
+ // Per [these
+ // docs](https://learn.microsoft.com/en-us/troubleshoot/windows-server/backup-and-storage/return-codes-used-robocopy-utility),
// check the return code.
if cfg!(windows) && exit_code >= 8 || !cfg!(windows) && exit_code != 0 {
Err(io::Error::new(
@@ -254,7 +258,8 @@ fn search_and_replace_file<
fs::write(&path, file_contents_replaced.as_bytes())
}
-// ## Core routines
+// Core routines
+// -------------
//
// These functions simplify common build-focused development tasks and support
// CI builds.
@@ -278,8 +283,8 @@ fn patch_file(patch: &str, before_patch: &str, file_path: &str) -> io::Result<()
}
/// After updating files in the client's Node files, perform some fix-ups.
fn patch_client_npm() -> io::Result<()> {
- // Apply a the fixes described in
- // [issue 27](https://github.com/bjones1/CodeChat_Editor/issues/27).
+ // Apply a the fixes described in [issue
+ // 27](https://github.com/bjones1/CodeChat_Editor/issues/27).
patch_file(
"
selectionNotFocus = this.view.state.facet(editable) ? focused : hasSelection(this.dom, this.view.observer.selectionRange)",
@@ -287,11 +292,15 @@ fn patch_client_npm() -> io::Result<()> {
hasSelection(this.dom, this.view.observer.selectionRange) && !(activeElt && this.dom.contains(activeElt));",
"../client/node_modules/@codemirror/view/dist/index.js"
)?;
- // In [older releases](https://www.tiny.cloud/docs/tinymce/5/6.0-upcoming-changes/#options), TinyMCE allowed users to change `whitespace_elements`; the whitespace inside these isn't removed by TinyMCE. However, this was removed in v6.0. Therefore, manually patch TinyMCE instead.
+ // In [older
+ // releases](https://www.tiny.cloud/docs/tinymce/5/6.0-upcoming-changes/#options),
+ // TinyMCE allowed users to change `whitespace_elements`; the whitespace
+ // inside these isn't removed by TinyMCE. However, this was removed in v6.0.
+ // Therefore, manually patch TinyMCE instead.
patch_file(
" wc-mermaid",
"const whitespaceElementsMap = createLookupTable('whitespace_elements', 'pre script noscript style textarea video audio iframe object code",
- "../client/node_modules/tinymce/tinymce.js"
+ "../client/node_modules/tinymce/tinymce.js",
)?;
// Copy across the parts of MathJax that are needed, since bundling it is
@@ -358,13 +367,13 @@ fn run_update() -> io::Result<()> {
fn run_test() -> io::Result<()> {
// On Windows, `cargo sort --check` fails since it default to LF, not CRLF,
// line endings. Work around this by changing this setting only on Windows.
- // See the
- // [cargo sort config docs](https://github.com/DevinR528/cargo-sort?tab=readme-ov-file#config)
- // and the
- // [related issue](https://github.com/DevinR528/cargo-sort/issues/85).
+ // See the [cargo sort config
+ // docs](https://github.com/DevinR528/cargo-sort?tab=readme-ov-file#config)
+ // and the [related
+ // issue](https://github.com/DevinR528/cargo-sort/issues/85).
//
- // However, this still fails: `cargo sort` uses
- // [inconsistent line endings](https://github.com/DevinR528/cargo-sort/issues/86).
+ // However, this still fails: `cargo sort` uses [inconsistent line
+ // endings](https://github.com/DevinR528/cargo-sort/issues/86).
/***
#[cfg(windows)]
{
@@ -469,7 +478,8 @@ fn run_postrelease(target: &str) -> io::Result<()> {
Ok(())
}
-// ## CLI implementation
+// CLI implementation
+// ------------------
//
// The following code implements the command-line interface for the CodeChat
// Editor.
diff --git a/client/.eslintrc.yml b/client/.eslintrc.yml
index b80e1b50..0ef013aa 100644
--- a/client/.eslintrc.yml
+++ b/client/.eslintrc.yml
@@ -16,17 +16,18 @@
# the CodeChat Editor. If not, see
# [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
#
-# # `.eslintrc.yml` -- Configure ESLint for this project
+# `.eslintrc.yml` -- Configure ESLint for this project
+# ====================================================
env:
browser: true
es2020: true
extends:
- standard
- # See the
- # [ESLint config prettier docs](https://github.com/prettier/eslint-config-prettier#installation)
- # and its parent link,
- # [integrating Prettier with linters](https://prettier.io/docs/en/integrating-with-linters.html).
+ # See the [ESLint config prettier
+ # docs](https://github.com/prettier/eslint-config-prettier#installation) and
+ # its parent link, [integrating Prettier with
+ # linters](https://prettier.io/docs/en/integrating-with-linters.html).
- prettier
parser: "@typescript-eslint/parser"
parserOptions:
@@ -36,6 +37,6 @@ plugins:
rules:
camelcase: off
# TypeScript already enforces this; otherwise, eslint complains that
- # `NodeJS` is undefined. See
- # [this GitHub issue](https://github.com/Chatie/eslint-config/issues/45#issuecomment-1003990077).
+ # `NodeJS` is undefined. See [this GitHub
+ # issue](https://github.com/Chatie/eslint-config/issues/45#issuecomment-1003990077).
no-undef: off
diff --git a/client/.gitignore b/client/.gitignore
index 2ad264a0..af96fcdc 100644
--- a/client/.gitignore
+++ b/client/.gitignore
@@ -16,7 +16,8 @@
# the CodeChat Editor. If not, see
# [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
#
-# # `.gitignore` -- files for Git to ignore
+# `.gitignore` -- files for Git to ignore
+# =======================================
#
# NPM
node_modules/
diff --git a/client/.prettierrc.json5 b/client/.prettierrc.json5
index fbae4fbd..399e5800 100644
--- a/client/.prettierrc.json5
+++ b/client/.prettierrc.json5
@@ -15,6 +15,7 @@
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
// `.prettierrc.json5` - Prettier configuration
+// ============================================
{
tabWidth: 4,
}
diff --git a/client/package-lock.json b/client/package-lock.json
index 020bcc9c..5acb1521 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "codechat-editor-client",
- "version": "0.1.9",
+ "version": "0.1.10",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "codechat-editor-client",
- "version": "0.1.9",
+ "version": "0.1.10",
"license": "GPL-3.0-or-later",
"dependencies": {
"@codemirror/lang-cpp": "^6",
@@ -37,7 +37,7 @@
"@typescript-eslint/eslint-plugin": "^8",
"@typescript-eslint/parser": "^8",
"chai": "^5",
- "esbuild": "^0.24",
+ "esbuild": "^0.25",
"eslint": "^9",
"eslint-config-prettier": "^10",
"eslint-plugin-import": "^2",
@@ -47,27 +47,52 @@
}
},
"node_modules/@antfu/install-pkg": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-0.4.1.tgz",
- "integrity": "sha512-T7yB5QNG29afhWVkVq7XeIMBa5U/vs9mX69YqayXypPRmYzUmzwnYltplHmPtZ4HPCn+sQKeXW8I47wCbuBOjw==",
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.0.0.tgz",
+ "integrity": "sha512-xvX6P/lo1B3ej0OsaErAjqgFYzYVcJpamjLAFLYh9vRJngBrMoUG7aVnrGTeqM7yxbyTD5p3F2+0/QUEh8Vzhw==",
"license": "MIT",
"dependencies": {
- "package-manager-detector": "^0.2.0",
- "tinyexec": "^0.3.0"
+ "package-manager-detector": "^0.2.8",
+ "tinyexec": "^0.3.2"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@antfu/utils": {
- "version": "0.7.10",
- "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz",
- "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==",
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-8.1.1.tgz",
+ "integrity": "sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
+ "node_modules/@babel/code-frame": {
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
+ "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
+ "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@braintree/sanitize-url": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.1.tgz",
@@ -114,9 +139,9 @@
"license": "Apache-2.0"
},
"node_modules/@codemirror/autocomplete": {
- "version": "6.18.4",
- "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.4.tgz",
- "integrity": "sha512-sFAphGQIqyQZfP2ZBsSHV7xQvo9Py0rV0dW7W3IMRdS+zDuNb2l3no78CvUaWKGfzFjI4FTrLdUSj86IGb2hRA==",
+ "version": "6.18.6",
+ "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.6.tgz",
+ "integrity": "sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg==",
"license": "MIT",
"dependencies": {
"@codemirror/language": "^6.0.0",
@@ -201,9 +226,9 @@
}
},
"node_modules/@codemirror/lang-javascript": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.2.tgz",
- "integrity": "sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==",
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.3.tgz",
+ "integrity": "sha512-8PR3vIWg7pSu7ur8A07pGiYHgy3hHj+mRYRCSG8q+mPIrl0F02rgpGv+DsQTHRTc30rydOsf5PZ7yjKFg2Ackw==",
"license": "MIT",
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
@@ -316,9 +341,9 @@
}
},
"node_modules/@codemirror/search": {
- "version": "6.5.8",
- "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.8.tgz",
- "integrity": "sha512-PoWtZvo7c1XFeZWmmyaOp2G0XVbOnm+fJzvghqGAktBW3cufwJUWvSCcNG0ppXiBEM05mZu6RhMtXPv2hpllig==",
+ "version": "6.5.9",
+ "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.9.tgz",
+ "integrity": "sha512-7DdQ9aaZMMxuWB1u6IIFWWuK9NocVZwvo4nG8QjJTS6oZGvteoLSiXw3EbVZVlO08Ri2ltO89JVInMpfcJxhtg==",
"license": "MIT",
"dependencies": {
"@codemirror/state": "^6.0.0",
@@ -327,18 +352,18 @@
}
},
"node_modules/@codemirror/state": {
- "version": "6.5.1",
- "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.1.tgz",
- "integrity": "sha512-3rA9lcwciEB47ZevqvD8qgbzhM9qMb8vCcQCNmDfVRPQG4JT9mSb0Jg8H7YjKGGQcFnLN323fj9jdnG59Kx6bg==",
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz",
+ "integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==",
"license": "MIT",
"dependencies": {
"@marijn/find-cluster-break": "^1.0.0"
}
},
"node_modules/@codemirror/view": {
- "version": "6.36.2",
- "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.36.2.tgz",
- "integrity": "sha512-DZ6ONbs8qdJK0fdN7AB82CgI6tYXf4HWk1wSVa0+9bhVznCuuvhQtX8bFBoy3dv8rZSQqUd8GvhVAcielcidrA==",
+ "version": "6.36.3",
+ "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.36.3.tgz",
+ "integrity": "sha512-N2bilM47QWC8Hnx0rMdDxO2x2ImJ1FvZWXubwKgjeoOrWwEiFrtpA7SFHcuZ+o2Ze2VzbkgbzWVj4+V18LVkeg==",
"license": "MIT",
"dependencies": {
"@codemirror/state": "^6.5.0",
@@ -347,9 +372,9 @@
}
},
"node_modules/@esbuild/aix-ppc64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz",
- "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz",
+ "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==",
"cpu": [
"ppc64"
],
@@ -364,9 +389,9 @@
}
},
"node_modules/@esbuild/android-arm": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz",
- "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz",
+ "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==",
"cpu": [
"arm"
],
@@ -381,9 +406,9 @@
}
},
"node_modules/@esbuild/android-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz",
- "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz",
+ "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==",
"cpu": [
"arm64"
],
@@ -398,9 +423,9 @@
}
},
"node_modules/@esbuild/android-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz",
- "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz",
+ "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==",
"cpu": [
"x64"
],
@@ -415,9 +440,9 @@
}
},
"node_modules/@esbuild/darwin-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz",
- "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz",
+ "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==",
"cpu": [
"arm64"
],
@@ -432,9 +457,9 @@
}
},
"node_modules/@esbuild/darwin-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz",
- "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz",
+ "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==",
"cpu": [
"x64"
],
@@ -449,9 +474,9 @@
}
},
"node_modules/@esbuild/freebsd-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz",
- "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz",
+ "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==",
"cpu": [
"arm64"
],
@@ -466,9 +491,9 @@
}
},
"node_modules/@esbuild/freebsd-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz",
- "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz",
+ "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==",
"cpu": [
"x64"
],
@@ -483,9 +508,9 @@
}
},
"node_modules/@esbuild/linux-arm": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz",
- "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz",
+ "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==",
"cpu": [
"arm"
],
@@ -500,9 +525,9 @@
}
},
"node_modules/@esbuild/linux-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz",
- "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz",
+ "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==",
"cpu": [
"arm64"
],
@@ -517,9 +542,9 @@
}
},
"node_modules/@esbuild/linux-ia32": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz",
- "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz",
+ "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==",
"cpu": [
"ia32"
],
@@ -534,9 +559,9 @@
}
},
"node_modules/@esbuild/linux-loong64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz",
- "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz",
+ "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==",
"cpu": [
"loong64"
],
@@ -551,9 +576,9 @@
}
},
"node_modules/@esbuild/linux-mips64el": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz",
- "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz",
+ "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==",
"cpu": [
"mips64el"
],
@@ -568,9 +593,9 @@
}
},
"node_modules/@esbuild/linux-ppc64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz",
- "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz",
+ "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==",
"cpu": [
"ppc64"
],
@@ -585,9 +610,9 @@
}
},
"node_modules/@esbuild/linux-riscv64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz",
- "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz",
+ "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==",
"cpu": [
"riscv64"
],
@@ -602,9 +627,9 @@
}
},
"node_modules/@esbuild/linux-s390x": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz",
- "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz",
+ "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==",
"cpu": [
"s390x"
],
@@ -619,9 +644,9 @@
}
},
"node_modules/@esbuild/linux-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz",
- "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz",
+ "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==",
"cpu": [
"x64"
],
@@ -636,9 +661,9 @@
}
},
"node_modules/@esbuild/netbsd-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz",
- "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz",
+ "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==",
"cpu": [
"arm64"
],
@@ -653,9 +678,9 @@
}
},
"node_modules/@esbuild/netbsd-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz",
- "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz",
+ "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==",
"cpu": [
"x64"
],
@@ -670,9 +695,9 @@
}
},
"node_modules/@esbuild/openbsd-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz",
- "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz",
+ "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==",
"cpu": [
"arm64"
],
@@ -687,9 +712,9 @@
}
},
"node_modules/@esbuild/openbsd-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz",
- "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz",
+ "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==",
"cpu": [
"x64"
],
@@ -704,9 +729,9 @@
}
},
"node_modules/@esbuild/sunos-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz",
- "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz",
+ "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==",
"cpu": [
"x64"
],
@@ -721,9 +746,9 @@
}
},
"node_modules/@esbuild/win32-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz",
- "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz",
+ "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==",
"cpu": [
"arm64"
],
@@ -738,9 +763,9 @@
}
},
"node_modules/@esbuild/win32-ia32": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz",
- "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz",
+ "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==",
"cpu": [
"ia32"
],
@@ -755,9 +780,9 @@
}
},
"node_modules/@esbuild/win32-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz",
- "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz",
+ "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==",
"cpu": [
"x64"
],
@@ -801,13 +826,13 @@
}
},
"node_modules/@eslint/config-array": {
- "version": "0.19.1",
- "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz",
- "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==",
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz",
+ "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/object-schema": "^2.1.5",
+ "@eslint/object-schema": "^2.1.6",
"debug": "^4.3.1",
"minimatch": "^3.1.2"
},
@@ -840,9 +865,9 @@
}
},
"node_modules/@eslint/core": {
- "version": "0.10.0",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz",
- "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==",
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.11.0.tgz",
+ "integrity": "sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -901,9 +926,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.18.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz",
- "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==",
+ "version": "9.20.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.20.0.tgz",
+ "integrity": "sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -911,9 +936,9 @@
}
},
"node_modules/@eslint/object-schema": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz",
- "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==",
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
+ "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -921,13 +946,13 @@
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz",
- "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==",
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.6.tgz",
+ "integrity": "sha512-+0TjwR1eAUdZtvv/ir1mGX+v0tUoR3VEPB8Up0LLJC+whRW0GgBBtpbOkg/a/U4Dxa6l5a3l9AJ1aWIQVyoWJA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/core": "^0.10.0",
+ "@eslint/core": "^0.11.0",
"levn": "^0.4.1"
},
"engines": {
@@ -987,9 +1012,9 @@
}
},
"node_modules/@humanwhocodes/retry": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz",
- "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==",
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz",
+ "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -1007,25 +1032,25 @@
"license": "MIT"
},
"node_modules/@iconify/utils": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.2.1.tgz",
- "integrity": "sha512-0/7J7hk4PqXmxo5PDBDxmnecw5PxklZJfNjIVG9FM0mEfVrvfudS22rYWsqVk6gR3UJ/mSYS90X4R3znXnqfNA==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.3.0.tgz",
+ "integrity": "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==",
"license": "MIT",
"dependencies": {
- "@antfu/install-pkg": "^0.4.1",
- "@antfu/utils": "^0.7.10",
+ "@antfu/install-pkg": "^1.0.0",
+ "@antfu/utils": "^8.1.0",
"@iconify/types": "^2.0.0",
"debug": "^4.4.0",
- "globals": "^15.13.0",
+ "globals": "^15.14.0",
"kolorist": "^1.8.0",
- "local-pkg": "^0.5.1",
- "mlly": "^1.7.3"
+ "local-pkg": "^1.0.0",
+ "mlly": "^1.7.4"
}
},
"node_modules/@iconify/utils/node_modules/globals": {
- "version": "15.14.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz",
- "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==",
+ "version": "15.15.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
+ "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
"license": "MIT",
"engines": {
"node": ">=18"
@@ -1034,6 +1059,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
+ "license": "MIT"
+ },
"node_modules/@lezer/common": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz",
@@ -1052,9 +1083,9 @@
}
},
"node_modules/@lezer/css": {
- "version": "1.1.9",
- "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.9.tgz",
- "integrity": "sha512-TYwgljcDv+YrV0MZFFvYFQHCfGgbPMR6nuqLabBdmZoFH3EP1gvw8t0vae326Ne3PszQkbXfVBjCnf3ZVCr0bA==",
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.10.tgz",
+ "integrity": "sha512-V5/89eDapjeAkWPBpWEfQjZ1Hag3aYUUJOL8213X0dFRuXJ4BXa5NKl9USzOnaLod4AOpmVCkduir2oKwZYZtg==",
"license": "MIT",
"dependencies": {
"@lezer/common": "^1.2.0",
@@ -1136,13 +1167,14 @@
}
},
"node_modules/@lezer/markdown": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.4.0.tgz",
- "integrity": "sha512-mk4MYeq6ZQdxgsgRAe0G7kqPRV6Desajfa14TcHoGGXIqqj1/2ARN31VFpmrXDgvXiGBWpA7RXtv0he+UdTkGw==",
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.4.1.tgz",
+ "integrity": "sha512-Za5okfyWoNaX6sSZ2dm94XegaFXbkQ9UjKJ8hAoZX88XDpbu6DoR63IuSl+dqj1VkVQBQGsdr0JnTcMsogQDdw==",
"license": "MIT",
"dependencies": {
"@lezer/common": "^1.0.0",
- "@lezer/highlight": "^1.0.0"
+ "@lezer/highlight": "^1.0.0",
+ "@marijn/buildtool": "^0.1.6"
}
},
"node_modules/@lezer/php": {
@@ -1189,6 +1221,26 @@
"@lezer/lr": "^1.0.0"
}
},
+ "node_modules/@marijn/buildtool": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/@marijn/buildtool/-/buildtool-0.1.6.tgz",
+ "integrity": "sha512-rcA2wljsM24MFAwx2U5vSBrt7IdIaPh4WPRfJPS8PuCUlbuQ8Pmky4c/ec00v3YFu90rZSbkVLnPuCeb/mUEng==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mocha": "^9.1.1",
+ "acorn": "^8.10.0",
+ "acorn-walk": "^8.2.0",
+ "rollup": "^3.28.0",
+ "rollup-plugin-dts": "^5.3.1",
+ "typescript": "^5.1.6"
+ }
+ },
+ "node_modules/@marijn/buildtool/node_modules/@types/mocha": {
+ "version": "9.1.1",
+ "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz",
+ "integrity": "sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==",
+ "license": "MIT"
+ },
"node_modules/@marijn/find-cluster-break": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
@@ -1435,9 +1487,9 @@
}
},
"node_modules/@types/d3-path": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz",
- "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz",
+ "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==",
"license": "MIT"
},
"node_modules/@types/d3-polygon": {
@@ -1459,9 +1511,9 @@
"license": "MIT"
},
"node_modules/@types/d3-scale": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz",
- "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==",
+ "version": "4.0.9",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz",
+ "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==",
"license": "MIT",
"dependencies": {
"@types/d3-time": "*"
@@ -1540,9 +1592,9 @@
"license": "MIT"
},
"node_modules/@types/geojson": {
- "version": "7946.0.15",
- "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.15.tgz",
- "integrity": "sha512-9oSxFzDCT2Rj6DfcHF8G++jxBKS7mBqXl5xrRW+Kbvjry6Uduya2iiwqHPhVXpasAVMBYKkEPGgKhd3+/HZ6xA==",
+ "version": "7946.0.16",
+ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz",
+ "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
"license": "MIT"
},
"node_modules/@types/js-beautify": {
@@ -1574,9 +1626,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "22.10.7",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.7.tgz",
- "integrity": "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==",
+ "version": "22.13.4",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.4.tgz",
+ "integrity": "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1591,21 +1643,21 @@
"optional": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.21.0.tgz",
- "integrity": "sha512-eTH+UOR4I7WbdQnG4Z48ebIA6Bgi7WO8HvFEneeYBxG8qCOYgTOFPSg6ek9ITIDvGjDQzWHcoWHCDO2biByNzA==",
+ "version": "8.24.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.24.1.tgz",
+ "integrity": "sha512-ll1StnKtBigWIGqvYDVuDmXJHVH4zLVot1yQ4fJtLpL7qacwkxJc1T0bptqw+miBQ/QfUbhl1TcQ4accW5KUyA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "8.21.0",
- "@typescript-eslint/type-utils": "8.21.0",
- "@typescript-eslint/utils": "8.21.0",
- "@typescript-eslint/visitor-keys": "8.21.0",
+ "@typescript-eslint/scope-manager": "8.24.1",
+ "@typescript-eslint/type-utils": "8.24.1",
+ "@typescript-eslint/utils": "8.24.1",
+ "@typescript-eslint/visitor-keys": "8.24.1",
"graphemer": "^1.4.0",
"ignore": "^5.3.1",
"natural-compare": "^1.4.0",
- "ts-api-utils": "^2.0.0"
+ "ts-api-utils": "^2.0.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1621,16 +1673,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.21.0.tgz",
- "integrity": "sha512-Wy+/sdEH9kI3w9civgACwabHbKl+qIOu0uFZ9IMKzX3Jpv9og0ZBJrZExGrPpFAY7rWsXuxs5e7CPPP17A4eYA==",
+ "version": "8.24.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.24.1.tgz",
+ "integrity": "sha512-Tqoa05bu+t5s8CTZFaGpCH2ub3QeT9YDkXbPd3uQ4SfsLoh1/vv2GEYAioPoxCWJJNsenXlC88tRjwoHNts1oQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/scope-manager": "8.21.0",
- "@typescript-eslint/types": "8.21.0",
- "@typescript-eslint/typescript-estree": "8.21.0",
- "@typescript-eslint/visitor-keys": "8.21.0",
+ "@typescript-eslint/scope-manager": "8.24.1",
+ "@typescript-eslint/types": "8.24.1",
+ "@typescript-eslint/typescript-estree": "8.24.1",
+ "@typescript-eslint/visitor-keys": "8.24.1",
"debug": "^4.3.4"
},
"engines": {
@@ -1646,14 +1698,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.21.0.tgz",
- "integrity": "sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA==",
+ "version": "8.24.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.24.1.tgz",
+ "integrity": "sha512-OdQr6BNBzwRjNEXMQyaGyZzgg7wzjYKfX2ZBV3E04hUCBDv3GQCHiz9RpqdUIiVrMgJGkXm3tcEh4vFSHreS2Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.21.0",
- "@typescript-eslint/visitor-keys": "8.21.0"
+ "@typescript-eslint/types": "8.24.1",
+ "@typescript-eslint/visitor-keys": "8.24.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1664,16 +1716,16 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.21.0.tgz",
- "integrity": "sha512-95OsL6J2BtzoBxHicoXHxgk3z+9P3BEcQTpBKriqiYzLKnM2DeSqs+sndMKdamU8FosiadQFT3D+BSL9EKnAJQ==",
+ "version": "8.24.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.24.1.tgz",
+ "integrity": "sha512-/Do9fmNgCsQ+K4rCz0STI7lYB4phTtEXqqCAs3gZW0pnK7lWNkvWd5iW545GSmApm4AzmQXmSqXPO565B4WVrw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/typescript-estree": "8.21.0",
- "@typescript-eslint/utils": "8.21.0",
+ "@typescript-eslint/typescript-estree": "8.24.1",
+ "@typescript-eslint/utils": "8.24.1",
"debug": "^4.3.4",
- "ts-api-utils": "^2.0.0"
+ "ts-api-utils": "^2.0.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1688,9 +1740,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.21.0.tgz",
- "integrity": "sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A==",
+ "version": "8.24.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.24.1.tgz",
+ "integrity": "sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1702,20 +1754,20 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.21.0.tgz",
- "integrity": "sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg==",
+ "version": "8.24.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.24.1.tgz",
+ "integrity": "sha512-UPyy4MJ/0RE648DSKQe9g0VDSehPINiejjA6ElqnFaFIhI6ZEiZAkUI0D5MCk0bQcTf/LVqZStvQ6K4lPn/BRg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.21.0",
- "@typescript-eslint/visitor-keys": "8.21.0",
+ "@typescript-eslint/types": "8.24.1",
+ "@typescript-eslint/visitor-keys": "8.24.1",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
"minimatch": "^9.0.4",
"semver": "^7.6.0",
- "ts-api-utils": "^2.0.0"
+ "ts-api-utils": "^2.0.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1729,16 +1781,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.21.0.tgz",
- "integrity": "sha512-xcXBfcq0Kaxgj7dwejMbFyq7IOHgpNMtVuDveK7w3ZGwG9owKzhALVwKpTF2yrZmEwl9SWdetf3fxNzJQaVuxw==",
+ "version": "8.24.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.24.1.tgz",
+ "integrity": "sha512-OOcg3PMMQx9EXspId5iktsI3eMaXVwlhC8BvNnX6B5w9a4dVgpkQZuU8Hy67TolKcl+iFWq0XX+jbDGN4xWxjQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
- "@typescript-eslint/scope-manager": "8.21.0",
- "@typescript-eslint/types": "8.21.0",
- "@typescript-eslint/typescript-estree": "8.21.0"
+ "@typescript-eslint/scope-manager": "8.24.1",
+ "@typescript-eslint/types": "8.24.1",
+ "@typescript-eslint/typescript-estree": "8.24.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1753,13 +1805,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.21.0.tgz",
- "integrity": "sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w==",
+ "version": "8.24.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.24.1.tgz",
+ "integrity": "sha512-EwVHlp5l+2vp8CoqJm9KikPZgi3gbdZAtabKT9KPShGeOcJhsv4Zdo3oc8T8I0uKEmYoU4ItyxbptjF08enaxg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.21.0",
+ "@typescript-eslint/types": "8.24.1",
"eslint-visitor-keys": "^4.2.0"
},
"engines": {
@@ -1814,6 +1866,18 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
+ "node_modules/acorn-walk": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
+ "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.11.0"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -1983,6 +2047,16 @@
"node": ">=12"
}
},
+ "node_modules/async-function": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
+ "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/available-typed-arrays": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
@@ -2049,9 +2123,9 @@
}
},
"node_modules/call-bind-apply-helpers": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz",
- "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2090,9 +2164,9 @@
}
},
"node_modules/chai": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz",
- "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==",
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz",
+ "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2898,9 +2972,9 @@
}
},
"node_modules/dompurify": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.3.tgz",
- "integrity": "sha512-U1U5Hzc2MO0oW3DF+G9qYN0aT7atAou4AgI0XjWz061nyBPbdxkfdhfy5uMgGn6+oLFCfn44ZGbdDqCzVmlOWA==",
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.4.tgz",
+ "integrity": "sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==",
"license": "(MPL-2.0 OR Apache-2.0)",
"optionalDependencies": {
"@types/trusted-types": "^2.0.7"
@@ -3037,13 +3111,16 @@
}
},
"node_modules/es-shim-unscopables": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz",
- "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
+ "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "hasown": "^2.0.0"
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
}
},
"node_modules/es-to-primitive": {
@@ -3065,9 +3142,9 @@
}
},
"node_modules/esbuild": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz",
- "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz",
+ "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -3078,31 +3155,31 @@
"node": ">=18"
},
"optionalDependencies": {
- "@esbuild/aix-ppc64": "0.24.2",
- "@esbuild/android-arm": "0.24.2",
- "@esbuild/android-arm64": "0.24.2",
- "@esbuild/android-x64": "0.24.2",
- "@esbuild/darwin-arm64": "0.24.2",
- "@esbuild/darwin-x64": "0.24.2",
- "@esbuild/freebsd-arm64": "0.24.2",
- "@esbuild/freebsd-x64": "0.24.2",
- "@esbuild/linux-arm": "0.24.2",
- "@esbuild/linux-arm64": "0.24.2",
- "@esbuild/linux-ia32": "0.24.2",
- "@esbuild/linux-loong64": "0.24.2",
- "@esbuild/linux-mips64el": "0.24.2",
- "@esbuild/linux-ppc64": "0.24.2",
- "@esbuild/linux-riscv64": "0.24.2",
- "@esbuild/linux-s390x": "0.24.2",
- "@esbuild/linux-x64": "0.24.2",
- "@esbuild/netbsd-arm64": "0.24.2",
- "@esbuild/netbsd-x64": "0.24.2",
- "@esbuild/openbsd-arm64": "0.24.2",
- "@esbuild/openbsd-x64": "0.24.2",
- "@esbuild/sunos-x64": "0.24.2",
- "@esbuild/win32-arm64": "0.24.2",
- "@esbuild/win32-ia32": "0.24.2",
- "@esbuild/win32-x64": "0.24.2"
+ "@esbuild/aix-ppc64": "0.25.0",
+ "@esbuild/android-arm": "0.25.0",
+ "@esbuild/android-arm64": "0.25.0",
+ "@esbuild/android-x64": "0.25.0",
+ "@esbuild/darwin-arm64": "0.25.0",
+ "@esbuild/darwin-x64": "0.25.0",
+ "@esbuild/freebsd-arm64": "0.25.0",
+ "@esbuild/freebsd-x64": "0.25.0",
+ "@esbuild/linux-arm": "0.25.0",
+ "@esbuild/linux-arm64": "0.25.0",
+ "@esbuild/linux-ia32": "0.25.0",
+ "@esbuild/linux-loong64": "0.25.0",
+ "@esbuild/linux-mips64el": "0.25.0",
+ "@esbuild/linux-ppc64": "0.25.0",
+ "@esbuild/linux-riscv64": "0.25.0",
+ "@esbuild/linux-s390x": "0.25.0",
+ "@esbuild/linux-x64": "0.25.0",
+ "@esbuild/netbsd-arm64": "0.25.0",
+ "@esbuild/netbsd-x64": "0.25.0",
+ "@esbuild/openbsd-arm64": "0.25.0",
+ "@esbuild/openbsd-x64": "0.25.0",
+ "@esbuild/sunos-x64": "0.25.0",
+ "@esbuild/win32-arm64": "0.25.0",
+ "@esbuild/win32-ia32": "0.25.0",
+ "@esbuild/win32-x64": "0.25.0"
}
},
"node_modules/escape-string-regexp": {
@@ -3119,18 +3196,18 @@
}
},
"node_modules/eslint": {
- "version": "9.18.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz",
- "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==",
+ "version": "9.20.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.20.1.tgz",
+ "integrity": "sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1",
"@eslint/config-array": "^0.19.0",
- "@eslint/core": "^0.10.0",
+ "@eslint/core": "^0.11.0",
"@eslint/eslintrc": "^3.2.0",
- "@eslint/js": "9.18.0",
+ "@eslint/js": "9.20.0",
"@eslint/plugin-kit": "^0.2.5",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
@@ -3553,9 +3630,9 @@
"license": "MIT"
},
"node_modules/fastq": {
- "version": "1.18.0",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz",
- "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==",
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz",
+ "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -3620,20 +3697,40 @@
}
},
"node_modules/flatted": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz",
- "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==",
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
"dev": true,
"license": "ISC"
},
"node_modules/for-each": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
- "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "is-callable": "^1.1.3"
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": {
@@ -3929,9 +4026,9 @@
}
},
"node_modules/import-fresh": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
- "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3998,12 +4095,13 @@
}
},
"node_modules/is-async-function": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.0.tgz",
- "integrity": "sha512-GExz9MtyhlZyXYLxzlJRj5WUCE661zhDa1Yna52CN57AJsymh+DvXXjyveSioqSRdxvUrdKdvqB1b5cVKsNpWQ==",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
+ "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
"dev": true,
"license": "MIT",
"dependencies": {
+ "async-function": "^1.0.0",
"call-bound": "^1.0.3",
"get-proto": "^1.0.1",
"has-tostringtag": "^1.0.2",
@@ -4033,13 +4131,13 @@
}
},
"node_modules/is-boolean-object": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz",
- "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==",
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
+ "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2",
+ "call-bound": "^1.0.3",
"has-tostringtag": "^1.0.2"
},
"engines": {
@@ -4324,13 +4422,13 @@
}
},
"node_modules/is-weakref": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz",
- "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
+ "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2"
+ "call-bound": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
@@ -4370,6 +4468,13 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
@@ -4500,13 +4605,13 @@
}
},
"node_modules/local-pkg": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz",
- "integrity": "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==",
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.0.0.tgz",
+ "integrity": "sha512-bbgPw/wmroJsil/GgL4qjDzs5YLTBMQ99weRsok1XCDccQeehbHA/I1oRvk2NPtr7KGZgT/Y5tPRnAtMqeG2Kg==",
"license": "MIT",
"dependencies": {
"mlly": "^1.7.3",
- "pkg-types": "^1.2.1"
+ "pkg-types": "^1.3.0"
},
"engines": {
"node": ">=14"
@@ -4545,12 +4650,21 @@
"license": "MIT"
},
"node_modules/loupe": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz",
- "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz",
+ "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==",
"dev": true,
"license": "MIT"
},
+ "node_modules/magic-string": {
+ "version": "0.30.17",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
+ "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0"
+ }
+ },
"node_modules/marked": {
"version": "13.0.3",
"resolved": "https://registry.npmjs.org/marked/-/marked-13.0.3.tgz",
@@ -4694,9 +4808,9 @@
"license": "MIT"
},
"node_modules/object-inspect": {
- "version": "1.13.3",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz",
- "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==",
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
"dev": true,
"license": "MIT",
"engines": {
@@ -4859,9 +4973,9 @@
}
},
"node_modules/package-manager-detector": {
- "version": "0.2.8",
- "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.8.tgz",
- "integrity": "sha512-ts9KSdroZisdvKMWVAVCXiKqnqNfXz4+IbrBG8/BWx/TR5le+jfenvoBuIZ6UWM9nz47W7AbD9qYfAwfWMIwzA==",
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.9.tgz",
+ "integrity": "sha512-+vYvA/Y31l8Zk8dwxHhL3JfTuHPm6tlxM2A3GeQyl7ovYnSp1+mzAxClxaOr0qO1TtPxbQxetI7v5XqKLJZk7Q==",
"license": "MIT"
},
"node_modules/parent-module": {
@@ -4911,9 +5025,9 @@
"license": "MIT"
},
"node_modules/pathe": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz",
- "integrity": "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
+ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
"license": "MIT"
},
"node_modules/pathval": {
@@ -4926,6 +5040,13 @@
"node": ">= 14.16"
}
},
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC",
+ "optional": true
+ },
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
@@ -4967,9 +5088,9 @@
}
},
"node_modules/possible-typed-array-names": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
- "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
+ "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -4987,9 +5108,9 @@
}
},
"node_modules/prettier": {
- "version": "3.4.2",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz",
- "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==",
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.1.tgz",
+ "integrity": "sha512-hPpFQvHwL3Qv5AdRvBFMhnKo4tYxp0ReXiPn2bxkiohEX6mBeBwEpBSQTkD458RaaDKQMYSp4hX4UtfUTA5wDw==",
"dev": true,
"license": "MIT",
"peer": true,
@@ -5139,6 +5260,44 @@
"integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==",
"license": "Unlicense"
},
+ "node_modules/rollup": {
+ "version": "3.29.5",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz",
+ "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==",
+ "license": "MIT",
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=14.18.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/rollup-plugin-dts": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-5.3.1.tgz",
+ "integrity": "sha512-gusMi+Z4gY/JaEQeXnB0RUdU82h1kF0WYzCWgVmV4p3hWXqelaKuCvcJawfeg+EKn2T1Ie+YWF2OiN1/L8bTVg==",
+ "license": "LGPL-3.0",
+ "dependencies": {
+ "magic-string": "^0.30.2"
+ },
+ "engines": {
+ "node": ">=v14.21.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/Swatinem"
+ },
+ "optionalDependencies": {
+ "@babel/code-frame": "^7.22.5"
+ },
+ "peerDependencies": {
+ "rollup": "^3.0",
+ "typescript": "^4.1 || ^5.0"
+ }
+ },
"node_modules/roughjs": {
"version": "4.6.6",
"resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz",
@@ -5254,9 +5413,9 @@
"license": "MIT"
},
"node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
+ "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"dev": true,
"license": "ISC",
"bin": {
@@ -5503,9 +5662,9 @@
"license": "MIT"
},
"node_modules/stylis": {
- "version": "4.3.5",
- "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.5.tgz",
- "integrity": "sha512-K7npNOKGRYuhAFFzkzMGfxFDpN6gDwf8hcMiE+uveTVbBgm93HrNP3ZDUpKqzZ4pG7TP6fmb+EMAQPjq9FqqvA==",
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz",
+ "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==",
"license": "MIT"
},
"node_modules/supports-color": {
@@ -5558,9 +5717,9 @@
"license": "MIT"
},
"node_modules/tinymce": {
- "version": "7.6.0",
- "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-7.6.0.tgz",
- "integrity": "sha512-kUrklnD7H8JbpSDEGRh51GKK6Mrf+pR9neSDzUHvXKV+2oRtMB7sqfAtEOnM0/WKdstwaX0qoNCZNo2H1Y0EFA==",
+ "version": "7.7.0",
+ "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-7.7.0.tgz",
+ "integrity": "sha512-zDFPXeje5fQIxuYzv9fE6YmjFBQmeB9SU+85ofizIHqCCkbBnDdEWhD5R8rBu9MwdjIQP3aNohgGe9D6JOhNaw==",
"license": "GPL-2.0-or-later"
},
"node_modules/to-regex-range": {
@@ -5577,9 +5736,9 @@
}
},
"node_modules/ts-api-utils": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz",
- "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz",
+ "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==",
"dev": true,
"license": "MIT",
"engines": {
@@ -5713,7 +5872,6 @@
"version": "5.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
- "dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
diff --git a/client/package.json b/client/package.json
index 66187278..fae32f7d 100644
--- a/client/package.json
+++ b/client/package.json
@@ -1,6 +1,6 @@
{
"name": "codechat-editor-client",
- "version": "0.1.9",
+ "version": "0.1.10",
"description": "The CodeChat Editor Client, part of a web-based literate programming editor (the CodeChat Editor).",
"homepage": "https://github.com/bjones1/CodeChat_Editor",
"type": "module",
@@ -24,7 +24,7 @@
"@typescript-eslint/eslint-plugin": "^8",
"@typescript-eslint/parser": "^8",
"chai": "^5",
- "esbuild": "^0.24",
+ "esbuild": "^0.25",
"eslint": "^9",
"eslint-config-prettier": "^10",
"eslint-plugin-import": "^2",
diff --git a/client/src/CodeChatEditor-test.mts b/client/src/CodeChatEditor-test.mts
index 4d57913a..60d68118 100644
--- a/client/src/CodeChatEditor-test.mts
+++ b/client/src/CodeChatEditor-test.mts
@@ -14,12 +14,14 @@
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
-// # `CodeChatEditor-test.mts` -- Tests for the CodeChat Editor client
+// `CodeChatEditor-test.mts` -- Tests for the CodeChat Editor client
+// =================================================================
//
// To run tests, add a `?test` to any web page served by the CodeChat Editor
// server.
//
-// ## Imports
+// Imports
+// -------
//
// I can't get Mocha to work with ESBuild, so I import it using a script tag.
import { assert } from "chai";
@@ -33,7 +35,8 @@ export { page_init };
// Provide convenient access to all functions tested here.
const { codechat_html_to_markdown } = exportedForTesting;
-// ## Tests
+// Tests
+// -----
//
// Defining this global variable signals the
// CodeChat Editor to [run tests](CodeChatEditor.mts#CodeChatEditor_test).
diff --git a/client/src/CodeChatEditor.mts b/client/src/CodeChatEditor.mts
index 7f20d98d..a9be067b 100644
--- a/client/src/CodeChatEditor.mts
+++ b/client/src/CodeChatEditor.mts
@@ -11,7 +11,8 @@
// details.
//
// You should have received a copy of the GNU General Public License along with
-// the CodeChat Editor. If not, see[http://www.gnu.org/licenses](http://www.gnu.org/licenses).
+// the CodeChat Editor. If not,
+// see[http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
// `CodeChatEditor.mts` -- the CodeChat Editor Client
// ==================================================
@@ -55,8 +56,8 @@ import {
} from "./CodeMirror-integration.mjs";
import "./EditorComponents.mjs";
import "./graphviz-webcomponent-setup.mts";
-// This must be imported*after* the previous setup import, so it's placed here, instead of in the
-// third-party category above.
+// This must be imported*after* the previous setup import, so it's placed here,
+// instead of in the third-party category above.
import "graphviz-webcomponent";
import { tinymce, init, Editor } from "./tinymce-config.mjs";
@@ -66,7 +67,9 @@ import "./css/CodeChatEditor.css";
// Data structures
// ---------------
//
-// Define all possible editor modes; these are passed as a[query string](https://en.wikipedia.org/wiki/Query_string) (`http://path/to/foo.py?mode=toc`, for example) to the page's URL.
+// Define all possible editor modes; these are passed as
+// a[query string](https://en.wikipedia.org/wiki/Query_string)
+// (`http://path/to/foo.py?mode=toc`, for example) to the page's URL.
enum EditorMode {
// Display the source code using CodeChat, but disallow editing.
view,
@@ -79,7 +82,8 @@ enum EditorMode {
raw,
}
-// Since this is experimental, TypeScript doesn't define it. See the[docs](https://developer.mozilla.org/en-US/docs/Web/API/NavigateEvent).
+// Since this is experimental, TypeScript doesn't define it. See
+// the[docs](https://developer.mozilla.org/en-US/docs/Web/API/NavigateEvent).
interface NavigateEvent extends Event {
canIntercept: boolean;
destination: any;
@@ -120,7 +124,8 @@ let autosaveEnabled = true;
// Store the lexer info for the currently-loaded language.
//
-// This mirrors the data provided by the server -- see[SourceFileMetadata](../../server/src/webserver.rs#SourceFileMetadata).
+// This mirrors the data provided by the server --
+// see[SourceFileMetadata](../../server/src/webserver.rs#SourceFileMetadata).
let current_metadata: {
mode: string;
};
@@ -130,7 +135,8 @@ let is_dirty = false;
// ### Markdown to HTML conversion
//
-// Instantiate[turndown](https://github.com/mixmark-io/turndown) for HTML to Markdown conversion
+// Instantiate[turndown](https://github.com/mixmark-io/turndown) for HTML to
+// Markdown conversion
const turndownService = new TurndownService({
br: "\\",
codeBlockStyle: "fenced",
@@ -138,7 +144,9 @@ const turndownService = new TurndownService({
wordWrap: [80, 40],
});
-// Add the plugins from[turndown-plugin-gfm](https://github.com/laurent22/joplin/tree/dev/packages/turndown-plugin-gfm) to enable conversions for tables, task lists, and strikethroughs.
+// Add the plugins
+// from[turndown-plugin-gfm](https://github.com/laurent22/joplin/tree/dev/packages/turndown-plugin-gfm)
+// to enable conversions for tables, task lists, and strikethroughs.
turndownService.use(gfm);
// Page initialization
@@ -172,7 +180,8 @@ 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).
+// 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.
@@ -204,14 +213,20 @@ const _open_lp = async (
// associated metadata. See[`AllSource`](#AllSource).
all_source: CodeChatForWeb,
) => {
- // Use[URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) to parse out the search parameters of this window's URL.
+ // Use[URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)
+ // to parse out the search parameters of this window's URL.
const urlParams = new URLSearchParams(window.location.search);
- // Get the mode from the page's query parameters. Default to edit using the[nullish coalescing operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator). This works, but TypeScript marks it as an error. Ignore this error by
- // including the[@ts-ignore directive](https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html#ts-check).
+ // Get the mode from the page's query parameters. Default to edit using
+ // the[nullish coalescing
+ // operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator).
+ // This works, but TypeScript marks it as an error. Ignore this error by
+ // including the[@ts-ignore
+ // directive](https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html#ts-check).
/// @ts-ignore
const editorMode = EditorMode[urlParams.get("mode") ?? "edit"];
- // Get thecurrent_metadata from the provided`all_source` struct and store it as a global variable.
+ // Get thecurrent_metadata from
+ // the provided`all_source` struct and store it as a global variable.
current_metadata = all_source["metadata"];
const source = all_source["source"];
const codechat_body = document.getElementById(
@@ -222,22 +237,31 @@ const _open_lp = async (
clearAutosaveTimer();
// Before calling any MathJax, make sure it's fully loaded.
await window.MathJax.startup.promise;
- // Per the[docs](https://docs.mathjax.org/en/latest/web/typeset.html#updating-previously-typeset-content), "If you modify the page to remove content that contains typeset
+ // Per
+ // the[docs](https://docs.mathjax.org/en/latest/web/typeset.html#updating-previously-typeset-content),
+ // "If you modify the page to remove content that contains typeset
// mathematics, you will need to tell MathJax about that so that it knows
// the typeset math that you are removing is no longer on the page."
window.MathJax.typesetClear(codechat_body);
if (is_doc_only()) {
if (tinymce.activeEditor === null) {
- // Special case: a CodeChat Editor document's HTML is stored in`source.doc`. We don't need the CodeMirror editor at all; instead, treat it
- // like a single doc block contents div.
+ // Special case: a CodeChat Editor document's HTML is stored
+ // in`source.doc`. We don't need the CodeMirror editor at all;
+ // instead, treat it like a single doc block contents div.
codechat_body.innerHTML = `
${source.doc}
`;
await init({
selector: ".CodeChat-doc-contents",
// In the doc-only mode, add autosave functionality. While there
- // is an[autosave plugin](https://www.tiny.cloud/docs/tinymce/6/autosave/), this autosave functionality is completely different from
- // the autosave provided here. Per[handling editor events](https://www.tiny.cloud/docs/tinymce/6/events/#handling-editor-events), this is how to create a TinyMCE event handler.
+ // is an[autosave
+ // plugin](https://www.tiny.cloud/docs/tinymce/6/autosave/),
+ // this autosave functionality is completely different from the
+ // autosave provided here. Per[handling editor
+ // events](https://www.tiny.cloud/docs/tinymce/6/events/#handling-editor-events),
+ // this is how to create a TinyMCE event handler.
setup: (editor: Editor) => {
- // The[editor core events list](https://www.tiny.cloud/docs/tinymce/6/events/#editor-core-events) includes the`Dirty` event.
+ // The[editor core events
+ // list](https://www.tiny.cloud/docs/tinymce/6/events/#editor-core-events)
+ // includes the`Dirty` event.
editor.on("Dirty", (_event: Event) => {
is_dirty = true;
startAutosaveTimer();
@@ -246,7 +270,9 @@ const _open_lp = async (
});
tinymce.activeEditor!.focus();
} else {
- // Save and restore cursor/scroll location after an update per the[docs](https://www.tiny.cloud/docs/tinymce/6/apis/tinymce.dom.bookmarkmanager). However, this doesn't seem to work for the cursor location.
+ // Save and restore cursor/scroll location after an update per
+ // the[docs](https://www.tiny.cloud/docs/tinymce/6/apis/tinymce.dom.bookmarkmanager).
+ // However, this doesn't seem to work for the cursor location.
// Perhaps when TinyMCE normalizes the document, this gets lost?
const bm = tinymce.activeEditor!.selection.getBookmark();
tinymce.activeEditor!.setContent(source.doc);
@@ -258,7 +284,10 @@ const _open_lp = async (
}
autosaveEnabled = true;
- // If tests should be run, then the[following global variable](CodeChatEditor-test.mts#CodeChatEditor_test) is function that runs them.
+ // If tests should be run, then
+ // the[following global
+ // variable](CodeChatEditor-test.mts#CodeChatEditor_test) is function that
+ // runs them.
if (typeof window.CodeChatEditor_test === "function") {
window.CodeChatEditor_test();
}
@@ -303,7 +332,8 @@ const save_lp = async () => {
return update;
};
-// Per[MDN](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/platform#examples), here's the least bad way to choose between the control key and the command
+// Per[MDN](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/platform#examples),
+// here's the least bad way to choose between the control key and the command
// key.
const os_is_osx =
navigator.platform.indexOf("Mac") === 0 || navigator.platform === "iPhone"
@@ -315,8 +345,8 @@ const on_save = async (only_if_dirty: boolean = false) => {
if (only_if_dirty && !is_dirty) {
return;
}
- // Save the provided contents back to the filesystem, by sending an update
- // message over the websocket.
+ // Save the provided contents back to the filesystem, by
+ // sending an update message over the websocket.
const webSocketComm = parent.window.CodeChatEditorFramework.webSocketComm;
console.log("Sent Update - saving document.");
await new Promise(async (resolve) => {
@@ -374,7 +404,10 @@ const clearAutosaveTimer = () => {
// current document before navigating.
const on_navigate = (navigateEvent: NavigateEvent) => {
if (
- // Some of this was copied from[Modern client-side routing: the Navigation API](https://developer.chrome.com/docs/web-platform/navigation-api/#deciding_how_to_handle_a_navigation). If we're navigating within the document, ignore this.
+ // Some of this was copied from[Modern client-side routing: the
+ // Navigation
+ // API](https://developer.chrome.com/docs/web-platform/navigation-api/#deciding_how_to_handle_a_navigation).
+ // If we're navigating within the document, ignore this.
navigateEvent.hashChange ||
// If this is a download, let the browser perform the download.
navigateEvent.downloadRequest ||
@@ -391,7 +424,8 @@ const on_navigate = (navigateEvent: NavigateEvent) => {
return;
}
- // If the IDE initiated this navigation via a`CurrentFile` message, then allow it.
+ // If the IDE initiated this navigation via a`CurrentFile` message, then
+ // allow it.
if (window.CodeChatEditor.allow_navigation) {
// We don't need to reset this flag, since this window will be reloaded.
return;
@@ -456,7 +490,8 @@ const save_then_navigate = (codeChatEditorUrl: URL) => {
// Testing
// -------
//
-// A great and simple idea taken from[SO](https://stackoverflow.com/a/54116079): wrap all testing exports in a single variable. This avoids namespace
+// A great and simple idea taken from[SO](https://stackoverflow.com/a/54116079):
+// wrap all testing exports in a single variable. This avoids namespace
// pollution, since only one name is exported, and it's clearly marked for
// testing only. Test code still gets access to everything it needs.
export const exportedForTesting = {
diff --git a/client/src/CodeChatEditorFramework.mts b/client/src/CodeChatEditorFramework.mts
index 79565a58..c99f354e 100644
--- a/client/src/CodeChatEditorFramework.mts
+++ b/client/src/CodeChatEditorFramework.mts
@@ -14,7 +14,8 @@
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
-// # `CodeChatEditorFramework.mts` -- the CodeChat Editor Client Framework
+// `CodeChatEditorFramework.mts` -- the CodeChat Editor Client Framework
+// =====================================================================
//
// This maintains a websocket connection between the CodeChat Editor Server. The
// accompanying HTML is a full-screen iframe, allowing the Framework to change
@@ -22,14 +23,16 @@
// to report navigation events to as a websocket message when the iframe's
// location changes.
//
-// ## Imports
+// Imports
+// -------
//
// ### JavaScript/TypeScript
//
// #### Third-party
import ReconnectingWebSocket from "./ReconnectingWebSocket.cjs";
-// ## Websocket
+// Websocket
+// ---------
//
// This code communicates with the CodeChat Editor Server via its websocket
// interface.
@@ -311,9 +314,9 @@ let testMode = false;
// Load the dynamic content into the static page.
export const page_init = (
// The pathname for the websocket to use. The remainder of the URL is
- // derived from the hosting page's URL. See the
- // [Location docs](https://developer.mozilla.org/en-US/docs/Web/API/Location)
- // for a nice, interactive definition of the components of a URL.
+ // derived from the hosting page's URL. See the [Location
+ // docs](https://developer.mozilla.org/en-US/docs/Web/API/Location) for a
+ // nice, interactive definition of the components of a URL.
ws_pathname: string,
// Test mode flag
testMode_: boolean,
diff --git a/client/src/CodeMirror-integration.mts b/client/src/CodeMirror-integration.mts
index 0cfaba06..76d87f48 100644
--- a/client/src/CodeMirror-integration.mts
+++ b/client/src/CodeMirror-integration.mts
@@ -14,7 +14,8 @@
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
-// # `CodeMirror-integration.mts` -- integrate CodeMirror into the CodeChat Editor
+// `CodeMirror-integration.mts` -- integrate CodeMirror into the CodeChat Editor
+// =============================================================================
//
// This file assumes the server has parsed the source. For example given the
// following original Python source code:
@@ -44,7 +45,8 @@
// contents are focused, apply the TinyMCE instance to those contents.
// 5. Define a set of StateEffects to add/update/etc. doc blocks.
//
-// ## Imports
+// Imports
+// -------
//
// ### Third-party
import { basicSetup } from "codemirror";
@@ -80,7 +82,8 @@ import { Editor, init, tinymce } from "./tinymce-config.mjs";
// ### Local
import { set_is_dirty, startAutosaveTimer } from "./CodeChatEditor.mjs";
-// ## Globals
+// Globals
+// -------
let current_view: EditorView;
let tinymce_singleton: Editor | undefined;
let ignore_next_dirty = false;
@@ -91,7 +94,8 @@ declare global {
}
}
-// ## Doc blocks in CodeMirror
+// Doc blocks in CodeMirror
+// ------------------------
//
// The goal: given a [Range](https://codemirror.net/docs/ref/#state.Range) of
// lines containing a doc block (a delimiter, indent, and contents) residing at
@@ -360,8 +364,9 @@ class DocBlockWidget extends WidgetType {
}
ignoreEvent(event: Event) {
- // Avoid handling other events, since this causes
- // [weird problems with event routing](https://discuss.codemirror.net/t/how-to-get-focusin-events-on-a-custom-widget-decoration/6792).
+ // Avoid handling other events, since this causes [weird problems with
+ // event
+ // routing](https://discuss.codemirror.net/t/how-to-get-focusin-events-on-a-custom-widget-decoration/6792).
if (event.type === "focusin" || event.type === "input") {
return false;
} else {
@@ -389,8 +394,8 @@ class DocBlockWidget extends WidgetType {
}
}
-// Typeset the provided node; taken from the
-// [MathJax docs](https://docs.mathjax.org/en/latest/web/typeset.html#handling-asynchronous-typesetting).
+// Typeset the provided node; taken from the [MathJax
+// docs](https://docs.mathjax.org/en/latest/web/typeset.html#handling-asynchronous-typesetting).
export const mathJaxTypeset = (node: HTMLElement) => {
window.MathJax.typesetPromise([node]).catch((err: any) =>
console.log("Typeset failed: " + err.message),
@@ -632,7 +637,8 @@ const DocBlockPlugin = ViewPlugin.fromClass(
},
);
-// ## UI
+// UI
+// --
//
// Allow only spaces and delete/backspaces when editing the indent of a doc
// block.
@@ -653,16 +659,16 @@ const doc_block_indent_on_before_input = (event_: Event) => {
};
// There doesn't seem to be any tracking of a dirty/clean flag built into
-// CodeMirror v6 (although
-// [v5 does](https://codemirror.net/5/doc/manual.html#isClean)). The best I've
-// found is a
-// [forum post](https://discuss.codemirror.net/t/codemirror-6-proper-way-to-listen-for-changes/2395/11)
+// CodeMirror v6 (although [v5
+// does](https://codemirror.net/5/doc/manual.html#isClean)). The best I've found
+// is a [forum
+// post](https://discuss.codemirror.net/t/codemirror-6-proper-way-to-listen-for-changes/2395/11)
// showing code to do this, which I use below.
//
// How this works: the
// [EditorView.updateListener](https://codemirror.net/docs/ref/#codemirror) is a
-// [Facet](https://codemirror.net/docs/ref/#state.Facet) with an
-// [of function](https://codemirror.net/docs/ref/#state.Facet.of) that creates a
+// [Facet](https://codemirror.net/docs/ref/#state.Facet) with an [of
+// function](https://codemirror.net/docs/ref/#state.Facet.of) that creates a
// CodeMirror extension.
const autosaveExtension = EditorView.updateListener.of(
// CodeMirror passes this function a
diff --git a/client/src/EditorComponents.mts b/client/src/EditorComponents.mts
index b5650338..4c87f6a8 100644
--- a/client/src/EditorComponents.mts
+++ b/client/src/EditorComponents.mts
@@ -14,7 +14,9 @@
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
-// # `EditorComponents.mts` -- Custom HTML tags which provide authoring support for the CodeChat Editor
+// `EditorComponents.mts` -- Custom HTML tags which provide authoring support
+// for the CodeChat Editor
+// ==========================================================================
//
// Create a combined editor/renderer component. It's not currently used, since
// TinyMCE doesn't allow the editor to be focused.
diff --git a/client/src/HashReader.mts b/client/src/HashReader.mts
index dc091af0..60948bb7 100644
--- a/client/src/HashReader.mts
+++ b/client/src/HashReader.mts
@@ -14,7 +14,8 @@
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
-// # `HashReader.mts` -- post-process esbuild output
+// `HashReader.mts` -- post-process esbuild output
+// ===============================================
//
// This script reads the output produced by esbuild to determine the location of
// the bundled files, which have hashes in their file names. It writes these
diff --git a/client/src/css/CodeChatEditor.css b/client/src/css/CodeChatEditor.css
index 9576cf6f..8808a667 100644
--- a/client/src/css/CodeChatEditor.css
+++ b/client/src/css/CodeChatEditor.css
@@ -16,23 +16,26 @@
the CodeChat Editor. If not, see
[http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
- # `CodeChatEditor.css` -- Styles for the CodeChat Editor
+ `CodeChatEditor.css` -- Styles for the CodeChat Editor
+ ======================================================
This style sheet is used by the HTML generated by
- [CodeChatEditor.mts](../../src/CodeChatEditor.mts).
+ [CodeChatEditor.mts](../CodeChatEditor.mts).
TODO: do a much better job of grouping common styles. Rename styles based on
whether they style a code or doc block.
- ## Import a theme
- Eventually, this will be a user-configurable setting.
- */
+ Import a theme
+ --------------
+
+ Eventually, this will be a user-configurable setting. */
@import url('themes/light.css');
-/* ## Styles for the entire page layout
+/* Styles for the entire page layout
+ ---------------------------------
- This is used only to store a reused variable value. See the
- [CSS docs](https://drafts.csswg.org/css-variables/). */
+ This is used only to store a reused variable value. See the [CSS
+ docs](https://drafts.csswg.org/css-variables/). */
:root {
--top-height: 6.7rem;
--body-padding: 0.2rem;
@@ -69,18 +72,20 @@ body {
overflow: auto;
}
}
-/* ## Misc styling
+/* Misc styling
+ ------------
- Make the filename compact. */
+ Make the filename compact. */
#CodeChat-filename p {
margin: 0px;
white-space: nowrap;
}
-/* ## Doc block styling */
+/* Doc block styling
+ ----------------- */
.CodeChat-doc {
- /* Use
- [flexbox layout](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox)
+ /* Use [flexbox
+ layout](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox)
to style doc blocks. The goal of this layout is:
\ \ \` contains \
- - `` contains \
- - `` contains \
- - `` contains the \
*/
+ * `` contains \
+ * `` contains \
+ * `` contains \
+ * `` contains the \
*/
display: flex;
padding: 0px 2px 0px 6px;
}
@@ -124,7 +129,8 @@ body {
outline-width: 0px;
}
-/* ## Combined code/doc block styling
+/* Combined code/doc block styling
+ -------------------------------
Remove space between a code block followed by a doc
block. Doc block elements typically have top margin and/or padding that
diff --git a/client/src/css/CodeChatEditorProject.css b/client/src/css/CodeChatEditorProject.css
index 0eb50fe6..e964b521 100644
--- a/client/src/css/CodeChatEditorProject.css
+++ b/client/src/css/CodeChatEditorProject.css
@@ -16,7 +16,8 @@
the CodeChat Editor. If not, see
[http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
- # `CodeChatEditorProject.css` -- Styles for the CodeChat Editor for projects */
+ `CodeChatEditorProject.css` -- Styles for the CodeChat Editor for projects
+ ========================================================================== */
:root {
--sidebar-width: 15rem;
}
@@ -25,7 +26,8 @@ body {
overflow: hidden;
}
-/* TODO: This is a overly simple, non-responsive layout to create a sidebar containing the table of contents. Fix. */
+/* TODO: This is a overly simple, non-responsive layout to create a sidebar
+ containing the table of contents. Fix. */
#CodeChat-sidebar {
width: var(--sidebar-width);
height: calc(100vh - 2 * var(--body-padding));
diff --git a/client/src/css/themes/light.css b/client/src/css/themes/light.css
index b1289370..05e529ec 100644
--- a/client/src/css/themes/light.css
+++ b/client/src/css/themes/light.css
@@ -16,10 +16,11 @@
the CodeChat Editor. If not, see
[http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
- # `light.css` -- Styles for the light theme
+ `light.css` -- Styles for the light theme
+ =========================================
- Use
- [CSS nesting](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting/Using_CSS_nesting)
+ Use [CSS
+ nesting](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting/Using_CSS_nesting)
to make everything in this style sheet apply only to the light theme. */
body.CodeChat-theme-light {
/* Style code blocks so that they are clearly separated from doc blocks. Per
diff --git a/client/src/graphviz-webcomponent-setup.mts b/client/src/graphviz-webcomponent-setup.mts
index 739328ca..640132b5 100644
--- a/client/src/graphviz-webcomponent-setup.mts
+++ b/client/src/graphviz-webcomponent-setup.mts
@@ -14,15 +14,16 @@
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
-// # `graphviz-webcomponent-setup.mts` -- Configure graphviz webcomponent options
+// `graphviz-webcomponent-setup.mts` -- Configure graphviz webcomponent options
+// ============================================================================
//
// Configure the Graphviz web component to load the (large) renderer only when a
// Graphviz web component is found on a page. See the
// [docs](https://github.com/prantlf/graphviz-webcomponent#configuration).
//
// Note that this must be in a separate module which is imported before the
-// graphviz webcomponent; see the
-// [ESBuild docs](https://esbuild.github.io/content-types/#real-esm-imports).
+// graphviz webcomponent; see the [ESBuild
+// docs](https://esbuild.github.io/content-types/#real-esm-imports).
(window as any).graphvizWebComponent = {
rendererUrl: "/static/graphviz-webcomponent/renderer.min.js",
delayWorkerLoading: true,
diff --git a/client/src/tinymce-config.mts b/client/src/tinymce-config.mts
index 0c6022c9..9214e1bf 100644
--- a/client/src/tinymce-config.mts
+++ b/client/src/tinymce-config.mts
@@ -14,7 +14,9 @@
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
-// # `tinymce-webpack.ts` -- integrate and configure the TinyMCE editor for use with the CodeChat Editor
+// `tinymce-webpack.ts` -- integrate and configure the TinyMCE editor for use
+// with the CodeChat Editor
+// ==========================================================================
//
// Import TinyMCE.
import {
@@ -89,15 +91,15 @@ export const init = async (
// The imports above apply the skins; don't try to dynamically load
// the skin's CSS.
skin: false,
- // Enable the
- // [browser-supplied spellchecker](https://www.tiny.cloud/docs/tinymce/6/spelling/#browser_spellcheck),
+ // Enable the [browser-supplied
+ // spellchecker](https://www.tiny.cloud/docs/tinymce/6/spelling/#browser_spellcheck),
// since TinyMCE's spellchecker is a premium feature.
browser_spellcheck: true,
- // Put more buttons on the
- // [quick toolbar](https://www.tiny.cloud/docs/tinymce/6/quickbars/)
- // that appears when text is selected. TODO: add a button for code
- // format (can't find this one -- it's only on the
- // [list of menu items](https://www.tiny.cloud/docs/tinymce/6/available-menu-items/#the-core-menu-items)
+ // Put more buttons on the [quick
+ // toolbar](https://www.tiny.cloud/docs/tinymce/6/quickbars/) that
+ // appears when text is selected. TODO: add a button for code format
+ // (can't find this one -- it's only on the [list of menu
+ // items](https://www.tiny.cloud/docs/tinymce/6/available-menu-items/#the-core-menu-items)
// as `codeformat`).
quickbars_selection_toolbar:
"align | bold italic underline | quicklink h2 h3 blockquote",
@@ -110,18 +112,18 @@ export const init = async (
// When true, this still prevents hyperlinks to anchors on the
// current page from working correctly. There's an onClick handler
// that prevents links in the current page from working -- need to
- // look into this. See also
- // [a related GitHub issue](https://github.com/tinymce/tinymce/issues/3836).
+ // look into this. See also [a related GitHub
+ // issue](https://github.com/tinymce/tinymce/issues/3836).
//readonly: true // Per the comment above, this is commented out.
// TODO: Notes on this setting.
relative_urls: true,
- // This combines the
- // [default TinyMCE toolbar buttons](https://www.tiny.cloud/blog/tinymce-toolbar/)
- // with a few more from plugins. I like the default, so this is
- // currently disabled.
+ // This combines the [default TinyMCE toolbar
+ // buttons](https://www.tiny.cloud/blog/tinymce-toolbar/) with a few
+ // more from plugins. I like the default, so this is currently
+ // disabled.
//toolbar: 'undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist | ltr rtl | help',
- // See
- // [License key](https://www.tiny.cloud/docs/tinymce/latest/license-key).
+ // See [License
+ // key](https://www.tiny.cloud/docs/tinymce/latest/license-key).
license_key: "gpl",
// Settings for plugins
diff --git a/client/src/typings.d.ts b/client/src/typings.d.ts
index 3320b2e3..c464083d 100644
--- a/client/src/typings.d.ts
+++ b/client/src/typings.d.ts
@@ -14,7 +14,8 @@
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
-// # `typing.d.ts` -- Global type definitions
+// `typing.d.ts` -- Global type definitions
+// ========================================
//
// The server passes this to the client to load a file. See
// [LexedSourceFile](../../server/src/webserver.rs#LexedSourceFile).
diff --git a/client/src/wc-mermaid/developer.md b/client/src/wc-mermaid/developer.md
index 1d319497..b25ea38e 100644
--- a/client/src/wc-mermaid/developer.md
+++ b/client/src/wc-mermaid/developer.md
@@ -1,3 +1,7 @@
-# Mermaid support
+Mermaid support
+===============
-This file is based on [wc-mermaid](https://github.com/manolakis/wc-mermaid). The code here was modified to allow a dynamic import of Mermaid and updated to support modern Mermaid. This software is licensed separately under the [Mermaid license](LICENSE.md).
+This file is based on [wc-mermaid](https://github.com/manolakis/wc-mermaid). The
+code here was modified to allow a dynamic import of Mermaid and updated to
+support modern Mermaid. This software is licensed separately under the [Mermaid
+license](LICENSE.md).
\ No newline at end of file
diff --git a/client/static/.gitignore b/client/static/.gitignore
index 71444ec7..ec6aa808 100644
--- a/client/static/.gitignore
+++ b/client/static/.gitignore
@@ -16,7 +16,8 @@
# the CodeChat Editor. If not, see
# [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
#
-# # `.gitignore` -- files for Git to ignore
+# `.gitignore` -- files for Git to ignore
+# =======================================
bundled/
mathjax/
mathjax-modern-font/
diff --git a/client/tsconfig.json b/client/tsconfig.json
index 2feac8ce..bbffbf1d 100644
--- a/client/tsconfig.json
+++ b/client/tsconfig.json
@@ -14,19 +14,20 @@
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
-// # tsconfig.json -- TypeScript configuration
+// tsconfig.json -- TypeScript configuration
+// =========================================
{
"compilerOptions": {
"allowJs": true,
// Required by ESBuild per their
// [docs](https://esbuild.github.io/content-types/#es-module-interop);
- // see also
- // [the TypeScript docs](https://www.typescriptlang.org/tsconfig#esModuleInterop).
+ // see also [the TypeScript
+ // docs](https://www.typescriptlang.org/tsconfig#esModuleInterop).
"esModuleInterop": true,
// Required by ESBuild per their
// [docs](https://esbuild.github.io/content-types/#isolated-modules);
- // see also
- // [the TypeScript docs](https://www.typescriptlang.org/tsconfig#isolatedModules).
+ // see also [the TypeScript
+ // docs](https://www.typescriptlang.org/tsconfig#isolatedModules).
"isolatedModules": true,
"module": "nodenext",
"moduleResolution": "nodenext",
diff --git a/docs/changelog.md b/docs/changelog.md
index 9436f120..0087bd17 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -21,6 +21,10 @@ Changelog
* [Github master](https://github.com/bjones1/CodeChat_Editor):
* No changes.
+* v0.1.10, 2025-Feb-20:
+ * Update to the 2024 editing of Rust.
+ * Update dependencies.
+ * Update source formatting using current CodeChat Editor.
* v0.1.9, 2025-Jan-20:
* Correct word wrapping inside Mermaid diagrams.
* Correct translation after adding newlines to code blocks in the Editor.
diff --git a/docs/design.md b/docs/design.md
index f7df3447..7187138d 100644
--- a/docs/design.md
+++ b/docs/design.md
@@ -1,12 +1,15 @@
-# CodeChat Editor design
+CodeChat Editor design
+======================
-## To build from source
+To build from source
+--------------------
1. Clone or download the repository.
2. [Install the Rust language](https://www.rust-lang.org/tools/install). I
recommend the 64-bit toolset for Windows.
-3. [Install NPM](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
- (the Node.js package manager).
+3. [Install
+ NPM](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) (the
+ Node.js package manager).
4. In the `server/` directory:
1. Run `./bt install --dev`.
2. Run `./bt build`.
@@ -16,70 +19,72 @@
Use `./bt` tool's options update all libraries (`updated`), run all tests
(`check`), and more.
-## Vision
+Vision
+-------------------------
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.
- - 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 page in a project build is a single-file page plus:
- - A TOC, along with previous/next/up navigation. The TOC is synchronized to
- the current page.
- - 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:
- - 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 link's
- destination (the heading text at the link's destination; a figure/table
- caption, etc.).
- - Auto-generated back links: anchors support auto-generated links back to all
- their referents, which can be used for footnotes, endnotes, citations, and
- indices. To enable this, all forward links must include an anchor and
- optionally the text to display at the target.
- - TOC support which, given some file(s), expands to a nested list of headings
- in the file(s). Authors may specify the depth of headings to include.
- - Autogenerated anchors for all anchors (headings, hyperlinks, etc.)
- - Hyperlinks to identifiers in code (use
- [ctags](https://github.com/universal-ctags/ctags)).
- - Substitutions.
- - Files/anchors can be freely moved without breaking links. This requires 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.)
+* 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.
+ * 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 page in a project build is a single-file page plus:
+ * A TOC, along with previous/next/up navigation. The TOC is
+ synchronized to the current page.
+ * 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:
+ * 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
+ link's destination (the heading text at the link's destination; a
+ figure/table caption, etc.).
+ * Auto-generated back links: anchors support auto-generated links back to
+ all their referents, which can be used for footnotes, endnotes,
+ citations, and indices. To enable this, all forward links must include
+ an anchor and optionally the text to display at the target.
+ * TOC support which, given some file(s), expands to a nested list of
+ headings in the file(s). Authors may specify the depth of headings to
+ include.
+ * Autogenerated anchors for all anchors (headings, hyperlinks, etc.)
+ * Hyperlinks to identifiers in code (use
+ [ctags](https://github.com/universal-ctags/ctags)).
+ * Substitutions.
+ * Files/anchors can be freely moved without breaking links. This requires
+ 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
-- Simple to install locally; provide a template CodeSpaces repo for web-based
- editing.
-- Support a static build: producing a set of view-only HTML files which don't
- need a server for a project, or a single HTML file outside a project.
-- An API-only view (Doxygen/Javadoc like feature).
+* Simple to install locally; provide a template CodeSpaces repo for web-based
+ editing.
+* Support a static build: producing a set of view-only HTML files which don't
+ need a server for a project, or a single HTML file outside a project.
+* An API-only view (Doxygen/Javadoc like feature).
-## Requirements
+Requirements
+--------------------------------------
The requirements expand on the vision by providing additional details.
@@ -111,43 +116,46 @@ indents are combined into a single, larger doc block.
// This is all one doc block, since only the preceding
// whitespace (there is none) matters, not the amount of
// whitespace following the opening comment delimiters.
// This is the beginning of a different doc
// block, since the indent is different.
// Here's a third doc block; inline and block comments
/* combine as long as the whitespace preceding the comment
delimiters is identical. Whitespace inside the comment doesn't affect
the classification. */
// These are two separate doc blocks,
void foo();
// since they are separated by a code block.
-### [Programming language support](index.md#programming-language-support)
+### [Programming language
+support](index.md#programming-language-support)
Initial targets come from the Stack Overflow Developer Survey 2022's section on
-[programming, scripting, and markup languages](https://survey.stackoverflow.co/2022/#section-most-popular-technologies-programming-scripting-and-markup-languages)
-and IEEE Spectrum's
-[Top Programming Languages 2022](https://spectrum.ieee.org/top-programming-languages-2022).
+[programming, scripting, and markup
+languages](https://survey.stackoverflow.co/2022/#section-most-popular-technologies-programming-scripting-and-markup-languages)
+and IEEE Spectrum's [Top Programming Languages
+2022](https://spectrum.ieee.org/top-programming-languages-2022).
### IDE/text editor integration
Initial targets come from the Stack Overflow Developer Survey 2022's section on
-[integrated development environments](https://survey.stackoverflow.co/2022/#section-most-popular-technologies-integrated-development-environment).
+[integrated development
+environments](https://survey.stackoverflow.co/2022/#section-most-popular-technologies-integrated-development-environment).
There are two basic approaches:
-- Sync with current window (simplest): have an additional IDE window open that
- displays the file currently being edited. This requires:
- - Auto-save: the CodeChat Editor autosaves any changes made, to keep files
- synced. Have the host IDE auto-save, so that updates get pushed quickly.
- - Auto-reload: if a the currently-opened file changes, then automatically
- reload it. Have the host IDE do the same.
- - Current file sync: when the current tab changes, update the CodeChat Editor
- with the new file. Ideally, also sync the cursor position.
-- Switchable editor (better, complex): provide a command to switch the current
- editor with the CodeChat Editor and vice versa. This requires:
- - To switch from the IDE editor to CodeChat, need to send the text of the
- IDE's editor to CodeChat. For the opposite, need to get the CodeChat Editor
- text and send that to the IDE's editor.
- - Need to preserve the current cursor location across switches. This is harder
- inside a doc block. An approximate find might be a good option.
+* Sync with current window (simplest): have an additional IDE window open
+ that displays the file currently being edited. This requires:
+ * Auto-save: the CodeChat Editor autosaves any changes made, to keep files
+ synced. Have the host IDE auto-save, so that updates get pushed quickly.
+ * Auto-reload: if a the currently-opened file changes, then automatically
+ reload it. Have the host IDE do the same.
+ * Current file sync: when the current tab changes, update the CodeChat
+ Editor with the new file. Ideally, also sync the cursor position.
+* Switchable editor (better, complex): provide a command to switch the
+ current editor with the CodeChat Editor and vice versa. This requires:
+ * To switch from the IDE editor to CodeChat, need to send the text of the
+ IDE's editor to CodeChat. For the opposite, need to get the CodeChat
+ Editor text and send that to the IDE's editor.
+ * Need to preserve the current cursor location across switches. This is
+ harder inside a doc block. An approximate find might be a good option.
Additional features:
-- Smart navigation: following links to a locally-editable file will open that
- file in the current editor, saving any edits before navigating away. Following
- non-local links opens the file in an external browser.
-- Memory: the editor remembers the last cursor location for recently-opened
- files, restoring that on the next file open.
+* Smart navigation: following links to a locally-editable file will open that
+ file in the current editor, saving any edits before navigating away.
+ Following non-local links opens the file in an external browser.
+* Memory: the editor remembers the last cursor location for recently-opened
+ files, restoring that on the next file open.
### Zero-build support
@@ -163,7 +171,8 @@ instead providing an option to edit the underlying tag that produced the text.
When a new tag is inserted, any tag-produced content should be immediately
added.
-## License
+License
+-------
Copyright (C) 2022 Bryan A. Jones.
@@ -181,4 +190,4 @@ details.
You should have received a [copy](LICENSE.html) of the GNU General Public
License along with the CodeChat Editor. If not, see
-[https://www.gnu.org/licenses/](https://www.gnu.org/licenses/).
+[https://www.gnu.org/licenses/](https://www.gnu.org/licenses/).
\ No newline at end of file
diff --git a/docs/implementation.md b/docs/implementation.md
index 59c0a909..4777dfcf 100644
--- a/docs/implementation.md
+++ b/docs/implementation.md
@@ -16,9 +16,11 @@ You should have received a copy of the GNU General Public License along with the
CodeChat Editor. If not, see
[http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
-# Implementation
+Implementation
+==============
-## Architecture
+Architecture
+------------------------------------------
### Client/server partitioning
@@ -31,89 +33,90 @@ elements, such as a cross-reference tag, depend on information from other pages
ability to access other files, while the server has direct access to these
files. Therefore, the overall strategy is:
-- On page load, the server transforms custom tags which depend on information
- from other pages into tags which include this information. For example, a
- cross-reference tag might be transformed into a hyperlink whose link text
- comes from the cross-reference on another page.
-- The client them defines a set of
- [Web Components](https://developer.mozilla.org/en-US/docs/Web/Web_Components)
- which implement custom tags which only need local information. For example, a
- GraphViz custom tag renders graphs based on a description of the graph inside
- the tag.
-- On save, the client sends its text back to the server, which de-transforms
- custom tags which depend on information from other pages. If de-transforms
- disagree with the provided text, then re-load the updated text after the save
- is complete. For example, after inserting an auto-titled link, the auto-titled
- text is missing; a save/reload fixes this.
+* On page load, the server transforms custom tags which depend on information
+ from other pages into tags which include this information. For example, a
+ cross-reference tag might be transformed into a hyperlink whose link text
+ comes from the cross-reference on another page.
+* The client them defines a set of [Web
+ Components](https://developer.mozilla.org/en-US/docs/Web/Web_Components)
+ which implement custom tags which only need local information. For example,
+ a GraphViz custom tag renders graphs based on a description of the graph
+ inside the tag.
+* On save, the client sends its text back to the server, which de-transforms
+ custom tags which depend on information from other pages. If de-transforms
+ disagree with the provided text, then re-load the updated text after the
+ save is complete. For example, after inserting an auto-titled link, the
+ auto-titled text is missing; a save/reload fixes this.
### Page processing pipeline
On load:
-- Classify the file; input are mutable global state (which, if present,
- indicates this is a project build), if the file is a TOC, the file's binary
- data, and the file's path. Output of the classification: binary, raw text, a
- CodeChat document (a Markdown file), or a CodeChat file. The load processing
- pipelines For CodeChat files:
-- (CodeChat files only) Run pre-parse hooks: they receive source code, file
- metadata. Examples: code formatters. Skip if cache is up to date.
-- (CodeChat files only) Lex the file into code and doc blocks.
-- Run post-parse hooks: they receive an array of code and doc blocks.
- - Transform Markdown to HTML.
-- Run HTML hooks:
- - Update the cache for the current file only if the current file's cache is
- stale. To do this, walk the DOM of each doc block. The hook specifies which
- tags it wants, and the tree walker calls the hook when it encounters these.
- If this requires adding/changing anything (anchors, for example), mark the
- document as dirty.
- - Update tags whose contents depend on data from other files. Hooks work the
- same as the cache updates, but have a different role. They're always run,
- while the cache update is skipped when the cache is current.
-- Determine next/prev/up hyperlinks based on this file's location in the TOC.
-- Transform the code and doc blocks into CodeMirror's format.
+* Classify the file; input are mutable global state (which, if present,
+ indicates this is a project build), if the file is a TOC, the file's binary
+ data, and the file's path. Output of the classification: binary, raw text, a
+ CodeChat document (a Markdown file), or a CodeChat file. The load processing
+ pipelines For CodeChat files:
+* (CodeChat files only) Run pre-parse hooks: they receive source code, file
+ metadata. Examples: code formatters. Skip if cache is up to date.
+* (CodeChat files only) Lex the file into code and doc blocks.
+* Run post-parse hooks: they receive an array of code and doc blocks.
+ * Transform Markdown to HTML.
+* Run HTML hooks:
+ * Update the cache for the current file only if the current file's cache
+ is stale. To do this, walk the DOM of each doc block. The hook specifies
+ which tags it wants, and the tree walker calls the hook when it
+ encounters these. If this requires adding/changing anything (anchors,
+ for example), mark the document as dirty.
+ * Update tags whose contents depend on data from other files. Hooks work
+ the same as the cache updates, but have a different role. They're always
+ run, while the cache update is skipped when the cache is current.
+* Determine next/prev/up hyperlinks based on this file's location in the TOC.
+* Transform the code and doc blocks into CodeMirror's format.
We want a clean separate between the webserver and the processing pipeline. The
webserver should provide I/O between the local file system and the client, but
do little processing. The processing pipeline should not perform I/O. Therefore:
-- On load, the webserver receives a request for a file. It should gather and
- pass the following to the page processor:
- - The loaded file as text (or an Err result).
- - The global state (empty if this isn't a project build).
- - The pathname of the file.
- - If this file should be processed as a TOC or not.
-- The page processor returns:
- - An Enum with the file's contents:
+* On load, the webserver receives a request for a file. It should gather
+ and pass the following to the page processor:
+ * The loaded file as text (or an Err result).
+ * The global state (empty if this isn't a project build).
+ * The pathname of the file.
+ * If this file should be processed as a TOC or not.
+* The page processor returns:
+ * An Enum with the file's contents:
On save:
-- Transform the CodeMirror format back to code and doc blocks.
-- Run HTML hooks:
- - Update the cache for the current file. Mark the file as "dirty" (reload
- needed) if any changes are made.
- - Check tags whose contents depend on data from other files; if the contents
- differ, mark the file as dirty.
- - Transform HTML to Markdown.
-- Run post-parse hooks; mark the file as dirty if any changes are made.
-- De-lex the file into source code.
-- Run pre-parse hooks; mark the file as dirty if any changes are made.
-- Save the file to disk.
-- If dirty, re-load the file.
+* Transform the CodeMirror format back to code and doc blocks.
+* Run HTML hooks:
+ * Update the cache for the current file. Mark the file as "dirty" (reload
+ needed) if any changes are made.
+ * Check tags whose contents depend on data from other files; if the
+ contents differ, mark the file as dirty.
+ * Transform HTML to Markdown.
+* Run post-parse hooks; mark the file as dirty if any changes are made.
+* De-lex the file into source code.
+* Run pre-parse hooks; mark the file as dirty if any changes are made.
+* Save the file to disk.
+* If dirty, re-load the file.
#### HTML to Markdown transformation
Currently, Turndown translates HTML to Markdown, then Prettier word-wraps the
result. This has several problems:
-- There are several bugs/open issues in Turndown; however, this package is no
- longer maintained.
-- Turndown doesn't have a good way to deal with raw HTML intermingled with
- Markdown; since raw HTML can change the meaning of HTML through styles, this
- is hard to avoid. But it still produces ugly results.
-- Prettier translates setext-style headings to ATX headings, which I don't like.
-- Because both packages are written in Javascript, they run in the browser.
- However, we need to run processing at the HTML level on the server first,
- requiring some round trips between client and sever in the future.
+* There are several bugs/open issues in Turndown; however, this package is no
+ longer maintained.
+* Turndown doesn't have a good way to deal with raw HTML intermingled with
+ Markdown; since raw HTML can change the meaning of HTML through styles, this
+ is hard to avoid. But it still produces ugly results.
+* Prettier translates setext-style headings to ATX headings, which I don't
+ like.
+* Because both packages are written in Javascript, they run in the browser.
+ However, we need to run processing at the HTML level on the server first,
+ requiring some round trips between client and sever in the future.
To build Turndown, simply execute `npm run build` or `npm run test`.
@@ -139,27 +142,30 @@ editor-overlay filesystem.
#### Network interfaces between the Client, Server, and IDE
-- The startup phase loads the Client framework into a browser:\
- 
-- If the current file in the IDE changes (including the initial startup, when
- the change is from no file to the current file), or a link is followed in the
- Client's iframe:\
- 
-- If the current file's contents in the IDE are edited:\
- 
-- If the current file's contents in the Client are edited, the Client sends the
- IDE an `Update` with the revised contents.
-- When the PC goes to sleep then wakes up, the IDE client and the Editor client
- both reconnect to the websocket URL containing their assigned ID.
-- If the Editor client or the IDE client are closed, they close their websocket,
- which send a `Close` message to the other websocket, causes it to also close
- and ending the session.
-- If the server is stopped (or crashes), both clients shut down after several
- reconnect retries.
-
-Note: to edit these diagrams, paste the URL into the
-[PlantUML web server](https://www.plantuml.com/plantuml/uml), click Decode URL,
-edit, then copy and paste the SVG URL back to this file.
+* The startup phase loads the Client framework into a browser:\
+ 
+* If the current file in the IDE changes (including the initial startup, when
+ the change is from no file to the current file), or a link is followed in
+ the Client's iframe:\
+ 
+* If the current file's contents in the IDE are edited:\
+ 
+* If the current file's contents in the Client are edited, the Client sends
+ the IDE an `Update` with the revised contents.
+* When the PC goes to sleep then wakes up, the IDE client and the Editor
+ client both reconnect to the websocket URL containing their assigned ID.
+* If the Editor client or the IDE client are closed, they close their
+ websocket, which send a `Close` message to the other websocket, causes it to
+ also close and ending the session.
+* If the server is stopped (or crashes), both clients shut down after several
+ reconnect retries.
+
+Note: to edit these diagrams, paste the URL into the [PlantUML web
+server](https://www.plantuml.com/plantuml/uml), click Decode URL, edit, then
+copy and paste the SVG URL back to this file.
#### Message IDs
@@ -169,7 +175,8 @@ Response message in return. Therefore, we need globally unique IDs for each
message. To achieve this, the Server uses IDs that are multiples of 3 (0, 3, 6,
...), the Client multiples of 3 + 1 (1, 4, 7, ...) and the IDE multiples of 3 +
2 (2, 5, 8, ...). A double-precision floating point number (the standard
-[numeric type](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#number_type)
+[numeric
+type](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#number_type)
in JavaScript) has a 53-bit mantissa, meaning IDs won't wrap around for a very
long time.
@@ -181,19 +188,19 @@ activity from the core processing needed to translate source code between a
CodeChat Editor Client and an IDE client. Specifically, one task handles the
receive and transmit function for the websocket:
-- The task sends a periodic ping to the CodeChat Editor Client or the IDE
- client, then waits for a pong, closing the connection if the pong isn't
- received in a timely manner. This helps detect a broken websocket connection
- produced when a computer is put to sleep then wakes back up.
-- Likewise, the task responds to a ping message from the CodeChat Editor Client
- by sending a pong in response.
-- It tracks messages sent and produces an error message if a sent message isn't
- acknowledged within a timeout window.
-- If the websocket is closed without warning, the websocket stores the relevant
- data so that it can resume when the client reconnects to it.
-- If the websocket is closed purposefully (for example, by closing a CodeChat
- Editor Client tab in a web browser), the receive task detects this and shuts
- down the websocket along with the associated IDE client tasks.
+* The task sends a periodic ping to the CodeChat Editor Client or the IDE
+ client, then waits for a pong, closing the connection if the pong isn't
+ received in a timely manner. This helps detect a broken websocket connection
+ produced when a computer is put to sleep then wakes back up.
+* Likewise, the task responds to a ping message from the CodeChat Editor
+ Client by sending a pong in response.
+* It tracks messages sent and produces an error message if a sent message
+ isn't acknowledged within a timeout window.
+* If the websocket is closed without warning, the websocket stores the
+ relevant data so that it can resume when the client reconnects to it.
+* If the websocket is closed purposefully (for example, by closing a CodeChat
+ Editor Client tab in a web browser), the receive task detects this and shuts
+ down the websocket along with the associated IDE client tasks.
To decouple these low-level websocket details from high-level processing (such
as translating between source code and its web equivalent), the websocket tasks
@@ -201,7 +208,39 @@ enqueue all high-level messages to the processing task; they listen to any
enqueued messages in the client or ide queue, passing these on via the websocket
connection. The following diagram illustrates this approach:
-
+
The queues use multiple-sender, single receiver (mpsc) types; hence, a single
task in the diagram receives data from a queue, while multiple tasks send data
@@ -217,58 +256,67 @@ this specific request instance. The endpoint then returns the provided response.
Simplest non-IDE integration: the file watcher.
-- On startup, it sends the current file to the CodeChat Editor.
-- It uses a file watcher to send update commands when the current file changes.
-- It writes a file to disk when it receives an update command.
-- It closes the editor if the file is deleted or moved.
+* On startup, it sends the current file to the CodeChat Editor.
+* It uses a file watcher to send update commands when the current file
+ changes.
+* It writes a file to disk when it receives an update command.
+* It closes the editor if the file is deleted or moved.
Simplest IDE integration:
-- On startup, it sends the current file to the CodeChat Editor.
-- It sends update commands if edits are made in the IDE, when scrolling, or when
- the active editor changes.
-- It updates the IDE contents or opens a new file when it receives a update
- command.
+* On startup, it sends the current file to the CodeChat Editor.
+* It sends update commands if edits are made in the IDE, when scrolling, or
+ when the active editor changes.
+* It updates the IDE contents or opens a new file when it receives a update
+ command.
More complex IDE integration: everything that the simple IDE does, plus the
ability to toggle between the IDE's editor and the CodeChat Editor.
-## Build system
+Build system
+------------
The app needs build support because of complexity:
-- The client's NPM libraries need patching and some partial copying.
-- After building a release for a platform, client/server binaries must be copied
- to the VSCode extension, then a release published for that platform.
+* The client's NPM libraries need patching and some partial copying.
+* After building a release for a platform, client/server binaries must be
+ copied to the VSCode extension, then a release published for that platform.
So, this project contains Rust code to automate this process -- see the
[builder](../builder/Cargo.toml).
-## Future work
+Future work
+-----------
### Table of contents
-- While the TOC file must be placed in the root of the project, it will be
- served alongside pages served from subdirectories. Therefore, place this in an
- iframe to avoid regenerating it for every page.
-- The TOC is just HTML. Numbered sections are expressed as nested ordered lists,
- with links to each section inside these lists.
-- All numbering is stored internally as a number, instead of the corresponding
- marker (I, II, III, etc.). This allows styles to customize numbering easily.
- - Given an `a` element in the TOC, looking through its parents provides the
- section number. Given an array of section numbers, use CSS to style all the
- headings. Implement numbering using CSS variables, which makes it easy for a
- style sheet to include or exclude section numbers:
-
- `:root {`\
- `--section-counter-reset: s1 4 s2 5;`\
- `--section-counter-content: counter(s1, numeric) '-' counter(s2, numeric);`\
- `}`
-
- `h1::before {`\
- `counter-reset: var(--section-counter-reset);`\
- `content: var(--section-counter-content);`\
- `}`
+* While the TOC file must be placed in the root of the project, it will be
+ served alongside pages served from subdirectories. Therefore, place this in
+ an iframe to avoid regenerating it for every page.
+* The TOC is just HTML. Numbered sections are expressed as nested ordered
+ lists, with links to each section inside these lists.
+* All numbering is stored internally as a number, instead of the
+ corresponding marker (I, II, III, etc.). This allows styles to customize
+ numbering easily.
+ * Given an `a` element in the TOC, looking through its parents provides
+ the section number. Given an array of section numbers, use CSS to style
+ all the headings. Implement numbering using CSS variables, which makes
+ it easy for a style sheet to include or exclude section numbers:
+
+ `:root {`\
+
+ `--section-counter-reset: s1 4 s2 5;`\
+
+ `--section-counter-content: counter(s1, numeric) '-' counter(s2,
+ numeric);`\
+ `}`
+
+ `h1::before {`\
+
+ `counter-reset: var(--section-counter-reset);`\
+
+ `content: var(--section-counter-content);`\
+ `}`
### Cached state
@@ -279,39 +327,41 @@ server, all needed hydration data should be stored in the cache.
What we need to know:
-- To generate the TOC, we need a way to find the linked file, then get a list of
- all its headings.
- - Problem: files can be moved. Better would be an invariant anchor, stored in
- the file, which doesn't change. It would make sense to link to the only
- \ element...but there may not be one, or it may not be at the top of the
- file. The easy solution would be an anchor tag at the beginning of the
- file...but this would break shell scripts, for example. Another is including
- an anchor tag somewhere in each document, but need authors to understand
- what it is (and not delete it). Another possibility is to link to any anchor
- in the file with a special query identifying it as link to the underlying
- file.
-- To auto-title a link, need to look up an anchor and get its location (page
- number, section number) and title.
-- For back links, need to look up all links to the given anchor, then get the
- location and title of each link.
-- To generate the TOC containing all anchors, we need a list of all anchors on a
- given page.
+* To generate the TOC, we need a way to find the linked file, then get a
+ list of all its headings.
+ * Problem: files can be moved. Better would be an invariant anchor, stored
+ in the file, which doesn't change. It would make sense to link to the
+ only \ element...but there may not be one, or it may not be at the
+ top of the file. The easy solution would be an anchor tag at the
+ beginning of the file...but this would break shell scripts, for example.
+ Another is including an anchor tag somewhere in each document, but need
+ authors to understand what it is (and not delete it). Another
+ possibility is to link to any anchor in the file with a special query
+ identifying it as link to the underlying file.
+* To auto-title a link, need to look up an anchor and get its location (page
+ number, section number) and title.
+* For back links, need to look up all links to the given anchor, then get the
+ location and title of each link.
+* To generate the TOC containing all anchors, we need a list of all anchors on
+ a given page.
Therefore, the cache must contain a `FileAnchor`, an enum of:
-- A `PlainFileAnchor` (a non-HTML file -- an image, PDF, etc.). Generate an ID
- based on a checksum of the file. Basically, this provides some way to find the
- (unmodified) file if it's moved/renamed. Cache data: |path, ID, file's
- metadata|.
-- An `HtmlFileAnchor` (an HTML file). Store an ID as a comment in it somewhere,
- probably at the end of the file. Cache data: |path, ID, file's metadata|, TOC
- numbering, a vector of `HeadingAnchor`s, a vector of `NonHeadingAnchor`s:
- - A `HeadingAnchor` in an HTML file: |weak ref to the containing
- `HtmlFileAnchor`, ID, anchor's inner HTML, optional hyperlink|, numbering on
- this page, a vector of `NonHeadingAnchors` contained in this heading.
- - A `NonHeadingAnchor` in an HTML file: |weak ref to the containing
- `HtmlFileAnchor`, ID, anchor's inner HTML, optional hyperlink|, optional
- parent heading, snippet of surrounding text, numbering group, number.
+* A `PlainFileAnchor` (a non-HTML file -- an image, PDF, etc.). Generate an ID
+ based on a checksum of the file. Basically, this provides some way to find
+ the (unmodified) file if it's moved/renamed. Cache data: |path, ID, file's
+ metadata|.
+* An `HtmlFileAnchor` (an HTML file). Store an ID as a comment in it
+ somewhere, probably at the end of the file. Cache data: |path, ID,
+ file's metadata|, TOC numbering, a vector of `HeadingAnchor`s, a vector
+ of `NonHeadingAnchor`s:
+ * A `HeadingAnchor` in an HTML file: |weak ref to the containing
+ `HtmlFileAnchor`, ID, anchor's inner HTML, optional hyperlink|,
+ numbering on this page, a vector of `NonHeadingAnchors` contained in
+ this heading.
+ * A `NonHeadingAnchor` in an HTML file: |weak ref to the containing
+ `HtmlFileAnchor`, ID, anchor's inner HTML, optional hyperlink|, optional
+ parent heading, snippet of surrounding text, numbering group, number.
A `Hyperlink` consists of a path and ID the link refers to.\
An `HtmlAnchor` is an enum of `HeadingAnchor` and `NonHeadingAnchor`.\
@@ -319,8 +369,8 @@ An `Anchor` is an enum of a `FileAnchor` and an `HtmlAnchor`.
Globals:
-- A map of `PathBuf`s to `FileAnchors`.
-- A map of IDs to (`Anchor`, set of IDs of referring links)
+* A map of `PathBuf`s to `FileAnchors`.
+* A map of IDs to (`Anchor`, set of IDs of referring links)
How to keep the sets of referring links up to date? If a link is deleted, we
won't know until that file is removed. To fix, add a validate() function that
@@ -353,8 +403,8 @@ flush, simply set the date/time stamp of that file to something old/invalid.
Options:
-- Path to linked file
-- Depth of numbering
+* Path to linked file
+* Depth of numbering
#### Example
@@ -378,18 +428,18 @@ make it easy to add more config values. Settings should also be available for
plug-ins. Store the config values in a bare JSON file; provide a web-based GUI
with descriptions of each setting.
-- Files/directories to process/ignore
-- Header/footer info (name, version, copyright, etc.)
-- The programming language, markup language, and spellchecker language for each
- source file.
-- Text wrap width when saving.
-- Visual styling (theme/style sheets, color, fonts, size of TOC sidebar,
- location of sidebar, etc.).
-- HTML `` modifications: CSS/JS to add to all pages/a set of pages.
-- Depth of headings to include in the page-local TOC.
-- Auto-reload if modified externally or not
-- Tabs vs spaces; newline type
-- Substitutions
+* Files/directories to process/ignore
+* Header/footer info (name, version, copyright, etc.)
+* The programming language, markup language, and spellchecker language for
+ each source file.
+* Text wrap width when saving.
+* Visual styling (theme/style sheets, color, fonts, size of TOC sidebar,
+ location of sidebar, etc.).
+* HTML `` modifications: CSS/JS to add to all pages/a set of pages.
+* Depth of headings to include in the page-local TOC.
+* Auto-reload if modified externally or not
+* Tabs vs spaces; newline type
+* Substitutions
### Core development priorities
@@ -399,8 +449,8 @@ with descriptions of each setting.
### Next steps
1. Refactor the webserver to pull out the processing step (converting source
- code to code/doc blocks). Run this in a separate thread -- see the
- [Tokio docs](https://docs.rs/tokio/latest/tokio/#cpu-bound-tasks-and-blocking-code)
+ code to code/doc blocks). Run this in a separate thread -- see the [Tokio
+ docs](https://docs.rs/tokio/latest/tokio/#cpu-bound-tasks-and-blocking-code)
on how to await a task running in another thread.
2. Implement caching for all anchors/headings.
3. Implement author support: TOC, auto-titled links.
@@ -420,27 +470,29 @@ with descriptions of each setting.
### Open questions
-- I'd like to be able to wrap a heading and associated content in a ``
- tag. This is hard to do -- if a heading appears in the middle of an indented
- comment, then need special processing (close the section, then the indent,
- then restart a new indent and section). In addition, it requires that code is
- nested inside doc blocks, which is tricky. However, I would like to do this.
-- How to handle images/videos/PDFs/etc. when file are moved? Currently, we
- expect the user to move them as well. There's not an easy way to tag them with
- an unique ID, then refer to them using that ID than I can think of.
-- Config file format: I really like and prefer Python's strictyaml. Basically, I
- want something that includes type validation and allows comments within the
- config file. Perhaps JSON with a pre-parse step to discard comments then
- [JSON Typedef](https://jsontypedef.com/)? Possibly, vlang can do this
- somewhat, since it wants to decode JSON into a V struct.)
-
-## Organization
+* I'd like to be able to wrap a heading and associated content in a
+ `` tag. This is hard to do -- if a heading appears in the middle of
+ an indented comment, then need special processing (close the section, then
+ the indent, then restart a new indent and section). In addition, it requires
+ that code is nested inside doc blocks, which is tricky. However, I would
+ like to do this.
+* How to handle images/videos/PDFs/etc. when file are moved? Currently, we
+ expect the user to move them as well. There's not an easy way to tag them
+ with an unique ID, then refer to them using that ID than I can think of.
+* Config file format: I really like and prefer Python's strictyaml. Basically,
+ I want something that includes type validation and allows comments within
+ the config file. Perhaps JSON with a pre-parse step to discard comments then
+ [JSON Typedef](https://jsontypedef.com/)? Possibly, vlang can do this
+ somewhat, since it wants to decode JSON into a V struct.)
+
+Organization
+------------
### Client
As shown in the figure below, the CodeChat Editor Client starts with
`client/package.json`, which tells
-[NPM]() which JavaScript libraries
+[NPM](https://en.wikipedia.org/wiki/Npm_\(software\)) which JavaScript libraries
are used in this project. Running `npm update` copies these libraries and all
their dependencies to the `client/node_modules` directory. The CodeChat Editor
Client source code (see [CodeChatEditor.mts](../client/src/CodeChatEditor.mts))
@@ -453,28 +505,68 @@ a smaller set of files. At a user's request, the CodeChat Editor Server
generates HTML which creates an editor around the user-requested file. This HTML
loads the packaged dependencies to create the CodeChat Editor Client webpage.
-
-
-Note: to edit these diagrams, use an
-[HTML entity encoder/decoder](https://mothereff.in/html-entities) and a Graphviz
-editor such as [Edotor](https://edotor.net/).
+
+
+Note: to edit these diagrams, use an [HTML entity
+encoder/decoder](https://mothereff.in/html-entities) and a Graphviz editor such
+as [Edotor](https://edotor.net/).
However, esbuild's code splitting doesn't work with dynamic imports -- the
splitter always picks Node-style default imports, while the Ace editor expects
Babel-style imports.
-TODO: GUIs using TinyMCE. See the
-[how-to guide](https://www.tiny.cloud/docs/tinymce/6/dialog-components/#panel-components).
+TODO: GUIs using TinyMCE. See the [how-to
+guide](https://www.tiny.cloud/docs/tinymce/6/dialog-components/#panel-components).
### System architecture
-
-
-## Code style
+
+
+Code style
+----------
JavaScript functions are a
[disaster](https://dmitripavlutin.com/differences-between-arrow-and-regular-functions/).
Therefore, we use only arrow functions for this codebase.
-Other than that, follow the
-[MDN style guide](https://developer.mozilla.org/en-US/docs/MDN/Writing_guidelines/Writing_style_guide/Code_style_guide/JavaScript).
+Other than that, follow the [MDN style
+guide](https://developer.mozilla.org/en-US/docs/MDN/Writing_guidelines/Writing_style_guide/Code_style_guide/JavaScript).
\ No newline at end of file
diff --git a/docs/style_guide.cpp b/docs/style_guide.cpp
index 6b443874..9a423549 100644
--- a/docs/style_guide.cpp
+++ b/docs/style_guide.cpp
@@ -1,4 +1,5 @@
-// # `style_guide.cpp` - Literate programming using the CodeChat Editor
+// `style_guide.cpp` - Literate programming using the CodeChat Editor
+// ==================================================================
//
// This document, written as a C++ source file, primarily demonstrates the use
// of the CodeChat Editor in literate programming. It should be viewed using the
@@ -20,7 +21,8 @@
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
-// ## Introduction
+// Introduction
+// ------------
//
// This document provides a style guide for literate programming using the
// CodeChat Editor. For basic use, see the [user manual](../README.md).
@@ -39,12 +41,13 @@ const char* CODE_BLOCK =
// doc blocks with differing indents cannot be combined.
/* Doc blocks may use either inline comments (`//` in C++) or block comments
(like this comment). Doc blocks with differing delimiters cannot be combined. */
-// Doc blocks are interpreted using Markdown
-// (specifically, [CommonMark](https://commonmark.org/)), enabling the use of
-// headings, _emphasis_, **strong emphasis**, `monospaced fonts`, and much more;
-// see a [brief overview of Markdown](https://commonmark.org/help/).
+// Doc blocks are interpreted using Markdown (specifically,
+// [CommonMark](https://commonmark.org/)), enabling the use of headings,
+// *emphasis*, **strong emphasis**, `monospaced fonts`, and much more; see a
+// [brief overview of Markdown](https://commonmark.org/help/).
//
-// ## Approach
+// Approach
+// --------
//
// Viewing a program as a document defines the heart of the literate programming
// paradigm. A program/document -- constructed as a series of code blocks and
@@ -70,23 +73,24 @@ const char* CODE_BLOCK =
// sense? Update your overall approach based on what you discover. Get another
// person to review what you wrote, then implement their ideas and suggestions.
//
-// ## Organization
+// Organization
+// -------------------------------------
//
// The program should use headings to appropriately organize the contents. Near
// the top of the file, include a single level-1 heading, providing the title of
-// the file; per the HTML spec, there should be
-// [only one level-1 heading](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Heading_Elements#avoid_using_multiple_h1_elements_on_one_page).
+// the file; per the HTML spec, there should be [only one level-1
+// heading](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Heading_Elements#avoid_using_multiple_h1_elements_on_one_page).
// For source files, include the file name at the beginning of the title, in a
// monospaced font.
//
-// Following the title, include additional heading levels;
-// [don't skip levels](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Heading_Elements#navigation),
+// Following the title, include additional heading levels; [don't skip
+// levels](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Heading_Elements#navigation),
// e.g. by placing a level-3 heading immediately following a level-1 heading.
-// Use headings to provide a natural outline of your program. The
-// [end of this document](#org-style) provides the recommended organizational
-// style.
+// Use headings to provide a natural outline of your program. The [end of this
+// document](#org-style) provides the recommended organizational style.
//
-// ## Location
+// Location
+// --------
//
// In general, place documentation before the corresponding code. For example:
//
@@ -105,7 +109,8 @@ class LedBlinker {
);
};
-// ## Use of mathematics
+// Use of mathematics
+// ------------------
//
// Formulas should be placed near code that implements them, along with good
// explanations of the equations used. For example:
@@ -120,17 +125,18 @@ double accurate_g(
// Height above sea level, in meters.
double height_meters
) {
- // This text comes from the
- // [SensorsOne Local Gravity Calculator](https://www.sensorsone.com/local-gravity-calculator/).
- // For more detail, see
- // [Theoretical Gravity](https://en.wikipedia.org/wiki/Theoretical_gravity).
+ // This text comes from the [SensorsOne Local Gravity
+ // Calculator](https://www.sensorsone.com/local-gravity-calculator/). For
+ // more detail, see [Theoretical
+ // Gravity](https://en.wikipedia.org/wiki/Theoretical_gravity).
//
- // The formulas used by this function are based on
- // the [International Gravity Formula IGF) 1980](https://en.wikipedia.org/wiki/Normal_gravity_formula#International_gravity_formula_1980) from
- // the parameters of
- // the [Geodetic Reference System 1980 (GRS80)](https://en.wikipedia.org/wiki/GRS_80),
- // which determines the gravity from the position of latitude, and
- // the [Free Air Correction (FAC)](https://en.wikipedia.org/wiki/Gravity_of_Earth#Free_air_correction)
+ // The formulas used by this function are based on the [International
+ // Gravity Formula IGF)
+ // 1980](https://en.wikipedia.org/wiki/Normal_gravity_formula#International_gravity_formula_1980)
+ // from the parameters of the [Geodetic Reference System 1980
+ // (GRS80)](https://en.wikipedia.org/wiki/GRS_80), which determines the
+ // gravity from the position of latitude, and the [Free Air Correction
+ // (FAC)](https://en.wikipedia.org/wiki/Gravity_of_Earth#Free_air_correction)
// which corrects for height above and below mean sea level in free air.
//
// Compute the International Gravity Formula (IGF):\
@@ -146,67 +152,70 @@ double accurate_g(
return IGF + FAC;
// Symbols:
//
- // - $g$ = Theoretical local gravity, in $m/s^2$.
- // - $\\phi$ = Latitude, in decimal degrees.
- // - $h$ = Height relative to sea level, in $m$.
+ // * $g$ = Theoretical local gravity, in $m/s^2$.
+ // * $\\phi$ = Latitude, in decimal degrees.
+ // * $h$ = Height relative to sea level, in $m$.
}
-// ## Excellence in code
+// Excellence in code
+// ------------------
//
// Literate programming should be accompanied by excellence in authoring code.
// Specifically:
//
-// - Use meaningful, descriptive names for variables, classes, functions, etc.
-// Doc blocks should only supply what
-// [self-documenting code](https://en.wikipedia.org/wiki/Self-documenting_code)
-// cannot -- design choices, purpose, etc.
-// - Be consistent; preferably, use a
-// [code formatter](https://en.wikipedia.org/wiki/Prettyprint#Programming_code_formatting)
-// to ensure this consistency.
-// - Employ [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)
-// principles.
-// - Address warnings, not only errors; preferably, use
-// a [linter]().
-// - Write automated tests; employ
-// [test-driven development](https://en.wikipedia.org/wiki/Test-driven_development).
-//
-// ## Editor configuration
+// * Use meaningful, descriptive names for variables, classes, functions, etc.
+// Doc blocks should only supply what [self-documenting
+// code](https://en.wikipedia.org/wiki/Self-documenting_code) cannot --
+// design choices, purpose, etc.
+// * Be consistent; preferably, use a [code
+// formatter](https://en.wikipedia.org/wiki/Prettyprint#Programming_code_formatting)
+// to ensure this consistency.
+// * Employ [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)
+// principles.
+// * Address warnings, not only errors; preferably, use a
+// [linter](https://en.wikipedia.org/wiki/Lint_\(software\)).
+// * Write automated tests; employ [test-driven
+// development](https://en.wikipedia.org/wiki/Test-driven_development).
+//
+// Editor configuration
+// --------------------
//
// 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)
-// - 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 a big monitor, place your IDE side by side with the CodeChat Editor.
-//
-// ## Common problems
-//
-// - Don't drag and drop an image into the Editor – this creates a mess.
-// Instead, save all images to a file, then use an SVG or PNG image for
-// text/line art or a JPEG image for photos. The Markdown syntax to insert
-// an image is ``.
-// - Indent your comments to match the indentation of nearby code; don't
-// purposelessly vary the comment indentation.
-// - Avoid inserting a one-line empty code block (a blank line) between
-// paragraphs in a doc block; instead, use a single doc block to store
-// multiple paragraphs.
-// - Use minimal formatting. Markdown is a simple, rather limited syntax;
-// however, it is very easy to use and read. While the CodeChat Editor will
-// happily replace simple Markdown constructs with verbose HTML to accomplish
-// the formatting you specify, avoid the resulting
-// messy syntax produced by this process.
-// Pasting from an HTML source (such as Word or a web page) directly to the
-// CodeChat Editor likewise produces a lot of messy syntax; consider pasting
-// text only, then reformatting as necessary.
+// * 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 a big monitor, place your IDE side by side with the CodeChat Editor.
+//
+// Common problems
+// ---------------
+//
+// * Don't drag and drop an image into the Editor – this creates a mess.
+// Instead, save all images to a file, then use an SVG or PNG image for
+// text/line art or a JPEG image for photos. The Markdown syntax to insert
+// an image is ``.
+// * Indent your comments to match the indentation of nearby code; don't
+// purposelessly vary the comment indentation.
+// * Avoid inserting a one-line empty code block (a blank line) between
+// paragraphs in a doc block; instead, use a single doc block to store
+// multiple paragraphs.
+// * Use minimal formatting. Markdown is a simple, rather limited syntax;
+// however, it is very easy to use and read. While the CodeChat Editor will
+// happily replace simple Markdown constructs with verbose HTML to
+// accomplish the formatting you specify, avoid the resulting messy syntax produced by this process.
+// Pasting from an HTML source (such as Word or a web page) directly to the
+// CodeChat Editor likewise produces a lot of messy syntax; consider pasting
+// text only, then reformatting as necessary.
//
// ### Commenting out code
//
@@ -220,16 +229,18 @@ double accurate_g(
// improved alternative to commenting out code using preprocessor directives for
// C/C++.
//
-// ## Example structure
+// Example structure
+// -----------------
//
// As discussed in [organization](#organization), the remainder of this document
// presents the preferred use of headings to organize source code.
//
-// ## Includes
+// Includes
+// ------------------------------
//
// Include files (in Python, imports; Rust, use statements; JavaScript,
-// require/import, etc.) should be organized by category; for example,
-// [PEP 8](https://peps.python.org/pep-0008/#imports) recommends the following
+// require/import, etc.) should be organized by category; for example, [PEP
+// 8](https://peps.python.org/pep-0008/#imports) recommends the following
// categories:
//
// ### Standard library
@@ -244,20 +255,24 @@ double accurate_g(
// Note: This is a fictitious file, here for example only.
#include
-// ## Global variables/constants
+// Global variables/constants
+// --------------------------
//
// Use units when describing physical quantities. For example, this gives the
// acceleration due to gravity in $m/s^2$.
const double accel_m_s2 = 9.8067;
-// ## Macros
+// Macros
+// ------
#define LED1 (LATB16)
-// ## Structures/classes
+// Structures/classes
+// ------------------
class BlinkLed {
};
-// ## Code
+// Code
+// ----
int main(int argc, char* argv[]) {
// Here's an example of commenting code out when using the CodeChat Editor:
/**
diff --git a/extensions/VSCode/.eslintrc.yml b/extensions/VSCode/.eslintrc.yml
index 45b12690..f2853c81 100644
--- a/extensions/VSCode/.eslintrc.yml
+++ b/extensions/VSCode/.eslintrc.yml
@@ -16,16 +16,17 @@
# the CodeChat Editor. If not, see
# [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
#
-# # `.eslintrc.yml` - Configure ESLint for this project
+# `.eslintrc.yml` - Configure ESLint for this project
+# ===================================================
env:
commonjs: true
node: true
extends:
- standard
- # See the
- # [ESLint config prettier docs](https://github.com/prettier/eslint-config-prettier#installation)
- # and its parent link,
- # [integrating Prettier with linters](https://prettier.io/docs/en/integrating-with-linters.html).
+ # See the [ESLint config prettier
+ # docs](https://github.com/prettier/eslint-config-prettier#installation) and
+ # its parent link, [integrating Prettier with
+ # linters](https://prettier.io/docs/en/integrating-with-linters.html).
- prettier
parser: "@typescript-eslint/parser"
parserOptions:
@@ -35,6 +36,6 @@ plugins:
rules:
camelcase: off
# TypeScript already enforces this; otherwise, eslint complains that
- # `NodeJS` is undefined. See
- # [this GitHub issue](https://github.com/Chatie/eslint-config/issues/45#issuecomment-1003990077).
+ # `NodeJS` is undefined. See [this GitHub
+ # issue](https://github.com/Chatie/eslint-config/issues/45#issuecomment-1003990077).
no-undef: off
diff --git a/extensions/VSCode/.gitignore b/extensions/VSCode/.gitignore
index cfa81522..acdac515 100644
--- a/extensions/VSCode/.gitignore
+++ b/extensions/VSCode/.gitignore
@@ -16,7 +16,8 @@
# the CodeChat Editor. If not, see
# [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
#
-# # `.gitignore` -- files for Git to ignore
+# `.gitignore` -- files for Git to ignore
+# =======================================
#
# NPM
node_modules/
diff --git a/extensions/VSCode/.vscodeignore b/extensions/VSCode/.vscodeignore
index 5b08932e..8af78d46 100644
--- a/extensions/VSCode/.vscodeignore
+++ b/extensions/VSCode/.vscodeignore
@@ -16,8 +16,11 @@
# the CodeChat Editor. If not, see
# [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
#
-# # `vscodeignore` - Files not to package
-# See https://code.visualstudio.com/api/working-with-extensions/publishing-extension#.vscodeignore.
+# `vscodeignore` - Files not to package
+# =====================================
+#
+# See
+# [Using .vscodeignore](https://code.visualstudio.com/api/working-with-extensions/publishing-extension#using-.vscodeignore).
#
# Omit all TypeScript source.
src/**
@@ -25,7 +28,8 @@ src/**
# Omit VSCode config.
.vscode/**
-# Omit target-specific binaries. (Comment out when publishing for a specific target.)
+# Omit target-specific binaries. (Comment out when publishing for a specific
+# target.)
#server/**
# Misc files not needed in a package.
diff --git a/extensions/VSCode/README.md b/extensions/VSCode/README.md
index c74e91cd..9141ccd5 100644
--- a/extensions/VSCode/README.md
+++ b/extensions/VSCode/README.md
@@ -1,26 +1,32 @@
-# The CodeChat Editor extension for Visual Studio Code
+The CodeChat Editor extension for Visual Studio Code
+====================================================
This extension provides the CodeChat Editor's capabilities within the Visual
Studio Code IDE.
-
+
-## Installation
+Installation
+------------
First, install [Visual Studio Code](https://code.visualstudio.com/). Next:
-1. [Install the CodeChat Editor extension](https://marketplace.visualstudio.com/items?itemName=CodeChat.codechat-editor-client).
-2. (Recommended)
- [switch to a light theme](https://code.visualstudio.com/docs/getstarted/themes),
- since the CodeChat Editor only provides a light theme.
+1. [Install the CodeChat Editor
+ extension](https://marketplace.visualstudio.com/items?itemName=CodeChat.codechat-editor-client).
+2. (Recommended) [switch to a light
+ theme](https://code.visualstudio.com/docs/getstarted/themes), since the
+ CodeChat Editor only provides a light theme.
-## Running
+Running
+-------
1. Open a file that the CodeChat Editor
[supports](https://github.com/bjones1/CodeChat_Editor/blob/main/README.md#supported-languages)
(many source files, along with Markdown files).
-2. Open the
- [Visual Studio Code command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette)
+
+2. Open the [Visual Studio Code command
+ palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette)
by pressing `Ctrl+Shift+P`. Type `CodeChat`, select "Enable the CodeChat
Editor", then press enter to run the extension. After a moment, the rendered
file should load. If it doesn't:
@@ -32,7 +38,8 @@ First, install [Visual Studio Code](https://code.visualstudio.com/). Next:
2. Run the extension again (close the existing window, type `Ctrl+Shift+P`
then select Enable the CodeChat Editor).
-## Additional documentation
+Additional documentation
+------------------------
-See the
-[user manual](https://github.com/bjones1/CodeChat_Editor/blob/main/README.md).
+See the [user
+manual](https://github.com/bjones1/CodeChat_Editor/blob/main/README.md).
\ No newline at end of file
diff --git a/extensions/VSCode/developer.md b/extensions/VSCode/developer.md
index 7c00aa17..f0412d46 100644
--- a/extensions/VSCode/developer.md
+++ b/extensions/VSCode/developer.md
@@ -1,42 +1,49 @@
-# Developer documentation
+Developer documentation
+=======================
-## From source
+From source
+-----------
To install from source:
-- Install [npm](https://nodejs.org/en/).
-- Install this extension's manifest
- ([package.json](https://code.visualstudio.com/api/references/extension-manifest)):
- from this directory, open a command prompt/terminal then execute::
-
- ```
- npm install
- ```
-
-## Debugging the extension
-
-- From VSCode, select File | Add Folder to Workspace... then choose the folder
- containing this file.
-- Press ctrl+shift+B to compile the extension.
-- Press F5 or click start debugging under the Debug menu.
-- A new instance of VSCode will start in a special mode (Extension Development
- Host) which contains the CodeChat extension.
-- Open any source code, then press Ctrl+Shift+P and type "CodeChat" to run the
- CodeChat extension. You will be able to see the rendered version of your
- active window.
-
-## Release procedure
-
-- In the Client:
- - Update the version of the plugin in `package.json`.
-- In the Server:
- - Update the version in `cargo.toml`.
-- Here:
- - Update the version of the plugin in `package.json`.
- - Run `cargo run -- release` on each platform, which produces a `.vsix` file for that platform
- - Run `npx vsce publish --packagePath blah`.
- ([docs](https://code.visualstudio.com/api/working-with-extensions/publishing-extension#platformspecific-extensions))
-
-## Tests
-
-TODO: tests are missing.
+* Install [npm](https://nodejs.org/en/).
+
+* Install this extension's manifest
+ ([package.json](https://code.visualstudio.com/api/references/extension-manifest)):
+ from this directory, open a command prompt/terminal then execute::
+
+ ```
+ npm install
+ ```
+
+Debugging the extension
+-----------------------
+
+* From VSCode, select File | Add Folder to Workspace... then choose the folder
+ containing this file.
+* Press ctrl+shift+B to compile the extension.
+* Press F5 or click start debugging under the Debug menu.
+* A new instance of VSCode will start in a special mode (Extension Development
+ Host) which contains the CodeChat extension.
+* Open any source code, then press Ctrl+Shift+P and type "CodeChat" to run the
+ CodeChat extension. You will be able to see the rendered version of your
+ active window.
+
+Release procedure
+-----------------
+
+* In the Client:
+ * Update the version of the plugin in `package.json`.
+* In the Server:
+ * Update the version in `cargo.toml`.
+* Here:
+ * Update the version of the plugin in `package.json`.
+ * Run `cargo run -- release` on each platform, which produces a `.vsix`
+ file for that platform
+ * Run `npx vsce publish --packagePath blah`.
+ ([docs](https://code.visualstudio.com/api/working-with-extensions/publishing-extension#platformspecific-extensions))
+
+Tests
+-----
+
+TODO: tests are missing.
\ No newline at end of file
diff --git a/extensions/VSCode/jsconfig.json b/extensions/VSCode/jsconfig.json
index b06629a3..09fe5253 100644
--- a/extensions/VSCode/jsconfig.json
+++ b/extensions/VSCode/jsconfig.json
@@ -14,12 +14,14 @@
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
-// `jsconfig.json` is a configuration file that controls the behavior of ???
+// `jsconfig.json` -- JavaScript configuration
+// ===========================================
{
"compilerOptions": {
"module": "NodeNext",
"target": "es6",
- "checkJs": true, /* Typecheck .js files. */
+ // Typecheck `.js` files.
+ "checkJs": true,
"lib": [
"es6"
]
diff --git a/extensions/VSCode/package-lock.json b/extensions/VSCode/package-lock.json
index dc1fb8f8..6351b240 100644
--- a/extensions/VSCode/package-lock.json
+++ b/extensions/VSCode/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "codechat-editor-client",
- "version": "0.1.9",
+ "version": "0.1.10",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "codechat-editor-client",
- "version": "0.1.9",
+ "version": "0.1.10",
"license": "GPL-3.0-only",
"dependencies": {
"escape-html": "^1",
@@ -81,9 +81,9 @@
}
},
"node_modules/@azure/core-rest-pipeline": {
- "version": "1.18.2",
- "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.18.2.tgz",
- "integrity": "sha512-IkTf/DWKyCklEtN/WYW3lqEsIaUDshlzWRlZNNwSYtFcCBQz++OtOjxNpm8rr1VcbMS6RpjybQa3u6B6nG0zNw==",
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.19.0.tgz",
+ "integrity": "sha512-bM3308LRyg5g7r3Twprtqww0R/r7+GyVxj4BafcmVPo4WQoGt5JXuaqxHEFjw2o3rvFZcUPiqJMg6WuvEEeVUA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -128,9 +128,9 @@
}
},
"node_modules/@azure/identity": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.6.0.tgz",
- "integrity": "sha512-ANpO1iAvcZmpD4QY7/kaE/P2n66pRXsDp3nMUC6Ow3c9KfXOZF7qMU9VgqPw8m7adP7TVIbVyrCEmD9cth3KQQ==",
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.7.0.tgz",
+ "integrity": "sha512-6z/S2KorkbKaZ0DgZFVRdu7RCuATmMSTjKpuhj7YpjxkJ0vnJ7kTM3cpNgzFgk9OPYfZ31wrBEtC/iwAS4jQDA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -141,11 +141,11 @@
"@azure/core-tracing": "^1.0.0",
"@azure/core-util": "^1.11.0",
"@azure/logger": "^1.0.0",
- "@azure/msal-browser": "^4.0.1",
- "@azure/msal-node": "^2.15.0",
+ "@azure/msal-browser": "^4.2.0",
+ "@azure/msal-node": "^3.2.1",
"events": "^3.0.0",
"jws": "^4.0.0",
- "open": "^8.0.0",
+ "open": "^10.1.0",
"stoppable": "^1.1.0",
"tslib": "^2.2.0"
},
@@ -167,22 +167,22 @@
}
},
"node_modules/@azure/msal-browser": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-4.0.1.tgz",
- "integrity": "sha512-jqiwVJPArnEOUhmc+dvo481OP8b2PMcsu3EtGtxt7sxmKgFtdQyGDCndj+2me62JVG/HEgArEgKyMA7L0aNhdA==",
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-4.4.0.tgz",
+ "integrity": "sha512-rU6juYXk67CKQmpgi6fDgZoPQ9InZ1760z1BSAH7RbeIc4lHZM/Tu+H0CyRk7cnrfvTkexyYE4pjYhMghpzheA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@azure/msal-common": "15.0.1"
+ "@azure/msal-common": "15.2.0"
},
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/@azure/msal-common": {
- "version": "15.0.1",
- "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-15.0.1.tgz",
- "integrity": "sha512-JELxEK3Pnc4Rq8u+mI9u6o37auSpSOPCB7jaq7QziOAKi9WliWEmZZORCFHPbwf2xKitpHBXTz/0uerj17NsSQ==",
+ "version": "15.2.0",
+ "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-15.2.0.tgz",
+ "integrity": "sha512-HiYfGAKthisUYqHG1nImCf/uzcyS31wng3o+CycWLIM9chnYJ9Lk6jZ30Y6YiYYpTQ9+z/FGUpiKKekd3Arc0A==",
"dev": true,
"license": "MIT",
"engines": {
@@ -190,13 +190,13 @@
}
},
"node_modules/@azure/msal-node": {
- "version": "2.16.2",
- "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.16.2.tgz",
- "integrity": "sha512-An7l1hEr0w1HMMh1LU+rtDtqL7/jw74ORlc9Wnh06v7TU/xpG39/Zdr1ZJu3QpjUfKJ+E0/OXMW8DRSWTlh7qQ==",
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-3.2.3.tgz",
+ "integrity": "sha512-0eaPqBIWEAizeYiXdeHb09Iq0tvHJ17ztvNEaLdr/KcJJhJxbpkkEQf09DB+vKlFE0tzYi7j4rYLTXtES/InEQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@azure/msal-common": "14.16.0",
+ "@azure/msal-common": "15.2.0",
"jsonwebtoken": "^9.0.0",
"uuid": "^8.3.0"
},
@@ -204,16 +204,6 @@
"node": ">=16"
}
},
- "node_modules/@azure/msal-node/node_modules/@azure/msal-common": {
- "version": "14.16.0",
- "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.16.0.tgz",
- "integrity": "sha512-1KOZj9IpcDSwpNiQNjt0jDYZpQvNZay7QAEi/5DLubay40iGYtLzya/jbjRPLyOTZhEKyL1MzPuw2HqBCjceYA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.8.0"
- }
- },
"node_modules/@eslint-community/eslint-utils": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
@@ -244,13 +234,13 @@
}
},
"node_modules/@eslint/config-array": {
- "version": "0.19.1",
- "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz",
- "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==",
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz",
+ "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/object-schema": "^2.1.5",
+ "@eslint/object-schema": "^2.1.6",
"debug": "^4.3.1",
"minimatch": "^3.1.2"
},
@@ -283,9 +273,9 @@
}
},
"node_modules/@eslint/core": {
- "version": "0.10.0",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz",
- "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==",
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.11.0.tgz",
+ "integrity": "sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -344,9 +334,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.18.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.18.0.tgz",
- "integrity": "sha512-fK6L7rxcq6/z+AaQMtiFTkvbHkBLNlwyRxHpKawP0x3u9+NC6MQTnFW+AdpwC6gfHTW0051cokQgtTN2FqlxQA==",
+ "version": "9.20.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.20.0.tgz",
+ "integrity": "sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -354,9 +344,9 @@
}
},
"node_modules/@eslint/object-schema": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz",
- "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==",
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
+ "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -364,13 +354,13 @@
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz",
- "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==",
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.6.tgz",
+ "integrity": "sha512-+0TjwR1eAUdZtvv/ir1mGX+v0tUoR3VEPB8Up0LLJC+whRW0GgBBtpbOkg/a/U4Dxa6l5a3l9AJ1aWIQVyoWJA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/core": "^0.10.0",
+ "@eslint/core": "^0.11.0",
"levn": "^0.4.1"
},
"engines": {
@@ -430,9 +420,9 @@
}
},
"node_modules/@humanwhocodes/retry": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz",
- "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==",
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz",
+ "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -535,9 +525,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "22.10.7",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.7.tgz",
- "integrity": "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==",
+ "version": "22.13.4",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.4.tgz",
+ "integrity": "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -545,16 +535,16 @@
}
},
"node_modules/@types/vscode": {
- "version": "1.96.0",
- "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.96.0.tgz",
- "integrity": "sha512-qvZbSZo+K4ZYmmDuaodMbAa67Pl6VDQzLKFka6rq+3WUTY4Kro7Bwoi0CuZLO/wema0ygcmpwow7zZfPJTs5jg==",
+ "version": "1.97.0",
+ "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.97.0.tgz",
+ "integrity": "sha512-ueE73loeOTe7olaVyqP9mrRI54kVPJifUPjblZo9fYcv1CuVLPOEKEkqW0GkqPC454+nCEoigLWnC2Pp7prZ9w==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/ws": {
- "version": "8.5.13",
- "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz",
- "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==",
+ "version": "8.5.14",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.14.tgz",
+ "integrity": "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -562,21 +552,21 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.21.0.tgz",
- "integrity": "sha512-eTH+UOR4I7WbdQnG4Z48ebIA6Bgi7WO8HvFEneeYBxG8qCOYgTOFPSg6ek9ITIDvGjDQzWHcoWHCDO2biByNzA==",
+ "version": "8.24.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.24.1.tgz",
+ "integrity": "sha512-ll1StnKtBigWIGqvYDVuDmXJHVH4zLVot1yQ4fJtLpL7qacwkxJc1T0bptqw+miBQ/QfUbhl1TcQ4accW5KUyA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "8.21.0",
- "@typescript-eslint/type-utils": "8.21.0",
- "@typescript-eslint/utils": "8.21.0",
- "@typescript-eslint/visitor-keys": "8.21.0",
+ "@typescript-eslint/scope-manager": "8.24.1",
+ "@typescript-eslint/type-utils": "8.24.1",
+ "@typescript-eslint/utils": "8.24.1",
+ "@typescript-eslint/visitor-keys": "8.24.1",
"graphemer": "^1.4.0",
"ignore": "^5.3.1",
"natural-compare": "^1.4.0",
- "ts-api-utils": "^2.0.0"
+ "ts-api-utils": "^2.0.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -592,16 +582,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.21.0.tgz",
- "integrity": "sha512-Wy+/sdEH9kI3w9civgACwabHbKl+qIOu0uFZ9IMKzX3Jpv9og0ZBJrZExGrPpFAY7rWsXuxs5e7CPPP17A4eYA==",
+ "version": "8.24.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.24.1.tgz",
+ "integrity": "sha512-Tqoa05bu+t5s8CTZFaGpCH2ub3QeT9YDkXbPd3uQ4SfsLoh1/vv2GEYAioPoxCWJJNsenXlC88tRjwoHNts1oQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/scope-manager": "8.21.0",
- "@typescript-eslint/types": "8.21.0",
- "@typescript-eslint/typescript-estree": "8.21.0",
- "@typescript-eslint/visitor-keys": "8.21.0",
+ "@typescript-eslint/scope-manager": "8.24.1",
+ "@typescript-eslint/types": "8.24.1",
+ "@typescript-eslint/typescript-estree": "8.24.1",
+ "@typescript-eslint/visitor-keys": "8.24.1",
"debug": "^4.3.4"
},
"engines": {
@@ -617,14 +607,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.21.0.tgz",
- "integrity": "sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA==",
+ "version": "8.24.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.24.1.tgz",
+ "integrity": "sha512-OdQr6BNBzwRjNEXMQyaGyZzgg7wzjYKfX2ZBV3E04hUCBDv3GQCHiz9RpqdUIiVrMgJGkXm3tcEh4vFSHreS2Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.21.0",
- "@typescript-eslint/visitor-keys": "8.21.0"
+ "@typescript-eslint/types": "8.24.1",
+ "@typescript-eslint/visitor-keys": "8.24.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -635,16 +625,16 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.21.0.tgz",
- "integrity": "sha512-95OsL6J2BtzoBxHicoXHxgk3z+9P3BEcQTpBKriqiYzLKnM2DeSqs+sndMKdamU8FosiadQFT3D+BSL9EKnAJQ==",
+ "version": "8.24.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.24.1.tgz",
+ "integrity": "sha512-/Do9fmNgCsQ+K4rCz0STI7lYB4phTtEXqqCAs3gZW0pnK7lWNkvWd5iW545GSmApm4AzmQXmSqXPO565B4WVrw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/typescript-estree": "8.21.0",
- "@typescript-eslint/utils": "8.21.0",
+ "@typescript-eslint/typescript-estree": "8.24.1",
+ "@typescript-eslint/utils": "8.24.1",
"debug": "^4.3.4",
- "ts-api-utils": "^2.0.0"
+ "ts-api-utils": "^2.0.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -659,9 +649,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.21.0.tgz",
- "integrity": "sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A==",
+ "version": "8.24.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.24.1.tgz",
+ "integrity": "sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A==",
"dev": true,
"license": "MIT",
"engines": {
@@ -673,20 +663,20 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.21.0.tgz",
- "integrity": "sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg==",
+ "version": "8.24.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.24.1.tgz",
+ "integrity": "sha512-UPyy4MJ/0RE648DSKQe9g0VDSehPINiejjA6ElqnFaFIhI6ZEiZAkUI0D5MCk0bQcTf/LVqZStvQ6K4lPn/BRg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.21.0",
- "@typescript-eslint/visitor-keys": "8.21.0",
+ "@typescript-eslint/types": "8.24.1",
+ "@typescript-eslint/visitor-keys": "8.24.1",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
"minimatch": "^9.0.4",
"semver": "^7.6.0",
- "ts-api-utils": "^2.0.0"
+ "ts-api-utils": "^2.0.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -700,16 +690,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.21.0.tgz",
- "integrity": "sha512-xcXBfcq0Kaxgj7dwejMbFyq7IOHgpNMtVuDveK7w3ZGwG9owKzhALVwKpTF2yrZmEwl9SWdetf3fxNzJQaVuxw==",
+ "version": "8.24.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.24.1.tgz",
+ "integrity": "sha512-OOcg3PMMQx9EXspId5iktsI3eMaXVwlhC8BvNnX6B5w9a4dVgpkQZuU8Hy67TolKcl+iFWq0XX+jbDGN4xWxjQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
- "@typescript-eslint/scope-manager": "8.21.0",
- "@typescript-eslint/types": "8.21.0",
- "@typescript-eslint/typescript-estree": "8.21.0"
+ "@typescript-eslint/scope-manager": "8.24.1",
+ "@typescript-eslint/types": "8.24.1",
+ "@typescript-eslint/typescript-estree": "8.24.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -724,13 +714,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.21.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.21.0.tgz",
- "integrity": "sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w==",
+ "version": "8.24.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.24.1.tgz",
+ "integrity": "sha512-EwVHlp5l+2vp8CoqJm9KikPZgi3gbdZAtabKT9KPShGeOcJhsv4Zdo3oc8T8I0uKEmYoU4ItyxbptjF08enaxg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.21.0",
+ "@typescript-eslint/types": "8.24.1",
"eslint-visitor-keys": "^4.2.0"
},
"engines": {
@@ -755,9 +745,9 @@
}
},
"node_modules/@vscode/vsce": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-3.2.1.tgz",
- "integrity": "sha512-AY9vBjwExakK1c0cI/3NN2Ey0EgiKLBye/fxl/ue+o4q6RZ7N+xzd1jAD6eI6eBeMVANi617+V2rxIAkDPco2Q==",
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-3.2.2.tgz",
+ "integrity": "sha512-4TqdUq/yKlQTHcQMk/DamR632bq/+IJDomSbexOMee/UAYWqYm0XHWA6scGslsCpzY+sCWEhhl0nqdOB0XW1kw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -767,7 +757,7 @@
"chalk": "^2.4.2",
"cheerio": "^1.0.0-rc.9",
"cockatiel": "^3.1.2",
- "commander": "^6.2.1",
+ "commander": "^12.1.0",
"form-data": "^4.0.0",
"glob": "^11.0.0",
"hosted-git-info": "^4.0.2",
@@ -1167,6 +1157,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/async-function": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
+ "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -1330,6 +1330,22 @@
"node": ">=6.14.2"
}
},
+ "node_modules/bundle-name": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz",
+ "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "run-applescript": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/call-bind": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
@@ -1350,9 +1366,9 @@
}
},
"node_modules/call-bind-apply-helpers": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz",
- "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1505,13 +1521,13 @@
}
},
"node_modules/commander": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
- "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
+ "version": "12.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
+ "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">= 6"
+ "node": ">=18"
}
},
"node_modules/concat-map": {
@@ -1673,6 +1689,36 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/default-browser": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz",
+ "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bundle-name": "^4.1.0",
+ "default-browser-id": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser-id": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz",
+ "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
@@ -1692,13 +1738,16 @@
}
},
"node_modules/define-lazy-prop": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
- "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
+ "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/define-properties": {
@@ -2005,13 +2054,16 @@
}
},
"node_modules/es-shim-unscopables": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz",
- "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
+ "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "hasown": "^2.0.0"
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
}
},
"node_modules/es-to-primitive": {
@@ -2049,18 +2101,18 @@
}
},
"node_modules/eslint": {
- "version": "9.18.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.18.0.tgz",
- "integrity": "sha512-+waTfRWQlSbpt3KWE+CjrPPYnbq9kfZIYUqapc0uBXyjTp8aYXZDsUH16m39Ryq3NjAVP4tjuF7KaukeqoCoaA==",
+ "version": "9.20.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.20.1.tgz",
+ "integrity": "sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1",
"@eslint/config-array": "^0.19.0",
- "@eslint/core": "^0.10.0",
+ "@eslint/core": "^0.11.0",
"@eslint/eslintrc": "^3.2.0",
- "@eslint/js": "9.18.0",
+ "@eslint/js": "9.20.0",
"@eslint/plugin-kit": "^0.2.5",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
@@ -2656,9 +2708,9 @@
"license": "MIT"
},
"node_modules/fastq": {
- "version": "1.18.0",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz",
- "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==",
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz",
+ "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -2733,9 +2785,9 @@
}
},
"node_modules/flatted": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz",
- "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==",
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
"dev": true,
"license": "ISC"
},
@@ -2761,13 +2813,19 @@
}
},
"node_modules/for-each": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
- "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "is-callable": "^1.1.3"
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/foreground-child": {
@@ -2788,14 +2846,15 @@
}
},
"node_modules/form-data": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
- "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
+ "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
"dev": true,
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
"mime-types": "^2.1.12"
},
"engines": {
@@ -3220,9 +3279,9 @@
}
},
"node_modules/import-fresh": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
- "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3296,12 +3355,13 @@
}
},
"node_modules/is-async-function": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.0.tgz",
- "integrity": "sha512-GExz9MtyhlZyXYLxzlJRj5WUCE661zhDa1Yna52CN57AJsymh+DvXXjyveSioqSRdxvUrdKdvqB1b5cVKsNpWQ==",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
+ "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
"dev": true,
"license": "MIT",
"dependencies": {
+ "async-function": "^1.0.0",
"call-bound": "^1.0.3",
"get-proto": "^1.0.1",
"has-tostringtag": "^1.0.2",
@@ -3331,13 +3391,13 @@
}
},
"node_modules/is-boolean-object": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz",
- "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==",
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
+ "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2",
+ "call-bound": "^1.0.3",
"has-tostringtag": "^1.0.2"
},
"engines": {
@@ -3425,16 +3485,16 @@
}
},
"node_modules/is-docker": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
- "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
+ "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
"dev": true,
"license": "MIT",
"bin": {
"is-docker": "cli.js"
},
"engines": {
- "node": ">=8"
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -3508,6 +3568,25 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-inside-container": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
+ "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^3.0.0"
+ },
+ "bin": {
+ "is-inside-container": "cli.js"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/is-map": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
@@ -3661,13 +3740,13 @@
}
},
"node_modules/is-weakref": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz",
- "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
+ "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2"
+ "call-bound": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
@@ -3694,16 +3773,19 @@
}
},
"node_modules/is-wsl": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
- "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz",
+ "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "is-docker": "^2.0.0"
+ "is-inside-container": "^1.0.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/isarray": {
@@ -3721,9 +3803,9 @@
"license": "ISC"
},
"node_modules/jackspeak": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz",
- "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==",
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.3.tgz",
+ "integrity": "sha512-oSwM7q8PTHQWuZAlp995iPpPJ4Vkl7qT0ZRD+9duL9j2oBy6KcTfyxc8mEuHJYC+z/kbps80aJLkaNzTOrf/kw==",
"dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
@@ -4169,9 +4251,9 @@
"license": "ISC"
},
"node_modules/napi-build-utils": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
- "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
+ "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
"dev": true,
"license": "MIT",
"optional": true
@@ -4184,9 +4266,9 @@
"license": "MIT"
},
"node_modules/node-abi": {
- "version": "3.73.0",
- "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.73.0.tgz",
- "integrity": "sha512-z8iYzQGBu35ZkTQ9mtR8RqugJZ9RCLn8fv3d7LsgDBzOijGQP3RdKTX4LA7LXw03ZhU5z0l4xfhIMgSES31+cg==",
+ "version": "3.74.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.74.0.tgz",
+ "integrity": "sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -4231,9 +4313,9 @@
}
},
"node_modules/object-inspect": {
- "version": "1.13.3",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz",
- "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==",
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
"dev": true,
"license": "MIT",
"engines": {
@@ -4339,18 +4421,19 @@
}
},
"node_modules/open": {
- "version": "8.4.2",
- "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
- "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz",
+ "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "define-lazy-prop": "^2.0.0",
- "is-docker": "^2.1.1",
- "is-wsl": "^2.2.0"
+ "default-browser": "^5.2.1",
+ "define-lazy-prop": "^3.0.0",
+ "is-inside-container": "^1.0.0",
+ "is-wsl": "^3.1.0"
},
"engines": {
- "node": ">=12"
+ "node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -4397,6 +4480,16 @@
"node": ">= 20"
}
},
+ "node_modules/ovsx/node_modules/commander": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
+ "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/ovsx/node_modules/yauzl": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.2.0.tgz",
@@ -4616,9 +4709,9 @@
}
},
"node_modules/possible-typed-array-names": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
- "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
+ "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -4626,9 +4719,9 @@
}
},
"node_modules/prebuild-install": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz",
- "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==",
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
+ "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -4638,7 +4731,7 @@
"github-from-package": "0.0.0",
"minimist": "^1.2.3",
"mkdirp-classic": "^0.5.3",
- "napi-build-utils": "^1.0.1",
+ "napi-build-utils": "^2.0.0",
"node-abi": "^3.3.0",
"pump": "^3.0.0",
"rc": "^1.2.7",
@@ -4888,6 +4981,19 @@
"node": ">=0.10.0"
}
},
+ "node_modules/run-applescript": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz",
+ "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -5003,9 +5109,9 @@
"license": "ISC"
},
"node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
+ "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"dev": true,
"license": "ISC",
"bin": {
@@ -5515,9 +5621,9 @@
}
},
"node_modules/ts-api-utils": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.0.tgz",
- "integrity": "sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz",
+ "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==",
"dev": true,
"license": "MIT",
"engines": {
diff --git a/extensions/VSCode/package.json b/extensions/VSCode/package.json
index 2f1d558e..1c760bc0 100644
--- a/extensions/VSCode/package.json
+++ b/extensions/VSCode/package.json
@@ -1,6 +1,6 @@
{
"name": "codechat-editor-client",
- "version": "0.1.9",
+ "version": "0.1.10",
"publisher": "CodeChat",
"engines": {
"vscode": "^1.61.0"
diff --git a/extensions/VSCode/src/extension.ts b/extensions/VSCode/src/extension.ts
index 5197b7cf..88017351 100644
--- a/extensions/VSCode/src/extension.ts
+++ b/extensions/VSCode/src/extension.ts
@@ -14,12 +14,14 @@
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
-// # `extension.ts` - The CodeChat Editor Visual Studio Code extension
+// `extension.ts` - The CodeChat Editor Visual Studio Code extension
+// =================================================================
//
// This extension creates a webview, then uses a websocket connection to the
// CodeChat Editor Server and Client to render editor text in that webview.
//
-// ## Imports
+// Imports
+// -------
//
// ### Node.js packages
import assert from "assert";
@@ -35,7 +37,8 @@ import { WebSocket } from "ws";
//
// None.
//
-// ## Globals
+// Globals
+// -------
enum CodeChatEditorClientLocation {
html,
browser,
@@ -135,7 +138,8 @@ interface JointMessage {
message: JointMessageContents;
}
-// ## Activation/deactivation
+// Activation/deactivation
+// -----------------------
//
// This is invoked when the extension is activated. It either creates a new
// CodeChat Editor Server instance or reveals the currently running one.
@@ -154,8 +158,8 @@ export const activate = (context: vscode.ExtensionContext) => {
subscribed = true;
// Render when the text is changed by listening for the
- // correct
- // `event `\_.
+ // correct `event
+ // `\_.
context.subscriptions.push(
vscode.workspace.onDidChangeTextDocument((event) => {
// VSCode sends empty change events -- ignore these.
@@ -325,8 +329,8 @@ export const activate = (context: vscode.ExtensionContext) => {
show_error(
`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);
+ // The close event will be [emitted
+ // next](https://nodejs.org/api/net.html#net_event_error_1);
// that will handle cleanup.
});
@@ -335,8 +339,8 @@ export const activate = (context: vscode.ExtensionContext) => {
"CodeChat Editor extension: closing websocket connection."
);
// If there was an error, the event handler above
- // already provided the message. Note: the
- // [parameter hadError](https://nodejs.org/api/net.html#net_event_close_1)
+ // already provided the message. Note: the [parameter
+ // hadError](https://nodejs.org/api/net.html#net_event_close_1)
// only applies to transmission errors, not to any other
// errors which trigger the error callback. Therefore,
// I'm using the `was_error` flag instead to catch
@@ -458,7 +462,8 @@ export const activate = (context: vscode.ExtensionContext) => {
const { timer_id, callback } =
pending_messages[id];
clearTimeout(timer_id);
- // eslint-disable-next-line n/no-callback-literal
+ // eslint-disable-next-line
+ // n/no-callback-literal
callback(true);
delete pending_messages[id];
}
@@ -531,7 +536,8 @@ export const deactivate = async () => {
console.log("CodeChat extension: deactivated.");
};
-// ## Supporting functions
+// Supporting functions
+// --------------------
//
// Send a message expecting a result to the server.
const send_message = (
@@ -695,8 +701,8 @@ const get_document = (file_path: string) => {
// are case-insensitive; I don't know how to easily determine the
// case-sensitivity of the current filesystem without extra probing code
// (write a file in mixed case, try to open it in another mixed case.)
- // Per
- // [How to Work with Different Filesystems](https://nodejs.org/en/learn/manipulating-files/working-with-different-filesystems#filesystem-behavior),
+ // Per [How to Work with Different
+ // Filesystems](https://nodejs.org/en/learn/manipulating-files/working-with-different-filesystems#filesystem-behavior),
// "Be wary of inferring filesystem behavior from `process.platform`.
// For example, do not assume that because your program is running on
// Darwin that you are therefore working on a case-insensitive
diff --git a/extensions/VSCode/tsconfig.json b/extensions/VSCode/tsconfig.json
index 01a27c6d..de8cd19a 100644
--- a/extensions/VSCode/tsconfig.json
+++ b/extensions/VSCode/tsconfig.json
@@ -14,6 +14,8 @@
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
+// tsconfig.json -- TypeScript configuration
+// =========================================
{
"compilerOptions": {
"module": "nodenext",
diff --git a/new-project-template/README.md b/new-project-template/README.md
index ce3c96b6..e956b622 100644
--- a/new-project-template/README.md
+++ b/new-project-template/README.md
@@ -1,7 +1,8 @@
-# New project template
+New project template
+====================
-This directory contains an example of a CodeChat Editor project. To create a
-new project using this template:
+This directory contains an example of a CodeChat Editor project. To create a new
+project using this template:
1. Copy this file and [toc.md](toc.md) to a newly-created directory of your
choice.
@@ -10,5 +11,5 @@ new project using this template:
3. Open this file and start editing. (If you don't want a readme file, you may
delete it; only [toc.md](toc.md) is required for a CodeChat Editor
project.) You may add any source files you like in this directory or in any
- subdirectory. When you add or delete a file, update the
- [table of contents](toc.md) to make navigation easier.
+ subdirectory. When you add or delete a file, update the [table of
+ contents](toc.md) to make navigation easier.
\ No newline at end of file
diff --git a/new-project-template/toc.md b/new-project-template/toc.md
index 248f08c4..a522f5dc 100644
--- a/new-project-template/toc.md
+++ b/new-project-template/toc.md
@@ -1,8 +1,10 @@
-# New project template
+New project template
+====================
This file provides a table of contents for a CodeChat Editor project.
-## Contents
+Contents
+--------
1. [Readme](README.md)
-2. [Table of contents](toc.md)
+2. [Table of contents](toc.md)
\ No newline at end of file
diff --git a/server/.cargo/config.toml b/server/.cargo/config.toml
index 3d284ba3..7f2396d3 100644
--- a/server/.cargo/config.toml
+++ b/server/.cargo/config.toml
@@ -1,26 +1,31 @@
-# # `config` - a Cargo configuration file
+# `config` - a Cargo configuration file
+# =====================================
#
# See the [docs](https://doc.rust-lang.org/cargo/reference/config.html) for this
# file.
#
# Code coverage, the manual way:
#
-# 1. Run `cargo install rustfilt` per the
-# [code coverage docs](https://doc.rust-lang.org/rustc/instrument-coverage.html#building-the-demangler).
+# 1. Run `cargo install rustfilt` per the [code coverage
+# docs](https://doc.rust-lang.org/rustc/instrument-coverage.html#building-the-demangler).
# 2. You must manually run `rustup component add llvm-tools-preview` following
-# the
-# [coverge docs](https://doc.rust-lang.org/rustc/instrument-coverage.html#installing-llvm-coverage-tools).
+# the [coverge
+# docs](https://doc.rust-lang.org/rustc/instrument-coverage.html#installing-llvm-coverage-tools).
# Per some searching, also run `cargo install cargo-binutils` to put these
# tools in the path.
-# 3. In Powershell, `$Env:RUSTFLAGS = "-C instrument-coverage"` then
-# `cargo test`. When the tests run, record the name of the test binary.
+# 3. In Powershell, `$Env:RUSTFLAGS = "-C instrument-coverage"` then `cargo
+# test`. When the tests run, record the name of the test binary.
# 4. `rust-profdata merge -sparse default_*.profraw -o default.profdata`.
-# 5. `rust-cov show --Xdemangler=rustfilt target\debug\deps\code_chat_editor-4dbe5c7815a53cd9.exe --instr-profile=default.profdata --ignore-filename-regex=\\.cargo\\registry --format=html --output-dir=coverage`,
-# replacing the binary path with the one recorded in step 3.
+# 5. `rust-cov show --Xdemangler=rustfilt
+# target\debug\deps\code_chat_editor-4dbe5c7815a53cd9.exe
+# --instr-profile=default.profdata
+# --ignore-filename-regex=\\.cargo\\registry --format=html
+# --output-dir=coverage`, replacing the binary path with the one recorded in
+# step 3.
# 6. Open the file `coverage\index.html`.
#
-# Or, `cargo install cargo-tarpaulin` then
-# `cargo tarpaulin --ignore-panics --out=html --skip-clean`.
+# Or, `cargo install cargo-tarpaulin` then `cargo tarpaulin --ignore-panics
+# --out=html --skip-clean`.
[build]
# Set these to match the output from `cargo tarpaulin --print-rust-flags` to
@@ -28,5 +33,3 @@
#
# This is commented out; for development, uncomment this.
##rustflags = ["-Cdebuginfo=2", "-Cstrip=none", "--cfg=tarpaulin", "-Cinstrument-coverage"]
-
-# CodeChat Editor lexer: python.
diff --git a/server/.gitignore b/server/.gitignore
index 8e188289..633877c8 100644
--- a/server/.gitignore
+++ b/server/.gitignore
@@ -16,7 +16,8 @@
# the CodeChat Editor. If not, see
# [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
#
-# # `.gitignore` -- files for Git to ignore
+# `.gitignore` -- files for Git to ignore
+# =======================================
#
# Rust build output
target/
diff --git a/server/Cargo.lock b/server/Cargo.lock
index 14b9c1b5..fe7cb4d6 100644
--- a/server/Cargo.lock
+++ b/server/Cargo.lock
@@ -72,7 +72,7 @@ dependencies = [
"mime",
"percent-encoding",
"pin-project-lite",
- "rand",
+ "rand 0.8.5",
"sha1",
"smallvec",
"tokio",
@@ -88,7 +88,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
dependencies = [
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
]
[[package]]
@@ -206,7 +206,7 @@ dependencies = [
"actix-router",
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
]
[[package]]
@@ -245,10 +245,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if",
- "getrandom",
+ "getrandom 0.2.15",
"once_cell",
"version_check",
- "zerocopy",
+ "zerocopy 0.7.35",
]
[[package]]
@@ -342,9 +342,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.95"
+version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
+checksum = "6b964d184e89d9b6b67dd2715bc8e74cf3107fb2b529990c90cf517326150bf4"
[[package]]
name = "arc-swap"
@@ -391,13 +391,13 @@ checksum = "0082388b8564898f945b04215e800e800a164af15307d8dfe714b02cc69356e9"
[[package]]
name = "async-trait"
-version = "0.1.85"
+version = "0.1.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056"
+checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
]
[[package]]
@@ -461,9 +461,9 @@ dependencies = [
[[package]]
name = "brotli-decompressor"
-version = "4.0.1"
+version = "4.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362"
+checksum = "74fa05ad7d803d413eb8380983b092cbbaf9a85f151b871360e7b00cd7060b37"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
@@ -482,9 +482,9 @@ dependencies = [
[[package]]
name = "bumpalo"
-version = "3.16.0"
+version = "3.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
+checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
[[package]]
name = "byteorder"
@@ -494,9 +494,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
-version = "1.9.0"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
+checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9"
dependencies = [
"serde",
]
@@ -512,9 +512,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.2.10"
+version = "1.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229"
+checksum = "0c3d1b2e905a3a7b00a6141adb0e4c0bb941d11caf55349d863942a1cc44e3c9"
dependencies = [
"jobserver",
"libc",
@@ -543,9 +543,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.27"
+version = "4.5.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "769b0145982b4b48713e01ec42d61614425f27b7058bda7180a3a41f30104796"
+checksum = "92b7b18d71fad5313a1e320fa9897994228ce274b60faa4d694fe0ea89cd9e6d"
dependencies = [
"clap_builder",
"clap_derive",
@@ -553,9 +553,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.27"
+version = "4.5.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7"
+checksum = "a35db2071778a7344791a4fb4f95308b5673d219dee3ae348b86642574ecc90c"
dependencies = [
"anstream",
"anstyle",
@@ -565,14 +565,14 @@ dependencies = [
[[package]]
name = "clap_derive"
-version = "4.5.24"
+version = "4.5.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c"
+checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed"
dependencies = [
"heck",
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
]
[[package]]
@@ -583,7 +583,7 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]]
name = "codechat-editor-server"
-version = "0.1.9"
+version = "0.1.10"
dependencies = [
"actix-files",
"actix-http",
@@ -661,9 +661,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "cpufeatures"
-version = "0.2.16"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
dependencies = [
"libc",
]
@@ -714,9 +714,9 @@ dependencies = [
[[package]]
name = "data-encoding"
-version = "2.7.0"
+version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e60eed09d8c01d3cee5b7d30acb059b76614c918fa0f992e0dd6eeb10daad6f"
+checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010"
[[package]]
name = "deranged"
@@ -740,15 +740,15 @@ dependencies = [
[[package]]
name = "derive_more"
-version = "0.99.18"
+version = "0.99.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce"
+checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f"
dependencies = [
"convert_case",
"proc-macro2",
"quote",
"rustc_version",
- "syn 2.0.96",
+ "syn 2.0.98",
]
[[package]]
@@ -782,7 +782,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
]
[[package]]
@@ -808,9 +808,9 @@ dependencies = [
[[package]]
name = "equivalent"
-version = "1.0.1"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "errno"
@@ -922,7 +922,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
]
[[package]]
@@ -970,7 +970,19 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi 0.13.3+wasi-0.2.2",
+ "windows-targets",
]
[[package]]
@@ -1073,9 +1085,9 @@ checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573"
[[package]]
name = "httparse"
-version = "1.9.5"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946"
+checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a"
[[package]]
name = "httpdate"
@@ -1227,7 +1239,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
]
[[package]]
@@ -1479,7 +1491,7 @@ dependencies = [
"log-mdc",
"once_cell",
"parking_lot",
- "rand",
+ "rand 0.8.5",
"serde",
"serde-value",
"serde_json",
@@ -1524,18 +1536,18 @@ dependencies = [
[[package]]
name = "miniz_oxide"
-version = "0.8.3"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924"
+checksum = "b3b1c9bd4fe1f0f8b387f6eb9eb3b4a1aa26185e5750efb9140301703f62cd1b"
dependencies = [
"adler2",
]
[[package]]
name = "minreq"
-version = "2.13.0"
+version = "2.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36a8e50e917e18a37d500d27d40b7bc7d127e71c0c94fb2d83f43b4afd308390"
+checksum = "da0c420feb01b9fb5061f8c8f452534361dd783756dcf38ec45191ce55e7a161"
dependencies = [
"log",
]
@@ -1548,7 +1560,7 @@ checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
dependencies = [
"libc",
"log",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.52.0",
]
@@ -1622,9 +1634,9 @@ dependencies = [
[[package]]
name = "once_cell"
-version = "1.20.2"
+version = "1.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
+checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
[[package]]
name = "open"
@@ -1724,7 +1736,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
]
[[package]]
@@ -1776,9 +1788,9 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "postgres-protocol"
-version = "0.6.7"
+version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acda0ebdebc28befa84bee35e651e4c5f09073d668c7aed4cf7e23c3cda84b23"
+checksum = "76ff0abab4a9b844b93ef7b81f1efc0a366062aaef2cd702c76256b5dc075c54"
dependencies = [
"base64",
"byteorder",
@@ -1787,16 +1799,16 @@ dependencies = [
"hmac",
"md-5",
"memchr",
- "rand",
+ "rand 0.9.0",
"sha2",
"stringprep",
]
[[package]]
name = "postgres-types"
-version = "0.2.8"
+version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f66ea23a2d0e5734297357705193335e0a957696f34bed2f2faefacb2fec336f"
+checksum = "613283563cd90e1dfc3518d548caee47e0e725455ed619881f5cf21f36de4b48"
dependencies = [
"bytes",
"chrono",
@@ -1816,7 +1828,7 @@ version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
dependencies = [
- "zerocopy",
+ "zerocopy 0.7.35",
]
[[package]]
@@ -1860,9 +1872,9 @@ dependencies = [
[[package]]
name = "pulldown-cmark"
-version = "0.12.2"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14"
+checksum = "1e8bbe1a966bd2f362681a44f6edce3c2310ac21e4d5067a6e7ec396297a6ea0"
dependencies = [
"bitflags 2.8.0",
"memchr",
@@ -1892,8 +1904,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
- "rand_chacha",
- "rand_core",
+ "rand_chacha 0.3.1",
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "rand"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
+dependencies = [
+ "rand_chacha 0.9.0",
+ "rand_core 0.9.1",
+ "zerocopy 0.8.20",
]
[[package]]
@@ -1903,7 +1926,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
- "rand_core",
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.9.1",
]
[[package]]
@@ -1912,7 +1945,17 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
- "getrandom",
+ "getrandom 0.2.15",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a88e0da7a2c97baa202165137c158d0a2e824ac465d13d81046727b34cb247d3"
+dependencies = [
+ "getrandom 0.3.1",
+ "zerocopy 0.8.20",
]
[[package]]
@@ -1976,9 +2019,9 @@ dependencies = [
[[package]]
name = "rustix"
-version = "0.38.43"
+version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6"
+checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
"bitflags 2.8.0",
"errno",
@@ -1995,9 +2038,9 @@ checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
[[package]]
name = "ryu"
-version = "1.0.18"
+version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
+checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
[[package]]
name = "same-file"
@@ -2022,9 +2065,9 @@ checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03"
[[package]]
name = "serde"
-version = "1.0.217"
+version = "1.0.218"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
+checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60"
dependencies = [
"serde_derive",
]
@@ -2041,20 +2084,20 @@ dependencies = [
[[package]]
name = "serde_derive"
-version = "1.0.217"
+version = "1.0.218"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
+checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
]
[[package]]
name = "serde_json"
-version = "1.0.137"
+version = "1.0.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b"
+checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6"
dependencies = [
"itoa",
"memchr",
@@ -2141,9 +2184,9 @@ dependencies = [
[[package]]
name = "smallvec"
-version = "1.13.2"
+version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
[[package]]
name = "socket2"
@@ -2197,9 +2240,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.96"
+version = "2.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
+checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
dependencies = [
"proc-macro2",
"quote",
@@ -2214,18 +2257,18 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
]
[[package]]
name = "tempfile"
-version = "3.15.0"
+version = "3.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704"
+checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230"
dependencies = [
"cfg-if",
"fastrand",
- "getrandom",
+ "getrandom 0.3.1",
"once_cell",
"rustix",
"windows-sys 0.59.0",
@@ -2263,7 +2306,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
]
[[package]]
@@ -2274,7 +2317,7 @@ checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
]
[[package]]
@@ -2369,14 +2412,14 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
]
[[package]]
name = "tokio-postgres"
-version = "0.7.12"
+version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b5d3742945bc7d7f210693b0c58ae542c6fd47b17adbbda0885f3dcb34a6bdb"
+checksum = "6c95d533c83082bb6490e0189acaa0bbeef9084e60471b696ca6988cd0541fb0"
dependencies = [
"async-trait",
"byteorder",
@@ -2391,7 +2434,7 @@ dependencies = [
"pin-project-lite",
"postgres-protocol",
"postgres-types",
- "rand",
+ "rand 0.9.0",
"socket2",
"tokio",
"tokio-util",
@@ -2400,9 +2443,9 @@ dependencies = [
[[package]]
name = "tokio-tungstenite"
-version = "0.26.1"
+version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be4bf6fecd69fcdede0ec680aaf474cdab988f9de6bc73d3758f0160e3b7025a"
+checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084"
dependencies = [
"futures-util",
"log",
@@ -2445,17 +2488,16 @@ dependencies = [
[[package]]
name = "tungstenite"
-version = "0.26.1"
+version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "413083a99c579593656008130e29255e54dcaae495be556cc26888f211648c24"
+checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13"
dependencies = [
- "byteorder",
"bytes",
"data-encoding",
"http 1.2.0",
"httparse",
"log",
- "rand",
+ "rand 0.9.0",
"sha1",
"thiserror 2.0.11",
"utf-8",
@@ -2472,9 +2514,9 @@ dependencies = [
[[package]]
name = "typenum"
-version = "1.17.0"
+version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
[[package]]
name = "ucd-trie"
@@ -2496,9 +2538,9 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
[[package]]
name = "unicode-ident"
-version = "1.0.14"
+version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
+checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe"
[[package]]
name = "unicode-normalization"
@@ -2585,9 +2627,9 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wait-timeout"
-version = "0.2.0"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
+checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11"
dependencies = [
"libc",
]
@@ -2608,6 +2650,15 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+[[package]]
+name = "wasi"
+version = "0.13.3+wasi-0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
+dependencies = [
+ "wit-bindgen-rt",
+]
+
[[package]]
name = "wasite"
version = "0.1.0"
@@ -2636,7 +2687,7 @@ dependencies = [
"log",
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
"wasm-bindgen-shared",
]
@@ -2658,7 +2709,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -2851,6 +2902,15 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+[[package]]
+name = "wit-bindgen-rt"
+version = "0.33.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
+dependencies = [
+ "bitflags 2.8.0",
+]
+
[[package]]
name = "write16"
version = "1.0.0"
@@ -2883,7 +2943,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
"synstructure",
]
@@ -2894,7 +2954,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"byteorder",
- "zerocopy-derive",
+ "zerocopy-derive 0.7.35",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.8.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dde3bb8c68a8f3f1ed4ac9221aad6b10cece3e60a8e2ea54a6a2dec806d0084c"
+dependencies = [
+ "zerocopy-derive 0.8.20",
]
[[package]]
@@ -2905,7 +2974,18 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eea57037071898bf96a6da35fd626f4f27e9cee3ead2a6c703cf09d472b2e700"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.98",
]
[[package]]
@@ -2925,7 +3005,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
"synstructure",
]
@@ -2948,32 +3028,32 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.96",
+ "syn 2.0.98",
]
[[package]]
name = "zstd"
-version = "0.13.2"
+version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9"
+checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
-version = "7.2.1"
+version = "7.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059"
+checksum = "f3051792fbdc2e1e143244dc28c60f73d8470e93f3f9cbd0ead44da5ed802722"
dependencies = [
"zstd-sys",
]
[[package]]
name = "zstd-sys"
-version = "2.0.13+zstd.1.5.6"
+version = "2.0.14+zstd.1.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa"
+checksum = "8fb060d4926e4ac3a3ad15d864e99ceb5f343c6b34f5bd6d81ae6ed417311be5"
dependencies = [
"cc",
"pkg-config",
diff --git a/server/Cargo.toml b/server/Cargo.toml
index d9de16f7..0fa0450f 100644
--- a/server/Cargo.toml
+++ b/server/Cargo.toml
@@ -16,26 +16,29 @@
# the CodeChat Editor. If not, see
# [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
#
-# # `Cargo.toml` -- Rust build/package management config for the server
+# `Cargo.toml` -- Rust build/package management config for the server
+# ===================================================================
#
-# ## General package configurations
+# General package configurations
+# ------------------------------
[package]
authors = ["Bryan A. Jones", "Peter Loux"]
categories = ["development-tools", "text-editors"]
description = "A programmer's word processor."
-edition = "2021"
+edition = "2024"
keywords = ["literate programming"]
license = "GPL-3.0-only"
name = "codechat-editor-server"
readme = "../README.md"
repository = "https://github.com/bjones1/CodeChat_Editor"
-version = "0.1.9"
+version = "0.1.10"
# This library allows other packages to use core CodeChat Editor features.
[lib]
name = "code_chat_editor"
-# ## Dependencies
+# Dependencies
+# ------------
[dependencies]
actix-files = "0.6"
actix-rt = "2.9.0"
@@ -61,7 +64,7 @@ pest = "2.7.14"
pest_derive = "2.7.14"
# Per the [docs](https://docs.rs/crate/pulldown-cmark/latest), skip building the
# binary.
-pulldown-cmark = { version = "0.12", default-features = false, features = ["html"] }
+pulldown-cmark = { version = "0.13", default-features = false, features = ["html"] }
regex = "1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
@@ -70,7 +73,8 @@ tokio-postgres = { version = "0.7", features = ["with-chrono-0_4"] }
url = "2.5.2"
urlencoding = "2"
-# [Windows-only dependencies](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#platform-specific-dependencies).
+# [Windows-only
+# dependencies](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#platform-specific-dependencies).
[target.'cfg(windows)'.dependencies]
win_partitions = "0.3.0"
@@ -89,7 +93,8 @@ tokio-tungstenite = "0.26"
#actix = { path = "../../actix/actix" }
#actix-rt = { path = "../../actix-net/actix-rt" }
-# ## Release
+# Release
+# -------
#
# Specify release-only features for pulldown. See the
# [docs](https://docs.rs/crate/pulldown-cmark/latest).
@@ -98,7 +103,8 @@ lto = true
codegen-units = 1
panic = "abort"
-# ## Features
+# Features
+# --------
#
# See the [docs](https://doc.rust-lang.org/cargo/reference/features.html).
[features]
@@ -110,7 +116,8 @@ lexer_explain = []
# Avoid a lint about tarpaulin.
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(tarpaulin_include)'] }
-# ## Distribution
+# Distribution
+# ------------
#
# This uses [cargo dist](https://opensource.axo.dev/cargo-dist) to build
# binaries across multiple platforms using github's CI/CD.
diff --git a/server/dist-workspace.toml b/server/dist-workspace.toml
index f90aeff1..d1281ada 100644
--- a/server/dist-workspace.toml
+++ b/server/dist-workspace.toml
@@ -16,7 +16,9 @@
# the CodeChat Editor. If not, see
# [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
#
-# `dist-workspace.toml' - Configure [cargo-dist](https://opensource.axo.dev/cargo-dist/)
+# `dist-workspace.toml` - Configure
+# [cargo-dist](https://opensource.axo.dev/cargo-dist/)
+# ====================================================
[workspace]
members = ["cargo:."]
@@ -24,7 +26,8 @@ members = ["cargo:."]
[dist]
# The preferred dist version to use in CI (Cargo.toml SemVer syntax)
cargo-dist-version = "0.28.0"
-# Extra static files to include in each App (path relative to this Cargo.toml's dir)
+# Extra static files to include in each App (path relative to this Cargo.toml's
+# dir)
include = ["log4rs.yml", "hashLocations.json", "../client/static"]
# The installers to generate for each app
installers = []
diff --git a/server/log4rs.yml b/server/log4rs.yml
index 11c1fe31..a5bb18a4 100644
--- a/server/log4rs.yml
+++ b/server/log4rs.yml
@@ -16,7 +16,8 @@
# the CodeChat Editor. If not, see
# [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
#
-# # `log4rs.yml` - configure logging
+# `log4rs.yml` - configure logging
+# ================================
#
# This file configures log4rs for this application.
appenders:
diff --git a/server/src/lexer.rs b/server/src/lexer.rs
index 87f31b93..deecab05 100644
--- a/server/src/lexer.rs
+++ b/server/src/lexer.rs
@@ -14,11 +14,14 @@
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
mod pest_parser;
-/// # `lexer.rs` -- Lex source code into code and doc blocks
-// ## Submodule definitions
+/// `lexer.rs` -- Lex source code into code and doc blocks
+/// ======================================================
+// Submodule definitions
+// ---------------------
pub mod supported_languages;
-// ## Imports
+// Imports
+// -------
//
// ### Standard library
#[cfg(feature = "lexer_explain")]
@@ -32,25 +35,27 @@ use regex::Regex;
// ### Local
use supported_languages::get_language_lexer_vec;
-/// ## Data structures
+/// Data structures
+/// ---------------
///
/// ### Language definition
///
/// These data structures define everything the lexer needs in order to analyze
/// a programming language:
///
-/// - It defines block and inline comment delimiters; these (when correctly
-/// formatted) become doc blocks.
-/// - It defines strings: what is the escape character? Are newlines allowed? If
-/// so, must newlines be escaped?
-/// - It defines heredocs in a flexible form (see `HeredocDelim` for more
-/// details).
-/// - It associates an Ace mode and filename extensions with the lexer.
+/// * It defines block and inline comment delimiters; these (when correctly
+/// formatted) become doc blocks.
+/// * It defines strings: what is the escape character? Are newlines allowed?
+/// If so, must newlines be escaped?
+/// * It defines heredocs in a flexible form (see `HeredocDelim` for more
+/// details).
+/// * It associates an Ace mode and filename extensions with the lexer.
///
/// This lexer ignores line continuation characters; in C/C++/Python, it's a `\`
-/// character followed immediately by a newline
-/// ([C reference](https://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf#page22),
-/// [Python reference](https://docs.python.org/3/reference/lexical_analysis.html#explicit-line-joining)).
+/// character followed immediately by a newline ([C
+/// reference](https://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf#page22),
+/// [Python
+/// reference](https://docs.python.org/3/reference/lexical_analysis.html#explicit-line-joining)).
/// From a lexer perspective, supporting these adds little value:
///
/// 1. It would allow the lexer to recognize the following C/C++ snippet as a
@@ -124,14 +129,15 @@ struct HeredocDelim {
enum SpecialCase {
/// There are no special cases for this language.
None,
- /// [Template literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals)
+ /// [Template
+ /// literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals)
/// support (for languages such as JavaScript, TypeScript, etc.).
TemplateLiteral,
- /// C#'s verbatim string literal -- see
- /// [6.4.5.6 String literals](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure#6456-string-literals).
+ /// C#'s verbatim string literal -- see [6.4.5.6 String
+ /// literals](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure#6456-string-literals).
CSharpVerbatimStringLiteral,
- /// MATLAB
- /// [block comments](https://www.mathworks.com/help/matlab/matlab_prog/comments.html)
+ /// MATLAB [block
+ /// comments](https://www.mathworks.com/help/matlab/matlab_prog/comments.html)
/// must start and end on a blank line.
Matlab,
}
@@ -258,18 +264,20 @@ pub enum CodeDocBlock {
DocBlock(DocBlock),
}
-// ## Globals
+// Globals
+// -------
//
-// Create constant regexes needed by the lexer, following the
-// [Regex docs recommendation](https://docs.rs/regex/1.6.0/regex/index.html#example-avoid-compiling-the-same-regex-in-a-loop).
+// Create constant regexes needed by the lexer, following the [Regex docs
+// recommendation](https://docs.rs/regex/1.6.0/regex/index.html#example-avoid-compiling-the-same-regex-in-a-loop).
lazy_static! {
static ref WHITESPACE_ONLY_REGEX: Regex = Regex::new("^[[:space:]]*$").unwrap();
/// TODO: This regex should also allow termination on an unescaped `${`
/// sequence, which then must count matching braces to find the end of the
/// expression.
static ref TEMPLATE_LITERAL_CLOSING_REGEX: Regex = Regex::new(
- // Allow `.` to match _any_ character, including a newline. See the
- // [regex docs](https://docs.rs/regex/1.6.0/regex/index.html#grouping-and-flags).
+ // Allow `.` to match *any* character, including a newline. See the
+ // [regex
+ // docs](https://docs.rs/regex/1.6.0/regex/index.html#grouping-and-flags).
&("(?s)".to_string() +
// Start at the beginning of the string, and require a match of every
// character. Allowing the regex to start matching in the middle means
@@ -403,9 +411,9 @@ fn build_lexer_regex(
// terminated by an unescaped newline or an unescaped delimiter.
// Escaped newlines or terminators should be included in the string.
(true, NewlineSupport::Escaped) => Regex::new(
- // Allow `.` to match _any_ character, including a newline. See
- // the
- // [regex docs](https://docs.rs/regex/1.6.0/regex/index.html#grouping-and-flags).
+ // Allow `.` to match *any* character, including a newline. See
+ // the [regex
+ // docs](https://docs.rs/regex/1.6.0/regex/index.html#grouping-and-flags).
&("(?s)".to_string() +
// Start at the beginning of the string, and require a match of
// every character. Allowing the regex to start matching in the
@@ -453,9 +461,9 @@ fn build_lexer_regex(
// Even simpler: look for an unescaped string delimiter.
(true, NewlineSupport::Unescaped) => Regex::new(
- // Allow `.` to match _any_ character, including a newline. See
- // the
- // [regex docs](https://docs.rs/regex/1.6.0/regex/index.html#grouping-and-flags).
+ // Allow `.` to match *any* character, including a newline. See
+ // the [regex
+ // docs](https://docs.rs/regex/1.6.0/regex/index.html#grouping-and-flags).
&("(?s)".to_string() +
// Start at the beginning of the string, and require a match of
// every character. Allowing the regex to start matching in the
@@ -539,8 +547,8 @@ fn build_lexer_regex(
// To match on a line which consists only of leading and
// trailing whitespace plus the opening comment delimiter, put
// these inside a `(?m:exp)` block, so that `^` and `$` will
- // match on any newline in the string; see the
- // [regex docs](https://docs.rs/regex/latest/regex/#grouping-and-flags).
+ // match on any newline in the string; see the [regex
+ // docs](https://docs.rs/regex/latest/regex/#grouping-and-flags).
// This also functions as a non-capturing group, to avoid
// whitespace capture as discussed earlier.
"(?m:" +
@@ -593,7 +601,8 @@ fn build_lexer_regex(
}
}
-// ## Compile lexers
+// Compile lexers
+// --------------
pub fn compile_lexers(language_lexer_arr: Vec) -> LanguageLexersCompiled {
let mut language_lexers_compiled = LanguageLexersCompiled {
language_lexer_compiled_vec: Vec::new(),
@@ -630,7 +639,8 @@ pub fn compile_lexers(language_lexer_arr: Vec) -> LanguageLexersC
language_lexers_compiled
}
-/// ## Source lexer
+/// Source lexer
+/// ------------
///
/// This lexer categorizes source code into code blocks or doc blocks.
///
@@ -647,15 +657,16 @@ pub fn source_lexer(
// to categorize all the source code into code blocks or doc blocks. To do
// it, it only needs to:
//
- // - Recognize where comments can't be—inside strings or string-like syntax,
- // such as [here text](https://en.wikipedia.org/wiki/Here_document) or
- // [template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals).
- // These are always part of a code block and can never contain a comment
- // or (by implication) a doc block.
- // - Outside of these special cases, look for inline or block comments,
- // categorizing everything else as plain code.
- // - After finding either an inline or block comment, determine if this is a
- // doc block.
+ // * Recognize where comments can't be—inside strings or string-like
+ // syntax, such as [here
+ // text](https://en.wikipedia.org/wiki/Here_document) or [template
+ // literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals).
+ // These are always part of a code block and can never contain a comment
+ // or (by implication) a doc block.
+ // * Outside of these special cases, look for inline or block comments,
+ // categorizing everything else as plain code.
+ // * After finding either an inline or block comment, determine if this is
+ // a doc block.
//
// ### Lexer operation
//
@@ -665,18 +676,18 @@ pub fn source_lexer(
// `language_lexer_compiled.map`. These divides source code into two
// categories: plain code and special cases. The special cases consist of:
//
- // - String-like code (strings, here text, template literals). In this case,
- // the lexer must find the end of the string-like element before it can
- // return to plain code.
- // - Comments (inline or block). In this case, the lexer must find the end
- // of the comment before it can return to plain code.
+ // * String-like code (strings, here text, template literals). In this
+ // case, the lexer must find the end of the string-like element before
+ // it can return to plain code.
+ // * Comments (inline or block). In this case, the lexer must find the end
+ // of the comment before it can return to plain code.
//
// This regex assumes the string it analyzes was preceded by plain code; its
// purpose is to identify the start of the next special case. **This code
// makes heavy use of regexes -- read the previous link thoroughly.**
//
- // To better explain the operation of the lexer, see the
- // [lexer walkthrough](lexer/lexer-walkthrough.md).
+ // To better explain the operation of the lexer, see the [lexer
+ // walkthrough](lexer/lexer-walkthrough.md).
//
// ### Helper function
//
@@ -758,19 +769,22 @@ pub fn source_lexer(
#[cfg(feature = "lexer_explain")]
println!(
"Searching the following source_code using the pattern {:?}:\n'{}'\n\nThe current code block is '{}'\n",
- language_lexer_compiled.next_token, &source_code[source_code_unlexed_index..], &source_code[current_code_block_index..source_code_unlexed_index]
+ language_lexer_compiled.next_token,
+ &source_code[source_code_unlexed_index..],
+ &source_code[current_code_block_index..source_code_unlexed_index]
);
// #### Find the next token
//
// Look for the next special case. Per the earlier discussion, this
// assumes that the text immediately preceding `source_code` was plain
// code.
- if let Some(classify_match) = language_lexer_compiled
+ match language_lexer_compiled
.next_token
.captures(&source_code[source_code_unlexed_index..])
{
- // Find the first group in the regex that matched.
- let matching_group_index = classify_match
+ Some(classify_match) => {
+ // Find the first group in the regex that matched.
+ let matching_group_index = classify_match
.iter()
// Group 0 is the entire match, which is always true. Skip this
// group.
@@ -779,23 +793,25 @@ pub fn source_lexer(
.unwrap()
// Correct the resulting group index, since we skipped group 0.
+ 1;
- let matching_group_str = &classify_match[matching_group_index];
-
- // Move everything preceding this match from `source_code` to the
- // current code block, since per the assumptions this is code.
- source_code_unlexed_index += classify_match.get(matching_group_index).unwrap().start();
-
- #[cfg(feature = "lexer_explain")]
- println!(
- "Matched the string {} in group {}. The current_code_block is now\n'{}'\n",
- matching_group_str,
- matching_group_index,
- &source_code[current_code_block_index..source_code_unlexed_index]
- );
+ let matching_group_str = &classify_match[matching_group_index];
+
+ // Move everything preceding this match from `source_code` to
+ // the current code block, since per the assumptions this is
+ // code.
+ source_code_unlexed_index +=
+ classify_match.get(matching_group_index).unwrap().start();
- // This helper function moves code from unlexed source code to the
- // current code block based on the provided regex.
- let mut append_code =
+ #[cfg(feature = "lexer_explain")]
+ println!(
+ "Matched the string {} in group {}. The current_code_block is now\n'{}'\n",
+ matching_group_str,
+ matching_group_index,
+ &source_code[current_code_block_index..source_code_unlexed_index]
+ );
+
+ // This helper function moves code from unlexed source code to
+ // the current code block based on the provided regex.
+ let mut append_code =
// The regex; code up to the end of this
// match will be appended to the current code
// block.
@@ -825,76 +841,76 @@ pub fn source_lexer(
};
- // In the map, index 0 refers to group 1 (since group 0 matches are
- // skipped). Adjust the index for this.
- match &language_lexer_compiled.map[matching_group_index - 1] {
- // #### Inline comment
- RegexDelimType::InlineComment => {
- // **First**, find the end of this comment: a newline.
- let end_of_comment_rel_index =
- source_code[source_code_unlexed_index..].find('\n');
-
- // Assign `full_comment` to contain the entire comment
- // (excluding the inline comment delimiter) until the
- // newline which ends the comment.
- let full_comment_start_index =
- source_code_unlexed_index + matching_group_str.len();
-
- // The current code block contains preceding code (which
- // might be multiple lines) until the inline comment
- // delimiter. Split this on newlines, grouping all the lines
- // before the last line into `code_lines_before_comment`
- // (which is all code), and everything else (from the
- // beginning of the last line to where the inline comment
- // delimiter appears) into `comment_line_prefix`. For
- // example, consider the fragment `a = 1\nb = 2 // Doc`.
- // After processing,
- // `code_lines_before_comment == "a = 1\n"` and
- // `comment_line_prefix == "b = 2 "`.
- let current_code_block =
- &source_code[current_code_block_index..source_code_unlexed_index];
- let comment_line_prefix = current_code_block.rsplit('\n').next().unwrap();
- let code_lines_before_comment =
- ¤t_code_block[..current_code_block.len() - comment_line_prefix.len()];
-
- // Move to the next block of source code to be lexed. No
- // matching newline means we're at the end of the file, so
- // the comment is all the remaining `source_code`.
- source_code_unlexed_index = if let Some(index) = end_of_comment_rel_index {
- // Note that `index` is the index of the newline; add 1
- // to include that newline in the comment.
- source_code_unlexed_index + index + 1
- } else {
- source_code.len()
- };
- let full_comment =
- &source_code[full_comment_start_index..source_code_unlexed_index];
+ // In the map, index 0 refers to group 1 (since group 0 matches
+ // are skipped). Adjust the index for this.
+ match &language_lexer_compiled.map[matching_group_index - 1] {
+ // #### Inline comment
+ RegexDelimType::InlineComment => {
+ // **First**, find the end of this comment: a newline.
+ let end_of_comment_rel_index =
+ source_code[source_code_unlexed_index..].find('\n');
+
+ // Assign `full_comment` to contain the entire comment
+ // (excluding the inline comment delimiter) until the
+ // newline which ends the comment.
+ let full_comment_start_index =
+ source_code_unlexed_index + matching_group_str.len();
+
+ // The current code block contains preceding code (which
+ // might be multiple lines) until the inline comment
+ // delimiter. Split this on newlines, grouping all the
+ // lines before the last line into
+ // `code_lines_before_comment` (which is all code), and
+ // everything else (from the beginning of the last line
+ // to where the inline comment delimiter appears) into
+ // `comment_line_prefix`. For example, consider the
+ // fragment `a = 1\nb = 2 // Doc`. After processing,
+ // `code_lines_before_comment == "a = 1\n"` and
+ // `comment_line_prefix == "b = 2 "`.
+ let current_code_block =
+ &source_code[current_code_block_index..source_code_unlexed_index];
+ let comment_line_prefix = current_code_block.rsplit('\n').next().unwrap();
+ let code_lines_before_comment = ¤t_code_block
+ [..current_code_block.len() - comment_line_prefix.len()];
+
+ // Move to the next block of source code to be lexed. No
+ // matching newline means we're at the end of the file,
+ // so the comment is all the remaining `source_code`.
+ source_code_unlexed_index = if let Some(index) = end_of_comment_rel_index {
+ // Note that `index` is the index of the newline;
+ // add 1 to include that newline in the comment.
+ source_code_unlexed_index + index + 1
+ } else {
+ source_code.len()
+ };
+ let full_comment =
+ &source_code[full_comment_start_index..source_code_unlexed_index];
- #[cfg(feature = "lexer_explain")]
- println!(
- "This is an inline comment. Source code before the line containing this comment is:\n'{}'\n\
+ #[cfg(feature = "lexer_explain")]
+ println!(
+ "This is an inline comment. Source code before the line containing this comment is:\n'{}'\n\
The text preceding this comment is: '{}'.\n\
The comment is: '{}'\n",
- code_lines_before_comment, comment_line_prefix, full_comment
- );
-
- // **Next**, determine if this comment is a doc block.
- // Criteria for doc blocks for an inline comment:
- //
- // 1. All characters preceding the comment on the line
- // containing the comment must be whitespace.
- // 2. Either:
- // 1. The inline comment delimiter is immediately
- // followed by a space, or
- // 2. the inline comment delimiter is followed by a
- // newline or the end of the file.
- //
- // With this last line located, apply the doc block
- // criteria.
- let ws_only = WHITESPACE_ONLY_REGEX.is_match(comment_line_prefix);
- let has_space_after_comment = full_comment.starts_with(' ');
- // Criteria 1 -- the whitespace matched.
- if ws_only &&
+ code_lines_before_comment, comment_line_prefix, full_comment
+ );
+
+ // **Next**, determine if this comment is a doc block.
+ // Criteria for doc blocks for an inline comment:
+ //
+ // 1. All characters preceding the comment on the line
+ // containing the comment must be whitespace.
+ // 2. Either:
+ // 1. The inline comment delimiter is immediately
+ // followed by a space, or
+ // 2. the inline comment delimiter is followed by a
+ // newline or the end of the file.
+ //
+ // With this last line located, apply the doc block
+ // criteria.
+ let ws_only = WHITESPACE_ONLY_REGEX.is_match(comment_line_prefix);
+ let has_space_after_comment = full_comment.starts_with(' ');
+ // Criteria 1 -- the whitespace matched.
+ if ws_only &&
// TODO: generalize this to specific lines that are
// never doc blocks.
full_comment != " prettier-ignore\n"
@@ -906,132 +922,144 @@ pub fn source_lexer(
// Criteria 2.2b -- end of file means the comment is
// empty.
full_comment.is_empty())
- )
- {
- // This is a doc block. Transition from the preceding
- // code block to this doc block.
- append_code_doc_block("", "", code_lines_before_comment);
-
- // Add this doc block by pushing the array \[whitespace
- // before the inline comment, inline comment contents,
- // inline comment delimiter\]. Since it's a doc block,
- // then `comment_line_prefix` contains the whitespace
- // before this comment and `matching_group_string`
- // contains the inline comment delimiter. For the
- // contents, omit the leading space if it's there (this
- // might be just a newline or an EOF).
- let contents = &full_comment[if has_space_after_comment { 1 } else { 0 }..];
- append_code_doc_block(comment_line_prefix, matching_group_str, contents);
+ ) {
+ // This is a doc block. Transition from the
+ // preceding code block to this doc block.
+ append_code_doc_block("", "", code_lines_before_comment);
+
+ // Add this doc block by pushing the array
+ // \[whitespace before the inline comment, inline
+ // comment contents, inline comment delimiter\].
+ // Since it's a doc block, then
+ // `comment_line_prefix` contains the whitespace
+ // before this comment and `matching_group_string`
+ // contains the inline comment delimiter. For the
+ // contents, omit the leading space if it's there
+ // (this might be just a newline or an EOF).
+ let contents =
+ &full_comment[if has_space_after_comment { 1 } else { 0 }..];
+ append_code_doc_block(
+ comment_line_prefix,
+ matching_group_str,
+ contents,
+ );
- #[cfg(feature = "lexer_explain")]
- println!(
- "This is a doc block. Possibly added the preceding code block\n\
+ #[cfg(feature = "lexer_explain")]
+ println!(
+ "This is a doc block. Possibly added the preceding code block\n\
'{}'.\n\
Added a doc block with indent = '{}', delimiter = '{}', and contents =\n\
'{}'.\n",
- current_code_block, comment_line_prefix, matching_group_str, contents
- );
+ current_code_block,
+ comment_line_prefix,
+ matching_group_str,
+ contents
+ );
- // We've now stored the current code block (which was
- // classified as a doc block) in `classified_lines`.
- // Make the current code block empty by moving its index
- // up to the unlexed code.
- current_code_block_index = source_code_unlexed_index;
- } else {
- // This comment is not a doc block; instead, treat it as
- // code. This code is already in the current code block,
- // so we're done.
+ // We've now stored the current code block (which
+ // was classified as a doc block) in
+ // `classified_lines`. Make the current code block
+ // empty by moving its index up to the unlexed code.
+ current_code_block_index = source_code_unlexed_index;
+ } else {
+ // This comment is not a doc block; instead, treat
+ // it as code. This code is already in the current
+ // code block, so we're done.
+ }
}
- }
- // #### Block comment
- RegexDelimType::BlockComment(comment_delim_regex) => 'block_comment: {
- #[cfg(feature = "lexer_explain")]
- println!("Block Comment Found.");
+ // #### Block comment
+ RegexDelimType::BlockComment(comment_delim_regex) => 'block_comment: {
+ #[cfg(feature = "lexer_explain")]
+ println!("Block Comment Found.");
- // Determine the location of the beginning of this block
- // comment's content.
- let mut comment_start_index =
- source_code_unlexed_index + matching_group_str.len();
+ // Determine the location of the beginning of this block
+ // comment's content.
+ let mut comment_start_index =
+ source_code_unlexed_index + matching_group_str.len();
- #[cfg(feature = "lexer_explain")]
- println!(
- "The opening delimiter is '{}', and the closing delimiter regex is '{}'.",
- matching_group_str, comment_delim_regex
- );
-
- // For nested comments, only treat the innermost comment as
- // a potential doc block; everything else is treated as
- // code. The rationale:
- //
- // 1. Typically, nested comments are used to comment out a
- // block of code, which may already contain "real"
- // comments (as opposed to commented-out code).
- // Therefore, we assume that only these innermost
- // comments are true comments, while everything else is
- // code. I can't think of any reason to nest true
- // comments. Assuming a legitimate use for nested
- // comments, what criteria would distinguish a nested
- // comment from a commented-out code block?
- // 2. The CodeChat Editor data structures don't support
- // nested doc blocks. So, while we might be able to
- // correctly parse nested comments as doc blocks, the
- // code that transforms these back to code would remove
- // the nesting.
- // 3. We lack criteria that would distinguish a nested doc
- // block from commented-out code.
- //
- // With these assumptions, we need to know if the current
- // comment is the innermost or not. If the last block
- // comment delimiter encountered was an opening comment, and
- // the current block comment delimiter is a closing block
- // comment, then this is an innermost comment which could be
- // a doc block. Otherwise, treat the text as a code block.
- let mut last_delimiter_was_opening = true;
- // To correctly handle nested block comments, we must avoid
- // any other parsing (recognizing strings/heredocs, in
- // particular) until we leave the nested comment block.
- // Therefore, keep track of the nesting depth; when this
- // returns to 0, we've found outermost closing block comment
- // delimiter, and can return to normal parsing. At this
- // point in the code, we've found one opening block comment
- // delimiter, so the nesting depth starts at 1.
- let mut nesting_depth = 1;
- let mut loop_count = 0;
- // Loop until we've outside all nested block comments.
- while nesting_depth != 0 && loop_count < 10 {
- loop_count += 1;
- // Get the index of the next block comment delimiter.
#[cfg(feature = "lexer_explain")]
println!(
- "Looking for a block comment delimiter in '{}'.",
- &source_code[comment_start_index
- ..min(comment_start_index + 30, source_code.len())]
+ "The opening delimiter is '{}', and the closing delimiter regex is '{}'.",
+ matching_group_str, comment_delim_regex
);
- let delimiter_captures_wrapped =
- comment_delim_regex.captures(&source_code[comment_start_index..]);
- if delimiter_captures_wrapped.is_none() {
+
+ // For nested comments, only treat the innermost comment
+ // as a potential doc block; everything else is treated
+ // as code. The rationale:
+ //
+ // 1. Typically, nested comments are used to comment
+ // out a block of code, which may already contain
+ // "real" comments (as opposed to commented-out
+ // code). Therefore, we assume that only these
+ // innermost comments are true comments, while
+ // everything else is code. I can't think of any
+ // reason to nest true comments. Assuming a
+ // legitimate use for nested comments, what criteria
+ // would distinguish a nested comment from a
+ // commented-out code block?
+ // 2. The CodeChat Editor data structures don't support
+ // nested doc blocks. So, while we might be able to
+ // correctly parse nested comments as doc blocks,
+ // the code that transforms these back to code would
+ // remove the nesting.
+ // 3. We lack criteria that would distinguish a nested
+ // doc block from commented-out code.
+ //
+ // With these assumptions, we need to know if the
+ // current comment is the innermost or not. If the last
+ // block comment delimiter encountered was an opening
+ // comment, and the current block comment delimiter is a
+ // closing block comment, then this is an innermost
+ // comment which could be a doc block. Otherwise, treat
+ // the text as a code block.
+ let mut last_delimiter_was_opening = true;
+ // To correctly handle nested block comments, we must
+ // avoid any other parsing (recognizing
+ // strings/heredocs, in particular) until we leave the
+ // nested comment block. Therefore, keep track of the
+ // nesting depth; when this returns to 0, we've found
+ // outermost closing block comment delimiter, and can
+ // return to normal parsing. At this point in the code,
+ // we've found one opening block comment delimiter, so
+ // the nesting depth starts at 1.
+ let mut nesting_depth = 1;
+ let mut loop_count = 0;
+ // Loop until we've outside all nested block comments.
+ while nesting_depth != 0 && loop_count < 10 {
+ loop_count += 1;
+ // Get the index of the next block comment
+ // delimiter.
#[cfg(feature = "lexer_explain")]
- println!("The closing comment delimiter wasn't found.");
- // If there's no closing delimiter, this is not a
- // doc block; it's a syntax error. The safe route is
- // to assume the rest of the contents are code,
- // which this program won't edit; it does edit
- // comments by cleaning up HTML tags, word-wrapping,
- // etc. which would be a disaster if this was
- // applied to code.
- source_code_unlexed_index = source_code.len();
- // Exit the block comment processing code here.
- break 'block_comment;
- }
- let delimiter_captures = delimiter_captures_wrapped.unwrap();
- // Sanity check:
- assert!(
- // either this language doesn't support nested
- // comments, so only the overall match group (a
- // closing block comment delimiter) was captured,
- // or...
- delimiter_captures.len() == 1
+ println!(
+ "Looking for a block comment delimiter in '{}'.",
+ &source_code[comment_start_index
+ ..min(comment_start_index + 30, source_code.len())]
+ );
+ let delimiter_captures_wrapped =
+ comment_delim_regex.captures(&source_code[comment_start_index..]);
+ if delimiter_captures_wrapped.is_none() {
+ #[cfg(feature = "lexer_explain")]
+ println!("The closing comment delimiter wasn't found.");
+ // If there's no closing delimiter, this is not
+ // a doc block; it's a syntax error. The safe
+ // route is to assume the rest of the contents
+ // are code, which this program won't edit; it
+ // does edit comments by cleaning up HTML tags,
+ // word-wrapping, etc. which would be a disaster
+ // if this was applied to code.
+ source_code_unlexed_index = source_code.len();
+ // Exit the block comment processing code here.
+ break 'block_comment;
+ }
+ let delimiter_captures = delimiter_captures_wrapped.unwrap();
+ // Sanity check:
+ assert!(
+ // either this language doesn't support nested
+ // comments, so only the overall match group (a
+ // closing block comment delimiter) was
+ // captured, or...
+ delimiter_captures.len() == 1
// ...for languages that support nested
// comments, there are two capture groups
// (in addition to capture group 0, the
@@ -1045,356 +1073,370 @@ pub fn source_lexer(
&& delimiter_captures.get(2).is_none())
|| (delimiter_captures.get(1).is_none()
&& delimiter_captures.get(2).is_some())))
- );
- // Is this an opening comment delimiter?
- if let Some(opening_delimiter) = delimiter_captures.get(1) {
- // Yes.
- last_delimiter_was_opening = true;
- nesting_depth += 1;
- // Mark all previous text as code, then continue the
- // loop.
- #[cfg(feature = "lexer_explain")]
- println!(
- "opening_delimiter.start() = {}, opening_delimiter.len() = {}",
- opening_delimiter.start(),
- opening_delimiter.len()
- );
- source_code_unlexed_index +=
- comment_start_index + opening_delimiter.start();
- comment_start_index =
- source_code_unlexed_index + opening_delimiter.len();
- #[cfg(feature = "lexer_explain")]
- println!(
- "Found a nested opening block comment delimiter. Nesting depth: {}",
- &nesting_depth
);
- continue;
- } else {
- // This is a closing comment delimiter.
- nesting_depth -= 1;
- assert!(nesting_depth >= 0);
- let closing_delimiter_match = if delimiter_captures.len() == 3 {
- delimiter_captures.get(2).unwrap()
- } else {
- delimiter_captures.get(0).unwrap()
- };
-
- // If `last_delimiter_was_opening` was false, then
- // mark this text as code and continue the loop.
- if !last_delimiter_was_opening {
- source_code_unlexed_index += comment_start_index
- + closing_delimiter_match.start()
- + closing_delimiter_match.len();
- last_delimiter_was_opening = false;
+ // Is this an opening comment delimiter?
+ if let Some(opening_delimiter) = delimiter_captures.get(1) {
+ // Yes.
+ last_delimiter_was_opening = true;
+ nesting_depth += 1;
+ // Mark all previous text as code, then continue
+ // the loop.
#[cfg(feature = "lexer_explain")]
- println!("Found a non-innermost closing block comment delimiter. Nesting depth: {}", &nesting_depth);
+ println!(
+ "opening_delimiter.start() = {}, opening_delimiter.len() = {}",
+ opening_delimiter.start(),
+ opening_delimiter.len()
+ );
+ source_code_unlexed_index +=
+ comment_start_index + opening_delimiter.start();
+ comment_start_index =
+ source_code_unlexed_index + opening_delimiter.len();
+ #[cfg(feature = "lexer_explain")]
+ println!(
+ "Found a nested opening block comment delimiter. Nesting depth: {}",
+ &nesting_depth
+ );
continue;
- }
+ } else {
+ // This is a closing comment delimiter.
+ nesting_depth -= 1;
+ assert!(nesting_depth >= 0);
+ let closing_delimiter_match = if delimiter_captures.len() == 3 {
+ delimiter_captures.get(2).unwrap()
+ } else {
+ delimiter_captures.get(0).unwrap()
+ };
+
+ // If `last_delimiter_was_opening` was false,
+ // then mark this text as code and continue the
+ // loop.
+ if !last_delimiter_was_opening {
+ source_code_unlexed_index += comment_start_index
+ + closing_delimiter_match.start()
+ + closing_delimiter_match.len();
+ last_delimiter_was_opening = false;
+ #[cfg(feature = "lexer_explain")]
+ println!(
+ "Found a non-innermost closing block comment delimiter. Nesting depth: {}",
+ &nesting_depth
+ );
+ continue;
+ }
- // Otherwise, this is a potential doc block: it's an
- // innermost nested block comment. See if this
- // qualifies as a doc block.
- let closing_delimiter_start_index =
- closing_delimiter_match.start() + comment_start_index;
- let closing_delimiter_end_index =
- closing_delimiter_match.end() + comment_start_index;
+ // Otherwise, this is a potential doc block:
+ // it's an innermost nested block comment. See
+ // if this qualifies as a doc block.
+ let closing_delimiter_start_index =
+ closing_delimiter_match.start() + comment_start_index;
+ let closing_delimiter_end_index =
+ closing_delimiter_match.end() + comment_start_index;
- // Capture the body of the comment -- everything but
- // the opening and closing delimiters.
- let comment_body =
- &source_code[comment_start_index..closing_delimiter_start_index];
+ // Capture the body of the comment -- everything
+ // but the opening and closing delimiters.
+ let comment_body = &source_code
+ [comment_start_index..closing_delimiter_start_index];
- #[cfg(feature = "lexer_explain")]
- println!(
- "The comment body is\n\
+ #[cfg(feature = "lexer_explain")]
+ println!(
+ "The comment body is\n\
'{}'.\n\
The closing delimiter is '{}'.",
- comment_body,
- closing_delimiter_match.as_str()
- );
- // Find the first \\n after the closing delimiter.
- // If there is a newline after the closing
- // delimiter, set
- // `newline_or_eof_after_closing_delimiter_index` to
- // the index of the first newline after the closing
- // delimiter else set it to the end of the file.
- let newline_or_eof_after_closing_delimiter_index =
- match source_code[closing_delimiter_end_index..].find('\n') {
- // The + 1 includes the newline in the
- // resulting index.
- Some(index) => index + closing_delimiter_end_index + 1,
- None => source_code.len(),
- };
+ comment_body,
+ closing_delimiter_match.as_str()
+ );
+ // Find the first \\n after the closing
+ // delimiter. If there is a newline after the
+ // closing delimiter, set
+ // `newline_or_eof_after_closing_delimiter_index`
+ // to the index of the first newline after the
+ // closing delimiter else set it to the end of
+ // the file.
+ let newline_or_eof_after_closing_delimiter_index =
+ match source_code[closing_delimiter_end_index..].find('\n') {
+ // The + 1 includes the newline in the
+ // resulting index.
+ Some(index) => index + closing_delimiter_end_index + 1,
+ None => source_code.len(),
+ };
+
+ // Capture the line which begins after the
+ // closing delimiter and ends at the next
+ // newline/EOF.
+ let post_closing_delimiter_line = &source_code
+ [closing_delimiter_end_index
+ ..newline_or_eof_after_closing_delimiter_index];
- // Capture the line which begins after the closing
- // delimiter and ends at the next newline/EOF.
- let post_closing_delimiter_line = &source_code
- [closing_delimiter_end_index
- ..newline_or_eof_after_closing_delimiter_index];
-
- #[cfg(feature = "lexer_explain")]
- println!(
- "The post-comment line is '{}'.",
- post_closing_delimiter_line
- );
-
- // Set the `current_code_block` to contain preceding
- // code (which might be multiple lines) until the
- // block comment delimiter. Split this on newlines,
- // grouping all the lines before the last line into
- // `code_lines_before_comment` (which is all code),
- // and everything else (from the beginning of the
- // last line to where the block comment delimiter
- // appears) into `comment_line_prefix`. For example,
- // consider the fragment:
- // `a = 1\nb = 2 /* comment */`. After processing,
- // `code_lines_before_comment` will be "`a = 1\n`"
- // and `comment_line_prefix` will be "`b = 2` ".
- let current_code_block =
- &source_code[current_code_block_index..source_code_unlexed_index];
- let comment_line_prefix =
- current_code_block.rsplit('\n').next().unwrap();
- let code_lines_before_comment = ¤t_code_block
- [..current_code_block.len() - comment_line_prefix.len()];
-
- // Move to the next block of source code to be
- // lexed.
- source_code_unlexed_index =
- newline_or_eof_after_closing_delimiter_index;
+ #[cfg(feature = "lexer_explain")]
+ println!(
+ "The post-comment line is '{}'.",
+ post_closing_delimiter_line
+ );
+
+ // Set the `current_code_block` to contain
+ // preceding code (which might be multiple
+ // lines) until the block comment delimiter.
+ // Split this on newlines, grouping all the
+ // lines before the last line into
+ // `code_lines_before_comment` (which is all
+ // code), and everything else (from the
+ // beginning of the last line to where the block
+ // comment delimiter appears) into
+ // `comment_line_prefix`. For example, consider
+ // the fragment: `a = 1\nb = 2 /* comment */`.
+ // After processing, `code_lines_before_comment`
+ // will be "`a = 1\n`" and `comment_line_prefix`
+ // will be "`b = 2` ".
+ let current_code_block = &source_code
+ [current_code_block_index..source_code_unlexed_index];
+ let comment_line_prefix =
+ current_code_block.rsplit('\n').next().unwrap();
+ let code_lines_before_comment = ¤t_code_block
+ [..current_code_block.len() - comment_line_prefix.len()];
+
+ // Move to the next block of source code to be
+ // lexed.
+ source_code_unlexed_index =
+ newline_or_eof_after_closing_delimiter_index;
- #[cfg(feature = "lexer_explain")]
- println!(
- "current_code_block is '{}'\n\
+ #[cfg(feature = "lexer_explain")]
+ println!(
+ "current_code_block is '{}'\n\
comment_line_prefix is '{}'\n\
code_lines_before_comment is '{}'",
- current_code_block, comment_line_prefix, code_lines_before_comment
- );
+ current_code_block,
+ comment_line_prefix,
+ code_lines_before_comment
+ );
- // Next, determine if this is a doc block. Criteria
- // for doc blocks for a block comment:
- //
- // 1. Must have a space or newline after the
- // opening delimiter.
- // 2. Must not have anything besides whitespace
- // before the opening comment delimiter on the
- // same line. This whitespace becomes the
- // indent.
- // 3. Must not have anything besides whitespace
- // after the closing comment delimiter on the
- // same line. This whitespace is included, as if
- // it were inside the block comment. Rationale:
- // this avoids deleting text (or, in this case,
- // whitespace); moving that whitespace around
- // seems like a better alternative than deleting
- // it.
- if (comment_body.starts_with(' ') || comment_body.starts_with('\n'))
- && WHITESPACE_ONLY_REGEX.is_match(comment_line_prefix)
- && WHITESPACE_ONLY_REGEX.is_match(post_closing_delimiter_line)
- {
- // Put the `code_lines_before_comment` into the
- // code block.
- append_code_doc_block("", "", code_lines_before_comment);
-
- // If there's a space at the end of the comment
- // body, remove it; also remove the initial
- // space/newline at the beginning of the comment
- // body.
+ // Next, determine if this is a doc block.
+ // Criteria for doc blocks for a block comment:
//
- // This `unwrap()` is always safe, since we know
- // that `comment_body` starts with a space or
- // newline.
- let last_char = comment_body.chars().last().unwrap();
- let ends_with_space = last_char == ' ' &&
+ // 1. Must have a space or newline after the
+ // opening delimiter.
+ // 2. Must not have anything besides whitespace
+ // before the opening comment delimiter on
+ // the same line. This whitespace becomes
+ // the indent.
+ // 3. Must not have anything besides whitespace
+ // after the closing comment delimiter on
+ // the same line. This whitespace is
+ // included, as if it were inside the block
+ // comment. Rationale: this avoids deleting
+ // text (or, in this case, whitespace);
+ // moving that whitespace around seems like
+ // a better alternative than deleting it.
+ if (comment_body.starts_with(' ') || comment_body.starts_with('\n'))
+ && WHITESPACE_ONLY_REGEX.is_match(comment_line_prefix)
+ && WHITESPACE_ONLY_REGEX.is_match(post_closing_delimiter_line)
+ {
+ // Put the `code_lines_before_comment` into
+ // the code block.
+ append_code_doc_block("", "", code_lines_before_comment);
+
+ // If there's a space at the end of the
+ // comment body, remove it; also remove the
+ // initial space/newline at the beginning of
+ // the comment body.
+ //
+ // This `unwrap()` is always safe, since we
+ // know that `comment_body` starts with a
+ // space or newline.
+ let last_char = comment_body.chars().last().unwrap();
+ let ends_with_space = last_char == ' ' &&
// Don't remove a space at the end of the
// comment body when it's also the space at
// the beginning of the comment body
// (meaning it's a single-character comment
// body).
comment_body.len() > 1;
- let trimmed_comment_body = &comment_body
- [1..comment_body.len() - if ends_with_space { 1 } else { 0 }];
- // The contents of the doc block are the trimmed
- // comment body plus any whitespace after the
- // closing comment delimiter.
- let contents = &(trimmed_comment_body.to_string()
- + post_closing_delimiter_line);
- // The indent is the whitespace before the
- // opening comment delimiter.
- let indent = comment_line_prefix;
- // The opening comment delimiter was captured in
- // the initial match.
- let delimiter = matching_group_str;
-
- // #### Block comment indentation processing
- //
- // There are several cases:
- //
- // - A single line: `/* comment */`. No special
- // handling needed.
- // - Multiple lines, in two styles.
- // - Each line of the comment is not
- // consistently whitespace-indented. No
- // special handling needed. For example:
- //
- // ```C
- // /* This is
- // not
- // consistently indented. */
- // ```
- //
- // - Each line of the comment is consistently
- // whitespace-indented; for example:
- //
- // ```C
- // /* This is
- // consistently indented. */
- // ```
- //
- // Consistently indented means the first
- // non-whitespace character on a line aligns
- // with, but never comes before, the
- // comment's start. Another example:
- //
- // ```C
- // /* This is
- // correct
- //
- // indentation.
- // */
- // ```
- //
- // Note that the third (blank) line doesn't
- // have an indent; since that line consists
- // only of whitespace, this is OK. Likewise,
- // the last line (containing the closing
- // comment delimiter of `*/`) consists only
- // of whitespace after the comment
- // delimiters are removed.
- //
- // Determine if this comment is indented.
- //
- // Determine the starting column of the indent
- // (assuming this block comment has a valid
- // indent). The +1 represents the space after
- // the opening delimiter.
- let indent_column = indent.len() + delimiter.len() + 1;
- let split_contents: Vec<&str> =
- contents.split_inclusive('\n').collect();
- // We need at least two lines of comment
- // contents to look for an indent. This is just
- // a first guess at `is_indented`, not the final
- // value.
- let mut is_indented = split_contents.len() > 1;
- if is_indented {
- // Ignore the first line, since the indent
- // and delimiter have already been split out
- // for that line.
- for line in &split_contents[1..] {
- let this_line_indent = if line.len() < indent_column {
- line
- } else {
- &line[..indent_column]
- };
- if !WHITESPACE_ONLY_REGEX.is_match(this_line_indent) {
- is_indented = false;
- break;
+ let trimmed_comment_body = &comment_body[1..comment_body.len()
+ - if ends_with_space { 1 } else { 0 }];
+ // The contents of the doc block are the
+ // trimmed comment body plus any whitespace
+ // after the closing comment delimiter.
+ let contents = &(trimmed_comment_body.to_string()
+ + post_closing_delimiter_line);
+ // The indent is the whitespace before the
+ // opening comment delimiter.
+ let indent = comment_line_prefix;
+ // The opening comment delimiter was
+ // captured in the initial match.
+ let delimiter = matching_group_str;
+
+ // #### Block comment indentation processing
+ //
+ // There are several cases:
+ //
+ // * A single line: `/* comment */`. No
+ // special handling needed.
+ // * Multiple lines, in two styles.
+ // * Each line of the comment is not
+ // consistently whitespace-indented. No
+ // special handling needed. For example:
+ //
+ // ```C
+ // /* This is
+ // not
+ // consistently indented. */
+ // ```
+ //
+ // * Each line of the comment is consistently
+ // whitespace-indented; for example:
+ //
+ // ```C
+ // /* This is
+ // consistently indented. */
+ // ```
+ //
+ // Consistently indented means the first
+ // non-whitespace character on a line
+ // aligns with, but never comes before, the
+ // comment's start. Another example:
+ //
+ // ```C
+ // /* This is
+ // correct
+ //
+ // indentation.
+ // */
+ // ```
+ //
+ // Note that the third (blank) line doesn't
+ // have an indent; since that line consists
+ // only of whitespace, this is OK.
+ // Likewise, the last line (containing the
+ // closing comment delimiter of `*/`)
+ // consists only of whitespace after the
+ // comment delimiters are removed.
+ //
+ // Determine if this comment is indented.
+ //
+ // Determine the starting column of the
+ // indent (assuming this block comment has a
+ // valid indent). The +1 represents the
+ // space after the opening delimiter.
+ let indent_column = indent.len() + delimiter.len() + 1;
+ let split_contents: Vec<&str> =
+ contents.split_inclusive('\n').collect();
+ // We need at least two lines of comment
+ // contents to look for an indent. This is
+ // just a first guess at `is_indented`, not
+ // the final value.
+ let mut is_indented = split_contents.len() > 1;
+ if is_indented {
+ // Ignore the first line, since the indent
+ // and delimiter have already been split
+ // out for that line.
+ for line in &split_contents[1..] {
+ let this_line_indent = if line.len() < indent_column {
+ line
+ } else {
+ &line[..indent_column]
+ };
+ if !WHITESPACE_ONLY_REGEX.is_match(this_line_indent) {
+ is_indented = false;
+ break;
+ }
}
}
- }
- // If the comment was indented, dedent it;
- // otherwise, leave it unchanged.
- let mut buf = String::new();
- let dedented_contents = if is_indented {
- // If this is indented, then the first line
- // must exist.
- buf += split_contents[0];
- for line in &split_contents[1..] {
- // Remove the indent, unless this line
- // didn't have an indent (just whitespace).
- buf += if line.len() < indent_column {
- // Tricky case: in the middle of a comment,
- // every line always ends with a newline;
- // if there's not enough whitespace to
- // remove the indent, then replace that
- // with just a newline. At the end of a
- // comment which is the last line of a
- // file, a lack of whitespace shouldn't be
- // replaced with a newline, since it's not
- // there in the original.
- if line.ends_with('\n') {
- "\n"
+ // If the comment was indented, dedent it;
+ // otherwise, leave it unchanged.
+ let mut buf = String::new();
+ let dedented_contents = if is_indented {
+ // If this is indented, then the first line
+ // must exist.
+ buf += split_contents[0];
+ for line in &split_contents[1..] {
+ // Remove the indent, unless this line
+ // didn't have an indent (just whitespace).
+ buf += if line.len() < indent_column {
+ // Tricky case: in the middle of a comment,
+ // every line always ends with a newline;
+ // if there's not enough whitespace to
+ // remove the indent, then replace that
+ // with just a newline. At the end of a
+ // comment which is the last line of a
+ // file, a lack of whitespace shouldn't be
+ // replaced with a newline, since it's not
+ // there in the original.
+ if line.ends_with('\n') { "\n" } else { "" }
} else {
- ""
- }
- } else {
- &line[indent_column..]
- };
- }
- &buf
+ &line[indent_column..]
+ };
+ }
+ &buf
+ } else {
+ contents
+ };
+
+ // Add this doc block:
+ append_code_doc_block(indent, delimiter, dedented_contents);
+
+ // print the doc block
+ #[cfg(feature = "lexer_explain")]
+ println!(
+ "Appending a doc block with indent '{}', delimiter '{}', and contents '{}'.",
+ &comment_line_prefix, matching_group_str, contents
+ );
+
+ // advance `current_code_block_index` to
+ // `source_code_unlexed_index`, since we've
+ // moved everything in the current code
+ // block into the `classified_source`.
+ current_code_block_index = source_code_unlexed_index;
+ // Likewise, move the `comment_start_index`
+ // up, since everything before
+ // `source_code_unlexed_index` has been
+ // classified.
+ comment_start_index = source_code_unlexed_index;
} else {
- contents
- };
-
- // Add this doc block:
- append_code_doc_block(indent, delimiter, dedented_contents);
-
- // print the doc block
- #[cfg(feature = "lexer_explain")]
- println!("Appending a doc block with indent '{}', delimiter '{}', and contents '{}'.", &comment_line_prefix, matching_group_str, contents);
-
- // advance `current_code_block_index` to
- // `source_code_unlexed_index`, since we've
- // moved everything in the current code block
- // into the `classified_source`.
- current_code_block_index = source_code_unlexed_index;
- // Likewise, move the `comment_start_index` up,
- // since everything before
- // `source_code_unlexed_index` has been
- // classified.
- comment_start_index = source_code_unlexed_index;
- } else {
- // Nothing to do -- the comment was simply added
- // to the current code block already.
+ // Nothing to do -- the comment was simply
+ // added to the current code block already.
+ }
}
}
}
- }
- // #### String-like syntax
- RegexDelimType::String(closing_regex) => {
- #[cfg(feature = "lexer_explain")]
- print!("This is a string. ");
- append_code(closing_regex)
- }
+ // #### String-like syntax
+ RegexDelimType::String(closing_regex) => {
+ #[cfg(feature = "lexer_explain")]
+ print!("This is a string. ");
+ append_code(closing_regex)
+ }
- RegexDelimType::TemplateLiteral => {
- #[cfg(feature = "lexer_explain")]
- print!("This is a template literal. ");
- append_code(&TEMPLATE_LITERAL_CLOSING_REGEX);
- }
+ RegexDelimType::TemplateLiteral => {
+ #[cfg(feature = "lexer_explain")]
+ print!("This is a template literal. ");
+ append_code(&TEMPLATE_LITERAL_CLOSING_REGEX);
+ }
- RegexDelimType::Heredoc(stop_prefix, stop_suffix) => {
- #[cfg(feature = "lexer_explain")]
- print!("This is a heredoc. ");
-
- // Get the string from the source code which (along with the
- // stop prefix/suffix) defines the end of the heredoc.
- let heredoc_string = &classify_match[language_lexer_compiled.map.len() + 1];
- // Make a regex from it.
- let closing_regex = Regex::new(
- &(stop_prefix.to_owned() + ®ex::escape(heredoc_string) + stop_suffix),
- )
- .unwrap();
- // Use this to find the end of the heredoc and add that to
- // `current_source_code`.
- append_code(&closing_regex);
+ RegexDelimType::Heredoc(stop_prefix, stop_suffix) => {
+ #[cfg(feature = "lexer_explain")]
+ print!("This is a heredoc. ");
+
+ // Get the string from the source code which (along with
+ // the stop prefix/suffix) defines the end of the
+ // heredoc.
+ let heredoc_string = &classify_match[language_lexer_compiled.map.len() + 1];
+ // Make a regex from it.
+ let closing_regex = Regex::new(
+ &(stop_prefix.to_owned()
+ + ®ex::escape(heredoc_string)
+ + stop_suffix),
+ )
+ .unwrap();
+ // Use this to find the end of the heredoc and add that
+ // to `current_source_code`.
+ append_code(&closing_regex);
+ }
}
}
- } else {
- // There's no match, so the rest of the source code belongs in the
- // current code block.
- source_code_unlexed_index = source_code.len();
+ _ => {
+ // There's no match, so the rest of the source code belongs in
+ // the current code block.
+ source_code_unlexed_index = source_code.len();
+ }
}
}
@@ -1404,10 +1446,11 @@ pub fn source_lexer(
classified_source
}
-// ## Tests
+// Tests
+// -----
//
-// Rust
-// [almost mandates](https://doc.rust-lang.org/book/ch11-03-test-organization.html)
+// Rust [almost
+// mandates](https://doc.rust-lang.org/book/ch11-03-test-organization.html)
// putting tests in the same file as the source, which I dislike. Here's a way
// to place them in a separate file.
#[cfg(test)]
diff --git a/server/src/lexer/lexer-walkthrough.md b/server/src/lexer/lexer-walkthrough.md
index aa73ca40..bfb69d4b 100644
--- a/server/src/lexer/lexer-walkthrough.md
+++ b/server/src/lexer/lexer-walkthrough.md
@@ -16,72 +16,79 @@ You should have received a [copy](LICENSE.html) of the GNU General Public
License along with the CodeChat Editor. If not, see
[https://www.gnu.org/licenses/](https://www.gnu.org/licenses/).
-# Lexer walkthrough
+Lexer walkthrough
+=================
This walkthrough shows how the lexer parses the following Python code fragment:
-print("""¶\
-# This is not a comment! It's a multi-line
+print("""¶\
+# This is not a comment! It's a multi-line
string.¶\
-""")¶\
-# This is a comment.
+""")¶\
+# This is a comment.
Paragraph marks (the ¶ character) are included to show how the lexer handles
-newlines. To explain the operation of the lexer, the code will be highlighted
-in yellow to represent the
-unlexed source code,
-represented by the contents of the
-variable `source_code[source_code_unlexed_index..]` and in green for the
-current code block,
-defined by `source_code[current_code_block_index..source_code_unlexed_index]`.
-Code that is classified by the lexer will be placed in the `classified_code`
-array.
-
-## Start of parse
-
-The unlexed source
-code holds all the code (everything is highlighted in yellow); the
-current code block
-is empty (there is no green highlight).
-
-print("""¶\
-#
+newlines. To explain the operation of the lexer, the code will be highlighted in
+yellow to represent the unlexed source
+code, represented by the contents of the variable
+`source_code[source_code_unlexed_index..]` and in green for the current code block, defined by
+`source_code[current_code_block_index..source_code_unlexed_index]`. Code that is
+classified by the lexer will be placed in the `classified_code` array.
+
+Start of parse
+--------------
+
+The unlexed source code holds
+all the code (everything is highlighted in yellow); the current code block is empty (there is
+no green highlight).
+
+print("""¶\
+#
This is not a comment! It's a multi-line string.¶\
-""")¶\
- #
-This is a comment.
+""")¶\
+
+ # This is a comment.
```
classified_code = [
]
```
-## Search for a token
+Search for a token
+------------------
The lexer begins by searching for the regex in
`language_lexer_compiled.next_token`, which is `(\#)|(""")|(''')|(")|(')`. The
-first token found is
-""". Everything up
-to the match is moved from the unlexed source code to the current code block,
-giving:
+first token found is """.
+Everything up to the match is moved from the unlexed source code to the current
+code block, giving:
-print("""¶\
-#
+print("""¶\
+#
This is not a comment! It's a multi-line string.¶\
-""")¶\
- #
-This is a comment.
+""")¶\
+
+ # This is a comment.
```
classified_code = [
]
```
-## String processing
+String processing
+-----------------
The regex is accompanied by a map named `language_lexer_compiled.map`, which
-connects the mapped group to which token it matched (see
-`struct RegexDelimType`):
+connects the mapped group to which token it matched (see `struct
+RegexDelimType`):
```
Regex: (#) | (""") | (''') | (") | (')
@@ -91,81 +98,92 @@ Group: 1 2 3 4 5
Since group 2 matched, looking up this group in the map tells the lexer it’s a
string, and also gives a regex which identifies the end of the string . This
-regex identifies the end of the string, moving it from the
-(unclassified) source
-code to the (classified)
-current code block.
+regex identifies the end of the string, moving it from the (unclassified) source code to the
+(classified) current code block.
It correctly skips what looks like a comment but is not a comment. After this
step, the lexer’s state is:
-print("""¶\
-#
+print("""¶\
+#
This is not a comment! It's a multi-line string.¶\
-""")¶\
- #
-This is a comment.
+""")¶\
+
+ # This is a comment.
```
classified_code = [
]
```
-## Search for a token (second time)
+Search for a token (second time)
+--------------------------------
Now, the lexer is back to its state of looking through code (as opposed to
looking inside a string, comment, etc.). It uses the `next_token` regex as
-before to identify the next token
-# and moves all the
-preceding characters from source code to the current code block. The lexer
-state is now:
+before to identify the next token # and moves all the preceding characters from
+source code to the current code block. The lexer state is now:
-print("""¶\
-#
+print("""¶\
+#
This is not a comment! It's a multi-line string.¶\
-""")¶\
- #
-This is a comment.
+""")¶\
+
+ # This is a
+comment.
```
classified_code = [
]
```
-## Inline comment lex
+Inline comment lex
+------------------
Based on the map, the lexer identifies this as an inline comment. The inline
comment lexer first identifies the end of the comment (the next newline or, as
-in this case, the end of the file), putting the entire inline comment except
-for the comment opening delimiter
-# into
-full_comment.
-It then splits the current code block into two
-groups: code_lines_before_comment
-(lines in the current code block which come before the current line) and the
-comment_line_prefix
-(the current line up to the start of the comment). The classification is:
-
-print("""¶\
-#
+in this case, the end of the file), putting the entire inline comment except for
+the comment opening delimiter # into full_comment. It then splits the current code
+block into two groups: code_lines_before_comment (lines in the current
+code block which come before the current line) and the comment_line_prefix (the
+current line up to the start of the comment). The classification is:
+
+print("""¶\
+#
This is not a comment! It's a multi-line string.¶\
-""")¶\
- #
-This is a comment.
+""")¶\
+
+ # This is a
+comment.
```
classified_code = [
]
```
-## Code/doc block classification
+Code/doc block classification
+-----------------------------
-Because
-comment_line_prefix
-contains only whitespace and
-full_comment has a
-space after the comment delimiter, the lexer classifies this as a doc block. It
-adds code_lines_before_comment
-as a code block, then the text of the comment as a doc block:
+Because comment_line_prefix contains only whitespace and full_comment has a space after the
+comment delimiter, the lexer classifies this as a doc block. It adds code_lines_before_comment as a code
+block, then the text of the comment as a doc block:
```
classified_code = [
@@ -180,8 +198,8 @@ classified_code = [
]
```
-## Done
+Done
+----
-After this, the unlexed source code is empty since the inline comment
-classified moved the remainder of its contents into `classified_code`. The
-function exits.
+After this, the unlexed source code is empty since the inline comment classified
+moved the remainder of its contents into `classified_code`. The function exits.
\ No newline at end of file
diff --git a/server/src/lexer/pest/c.pest b/server/src/lexer/pest/c.pest
index 578c2f03..4891c9a6 100644
--- a/server/src/lexer/pest/c.pest
+++ b/server/src/lexer/pest/c.pest
@@ -14,21 +14,23 @@
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
-// # `c.pest` - Pest parser definition for the C language
+// `c.pest` - Pest parser definition for the C language
+// ====================================================
//
-// ## Comments
+// Comments
+// --------
doc_block = _{ inline_comment | block_comment }
-// Per the
-// [C standard, section 6.4.3](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#page=65),
+// Per the [C standard, section
+// 6.4.3](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#page=65),
// "white-space consists of: (space, horizontal tab, new-line, vertical tab, and
// form-feed)." Omit newlines, since the rest of this parser uses these.
vertical_tab = { "\x0B" }
form_feed = { "\x0C" }
white_space = { (" " | "\t" | vertical_tab | form_feed)* }
-// The
-// [C standard, section 6.4.9](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#page=65),
+// The [C standard, section
+// 6.4.9](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#page=65),
// defines inline and block comments.
//
// ### Inline comments
@@ -47,10 +49,11 @@ block_comment_closing_delim_0 = { "*/" }
block_comment_closing_delim_1 = { unused }
block_comment_closing_delim_2 = { unused }
-// ## Code
+// Code
+// ----
//
-// Per the
-// [C standard, section 5.1.1.2](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#page=24),
+// Per the [C standard, section
+// 5.1.1.2](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#page=24),
// if a line of code ends with a backslash, it continues on the next line. This
// is a logical line; treat it as a single line. Therefore, consider a
// backslash-newline (or anything that's not a newline) a part of the current
@@ -59,11 +62,12 @@ block_comment_closing_delim_2 = { unused }
//
// 1. Comments continued onto another line don't look like a comment; this
// would confuse most developers.
-// 2. The backslash-newline in a comment creates a
-// [hard line break](https://spec.commonmark.org/0.31.2/#hard-line-breaks)
-// in Markdown, which means inserting a hard line break this way in an
-// inline comment requires the next line to omit the inline comment
-// delimiters. For example:
+//
+// 2. The backslash-newline in a comment creates a [hard line
+// break](https://spec.commonmark.org/0.31.2/#hard-line-breaks) in Markdown,
+// which means inserting a hard line break this way in an inline comment
+// requires the next line to omit the inline comment delimiters. For
+// example:
//
// ```C
// // This is a hard line break\
@@ -71,65 +75,69 @@ block_comment_closing_delim_2 = { unused }
// // delimiter on the line after the line break, but which must
// include them on following lines.
// ```
+//
// 3. The CodeChat Editor web-to-code function produces incorrect results in
// this case, adding a comment delimiter when it shouldn't. To fix this, it
// would have to look for a backslash newline only in C/C++-like languages.
logical_line_char = _{ ("\\" ~ NEWLINE) | not_newline }
code_line_token = _{ logical_line_char }
-// ## Dedenter
+// Dedenter
+// --------
//
// This parser runs separately; it dedents block comments. There are several
// cases:
//
-// - A single line: `/* comment */`. No special handling needed.
-// - Multiple lines, in two styles.
-// - Each line of the comment is not consistently whitespace-indented. No
-// special handling needed. For example:
-//
-// ```C
-// /* This is
-// not
-// consistently indented. */
-// ```
-//
-// - Each line of the comment is consistently whitespace-indented; for
-// example:
-//
-// ```C
-// /* This is
-// consistently indented. */
-// ```
-//
-// Consistently indented means the first non-whitespace character on a line
-// aligns with, but never comes before, the comment's start. Another
-// example:
-//
-// ```C
-// /* This is
-// correct
-//
-// indentation.
-// */
-// ```
-//
-// Note that the third (blank) line doesn't have an indent; since that line
-// consists only of whitespace, this is OK. Likewise, the last line
-// (containing the closing comment delimiter of `*/`) consists only of
-// whitespace after the comment delimiters are removed.
-//
-// - Each line of the comment is consistently asterisk-indented; for example:
-//
-// ```C
-// /* This is
-// * correct
-// *
-// * indentation.
-// */
-// ```
-//
-// Note that in this case, no whitespace-only lines are allowed. Instead,
-// the special case is lines which have a newline immediately after the `*`.
+// * A single line: `/* comment */`. No special handling needed.
+// * Multiple lines, in two styles.
+// * Each line of the comment is not consistently whitespace-indented. No
+// special handling needed. For example:
+//
+// ```C
+// /* This is
+// not
+// consistently indented. */
+// ```
+//
+// * Each line of the comment is consistently whitespace-indented; for
+// example:
+//
+// ```C
+// /* This is
+// consistently indented. */
+// ```
+//
+// Consistently indented means the first non-whitespace character on a
+// line aligns with, but never comes before, the comment's start.
+// Another example:
+//
+// ```C
+// /* This is
+// correct
+//
+// indentation.
+// */
+// ```
+//
+// Note that the third (blank) line doesn't have an indent; since that
+// line consists only of whitespace, this is OK. Likewise, the last line
+// (containing the closing comment delimiter of `*/`) consists only of
+// whitespace after the comment delimiters are removed.
+//
+// * Each line of the comment is consistently asterisk-indented; for
+// example:
+//
+// ```C
+// /* This is
+// * correct
+// *
+// * indentation.
+// */
+// ```
+//
+// Note that in this case, no whitespace-only lines are allowed.
+// Instead, the special case is lines which have a newline immediately
+// after the `*`.
//
// To implement this dedenting, we must have two paths to accepting the contents
// of a block comment. Otherwise, this parser rejects the block (it cannot be
@@ -162,4 +170,4 @@ vis_newline = { NEWLINE }
not_newline_eoi = _{ !(NEWLINE ~ EOI) }
star_dedent = _{ PEEK ~ " * " }
-// CodeChat Editor lexer: c_cpp.
+/// CodeChat Editor lexer: c_cpp.
diff --git a/server/src/lexer/pest/parser_design.md b/server/src/lexer/pest/parser_design.md
index d5a5d40b..3b10ac41 100644
--- a/server/src/lexer/pest/parser_design.md
+++ b/server/src/lexer/pest/parser_design.md
@@ -1,4 +1,5 @@
-# Parser design
+Parser design
+=============
The CodeChat Editor uses the [Pest parser](https://pest.rs/), a Rust
implementation of a parsing expression grammar (or PEG). The purpose of the
@@ -6,39 +7,46 @@ parser from a CodeChat Editor perspective is to classify a source file into code
blocks and doc blocks. To accomplish this goal, grammar files (`.pest`) are
divided into:
-- A shared grammar ([shared.pest](shared.pest)), which contains basic
- definitions applicable to all languages;
-- A language-specific grammar, which builds on these shared definitions by
- providing necessary language-specific customizations.
+* A shared grammar ([shared.pest](shared.pest)), which contains basic
+ definitions applicable to all languages;
+* A language-specific grammar, which builds on these shared definitions by
+ providing necessary language-specific customizations.
In particular, a language-specific grammar must provide:
-- The definition of a `doc_block`; for most languages,
- `doc_block = _{ 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:
+* The definition of a `doc_block`; for most languages, `doc_block = _{
+ 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:
+
+ ```
+ inline_comment_delims = _{ inline_comment_delim_0 }
+ inline_comment_delim_0 = { "//" }
+ inline_comment_delim_1 = { unused }
+ inline_comment_delim_2 = { unused }
+ ```
+
+ * A token which defines characters in the body of on an inline comment.
+ For Python, this is:
+
+ ```
+ inline_comment_char = { not_newline }
+ ```
+
+* Block comment definitions: provide opening and closing delimiter
+ definitions. For C, this is:
```
- inline_comment_delims = _{ inline_comment_delim_0 }
- inline_comment_delim_0 = { "//" }
- inline_comment_delim_1 = { unused }
- inline_comment_delim_2 = { unused }
- ```
- - A token which defines characters in the body of on an inline comment. For Python, this is:
- ```
- inline_comment_char = { not_newline }
+ block_comment = { block_comment_0 }
+ block_comment_opening_delim_0 = { "/*" }
+ block_comment_opening_delim_1 = { unused }
+ block_comment_opening_delim_2 = { unused }
+ block_comment_closing_delim_0 = { "*/" }
+ block_comment_closing_delim_1 = { unused }
+ block_comment_closing_delim_2 = { unused }
```
-- Block comment definitions: provide opening and closing delimiter definitions. For C, this is:
- ```
- block_comment = { block_comment_0 }
- block_comment_opening_delim_0 = { "/*" }
- block_comment_opening_delim_1 = { unused }
- block_comment_opening_delim_2 = { unused }
- block_comment_closing_delim_0 = { "*/" }
- block_comment_closing_delim_1 = { unused }
- block_comment_closing_delim_2 = { unused }
- ```
-- `code_line_token`, a token used to recognize tokens in a code line.
+
+* `code_line_token`, a token used to recognize tokens in a code line.
\ No newline at end of file
diff --git a/server/src/lexer/pest/python.pest b/server/src/lexer/pest/python.pest
index cdf0dbc1..0e96d79e 100644
--- a/server/src/lexer/pest/python.pest
+++ b/server/src/lexer/pest/python.pest
@@ -14,28 +14,30 @@
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
-// # `python.pest` - Pest parser definition for Python
+// `python.pest` - Pest parser definition for Python
+// =================================================
doc_block = _{ inline_comment }
-// Per the
-// [Python language reference](https://docs.python.org/3/reference/lexical_analysis.html#indentation),
+// Per the [Python language
+// reference](https://docs.python.org/3/reference/lexical_analysis.html#indentation),
// leading whitespace used to determine the indentation level consists of spaces
// and tabs.
white_space = { (" " | "\t")* }
-// ## Inline comments
-//
+// Inline comments
+// ---------------
inline_comment_delims = _{ inline_comment_delim_0 }
inline_comment_delim_0 = { "#" }
inline_comment_delim_1 = { unused }
inline_comment_delim_2 = { unused }
-// Per the
-// [Python language reference, section 2.1.3](https://docs.python.org/3/reference/lexical_analysis.html#comments),
+// Per the [Python language reference, section
+// 2.1.3](https://docs.python.org/3/reference/lexical_analysis.html#comments),
// comments end at the end of a physical line. There's no C-like backslash that
// can join physical lines into logical lines for comments.
inline_comment_char = { not_newline }
-// ## Block comments
+// Block comments
+// --------------
//
// Other languages support block comments; even though Python doesn't, the
// following must be defined. Block comments never combine.
@@ -47,7 +49,8 @@ block_comment_closing_delim_0 = { unused }
block_comment_closing_delim_1 = { unused }
block_comment_closing_delim_2 = { unused }
-// ## Code blocks
+// Code blocks
+// -----------
code_line_token = _{ long_string | short_string | not_newline }
long_string = _{
// The opening string delimiter.
@@ -69,7 +72,8 @@ short_string = _{
(POP | ((EOI | &NEWLINE) ~ DROP) )
}
-// ## Dedenter
+// Dedenter
+// --------
dedenter = { unused }
-// CodeChat Editor lexer: c_cpp.
+/// CodeChat Editor lexer: c_cpp.
diff --git a/server/src/lexer/pest/shared.pest b/server/src/lexer/pest/shared.pest
index cc9e2544..1f8b5911 100644
--- a/server/src/lexer/pest/shared.pest
+++ b/server/src/lexer/pest/shared.pest
@@ -14,10 +14,12 @@
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
//
-// # `shared.pest` - Pest parser definition shared by all languages
+// `shared.pest` - Pest parser definition shared by all languages
+// ==============================================================
file = { SOI ~ (doc_block | code_block)* ~ EOI }
-// ## Inline comments
+// Inline comments
+// ---------------
//
// Use this approach to match a group of inline comments with the same
// whitespace indentation.
@@ -39,11 +41,12 @@ inline_comment_line = { (" " ~ inline_comment_body) | newline_eoi }
//
// becomes:
//
-// - inline_comment_body > logical_line: `a\n`
-// - inline_comment_body: `\n`
+// * inline\_comment\_body > logical\_line: `a\n`
+// * inline\_comment\_body: `\n`
inline_comment_body = { inline_comment_char* ~ newline_eoi }
-// ## Block comments
+// Block comments
+// --------------
//
// Support multiple opening and closing delimiters using some repetition.
block_comment_0 = _{
@@ -68,14 +71,16 @@ optional_space = { " "? }
// Use this so that the ending (usually a newline) gets captured in a token.
block_comment_ending = { newline_eoi }
-// ## Code blocks
+// Code blocks
+// -----------
code_block = { code_line+ }
code_line = _{ (!doc_block ~ code_line_token* ~ NEWLINE) | (!doc_block ~ code_line_token+ ~ EOI) }
-// ## Other commonly-used tokens
+// Other commonly-used tokens
+// --------------------------
newline_eoi = _{ NEWLINE | EOI }
not_newline = _{ !NEWLINE ~ ANY }
// Indicates this token isn't used by the parser.
unused = { "unused" }
-// CodeChat Editor lexer: c_cpp.
+/// CodeChat Editor lexer: c_cpp.
diff --git a/server/src/lexer/pest_parser.rs b/server/src/lexer/pest_parser.rs
index 7594c872..5b14e766 100644
--- a/server/src/lexer/pest_parser.rs
+++ b/server/src/lexer/pest_parser.rs
@@ -13,8 +13,12 @@
// You should have received a copy of the GNU General Public License along with
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
-// # `pest_parser.rs` -- Lex source code into code and doc blocks
-// ## Imports
+//
+// `pest_parser.rs` -- Lex source code into code and doc blocks
+// ============================================================
+//
+// Imports
+// -------
//
// ### Standard library
//
@@ -27,12 +31,13 @@
// ### Local
//
// None.
-//
-/// ## Parser generator
-/// This macro generates a parser function that converts the provided string into
-/// a series of code and doc blocks. I'd prefer to use traits, but don't see a
-/// way to pass the `Rule` types as a usable. (Using `RuleType` means we can't
-/// access `Rule::file`, etc.)
+/// Parser generator
+/// ----------------
+///
+/// This macro generates a parser function that converts the provided string
+/// into a series of code and doc blocks. I'd prefer to use traits, but don't
+/// see a way to pass the `Rule` types as a usable. (Using `RuleType` means we
+/// can't access `Rule::file`, etc.)
#[macro_export]
macro_rules! make_parse_to_code_doc_blocks {
($parser: ty) => {
@@ -45,22 +50,23 @@ macro_rules! make_parse_to_code_doc_blocks {
&String::from_iter(normalize_line_endings::normalized(input.chars()));
let pairs = match <$parser>::parse(Rule::file, normalized_input) {
Ok(pairs) => pairs,
- Err(e) =>
- panic!("Parse error: {e:#?}")
+ Err(e) => panic!("Parse error: {e:#?}"),
}
- // The first (and only) element is the `file` token.
- .next()
- .unwrap()
- // Return the contents of this token (code and doc block
- // tokens).
- .into_inner();
+ // The first (and only) element is the `file` token.
+ .next()
+ .unwrap()
+ // Return the contents of this token (code and doc block tokens).
+ .into_inner();
// For debugging, print out the parse tree.
//println!("{:#?}", pairs);
// The last token is the `EOI` token.
assert_eq!(pairs.clone().last().unwrap().as_rule(), Rule::EOI);
// Transform these tokens into code and doc blocks; ignore the last
// token (EOI).
- pairs.rev().skip(1).rev()
+ pairs
+ .rev()
+ .skip(1)
+ .rev()
.map(|block| match block.as_rule() {
Rule::inline_comment => {
// Gather all tokens in the inline comment.
@@ -70,29 +76,35 @@ macro_rules! make_parse_to_code_doc_blocks {
let whitespace = whitespace_pair.as_str();
let inline_comment_delim = inline_comment.next().unwrap();
// Combine the text of all the inline comments.
- let comment = &mut inline_comment.fold(String::new(), |mut acc, inline_comment_body| {
- assert_eq!(inline_comment_body.as_rule(), Rule::inline_comment_line);
- let s = inline_comment_body.as_str();
- let inner = &mut inline_comment_body.into_inner();
- // See the notes on inline comments in
- // [c.pest](pest/c.pest) for the expected structure
- // of the `inline_comment_body`.
- let contents = if let Some(inline_comment_contents) = inner.next() {
- // For comments which contains contents, include
- // that.
- inline_comment_contents.as_str()
- } else {
- // For comments which are just a newline, include
- // that.
- s
- };
- assert!(inner.next().is_none());
+ let comment = &mut inline_comment.fold(
+ String::new(),
+ |mut acc, inline_comment_body| {
+ assert_eq!(
+ inline_comment_body.as_rule(),
+ Rule::inline_comment_line
+ );
+ let s = inline_comment_body.as_str();
+ let inner = &mut inline_comment_body.into_inner();
+ // See the notes on inline comments in
+ // [c.pest](pest/c.pest) for the expected
+ // structure of the `inline_comment_body`.
+ let contents = if let Some(inline_comment_contents) = inner.next() {
+ // For comments which contains contents,
+ // include that.
+ inline_comment_contents.as_str()
+ } else {
+ // For comments which are just a newline,
+ // include that.
+ s
+ };
+ assert!(inner.next().is_none());
- // Add this string (the raw newline, or the comment
- // contents) to the accumulator.
- acc.push_str(contents);
- acc
- });
+ // Add this string (the raw newline, or the
+ // comment contents) to the accumulator.
+ acc.push_str(contents);
+ acc
+ },
+ );
// Determine which opening delimiter was used.
let _delimiter_index = match inline_comment_delim.as_rule() {
@@ -124,19 +136,22 @@ macro_rules! make_parse_to_code_doc_blocks {
let block_comment_pre = block_comment_pre_pair.as_str();
let comment_pair = block_comment.next().unwrap();
assert!(
- comment_pair.as_rule() == Rule::contents_0 ||
- comment_pair.as_rule() == Rule::contents_1 ||
- comment_pair.as_rule() == Rule::contents_2
+ comment_pair.as_rule() == Rule::contents_0
+ || comment_pair.as_rule() == Rule::contents_1
+ || comment_pair.as_rule() == Rule::contents_2
);
let comment = comment_pair.as_str();
let optional_space_pair = block_comment.next().unwrap();
assert_eq!(optional_space_pair.as_rule(), Rule::optional_space);
let optional_space = optional_space_pair.as_str();
- let block_comment_closing_delim_rule = block_comment.next().unwrap().as_rule();
+ let block_comment_closing_delim_rule =
+ block_comment.next().unwrap().as_rule();
assert!(
- block_comment_closing_delim_rule == Rule::block_comment_closing_delim_0 ||
- block_comment_closing_delim_rule == Rule::block_comment_closing_delim_1 ||
- block_comment_closing_delim_rule == Rule::block_comment_closing_delim_2
+ block_comment_closing_delim_rule == Rule::block_comment_closing_delim_0
+ || block_comment_closing_delim_rule
+ == Rule::block_comment_closing_delim_1
+ || block_comment_closing_delim_rule
+ == Rule::block_comment_closing_delim_2
);
let post_whitespace_pair = block_comment.next().unwrap();
assert_eq!(post_whitespace_pair.as_rule(), Rule::white_space);
@@ -145,7 +160,10 @@ macro_rules! make_parse_to_code_doc_blocks {
// is exactly what we want. Otherwise, use the newline
// provided by the `block_comment_ending` token.
let block_comment_ending_pair = block_comment.next().unwrap();
- assert_eq!(block_comment_ending_pair.as_rule(), Rule::block_comment_ending);
+ assert_eq!(
+ block_comment_ending_pair.as_rule(),
+ Rule::block_comment_ending
+ );
let block_comment_ending = block_comment_ending_pair.as_str();
assert!(block_comment.next().is_none());
@@ -232,7 +250,8 @@ macro_rules! make_parse_block_comment {
};
}
-// ## Parsers
+// Parsers
+// -------
//
// Each parser is kept in a separate module to avoid name conflicts, since Pest
// generates a `Rule` enum for each grammar.
@@ -260,7 +279,8 @@ pub mod python {
make_parse_block_comment!(ThisParser);
}
-// ## Tests
+// Tests
+// -----
#[cfg(test)]
mod test {
use indoc::indoc;
diff --git a/server/src/lexer/supported_languages.rs b/server/src/lexer/supported_languages.rs
index bd4c105f..ba4a5573 100644
--- a/server/src/lexer/supported_languages.rs
+++ b/server/src/lexer/supported_languages.rs
@@ -14,12 +14,14 @@
/// the CodeChat Editor. If not, see
/// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
///
-/// # `supported_languages.rs` - Provide lexer info for all supported languages
+/// `supported_languages.rs` - Provide lexer info for all supported languages
+/// =========================================================================
///
/// This file contains a data structure which describes all supported languages;
/// the [lexer](../lexer.rs) uses this lex a given language.
///
-/// ## Lexer implementation
+/// Lexer implementation
+/// --------------------
///
/// Ordering matters: all these delimiters end up in a large regex separated by
/// an or operator. The regex or operator matches from left to right. So, longer
@@ -42,18 +44,20 @@
/// strings. In this case, they would be `'She'` and `'s here.'`. While this
/// doesn't parse the string correctly, it does correctly identify where
/// comments can't be, which is all that the lexer needs to do.
-// ## Imports
+// Imports
+// -------
//
// ### Standard library
use std::sync::Arc;
// ### Local
use super::{
- pest_parser, BlockCommentDelim, CodeDocBlock, HeredocDelim, LanguageLexer, NewlineSupport,
- SpecialCase, StringDelimiterSpec,
+ BlockCommentDelim, CodeDocBlock, HeredocDelim, LanguageLexer, NewlineSupport, SpecialCase,
+ StringDelimiterSpec, pest_parser,
};
-// ## Helper functions
+// Helper functions
+// ----------------
//
// These functions simplify the syntax needed to create a `LanguageLexer`.
#[allow(clippy::too_many_arguments)]
@@ -118,7 +122,8 @@ fn make_block_comment_delim(opening: &str, closing: &str, is_nestable: bool) ->
}
}
-// ## Define lexers for each supported language.
+// Define lexers for each supported language.
+// ------------------------------------------
pub fn get_language_lexer_vec() -> Vec {
vec.
- // TODO: Pest doesn't support line continuations and allows
- // multiline strings, so this is a inaccurate.
+ // * The `.ino` extension is for Arduino source files.
+ // * The `.pest` extension is for [Pest
+ // grammars](https://docs.rs/pest/latest/pest/#grammar). TODO:
+ // Pest doesn't support line continuations and allows multiline
+ // strings, so this is a inaccurate.
&["c", "cc", "cpp", "h", "hh", "hpp", "ino", "pest"],
&["//"],
&[make_block_comment_delim("/*", "*/", false)],
@@ -159,8 +164,9 @@ pub fn get_language_lexer_vec() -> Vec {
// Note: the C/C++ support expects C++11 or newer. Don't worry about
// supporting C or older C++ using another lexer entry, since the
// raw string syntax in C++11 and newer is IMHO so rare we won't
- // encounter it in older code. See the C++
- // [string literals docs for the reasoning behind the start body regex.](https://en.cppreference.com/w/cpp/language/string_literal)
+ // encounter it in older code. See the C++ [string literals docs for
+ // the reasoning behind the start body
+ // regex.](https://en.cppreference.com/w/cpp/language/string_literal)
make_heredoc_delim("R\"", "[^()\\\\[[:space:]]]*", "(", ")", "\""),
SpecialCase::None,
Some(pest_parser::c::parse_to_code_doc_blocks),
@@ -169,18 +175,18 @@ pub fn get_language_lexer_vec() -> Vec {
make_language_lexer(
"csharp",
&["cs"],
- // See
- // [6.3.3 Comments](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure#633-comments).
- // Also provide support for
- // [documentation comments](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/documentation-comments).
+ // See [6.3.3
+ // Comments](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure#633-comments).
+ // Also provide support for [documentation
+ // comments](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/documentation-comments).
&["//", "///"],
&[
make_block_comment_delim("/*", "*/", false),
make_block_comment_delim("/**", "*/", false),
],
&[make_string_delimiter_spec(
- // See
- // [6.4.5.6 String literals](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure#6456-string-literals).
+ // See [6.4.5.6 String
+ // literals](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure#6456-string-literals).
"\"",
"\\",
NewlineSupport::None,
@@ -207,9 +213,9 @@ pub fn get_language_lexer_vec() -> Vec {
make_language_lexer(
"golang",
&["go"],
- // See
- // [The Go Programming Language Specification](https://go.dev/ref/spec)
- // on [Comments](https://go.dev/ref/spec#Comments).
+ // See [The Go Programming Language
+ // Specification](https://go.dev/ref/spec) on
+ // [Comments](https://go.dev/ref/spec#Comments).
&[],
&[make_block_comment_delim("/*", "*/", false)],
// See [String literals](https://go.dev/ref/spec#String_literals).
@@ -239,16 +245,17 @@ pub fn get_language_lexer_vec() -> Vec {
make_language_lexer(
"java",
&["java", "kt"],
- // See the
- // [Java Language Specification, Java SE 19 edition](https://docs.oracle.com/javase/specs/jls/se19/html/index.html),
- // [§3.7. Comments](https://docs.oracle.com/javase/specs/jls/se19/html/jls-3.html#jls-3.7).
+ // See the [Java Language Specification, Java SE 19
+ // edition](https://docs.oracle.com/javase/specs/jls/se19/html/index.html),
+ // [§3.7.
+ // Comments](https://docs.oracle.com/javase/specs/jls/se19/html/jls-3.html#jls-3.7).
// The end of this section notes that comments do not occur
// within character literals, string literals, or text blocks,
// which describes the approach of this lexer nicely.
&["//"],
&[make_block_comment_delim("/*", "*/", false)],
- // See
- // [§3.10.5. String Literals](https://docs.oracle.com/javase/specs/jls/se19/html/jls-3.html#jls-3.10.5).
+ // See [§3.10.5. String
+ // Literals](https://docs.oracle.com/javase/specs/jls/se19/html/jls-3.html#jls-3.10.5).
&[
make_string_delimiter_spec(
"\"",
@@ -258,8 +265,8 @@ pub fn get_language_lexer_vec() -> Vec {
// and before the matching closing "."
NewlineSupport::None,
),
- // See
- // [§3.10.6. Text Blocks](https://docs.oracle.com/javase/specs/jls/se19/html/jls-3.html#jls-3.10.6).
+ // See [§3.10.6. Text
+ // Blocks](https://docs.oracle.com/javase/specs/jls/se19/html/jls-3.html#jls-3.10.6).
make_string_delimiter_spec("\"\"\"", "\\", NewlineSupport::Unescaped),
],
None,
@@ -271,19 +278,19 @@ pub fn get_language_lexer_vec() -> Vec {
"javascript",
&[
"js", "mjs",
- // Note that
- // [Qt's QML language](https://doc.qt.io/qt-6/qtqml-syntax-basics.html)
- // is basically JSON with some embedded JavaScript. Treat it as
+ // Note that [Qt's QML
+ // language](https://doc.qt.io/qt-6/qtqml-syntax-basics.html) is
+ // basically JSON with some embedded JavaScript. Treat it as
// JavaScript, since those rules include template literals.
"qml",
],
- // See
- // [§12.4 Comments](https://262.ecma-international.org/13.0/#sec-comments)
+ // See [§12.4
+ // Comments](https://262.ecma-international.org/13.0/#sec-comments)
&["//"],
&[make_block_comment_delim("/*", "*/", false)],
&[
- // See
- // [§12.8.4 String Literals](https://262.ecma-international.org/13.0/#prod-StringLiteral).
+ // See [§12.8.4 String
+ // Literals](https://262.ecma-international.org/13.0/#prod-StringLiteral).
make_string_delimiter_spec("\"", "\\", NewlineSupport::Escaped),
make_string_delimiter_spec("'", "\\", NewlineSupport::Escaped),
],
@@ -309,15 +316,16 @@ pub fn get_language_lexer_vec() -> Vec {
make_language_lexer(
"matlab",
&["m"],
- // See the
- // [MATLAB docs on comments](https://www.mathworks.com/help/matlab/matlab_prog/comments.html).
+ // See the [MATLAB docs on
+ // comments](https://www.mathworks.com/help/matlab/matlab_prog/comments.html).
// Block comments are a special case, so they're not included here.
&["%", "..."],
&[],
- // Per the
- // [MATLAB docs](https://www.mathworks.com/help/matlab/matlab_prog/represent-text-with-character-and-string-arrays.html),
+ // Per the [MATLAB
+ // docs](https://www.mathworks.com/help/matlab/matlab_prog/represent-text-with-character-and-string-arrays.html),
// there are two types of strings. Although MATLAB supports
- // [standard escape sequences](https://www.mathworks.com/help/matlab/matlab_prog/matlab-operators-and-special-characters.html#bvg44q6)
+ // [standard escape
+ // sequences](https://www.mathworks.com/help/matlab/matlab_prog/matlab-operators-and-special-characters.html#bvg44q6)
// (scroll to the bottom of the page), these don't affect quotes;
// instead, doubled quotes are used to insert a single quote. See
// [string delimiter doubling](#string_delimiter_doubling).
@@ -337,8 +345,8 @@ pub fn get_language_lexer_vec() -> Vec {
&[],
&[
// Note that raw strings still allow escaping the single/double
- // quote. See the
- // [language reference](https://docs.python.org/3/reference/lexical_analysis.html#literals).
+ // quote. See the [language
+ // reference](https://docs.python.org/3/reference/lexical_analysis.html#literals).
make_string_delimiter_spec("\"\"\"", "\\", NewlineSupport::Unescaped),
make_string_delimiter_spec("'''", "\\", NewlineSupport::Unescaped),
make_string_delimiter_spec("\"", "\\", NewlineSupport::Escaped),
@@ -371,10 +379,11 @@ pub fn get_language_lexer_vec() -> Vec {
&["sql"],
// See
// [Wikipedia](https://en.wikipedia.org/wiki/SQL_syntax#Comments).
- // The
- // [SQL specification isn't free](https://en.wikipedia.org/wiki/SQL#Standardization_history),
+ // The [SQL specification isn't
+ // free](https://en.wikipedia.org/wiki/SQL#Standardization_history),
// sadly. Oracle publishes their flavor of the 2016 spec; see
- // [Comments within SQL statements](https://docs.oracle.com/database/121/SQLRF/sql_elements006.htm#SQLRF51099).
+ // [Comments within SQL
+ // statements](https://docs.oracle.com/database/121/SQLRF/sql_elements006.htm#SQLRF51099).
// Postgresql defines
// [comments](https://www.postgresql.org/docs/15/sql-syntax-lexical.html#SQL-SYNTAX-COMMENTS)
// as well.
@@ -382,11 +391,11 @@ pub fn get_language_lexer_vec() -> Vec {
&[make_block_comment_delim("/*", "*/", false)],
&[
// SQL standard strings allow newlines and don't provide an
- // escape character. This language uses
- // [string delimiter doubling](#string_delimiter_doubling).
- // Unfortunately, each variant of SQL also supports their custom
- // definition of strings; these must be handled by
- // vendor-specific flavors of this basic lexer definition.
+ // escape character. This language uses [string delimiter
+ // doubling](#string_delimiter_doubling). Unfortunately, each
+ // variant of SQL also supports their custom definition of
+ // strings; these must be handled by vendor-specific flavors of
+ // this basic lexer definition.
make_string_delimiter_spec("'", "", NewlineSupport::Unescaped),
],
None,
@@ -401,8 +410,8 @@ pub fn get_language_lexer_vec() -> Vec {
// [comments](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics#Comments).
&["//"],
&[make_block_comment_delim("/*", "*/", true)],
- // See
- // [Strings and Characters](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters).
+ // See [Strings and
+ // Characters](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters).
&[
// Technically, this would include optional whitespace after the
// triple quotes then a newlines then end with a newline before
@@ -411,14 +420,14 @@ pub fn get_language_lexer_vec() -> Vec {
make_string_delimiter_spec("\"\"\"", "\\", NewlineSupport::Unescaped),
make_string_delimiter_spec("\"", "\\", NewlineSupport::None),
],
- // Swift supports
- // [extended string delimiters](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters#Extended-String-Delimiters)
+ // Swift supports [extended string
+ // delimiters](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters#Extended-String-Delimiters)
// in both string literal and multiline string flavors. Since this
// parser only supports a single heredoc type, we ignore the string
- // literal flavor. This is a bug: consider the string
- // `#"Not a comment "/*"#`. This would parse as a code block
- // containing just `#`, then the string `"Not a comment "` then a
- // comment starting with `/*"#`.
+ // literal flavor. This is a bug: consider the string `#"Not a
+ // comment "/*"#`. This would parse as a code block containing just
+ // `#`, then the string `"Not a comment "` then a comment starting
+ // with `/*"#`.
make_heredoc_delim("", "#+", "\"\"\"", "\"\"\"", ""),
SpecialCase::None,
None,
@@ -468,8 +477,8 @@ pub fn get_language_lexer_vec() -> Vec {
&["--"],
&[make_block_comment_delim("/*", "*/", false)],
// Per section 15.7 of the standard, strings may not contain
- // newlines. This language uses
- // [string delimiter doubling](#string_delimiter_doubling).
+ // newlines. This language uses [string delimiter
+ // doubling](#string_delimiter_doubling).
&[make_string_delimiter_spec("\"", "", NewlineSupport::None)],
None,
SpecialCase::None,
@@ -516,19 +525,19 @@ pub fn get_language_lexer_vec() -> Vec {
&["#"],
&[],
&[
- // See
- // [double-quoted style](https://yaml.org/spec/1.2.2/#double-quoted-style).
+ // See [double-quoted
+ // style](https://yaml.org/spec/1.2.2/#double-quoted-style).
// Something I don't understand and will probably ignore:
// "Single- and double-quoted scalars are restricted to a single
// line when contained inside an implicit key."
make_string_delimiter_spec("\"", "\\", NewlineSupport::Unescaped),
- // See
- // [single-quoted style](https://yaml.org/spec/1.2.2/#single-quoted-style).
+ // See [single-quoted
+ // style](https://yaml.org/spec/1.2.2/#single-quoted-style).
// Single-quoted strings escape a single quote by repeating it
// twice: `'That''s unusual.'` Rather than try to parse this,
- // treat it as two back-to-back strings: `'That'` and
- // `'s unusual.'` We don't care about getting the correct value
- // for strings; the only purpose is to avoid interpreting string
+ // treat it as two back-to-back strings: `'That'` and `'s
+ // unusual.'` We don't care about getting the correct value for
+ // strings; the only purpose is to avoid interpreting string
// contents as inline or block comments.
make_string_delimiter_spec("'", "", NewlineSupport::Unescaped),
],
diff --git a/server/src/lexer/tests.rs b/server/src/lexer/tests.rs
index 55a4b299..2a4480d8 100644
--- a/server/src/lexer/tests.rs
+++ b/server/src/lexer/tests.rs
@@ -14,14 +14,17 @@
/// the CodeChat Editor. If not, see
/// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
///
-/// # `test.rs` -- Unit tests for the lexer
-// ## Imports
+/// `test.rs` -- Unit tests for the lexer
+/// =====================================
+// Imports
+// -------
use super::supported_languages::get_language_lexer_vec;
-use super::{compile_lexers, source_lexer, CodeDocBlock, DocBlock};
+use super::{CodeDocBlock, DocBlock, compile_lexers, source_lexer};
use crate::test_utils::stringit;
use indoc::indoc;
-// ## Utilities
+// Utilities
+// ---------
//
// Provide a compact way to create a `CodeDocBlock`.
fn build_doc_block(indent: &str, delimiter: &str, contents: &str) -> CodeDocBlock {
diff --git a/server/src/lib.rs b/server/src/lib.rs
index f44971c9..78cc30c1 100644
--- a/server/src/lib.rs
+++ b/server/src/lib.rs
@@ -15,7 +15,8 @@ pub mod capture;
/// the CodeChat Editor. If not, see
/// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
///
-/// # `lib.rs` -- Define library modules for the CodeChat Editor Server
+/// `lib.rs` -- Define library modules for the CodeChat Editor Server
+/// =================================================================
///
/// TODO: Add the ability to use
/// [plugins](https://zicklag.github.io/rust-tutorials/rust-plugins.html).
diff --git a/server/src/main.rs b/server/src/main.rs
index c7bd3e00..8e90cbc8 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -13,8 +13,10 @@
// You should have received a copy of the GNU General Public License along with
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
-/// # `main.rs` -- Entrypoint for the CodeChat Editor Server
-// ## Imports
+/// `main.rs` -- Entrypoint for the CodeChat Editor Server
+/// ======================================================
+// Imports
+// -------
//
// ### Standard library
use std::{
@@ -33,7 +35,8 @@ use log::LevelFilter;
// ### Local
use code_chat_editor::webserver::{self, IP_ADDRESS};
-// ## Data structures
+// Data structures
+// ---------------
//
// ### Command-line interface
//
@@ -75,7 +78,8 @@ enum Commands {
Stop,
}
-// ## Code
+// Code
+// ----
//
// The following code implements the command-line interface for the CodeChat
// Editor.
@@ -120,7 +124,10 @@ impl Cli {
}
match process {
- // If the process isn't started, then do so. We wait to here to start the process, in case the server was already running; in this case, the ping above will see the running server then exit.
+ // If the process isn't started, then do so. We wait to
+ // here to start the process, in case the server was
+ // already running; in this case, the ping above will
+ // see the running server then exit.
None => {
println!("Starting server in background...");
let current_exe = match env::current_exe() {
@@ -128,7 +135,7 @@ impl Cli {
Err(e) => {
return Err(
format!("Failed to get current executable: {e}").into()
- )
+ );
}
};
#[cfg(not(debug_assertions))]
@@ -148,10 +155,11 @@ impl Cli {
}
process = match cmd
.args(["--port", &self.port.to_string(), "serve", "--log", "off"])
- // Subtle: the default of `stdout(Stdio::inherit())` causes
- // a parent process to block, since the child process
- // inherits the parent's stdout. So, use the pipes to avoid
- // blocking.
+ // Subtle: the default of
+ // `stdout(Stdio::inherit())` causes a parent
+ // process to block, since the child process
+ // inherits the parent's stdout. So, use the
+ // pipes to avoid blocking.
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
@@ -174,9 +182,9 @@ impl Cli {
stdout.read_to_string(&mut stdout_buf).unwrap();
stderr.read_to_string(&mut stderr_buf).unwrap();
return Err(format!(
- "Server failed to start: {status:?}\n{stdout_buf}\n{stderr_buf}"
- )
- .into());
+ "Server failed to start: {status:?}\n{stdout_buf}\n{stderr_buf}"
+ )
+ .into());
}
Ok(None) => {}
Err(e) => return Err(format!("Error starting server: {e}").into()),
diff --git a/server/src/processing.rs b/server/src/processing.rs
index 661936e0..2ec12cdb 100644
--- a/server/src/processing.rs
+++ b/server/src/processing.rs
@@ -14,8 +14,11 @@
/// the CodeChat Editor. If not, see
/// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
///
-/// # `processing.rs` -- Transform source code to its web-editable equivalent and back
-// ## Imports
+/// `processing.rs` -- Transform source code to its web-editable equivalent and
+/// back
+/// ===========================================================================
+// Imports
+// -------
//
// ### Standard library
//
@@ -34,17 +37,19 @@ use std::path::PathBuf;
// ### Third-party
use lazy_static::lazy_static;
-use pulldown_cmark::{html, Options, Parser};
+use pulldown_cmark::{Options, Parser, html};
use regex::Regex;
use serde::{Deserialize, Serialize};
use crate::lexer::LEXERS;
// ### Local
-use crate::lexer::{source_lexer, CodeDocBlock, DocBlock, LanguageLexerCompiled};
+use crate::lexer::{CodeDocBlock, DocBlock, LanguageLexerCompiled, source_lexer};
-// ## Data structures
+// Data structures
+// ---------------
//
-// ### Translation between a local (traditional) source file and its web-editable, client-side representation
+// ### Translation between a local (traditional) source file and its web-editable,
+// client-side representation
//
// There are three ways that a source file is represented:
//
@@ -132,7 +137,8 @@ pub enum TranslationResultsString {
// On save, the process is CodeChatForWeb -> Vec\ -> source code.
//
-// ## Globals
+// Globals
+// -------
lazy_static! {
/// Match the lexer directive in a source file.
static ref LEXER_DIRECTIVE: Regex = Regex::new(r"CodeChat Editor lexer: (\w+)").unwrap();
@@ -143,7 +149,8 @@ lazy_static! {
const DOC_BLOCK_SEPARATOR_STRING: &str = "\n\n\n";
-// ## Determine if the provided file is part of a project.
+// Determine if the provided file is part of a project.
+// ----------------------------------------------------
pub fn find_path_to_toc(file_path: &Path) -> Option {
// To determine if this source code is part of a project, look for a project
// file by searching the current directory, then all its parents, for a file
@@ -166,9 +173,10 @@ pub fn find_path_to_toc(file_path: &Path) -> Option {
}
}
-// ## Transform `CodeChatForWeb` to source code
-/// This function takes in a source file in web-editable format
-/// (the `CodeChatForWeb` struct) and transforms it into source code.
+// Transform `CodeChatForWeb` to source code
+// -----------------------------------------
+/// This function takes in a source file in web-editable format (the
+/// `CodeChatForWeb` struct) and transforms it into source code.
pub fn codechat_for_web_to_source(
// The file to save plus metadata, stored in the `LexedSourceFile`
codechat_for_web: &CodeChatForWeb,
@@ -270,8 +278,8 @@ fn code_doc_block_vec_to_source(
// `split_inclusive` becomes an empty list, not `[""]`. Note
// that this mirrors what Python's
// [splitlines](https://docs.python.org/3/library/stdtypes.html#str.splitlines)
- // does, and is also the subject of a
- // [Rust bug report](https://github.com/rust-lang/rust/issues/111457).
+ // does, and is also the subject of a [Rust bug
+ // report](https://github.com/rust-lang/rust/issues/111457).
let lines: Vec<_> = doc_block.contents.split_inclusive('\n').collect();
let lines_fixed = if lines.is_empty() { vec![""] } else { lines };
for content_line in lines_fixed {
@@ -293,7 +301,7 @@ fn code_doc_block_vec_to_source(
return Err(format!(
"Unknown comment opening delimiter '{}'.",
doc_block.delimiter
- ))
+ ));
}
};
@@ -347,12 +355,12 @@ fn code_doc_block_vec_to_source(
);
// Since this isn't a first line:
} else {
- // - If this line is just a newline, include just
- // the newline.
+ // * If this line is just a newline, include just
+ // the newline.
if *content_line == "\n" {
append_doc_block("", "", "\n");
- // - Otherwise, include spaces in place of the
- // delimiter.
+ // * Otherwise, include spaces in place of the
+ // delimiter.
} else {
append_doc_block(
&doc_block.indent,
@@ -376,7 +384,8 @@ fn code_doc_block_vec_to_source(
Ok(file_contents)
}
-// ## Transform from source code to `CodeChatForWeb`
+// Transform from source code to `CodeChatForWeb`
+// ----------------------------------------------
//
// Given the contents of a file, classify it and (for CodeChat Editor files)
// convert it to the `CodeChatForWeb` format.
@@ -401,16 +410,17 @@ pub fn source_to_codechat_for_web(
return TranslationResults::Err(format!(
"Unknown lexer type {}.
",
&lexer_name
- ))
+ ));
}
}
} else {
// Otherwise, look up the lexer by the file's extension.
- if let Some(llc) = LEXERS.map_ext_to_lexer_vec.get(file_ext) {
- llc.first().unwrap()
- } else {
- // The file type is unknown; treat it as plain text.
- return TranslationResults::Unknown;
+ match LEXERS.map_ext_to_lexer_vec.get(file_ext) {
+ Some(llc) => llc.first().unwrap(),
+ _ => {
+ // The file type is unknown; treat it as plain text.
+ return TranslationResults::Unknown;
+ }
}
};
@@ -444,8 +454,8 @@ pub fn source_to_codechat_for_web(
// Combine all the doc blocks into a single string, separated by a
// delimiter. Transform this to markdown, then split the transformed
// content back into the doc blocks they came from. This is
- // necessary to allow
- // [link reference definitions](https://spec.commonmark.org/0.31.2/#link-reference-definitions)
+ // necessary to allow [link reference
+ // definitions](https://spec.commonmark.org/0.31.2/#link-reference-definitions)
// between doc blocks to work; for example, `[Link][1]` in one doc
// block, then `[1]: http:/foo.org` in another doc block requires
// both to be in the same Markdown document to translate correctly.
@@ -574,59 +584,61 @@ fn markdown_to_html(markdown: &str) -> String {
// load/save, then do some accesses during those processes.
//
// Top-level data structures: a file HashSet and an id
-// HashMap}>. Some FileAnchors in the file
+// HashMap}>. Some FileAnchors in the file
// HashSet are also in a pending load list.
//
-// - To update a file:
-// - Remove the old file from the file HasHMap. Add an empty FileAnchor to the
-// file HashMap.
-// - For each id, see if that id already exists.
-// - If the id exists: if it refers to an id in the old FileAnchor, replace
-// it with the new one. If not, need to perform resolution on this id (we
-// have a non-unique id; how to fix?).
-// - If the id doesn't exist: create a new one.
-// - For each hyperlink, see if that id already exists.
-// - If so, upsert the referring id. Check the metadata on the id to make
-// sure that data is current. If not, add this to the pending hyperlinks
-// list. If the file is missing, delete it from the cache.
-// - If not, create a new entry in the id HashSet and add the referring id
-// to the HashSet. Add the file to a pending hyperlinks list.
-// - When the file is processed:
-// - Look for all entries in the pending file list that refer to the current
-// file and resolve these. Start another task to load in all pending
-// files.
-// - Look at the old file; remove each id that's still in the id HashMap. If
-// the id was in the HashMap and it also was a Hyperlink, remove that from
-// the HashSet.
-// - To remove a file from the HashMap:
-// - Remove it from the file HashMap.
-// - For each hyperlink, remove it from the HashSet of referring links (if
-// that id still exists).
-// - For each id, remove it from the id HashMap.
-// - To add a file from the HashSet:
-// - Perform an update with an empty FileAnchor.
+// * To update a file:
+// * Remove the old file from the file HasHMap. Add an empty FileAnchor to
+// the file HashMap.
+// * For each id, see if that id already exists.
+// * If the id exists: if it refers to an id in the old FileAnchor,
+// replace it with the new one. If not, need to perform resolution
+// on this id (we have a non-unique id; how to fix?).
+// * If the id doesn't exist: create a new one.
+// * For each hyperlink, see if that id already exists.
+// * If so, upsert the referring id. Check the metadata on the id to
+// make sure that data is current. If not, add this to the pending
+// hyperlinks list. If the file is missing, delete it from the
+// cache.
+// * If not, create a new entry in the id HashSet and add the
+// referring id to the HashSet. Add the file to a pending hyperlinks
+// list.
+// * When the file is processed:
+// * Look for all entries in the pending file list that refer to the
+// current file and resolve these. Start another task to load in all
+// pending files.
+// * Look at the old file; remove each id that's still in the id
+// HashMap. If the id was in the HashMap and it also was a
+// Hyperlink, remove that from the HashSet.
+// * To remove a file from the HashMap:
+// * Remove it from the file HashMap.
+// * For each hyperlink, remove it from the HashSet of referring links (if
+// that id still exists).
+// * For each id, remove it from the id HashMap.
+// * To add a file from the HashSet:
+// * Perform an update with an empty FileAnchor.
//
// Pending hyperlinks list: for each hyperlink,
//
-// - check if the id is now current in the cache. If so, add the referring id to
-// the HashSet then move to the next hyperlink.
-// - check if the file is now current in the cache. If not, load the file and
-// update the cache, then go to step 1.
-// - The id was not found, even in the expected file. Add the hyperlink to a
-// broken links set?
+// * check if the id is now current in the cache. If so, add the referring id
+// to the HashSet then move to the next hyperlink.
+// * check if the file is now current in the cache. If not, load the file and
+// update the cache, then go to step 1.
+// * The id was not found, even in the expected file. Add the hyperlink to a
+// broken links set?
//
// Global operations:
//
-// - Scan all files, then perform add/upsert/removes based on differences with
-// the cache.
+// * Scan all files, then perform add/upsert/removes based on differences with
+// the cache.
//
// Functions:
//
-// - Upsert an Anchor.
-// - Upsert a Hyperlink.
-// - Upsert a file.
-// - Remove a file.
-/*
+// * Upsert an Anchor.
+// * Upsert a Hyperlink.
+// * Upsert a file.
+// * Remove a file.
+/*x
/// There are two types of files that can serve as an anchor: these are file
/// anchor targets.
enum FileAnchor {
@@ -780,17 +792,18 @@ fn html_analyze(
}
*/
-// ## Tests
+// Tests
+// -----
#[cfg(test)]
mod tests {
use std::{path::PathBuf, str::FromStr};
use predicates::prelude::predicate::str;
- use super::{find_path_to_toc, TranslationResults};
use super::{CodeChatForWeb, CodeMirror, CodeMirrorDocBlocks, SourceFileMetadata};
+ use super::{TranslationResults, find_path_to_toc};
use crate::lexer::{
- compile_lexers, supported_languages::get_language_lexer_vec, CodeDocBlock, DocBlock,
+ CodeDocBlock, DocBlock, compile_lexers, supported_languages::get_language_lexer_vec,
};
use crate::processing::{
code_doc_block_vec_to_source, code_mirror_to_code_doc_blocks, codechat_for_web_to_source,
@@ -1331,9 +1344,9 @@ mod tests {
// Trigger special cases:
//
- // - An empty doc block at the beginning of the file.
- // - A doc block in the middle of the file
- // - A doc block with no trailing newline at the end of the file.
+ // * An empty doc block at the beginning of the file.
+ // * A doc block in the middle of the file
+ // * A doc block with no trailing newline at the end of the file.
assert_eq!(
source_to_codechat_for_web("//\n\n//\n\n//", &"cpp".to_string(), false, false),
TranslationResults::CodeChat(build_codechat_for_web(
diff --git a/server/src/test_utils.rs b/server/src/test_utils.rs
index 46576ecf..53034de2 100644
--- a/server/src/test_utils.rs
+++ b/server/src/test_utils.rs
@@ -14,43 +14,45 @@
/// the CodeChat Editor. If not, see
/// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
///
-/// # `test_utils.rs` -- Reusable routines for testing
+/// `test_utils.rs` -- Reusable routines for testing
+/// ================================================
///
/// Placing this file in the `tests/` directory prevents me from importing it
/// outside that directory tree; the desire was to import this for unit tests in
/// the `src/` directory tree. So, it's instead placed here, then conditionally
/// imported in `lib.rs`.
-// ## Imports
+// Imports
+// -------
//
// ### Standard library
use std::env;
-use std::path::PathBuf;
use std::path::MAIN_SEPARATOR_STR;
+use std::path::PathBuf;
// ### Third-party
-use assert_fs::fixture::PathCopy;
use assert_fs::TempDir;
+use assert_fs::fixture::PathCopy;
use assertables::assert_le;
use log::Level;
// ### Local
use crate::testing_logger;
-// ## Macros
+// Macros
+// ------
//
-// Extract a known enum variant or fail. More concise than the alternative
-// (`if let``, or` let
-// else`). From [SO](https://stackoverflow.com/a/69324393). The macro does not handle nested pattern like`
-// Some(Animal(cat))\`.
+// Extract a known enum variant or fail. More concise than the alternative (`if
+// let``, or` let else`). From [SO](https://stackoverflow.com/a/69324393). The
+// macro does not handle nested pattern like` Some(Animal(cat))\`.
#[macro_export]
macro_rules! cast {
- ($target: expr, $pat: path) => {{
+ ($target: expr_2021, $pat: path) => {{
// The if let exploits recent Rust compiler's smart pattern matching.
- // Contrary to other solutions like
- // `into_variant`` and friends, this one macro covers all ownership usage like`
- // self``, `&self`` and `&mut self``. On the other hand`
- // {into,as,as_mut}\_{variant}\`\` solution usually needs 3 \* N method
- // definitions where N is the number of variants.
+ // Contrary to other solutions like `into_variant`` and friends, this
+ // one macro covers all ownership usage like` self``, `&self`` and `&mut
+ // self``. On the other hand` {into,as,as\_mut}\_{variant}\`\` solution
+ // usually needs 3 \* N method definitions where N is the number of
+ // variants.
if let $pat(a) = $target {
a
} else {
@@ -87,7 +89,8 @@ macro_rules! prep_test_dir {
}};
}
-// ## Code
+// Code
+// ----
//
// Use the `tests/fixtures` path (relative to the root of this Rust project) to
// store files for testing. A subdirectory tree, named by the module path then
@@ -111,8 +114,9 @@ pub fn _prep_test_dir(
// Switch from `::` to a filesystem path separator.
let test_path = &test_path.replace("::", MAIN_SEPARATOR_STR);
- // First, get the project root directory, based on the
- // [location of the cargo.toml file](https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates).
+ // First, get the project root directory, based on the [location of the
+ // cargo.toml
+ // file](https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates).
let root_dir = &env::var("CARGO_MANIFEST_DIR")
.expect("Environment variable CARGO_MANIFEST_DIR not defined.");
let mut source_path = PathBuf::from(root_dir);
@@ -127,7 +131,7 @@ pub fn _prep_test_dir(
source_path.pop();
// For debugging, append
- // [.into_persistent()](https://docs.rs/assert_fs/latest/assert_fs/fixture/struct.TempDir.html#method.into_persistent).
+ // [.into\_persistent()](https://docs.rs/assert_fs/latest/assert_fs/fixture/struct.TempDir.html#method.into_persistent).
let temp_dir = TempDir::new().unwrap();
// Create a temporary directory, then copy everything needed for this test
// to it. Since the `patterns` parameter is a glob, append `/**` to the
diff --git a/server/src/webserver.rs b/server/src/webserver.rs
index 212c19a0..adc19a26 100644
--- a/server/src/webserver.rs
+++ b/server/src/webserver.rs
@@ -13,20 +13,23 @@
// You should have received a copy of the GNU General Public License along with
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
-/// # `webserver.rs` -- Serve CodeChat Editor Client webpages
-// ## Submodules
+/// `webserver.rs` -- Serve CodeChat Editor Client webpages
+/// =======================================================
+// Submodules
+// ----------
mod filewatcher;
#[cfg(test)]
pub mod tests;
mod vscode;
-// ## Imports
+// Imports
+// -------
//
// ### Standard library
use std::{
collections::{HashMap, HashSet},
env, fs,
- path::{self, Path, PathBuf, MAIN_SEPARATOR_STR},
+ path::{self, MAIN_SEPARATOR_STR, Path, PathBuf},
str::FromStr,
sync::{Arc, Mutex},
time::Duration,
@@ -35,11 +38,12 @@ use std::{
// ### Third-party
use actix_files;
use actix_web::{
+ App, HttpRequest, HttpResponse, HttpServer,
dev::{ServerHandle, ServiceFactory, ServiceRequest},
error::Error,
get,
http::header::ContentType,
- web, App, HttpRequest, HttpResponse, HttpServer,
+ web,
};
use actix_ws::AggregatedMessage;
use bytes::Bytes;
@@ -47,7 +51,7 @@ use dunce::simplified;
use futures_util::StreamExt;
use indoc::{formatdoc, indoc};
use lazy_static::lazy_static;
-use log::{error, info, warn, LevelFilter};
+use log::{LevelFilter, error, info, warn};
use log4rs;
use mime::Mime;
use mime_guess;
@@ -73,16 +77,18 @@ use vscode::{
// ### Local
//use crate::capture::EventCapture;
use crate::processing::{
- source_to_codechat_for_web_string, CodeChatForWeb, TranslationResultsString,
+ CodeChatForWeb, TranslationResultsString, source_to_codechat_for_web_string,
};
use filewatcher::{
filewatcher_browser_endpoint, filewatcher_client_endpoint, filewatcher_root_fs_redirect,
filewatcher_websocket,
};
-// ## Data structures
+// Data structures
+// ---------------
//
-// ### Data structures supporting a websocket connection between the IDE, this server, and the CodeChat Editor Client
+// ### Data structures supporting a websocket connection between the IDE, this
+// server, and the CodeChat Editor Client
/// Provide queues which send data to the IDE and the CodeChat Editor Client.
#[derive(Debug)]
struct WebsocketQueues {
@@ -251,18 +257,19 @@ pub struct AppState {
vscode_connection_id: Arc>>,
}
-// ## Macros
+// Macros
+// ------
/// Create a macro to report an error when enqueueing an item.
#[macro_export]
macro_rules! oneshot_send {
// Provide two options: `break` or `break 'label`.
- ($tx: expr) => {
+ ($tx: expr_2021) => {
if let Err(err) = $tx {
error!("Unable to enqueue: {err:?}");
break;
}
};
- ($tx: expr, $label: tt) => {
+ ($tx: expr_2021, $label: tt) => {
if let Err(err) = $tx {
error!("Unable to enqueue: {err:?}");
break $label;
@@ -272,15 +279,16 @@ macro_rules! oneshot_send {
#[macro_export]
macro_rules! queue_send {
- ($tx: expr) => {
+ ($tx: expr_2021) => {
$crate::oneshot_send!($tx.await)
};
- ($tx: expr, $label: tt) => {
+ ($tx: expr_2021, $label: tt) => {
$crate::oneshot_send!($tx.await, $label)
};
}
-/// ## Globals
+/// Globals
+/// -------
///
/// The IP address on which the server listens for incoming connections.
pub const IP_ADDRESS: &str = "127.0.0.1";
@@ -360,7 +368,8 @@ lazy_static! {
}
-// ## Webserver functionality
+// Webserver functionality
+// -----------------------
#[get("/ping")]
async fn ping() -> HttpResponse {
HttpResponse::Ok().body("pong")
@@ -435,7 +444,7 @@ fn get_client_framework(
Err(err) => {
return Err(format!(
"Unable to encode websocket URL for {ide_path}, id {connection_id}: {err}"
- ))
+ ));
}
};
let codechat_editor_framework_js = BUNDLED_FILES_MAP.get("CodeChatEditorFramework.js").unwrap();
@@ -711,7 +720,7 @@ async fn serve_file(
}
// Report a lexer error.
TranslationResultsString::Err(err_string) => {
- return (SimpleHttpResponse::Err(err_string), None)
+ return (SimpleHttpResponse::Err(err_string), None);
}
// This is a CodeChat file. The following code wraps the CodeChat for
// web results in a CodeChat Editor Client webpage.
@@ -811,7 +820,8 @@ async fn serve_file(
)
}
-/// ## Websockets
+/// Websockets
+/// ----------
///
/// Each CodeChat Editor IDE instance pairs with a CodeChat Editor Client
/// through the CodeChat Editor Server. Together, these form a joint editor,
@@ -869,8 +879,9 @@ async fn client_websocket(
// sent), the Client closes the websocket. The rest of this
// sequence is covered in the next case.
// 2. Either websocket is closed. In this case, the other websocket
- // should be immediately closed; there's no longer the opportunity
- // to perform a more controlled shutdown (see the first case).
+ // should be immediately closed; there's no longer the
+ // opportunity to perform a more controlled shutdown (see the
+ // first case).
// 1. The websocket which closed enqueues a `Closed` message for
// the other websocket.
// 2. When the other websocket receives this message, it closes.
@@ -1073,7 +1084,8 @@ async fn client_websocket(
Ok(response)
}
-// ## Webserver core
+// Webserver core
+// --------------
#[actix_web::main]
pub async fn main(port: u16) -> std::io::Result<()> {
run_server(port).await
@@ -1114,7 +1126,7 @@ pub fn configure_logger(level: LevelFilter) {
}
// Quoting the [docs](https://actix.rs/docs/application#shared-mutable-state),
-// "To achieve _globally_ shared state, it must be created **outside** of the
+// "To achieve *globally* shared state, it must be created **outside** of the
// closure passed to `HttpServer::new` and moved/cloned in." Putting this code
// inside `configure_app` places it inside the closure which calls
// `configure_app`, preventing globally shared state.
@@ -1163,7 +1175,8 @@ where
.route("/fw/fsb", web::get().to(filewatcher_root_fs_redirect))
}
-// ## Utilities
+// Utilities
+// ---------
//
// Send a response to the client after processing a message from the client.
async fn send_response(client_tx: &Sender, id: f64, result: MessageResult) {
diff --git a/server/src/webserver/filewatcher.rs b/server/src/webserver/filewatcher.rs
index 8a30ae44..76f93dc8 100644
--- a/server/src/webserver/filewatcher.rs
+++ b/server/src/webserver/filewatcher.rs
@@ -13,8 +13,10 @@
// You should have received a copy of the GNU General Public License along with
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
-/// # `filewatcher.rs` -- Implement the File Watcher "IDE"
-// ## Imports
+/// `filewatcher.rs` -- Implement the File Watcher "IDE"
+/// ====================================================
+// Imports
+// -------
//
// ### Standard library
use std::{
@@ -24,19 +26,19 @@ use std::{
// ### Third-party
use actix_web::{
+ HttpRequest, HttpResponse, Responder,
error::Error,
get,
http::header::{self, ContentType},
- web, HttpRequest, HttpResponse, Responder,
+ web,
};
use dunce::simplified;
use indoc::formatdoc;
use lazy_static::lazy_static;
use log::{error, info, warn};
use notify_debouncer_full::{
- new_debouncer,
+ DebounceEventResult, new_debouncer,
notify::{EventKind, RecursiveMode},
- DebounceEventResult,
};
use regex::Regex;
use tokio::{
@@ -52,23 +54,24 @@ use win_partitions::win_api::get_logical_drive;
// ### Local
use super::{
+ AppState, EditorMessage, EditorMessageContents, UpdateMessageContents, WebsocketQueues,
client_websocket, escape_html, get_client_framework, get_connection_id, html_not_found,
- html_wrapper, path_display, send_response, AppState, EditorMessage, EditorMessageContents,
- UpdateMessageContents, WebsocketQueues,
+ html_wrapper, path_display, send_response,
};
use crate::{
oneshot_send,
processing::{
- codechat_for_web_to_source, source_to_codechat_for_web_string, TranslationResultsString,
+ TranslationResultsString, codechat_for_web_to_source, source_to_codechat_for_web_string,
},
queue_send,
webserver::{
- filesystem_endpoint, get_test_mode, make_simple_http_response, path_to_url, url_to_path,
- ResultOkTypes,
+ ResultOkTypes, filesystem_endpoint, get_test_mode, make_simple_http_response, path_to_url,
+ url_to_path,
},
};
-// ## Globals
+// Globals
+// -------
lazy_static! {
/// Matches a bare drive letter. Only needed on Windows.
static ref DRIVE_LETTER_REGEX: Regex = Regex::new("^[a-zA-Z]:$").unwrap();
@@ -76,7 +79,8 @@ lazy_static! {
pub const FILEWATCHER_PATH_PREFIX: &[&str] = &["fw", "fsc"];
-/// ## File browser endpoints
+/// File browser endpoints
+/// ----------------------
///
/// The file browser provides a very crude interface, allowing a user to select
/// a file from the local filesystem for editing. Long term, this should be
@@ -131,7 +135,7 @@ async fn filewatcher_browser_endpoint(
Err(err) => {
return html_not_found(&format!(
"The requested path {fixed_path} is not valid: {err}.
"
- ))
+ ));
}
};
if canon_path.is_dir() {
@@ -200,7 +204,7 @@ async fn dir_listing(web_path: &str, dir_path: &Path) -> HttpResponse {
return html_not_found(&format!(
"Unable to list the directory {}: {err}/
",
path_display(dir_path)
- ))
+ ));
}
};
@@ -217,7 +221,7 @@ async fn dir_listing(web_path: &str, dir_path: &Path) -> HttpResponse {
return html_not_found(&format!(
"Unable to determine the type of {}: {err}.",
path_display(&dir_entry.path()),
- ))
+ ));
}
};
if file_type.is_file() {
@@ -231,7 +235,7 @@ async fn dir_listing(web_path: &str, dir_path: &Path) -> HttpResponse {
}
}
Err(err) => {
- return html_not_found(&format!("
Unable to read file in directory: {err}."))
+ return html_not_found(&format!("
Unable to read file in directory: {err}."));
}
};
}
@@ -253,7 +257,7 @@ async fn dir_listing(web_path: &str, dir_path: &Path) -> HttpResponse {
Err(err) => {
return html_not_found(&format!(
"
Unable to decode directory name '{err:?}' as UTF-8."
- ))
+ ));
}
};
let encoded_dir = urlencoding::encode(&dir_name);
@@ -280,7 +284,9 @@ async fn dir_listing(web_path: &str, dir_path: &Path) -> HttpResponse {
let file_name = match file.file_name().into_string() {
Ok(v) => v,
Err(err) => {
- return html_not_found(&format!("
Unable to decode file name {err:?} as UTF-8.",))
+ return html_not_found(
+ &format!("
Unable to decode file name {err:?} as UTF-8.",),
+ );
}
};
let encoded_file = urlencoding::encode(&file_name);
@@ -396,8 +402,8 @@ async fn processing_task(file_path: &Path, app_state: web::Data, conne
message: EditorMessageContents::CurrentFile(url_pathbuf)
}), 'task);
// Note: it's OK to postpone the increment to here; if the
- // `queue_send` exits before this runs, the message didn't get sent,
- // so the ID wasn't used.
+ // `queue_send` exits before this runs, the message didn't get
+ // sent, so the ID wasn't used.
id += 1.0;
};
@@ -430,7 +436,8 @@ async fn processing_task(file_path: &Path, app_state: web::Data, conne
Ok(debounced_event_vec) => {
for debounced_event in debounced_event_vec {
let is_modify = match debounced_event.event.kind {
- // On OS X, we get a `Create` event when a file is modified.
+ // On OS X, we get a `Create` event when a
+ // file is modified.
EventKind::Create(_create_kind) => true,
// On Windows, the `_modify_kind` is `Any`;
// therefore; ignore it rather than trying
@@ -444,7 +451,7 @@ async fn processing_task(file_path: &Path, app_state: web::Data, conne
};
if is_modify {
if debounced_event.event.paths.len() != 1 ||
- current_filepath.as_ref().map_or(true, |cfp| cfp != &debounced_event.event.paths[0])
+ current_filepath.as_ref().is_none_or(|cfp| cfp != &debounced_event.event.paths[0])
{
warn!("Modification to different file {}.", debounced_event.event.paths[0].to_string_lossy());
} else {
@@ -523,7 +530,8 @@ async fn processing_task(file_path: &Path, app_state: web::Data, conne
}
Some(http_request) = from_http_rx.recv() => {
- // If there's no current file, replace it with an empty file, which will still produce an error.
+ // If there's no current file, replace it with an empty
+ // file, which will still produce an error.
let empty_path = PathBuf::new();
let cfp = current_filepath.as_ref().unwrap_or(&empty_path);
let (simple_http_response, option_update) = make_simple_http_response(&http_request, cfp).await;
@@ -539,7 +547,9 @@ async fn processing_task(file_path: &Path, app_state: web::Data, conne
match m.message {
EditorMessageContents::Update(update_message_contents) => {
let result = 'process: {
- // Check that the file path matches the current file. If `canonicalize` fails, then the files don't match.
+ // Check that the file path matches the
+ // current file. If `canonicalize` fails,
+ // then the files don't match.
if Some(Path::new(&update_message_contents.file_path).to_path_buf()) != current_filepath {
break 'process Err(format!(
"Update for file '{}' doesn't match current file '{current_filepath:?}'.",
@@ -567,7 +577,9 @@ async fn processing_task(file_path: &Path, app_state: web::Data, conne
};
let cfp = current_filepath.as_ref().unwrap();
- // Unwrap the file, write to it, then rewatch it, in order to avoid a watch notification from this write.
+ // Unwrap the file, write to it, then
+ // rewatch it, in order to avoid a watch
+ // notification from this write.
if let Err(err) = debounced_watcher.unwatch(cfp) {
let msg = format!(
"Unable to unwatch file '{}': {err}.",
@@ -697,7 +709,8 @@ pub async fn filewatcher_websocket(
.await
}
-// ## Tests
+// Tests
+// -----
#[cfg(test)]
mod tests {
use std::{
@@ -709,9 +722,10 @@ mod tests {
use actix_http::Request;
use actix_web::{
+ App,
body::BoxBody,
dev::{Service, ServiceResponse},
- test, web, App,
+ test, web,
};
use assertables::assert_starts_with;
use dunce::simplified;
@@ -720,17 +734,17 @@ mod tests {
use url::Url;
use super::{
- super::{configure_app, make_app_data, WebsocketQueues},
- send_response, AppState, EditorMessage, EditorMessageContents, UpdateMessageContents,
+ super::{WebsocketQueues, configure_app, make_app_data},
+ AppState, EditorMessage, EditorMessageContents, UpdateMessageContents, send_response,
};
use crate::{
cast, prep_test_dir,
processing::{
- source_to_codechat_for_web, CodeChatForWeb, CodeMirror, SourceFileMetadata,
- TranslationResults,
+ CodeChatForWeb, CodeMirror, SourceFileMetadata, TranslationResults,
+ source_to_codechat_for_web,
},
test_utils::{check_logger_errors, configure_testing_logger},
- webserver::{tests::IP_PORT, IdeType, ResultOkTypes},
+ webserver::{IdeType, ResultOkTypes, tests::IP_PORT},
};
async fn get_websocket_queues(
@@ -738,7 +752,7 @@ mod tests {
test_dir: &Path,
) -> (
WebsocketQueues,
- impl Service, Error = actix_web::Error>,
+ impl Service, Error = actix_web::Error> + use<>,
) {
let app_data = make_app_data(IP_PORT);
let app = test::init_service(configure_app(App::new(), &app_data)).await;
@@ -777,7 +791,7 @@ mod tests {
}
macro_rules! get_message_as {
- ($client_rx: expr, $cast_type: ty) => {{
+ ($client_rx: expr_2021, $cast_type: ty) => {{
let m = get_message(&mut $client_rx).await;
(m.id, cast!(m.message, $cast_type))
}};
diff --git a/server/src/webserver/tests.rs b/server/src/webserver/tests.rs
index 7c13a259..cfa010e1 100644
--- a/server/src/webserver/tests.rs
+++ b/server/src/webserver/tests.rs
@@ -13,10 +13,12 @@
// You should have received a copy of the GNU General Public License along with
// the CodeChat Editor. If not, see
// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
-/// # `test.rs` -- Unit tests for the webserver
-// ## Imports
+/// `test.rs` -- Unit tests for the webserver
+/// =========================================
+// Imports
+// -------
use std::{
- path::{PathBuf, MAIN_SEPARATOR_STR},
+ path::{MAIN_SEPARATOR_STR, PathBuf},
thread::{self, sleep},
time::Duration,
};
@@ -27,16 +29,19 @@ use assertables::{assert_ends_with, assert_starts_with};
use super::{filewatcher::FILEWATCHER_PATH_PREFIX, path_to_url, url_to_path};
use crate::prep_test_dir;
-// ## Constants
+// Constants
+// ---------
/// The default port on which the server listens for incoming connections.
pub const IP_PORT: u16 = 8080;
-// ## Support functions
+// Support functions
+// -----------------
fn get_server() -> Command {
Command::cargo_bin("codechat-editor-server").unwrap()
}
-// ## Tests
+// Tests
+// -----
#[test]
fn test_url_to_path() {
let (temp_dir, test_dir) = prep_test_dir!();
diff --git a/server/src/webserver/vscode.rs b/server/src/webserver/vscode.rs
index 5493a6d2..ecb2f744 100644
--- a/server/src/webserver/vscode.rs
+++ b/server/src/webserver/vscode.rs
@@ -14,16 +14,20 @@
/// the CodeChat Editor. If not, see
/// [http://www.gnu.org/licenses](http://www.gnu.org/licenses).
///
-/// # `vscode.rs` -- Implement server-side functionality for the Visual Studio Code IDE
-// ## Imports
+/// `vscode.rs` -- Implement server-side functionality for the Visual Studio
+/// Code IDE
+/// ========================================================================
+// Imports
+// -------
//
// ### Standard library
use std::{cmp::min, collections::HashMap, path::PathBuf};
// ### Third-party
use actix_web::{
+ HttpRequest, HttpResponse,
error::{Error, ErrorBadRequest},
- get, web, HttpRequest, HttpResponse,
+ get, web,
};
use indoc::formatdoc;
use log::{debug, error, warn};
@@ -32,29 +36,32 @@ use tokio::{select, sync::mpsc};
// ### Local
use super::{
- client_websocket, get_client_framework, send_response, AppState, EditorMessage,
- EditorMessageContents, IdeType, WebsocketQueues, IP_ADDRESS,
+ AppState, EditorMessage, EditorMessageContents, IP_ADDRESS, IdeType, WebsocketQueues,
+ client_websocket, get_client_framework, send_response,
};
use crate::{
oneshot_send,
processing::{
- codechat_for_web_to_source, source_to_codechat_for_web_string, CodeChatForWeb, CodeMirror,
- TranslationResultsString,
+ CodeChatForWeb, CodeMirror, TranslationResultsString, codechat_for_web_to_source,
+ source_to_codechat_for_web_string,
},
queue_send,
webserver::{
- escape_html, filesystem_endpoint, html_wrapper, make_simple_http_response, path_to_url,
- text_file_to_response, try_canonicalize, url_to_path, ProcessingTaskHttpRequest,
- ResultOkTypes, UpdateMessageContents, INITIAL_MESSAGE_ID, MESSAGE_ID_INCREMENT,
+ INITIAL_MESSAGE_ID, MESSAGE_ID_INCREMENT, ProcessingTaskHttpRequest, ResultOkTypes,
+ UpdateMessageContents, escape_html, filesystem_endpoint, html_wrapper,
+ make_simple_http_response, path_to_url, text_file_to_response, try_canonicalize,
+ url_to_path,
},
};
-// ## Globals
+// Globals
+// -------
const VSCODE_PATH_PREFIX: &[&str] = &["vsc", "fs"];
// The max length of a message to show in the console.
const MAX_MESSAGE_LENGTH: usize = 200;
-// ## Code
+// Code
+// ----
//
// This is the processing task for the Visual Studio Code IDE. It handles all
// the core logic to moving data between the IDE and the client.
@@ -108,32 +115,36 @@ pub async fn vscode_ide_websocket(
// connections.
let (from_ide_tx, mut from_ide_rx) = mpsc::channel(10);
let (to_ide_tx, to_ide_rx) = mpsc::channel(10);
- assert!(app_state
- .vscode_ide_queues
- .lock()
- .unwrap()
- .insert(
- connection_id_str.clone(),
- WebsocketQueues {
- from_websocket_tx: from_ide_tx,
- to_websocket_rx: to_ide_rx,
- },
- )
- .is_none());
+ assert!(
+ app_state
+ .vscode_ide_queues
+ .lock()
+ .unwrap()
+ .insert(
+ connection_id_str.clone(),
+ WebsocketQueues {
+ from_websocket_tx: from_ide_tx,
+ to_websocket_rx: to_ide_rx,
+ },
+ )
+ .is_none()
+ );
let (from_client_tx, mut from_client_rx) = mpsc::channel(10);
let (to_client_tx, to_client_rx) = mpsc::channel(10);
- assert!(app_state
- .vscode_client_queues
- .lock()
- .unwrap()
- .insert(
- connection_id_str.clone(),
- WebsocketQueues {
- from_websocket_tx: from_client_tx,
- to_websocket_rx: to_client_rx,
- },
- )
- .is_none());
+ assert!(
+ app_state
+ .vscode_client_queues
+ .lock()
+ .unwrap()
+ .insert(
+ connection_id_str.clone(),
+ WebsocketQueues {
+ from_websocket_tx: from_client_tx,
+ to_websocket_rx: to_client_rx,
+ },
+ )
+ .is_none()
+ );
app_state
.vscode_connection_id
.lock()
@@ -146,8 +157,8 @@ pub async fn vscode_ide_websocket(
// Start the processing task.
actix_rt::spawn(async move {
- // Use a
- // [labeled block expression](https://doc.rust-lang.org/reference/expressions/loop-expr.html#labelled-block-expressions)
+ // Use a [labeled block
+ // expression](https://doc.rust-lang.org/reference/expressions/loop-expr.html#labelled-block-expressions)
// to provide a way to exit the current task.
'task: {
let mut current_file = PathBuf::new();
@@ -568,7 +579,9 @@ pub async fn vscode_ide_websocket(
.remove(&connection_id_task)
.is_none()
{
- error!("Unable to remove connection ID {connection_id_task} from processing task queue.");
+ error!(
+ "Unable to remove connection ID {connection_id_task} from processing task queue."
+ );
}
if app_state_task
.vscode_client_queues
@@ -661,7 +674,8 @@ async fn serve_vscode_fs(
filesystem_endpoint(request_path, &req, &app_state).await
}
-// ## Tests
+// Tests
+// -----
#[cfg(test)]
mod test {
use std::{
@@ -687,13 +701,12 @@ mod test {
time::sleep,
};
use tokio_tungstenite::{
- connect_async,
+ MaybeTlsStream, WebSocketStream, connect_async,
tungstenite::{http::StatusCode, protocol::Message},
- MaybeTlsStream, WebSocketStream,
};
use super::super::{
- run_server, tests::IP_PORT, EditorMessage, EditorMessageContents, IdeType, IP_ADDRESS,
+ EditorMessage, EditorMessageContents, IP_ADDRESS, IdeType, run_server, tests::IP_PORT,
};
use crate::{
cast,
diff --git a/server/tests/cli.rs b/server/tests/cli.rs
index 984314c8..c55efe3d 100644
--- a/server/tests/cli.rs
+++ b/server/tests/cli.rs
@@ -1,6 +1,8 @@
-// # `cli.rs` - Test the CLI interface
+// `cli.rs` - Test the CLI interface
+// =================================
//
-// ## Imports
+// Imports
+// -------
//
// ### Standard library
//
@@ -15,12 +17,14 @@ use predicates::{prelude::predicate, str::contains};
use code_chat_editor::webserver::IP_ADDRESS;
use tokio::task::spawn_blocking;
-// ## Support functions
+// Support functions
+// -----------------
fn get_server() -> Command {
Command::cargo_bin("codechat-editor-server").unwrap()
}
-// ## Tests
+// Tests
+// -----
#[test]
fn test_start_not_found() {
let mut cmd = get_server();
diff --git a/toc.md b/toc.md
index 3ce38be7..7be984fc 100644
--- a/toc.md
+++ b/toc.md
@@ -1,25 +1,30 @@
-# The CodeChat Editor
+The CodeChat Editor
+===================
-## User documentation
+User documentation
+------------------
1. [The CodeChat Editor manual](README.md)
-2. [The CodeChat Editor extension for Visual Studio Code manual](extensions/VSCode/README.md)
+2. [The CodeChat Editor extension for Visual Studio Code
+ manual](extensions/VSCode/README.md)
3. [Literate programming using the CodeChat Editor](docs/style_guide.cpp)
-## Design
+Design
+------
1. [CodeChat Editor Design](docs/design.md)
2. [Implementation](docs/implementation.md)
-## Implementation
+Implementation
+--------------
1. Server
1. [main.rs](server/src/main.rs)
2. [lib.rs](server/src/lib.rs)
3. [lexer.rs](server/src/lexer.rs)
1. [Lexer walkthrough](server/src/lexer/lexer-walkthrough.md)
- 2. [supported_languages.rs](server/src/lexer/supported_languages.rs)
- 3. [pest_parser.rs](server/src/lexer/pest_parser.rs)
+ 2. [supported\_languages.rs](server/src/lexer/supported_languages.rs)
+ 3. [pest\_parser.rs](server/src/lexer/pest_parser.rs)
1. [Parser design](server/src/lexer/pest/parser_design.md)
2. [shared.pest](server/src/lexer/pest/shared.pest)
3. [c.pest](server/src/lexer/pest/c.pest)
@@ -30,7 +35,7 @@
3. [log4rs.yml](server/log4rs.yml)
5. [processing.rs](server/src/processing.rs)
6. Tests
- 1. [test_utils.rs](server/src/test_utils.rs)
+ 1. [test\_utils.rs](server/src/test_utils.rs)
2. Lexer [tests.rs](server/src/lexer/tests.rs)
3. Webserver [tests.rs](server/src/webserver/tests.rs)
4. [cli.rs](server/tests/cli.rs)
@@ -46,10 +51,10 @@
5. [Mermaid](client/src/wc-mermaid/developer.md)
6. [typings.d.ts](client/src/typings.d.ts)
2. Styles
- 1. [CodeChatEditor.css](client/static/css/CodeChatEditor.css)
- 2. [CodeChatEditorProject.css](client/static/css/CodeChatEditorProject.css)
+ 1. [CodeChatEditor.css](client/src/css/CodeChatEditor.css)
+ 2. [CodeChatEditorProject.css](client/src/css/CodeChatEditorProject.css)
3. Themes
- 1. [light.css](client/static/css/themes/light.css)
+ 1. [light.css](client/src/css/themes/light.css)
3. Tests
1. [CodeChatEditor-test.mts](client/src/CodeChatEditor-test.mts)
1. [Run tests](server/src/lib.rs?test)
@@ -84,17 +89,20 @@
2. [dist-workspace.toml](server/dist-workspace.toml) - cargo-dist
configuration
-## Misc
+Misc
+----
-- New
- project template
-- [Table of contents](toc.md)
-- [Changelog](docs/CHANGELOG.md)
-- [Index](docs/index.md)
+* New
+ project template
+* [Table of contents](toc.md)
+* [Changelog](docs/CHANGELOG.md)
+* [Index](docs/index.md)
-## Notes
+Notes
+-----
-- TODO: all links here should be auto-titled and
- autogenerate the page-local TOC.
+* TODO: all links here should be auto-titled and
+ autogenerate the page-local TOC.
-## [License](LICENSE.md)
+[License](LICENSE.md)
+---------------------
\ No newline at end of file