From 7b8bfe92ccfd5b6a19a30cdaa457ed44f25cbc33 Mon Sep 17 00:00:00 2001 From: "Bryan A. Jones" Date: Tue, 16 Dec 2025 16:57:16 -0600 Subject: [PATCH 01/25] Docs: improve; wrap lines. --- docs/implementation.md | 110 ++++++++++++------- server/readme.md | 16 +++ test_utils/readme.md | 9 ++ test_utils/src/test_macros.rs | 11 +- test_utils/src/test_utils.rs | 29 +++-- toc.md | 200 +++++++++++++++++----------------- 6 files changed, 214 insertions(+), 161 deletions(-) create mode 100644 server/readme.md create mode 100644 test_utils/readme.md diff --git a/docs/implementation.md b/docs/implementation.md index 8bd9b006..9f4f1bcb 100644 --- a/docs/implementation.md +++ b/docs/implementation.md @@ -21,35 +21,54 @@ Implementation ### System architecture -; - websocket_server [label = "Websocket\nserver"]; - web_server [label = "Web\nserver"]; + websocket_server [label = "Websocket\nserver"]; + web_server [label = "Web\nserver"]; } subgraph cluster_client_framework { - label = "CodeChat Editor Client framework" + label = "CodeChat Editor Client framework" subgraph cluster_client { - label = "CodeChat Editor Client\n(Editor/Viewer/Simple Viewer)" - rendered_code [label = "Rendered code", style = dashed]; + label = "CodeChat Editor Client" + rendered_code [label = "Rendered document", style = dashed]; } } - CodeChat_plugin -> websocket_server [label = "websocket", dir = both]; - websocket_server -> rendered_code [label = "websocket", dir = both, lhead = cluster_client_framework]; - web_server -> rendered_code [label = "HTTP", dir = both, lhead = cluster_client ]; - }"> + CodeChat_plugin -> websocket_server [label = "NAPI-RS", dir = both, lhead = cluster_server]; + websocket_server -> rendered_code [label = "websocket", dir = both, lhead = cluster_client_framework]; + web_server -> rendered_code [label = "HTTP", dir = both, lhead = cluster_client ]; +} +``` + +Inside the client: + +* The Framework exchanges messages with the Server and loads the appropriate + Client (simple view, PDF view, editor, document-only editor). +* The editor provides basic Client services and handles document-only mode. +* The CodeMirror integration module embeds TinyMCE into CodeMirror, providing + the primary editing environment. + +The entire VSCode interface is contained in the extension, with the NAPI-RS glue +in the corresponding library. + +Does this make more sense to place in the TOC? Or is it too wordy there? I think +a diagram as an overview might be helpful. Perhaps the server, client, etc. +should have its of readme files providing some of this. Architecture -------------------------------------------------------------------------------- +Overall, the code is something like this: + ### Client/server partitioning Doc blocks consist of Markdown augmented with custom HTML elements which provide @@ -246,14 +265,20 @@ So, this project contains Rust code to automate this process -- see the Misc topics -------------------------------------------------------------------------------- -### CodeChat Editor Client Simple Viewer +### CodeChat Editor Client Viewer Types + +The Client supports several classes of files: -When in project mode, the CodeChat Editor cannot edit some files -- -miscellaneous text files, unsupported languages, images, video, etc. The simple -viewer displays (without allowing editing) these files as raw text in the -browser, though wrapped in the appropriate project structure (with a TOC on the -left). For the Visual Studio Code extension, the simple viewer also provides -support for viewing PDFs (which VSCode's built-in web browser doesn't support). +* Source files, rendered as intermingled code/doc blocks. +* Document-only files -- these contain only Markdown and typically have a file + extension of `.md`. +* Unsupported text files -- the CodeChat Editor cannot edit some files, such as + miscellaneous text files, unsupported languages, images, video, etc. The + simple viewer displays (without allowing editing) these files as raw text in + the browser, though wrapped in the appropriate project structure (with a TOC + on the left). +* PDFs, where a plugin viewer for VSCode provides rendering, since the built-in + browser doesn't. ### Broken fences (Markdown challenges) @@ -284,12 +309,11 @@ Future work 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);` - `}` + `: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);` `}` + `h1::before {` `counter-reset: var(--section-counter-reset);` `content: + var(--section-counter-content);` `}` ### Cached state @@ -462,41 +486,43 @@ Organization As shown in the figure below, the CodeChat Editor Client starts with `client/package.json`, which tells [NPM](https://en.wikipedia.org/wiki/Npm_(software)) which JavaScript libraries -are used in this project. Running `npm update` copies these libraries and all +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)) imports these libraries. Next, [esbuild](https://esbuild.github.io/) analyzes the CodeChat Editor client -based by transforming any [TypeScript](https://www.typescriptlang.org/) into +based by transforming any [TypeScript](https://www.typescriptlang.org/) into JavaScript then packaging all dependencies (JavaScript, CSS, images, etc.) into 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. - JS_lib [label = "npm update"] JS_lib -> esbuild; - CCE_source [label = "CodeChat Editor\nClient source"] - JS_lib -> CCE_source [label = "imports"] + CCE_source [label = "CodeChat Editor\nClient source"] + JS_lib -> CCE_source [label = "imports"] CCE_source -> esbuild - esbuild -> "Bundled JavaScript" - esbuild -> "Bundle metadata" - "Bundle metadata" -> "HashReader.mts" - "HashReader.mts" -> server_HTML - CCE_webpage [label = "CodeChat Editor\nClient webpage"] - "Bundled JavaScript" -> CCE_webpage - server_HTML [label = "CodeChat Editor\nServer-generated\nHTML"] + esbuild -> "Bundled JavaScript" + esbuild -> "Bundle metadata" + "Bundle metadata" -> "HashReader.mts" + "HashReader.mts" -> server_HTML + CCE_webpage [label = "CodeChat Editor\nClient webpage"] + "Bundled JavaScript" -> CCE_webpage + server_HTML [label = "CodeChat Editor\nServer-generated\nHTML"] server_HTML -> CCE_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/). -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). Code style -------------------------------------------------------------------------------- diff --git a/server/readme.md b/server/readme.md new file mode 100644 index 00000000..bd455f1f --- /dev/null +++ b/server/readme.md @@ -0,0 +1,16 @@ +`readme.md` - Overview of the Server +================================================================================ + +Overall: + +* The webserver module runs the overall Server. +* The translation module translates messages sent between the IDE and the + Client. + * The ide module provides an API interface between the Server and an IDE that + uses language-neutral data structures. Its submodules provide IDE-specific + code (for VSCode and for a file watcher). +* The processing module handles conversion of source code to the Client's format + and vice versa. + * The lexer divides source code into code and doc blocks. +* A main module provides a basic CLI interface for running the server outside an + IDE using the file watcher. diff --git a/test_utils/readme.md b/test_utils/readme.md new file mode 100644 index 00000000..74a0e0e5 --- /dev/null +++ b/test_utils/readme.md @@ -0,0 +1,9 @@ +`readme.md` - Overview of test utilities +================================================================================ + +These test utilities are used both in unit tests and in integration tests. +Integration tests can't access code inside a `#[cfg(test)]` configuration +predicate that's in the library being compiled; unit tests can't access code in +the `test/` subdirectory. Therefore, these utilities are placed in a separate +library (this one) then included in the `dev-dependencies` to solve both these +problems. diff --git a/test_utils/src/test_macros.rs b/test_utils/src/test_macros.rs index fe19f8ec..c0883882 100644 --- a/test_utils/src/test_macros.rs +++ b/test_utils/src/test_macros.rs @@ -15,18 +15,19 @@ /// [http://www.gnu.org/licenses](http://www.gnu.org/licenses). /// /// `test_macros.rs` -- Reusable macros 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 -// ------- +// ----------------------------------------------------------------------------- +// // None. // // 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 @@ -36,8 +37,8 @@ macro_rules! cast { // For an enum containing a single value (the typical case). ($target: expr, $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 + // 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. diff --git a/test_utils/src/test_utils.rs b/test_utils/src/test_utils.rs index 5c1ff033..7d05e95d 100644 --- a/test_utils/src/test_utils.rs +++ b/test_utils/src/test_utils.rs @@ -14,15 +14,15 @@ /// 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 -// ------- +// ----------------------------------------------------------------------------- // // ### Standard library use std::env; @@ -38,7 +38,7 @@ use log::Level; use crate::testing_logger; // 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 @@ -102,7 +102,7 @@ macro_rules! prep_test_dir { } // 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 @@ -123,9 +123,8 @@ 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); @@ -163,13 +162,13 @@ pub fn _prep_test_dir( // straightforward. However, to sometimes simply log data and at other times // examine logs requires care: // -// 1. The global logger can only be configured once. Configuring it for one -// test for the production logger and for another test using the testing -// logger doesn't work. -// 2. Since tests are run by default in multiple threads, the logger used -// should keep each thread's logs separate. -// 3. The logger needs to be initialized for all tests and for production, -// preferably without adding code to each test. +// 1. The global logger can only be configured once. Configuring it for one test +// for the production logger and for another test using the testing logger +// doesn't work. +// 2. Since tests are run by default in multiple threads, the logger used should +// keep each thread's logs separate. +// 3. The logger needs to be initialized for all tests and for production, +// preferably without adding code to each test. // // The modified `testing_logger` takes care of items 2 and 3. For item 3, I // don't have a way to auto-initialize the logger for all tests easily; diff --git a/toc.md b/toc.md index c765d45d..6495932a 100644 --- a/toc.md +++ b/toc.md @@ -1,117 +1,119 @@ The CodeChat Editor -=================== +================================================================================ User documentation ------------------- +-------------------------------------------------------------------------------- -1. [The CodeChat Editor manual](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) +1. [The CodeChat Editor manual](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 ------- +-------------------------------------------------------------------------------- -1. [CodeChat Editor Design](docs/design.md) -2. [Implementation](docs/implementation.md) +1. [CodeChat Editor Design](docs/design.md) +2. [Implementation](docs/implementation.md) 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) - 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) - 4. [python.pest](server/src/lexer/pest/python.pest) - 4. [webserver.rs](server/src/webserver.rs) - 1. [log4rs.yml](server/log4rs.yml) - 5. [ide.rs](server/src/ide.rs) - 1. [filewatcher.rs](server/src/ide/filewatcher.rs) - 2. [vscode.rs](server/src/ide/vscode.rs) - 6. [translation.rs](server/src/translation.rs) - 7. [processing.rs](server/src/processing.rs) - 8. Tests - 1. [test\_utils.rs](server/src/test_utils.rs) - 2. [testing\_logger.rs](server/src/testing_logger.rs) - 3. Lexer [tests.rs](server/src/lexer/tests.rs) - 4. Webserver [tests.rs](server/src/webserver/tests.rs) - 5. ide/vscode [tests.rs](server/src/ide/vscode/tests.rs) - 6. Processing [tests.rs](server/src/processing/tests.rs) - 7. [cli.rs](server/tests/cli.rs) - 9. [Cargo.toml](server/Cargo.toml) -2. Client - 1. Editor - 1. [CodeChatEditorFramework.mts](client/src/CodeChatEditorFramework.mts) - 2. [CodeChatEditor.mts](client/src/CodeChatEditor.mts) - 1. [CodeMirror-integration.mts](client/src/CodeMirror-integration.mts) - 2. [tinymce-config.mts](client/src/tinymce-config.mts) - 3. [EditorComponents.mts](client/src/EditorComponents.mts) - 4. [graphviz-webcomponent-setup.mts](client/src/graphviz-webcomponent-setup.mts) - 5. [Mermaid](client/src/wc-mermaid/developer.md) - 6. [shared\_types.mts](client/src/shared_types.mts) - 7. [assert.mts](client/src/assert.mts) - 8. [show\_toast.mts](client/src/show_toast.mts) - 9. [typings.d.ts](client/src/typings.d.ts) - 2. Styles - 1. [CodeChatEditor.css](client/src/css/CodeChatEditor.css) - 2. [CodeChatEditorProject.css](client/src/css/CodeChatEditorProject.css) - 3. Themes - 1. [light.css](client/src/css/themes/light.css) - 3. Tests - 1. [CodeChatEditor-test.mts](client/src/CodeChatEditor-test.mts) - 1. [Run tests](README.md?test) - 2. [HTML to Markdown conversion test document](docs/Markdown_HTML.js) -3. Extensions - 1. Visual Studio Code - 1. [extension.ts](extensions/VSCode/src/extension.ts) - 2. [lib.rs](extensions/VSCode/src/lib.rs) - 3. [Cargo.toml](extensions/VSCode/Cargo.toml) - 4. [Developer documentation](extensions/VSCode/developer.md) -4. Development tools - 1. Builder - 1. [builder/Cargo.toml](builder/Cargo.toml) - 2. [builder/src/main.rs](builder/src/main.rs) - 2. Git - 1. [server/.gitignore](server/.gitignore) - 2. [client/static/.gitignore](client/static/.gitignore) - 3. [client/.gitignore](client/.gitignore) - 4. [extensions/VSCode/.gitignore](extensions/VSCode/.gitignore) - 5. [builder/.gitignore](builder/.gitignore) - 3. NPM/esbuild - 1. [HashReader.mts](client/src/HashReader.mts) - 2. client/package.json - 3. [client/tsconfig.json](client/tsconfig.json) - 4. [client/eslint.config.js](client/eslint.config.js) - 5. [client/.prettierrc.json5](client/.prettierrc.json5) - 6. [extensions/VSCode/eslint.config.js](extensions/VSCode/eslint.config.js) - 7. [extensions/VSCode/tsconfig.json](extensions/VSCode/tsconfig.json) - 8. [extensions/VSCode/jsconfig.json](extensions/VSCode/jsconfig.json) - 9. [extensions/VSCode/.vscodeignore](extensions/VSCode/.vscodeignore) - 10. [.prettierignore](.prettierignore) - 4. Misc - 1. [config.toml](server/.cargo/config.toml) - for Rust code coverage - 2. [dist-workspace.toml](dist-workspace.toml) - cargo-dist - configuration - 3. [dist.toml](server/dist.toml) - additional cargo-dist configuration +1. [Server](server/readme.md) + 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) + 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) + 4. [python.pest](server/src/lexer/pest/python.pest) + 4. [webserver.rs](server/src/webserver.rs) + 1. [log4rs.yml](server/log4rs.yml) + 5. [ide.rs](server/src/ide.rs) + 1. [filewatcher.rs](server/src/ide/filewatcher.rs) + 2. [vscode.rs](server/src/ide/vscode.rs) + 6. [translation.rs](server/src/translation.rs) + 7. [processing.rs](server/src/processing.rs) + 8. Tests + 1. [Test utilities](test_utils/readme.md) + 1. [test\_utils.rs](test_utils/src/test_utils.rs) + 2. [testing\_logger.rs](test_utils/src/testing_logger.rs) + 3. [test\_macros.rs](test_utils/src/test_macros.rs) + 2. Lexer [tests.rs](server/src/lexer/tests.rs) + 3. Webserver [tests.rs](server/src/webserver/tests.rs) + 4. ide/vscode [tests.rs](server/src/ide/vscode/tests.rs) + 5. Processing [tests.rs](server/src/processing/tests.rs) + 6. [cli.rs](server/tests/cli.rs) + 9. [Cargo.toml](server/Cargo.toml) +2. Client + 1. Editor + 1. [CodeChatEditorFramework.mts](client/src/CodeChatEditorFramework.mts) + 2. [CodeChatEditor.mts](client/src/CodeChatEditor.mts) + 1. [CodeMirror-integration.mts](client/src/CodeMirror-integration.mts) + 2. [tinymce-config.mts](client/src/tinymce-config.mts) + 3. [EditorComponents.mts](client/src/EditorComponents.mts) + 4. [graphviz-webcomponent-setup.mts](client/src/graphviz-webcomponent-setup.mts) + 5. [Mermaid](client/src/wc-mermaid/developer.md) + 6. [shared\_types.mts](client/src/shared_types.mts) + 7. [assert.mts](client/src/assert.mts) + 8. [show\_toast.mts](client/src/show_toast.mts) + 9. [typings.d.ts](client/src/typings.d.ts) + 2. Styles + 1. [CodeChatEditor.css](client/src/css/CodeChatEditor.css) + 2. [CodeChatEditorProject.css](client/src/css/CodeChatEditorProject.css) + 3. Themes + 1. [light.css](client/src/css/themes/light.css) + 3. Tests + 1. [CodeChatEditor-test.mts](client/src/CodeChatEditor-test.mts) + 1. [Run tests](README.md?test) + 2. [HTML to Markdown conversion test document](docs/Markdown_HTML.js) +3. Extensions + 1. Visual Studio Code + 1. [extension.ts](extensions/VSCode/src/extension.ts) + 2. [lib.rs](extensions/VSCode/src/lib.rs) + 3. [Cargo.toml](extensions/VSCode/Cargo.toml) + 4. [Developer documentation](extensions/VSCode/developer.md) +4. Development tools + 1. Builder + 1. [builder/Cargo.toml](builder/Cargo.toml) + 2. [builder/src/main.rs](builder/src/main.rs) + 2. Git + 1. [server/.gitignore](server/.gitignore) + 2. [client/static/.gitignore](client/static/.gitignore) + 3. [client/.gitignore](client/.gitignore) + 4. [extensions/VSCode/.gitignore](extensions/VSCode/.gitignore) + 5. [builder/.gitignore](builder/.gitignore) + 3. NPM/esbuild + 1. [HashReader.mts](client/src/HashReader.mts) + 2. client/package.json + 3. [client/tsconfig.json](client/tsconfig.json) + 4. [client/eslint.config.js](client/eslint.config.js) + 5. [client/.prettierrc.json5](client/.prettierrc.json5) + 6. [extensions/VSCode/eslint.config.js](extensions/VSCode/eslint.config.js) + 7. [extensions/VSCode/tsconfig.json](extensions/VSCode/tsconfig.json) + 8. [extensions/VSCode/jsconfig.json](extensions/VSCode/jsconfig.json) + 9. [extensions/VSCode/.vscodeignore](extensions/VSCode/.vscodeignore) + 10. [.prettierignore](.prettierignore) + 4. Misc + 1. [config.toml](server/.cargo/config.toml) - for Rust code coverage + 2. [dist-workspace.toml](dist-workspace.toml) - cargo-dist configuration + 3. [dist.toml](server/dist.toml) - additional cargo-dist configuration Misc ----- +-------------------------------------------------------------------------------- -* New project template -* [Table of contents](toc.md) -* [Changelog](CHANGELOG.md) -* [Index](docs/index.md) +* New + project template +* [Table of contents](toc.md) +* [Changelog](CHANGELOG.md) +* [Index](docs/index.md) 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) ---------------------- \ No newline at end of file +-------------------------------------------------------------------------------- From e538b9a796d988d67b2f51c27435464147521758 Mon Sep 17 00:00:00 2001 From: "Bryan A. Jones" Date: Tue, 16 Dec 2025 17:03:40 -0600 Subject: [PATCH 02/25] Fix: revert to @codemirror/view 6.38 until bugs are fixed. --- builder/src/main.rs | 10 +++++++++- client/package.json5 | 7 ++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/builder/src/main.rs b/builder/src/main.rs index 7849dc8d..353fb95a 100644 --- a/builder/src/main.rs +++ b/builder/src/main.rs @@ -312,7 +312,15 @@ 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_libs() -> io::Result<()> { - // In [older + // 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)", + " let selectionNotFocus = !focused && !(this.view.state.facet(editable) || this.dom.tabIndex > -1) && + hasSelection(this.dom, this.view.observer.selectionRange) && !(activeElt && this.dom.contains(activeElt));", + &format!("{CLIENT_PATH}/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. diff --git a/client/package.json5 b/client/package.json5 index b526dbe8..348d921a 100644 --- a/client/package.json5 +++ b/client/package.json5 @@ -44,6 +44,11 @@ }, type: 'module', version: '0.1.46', + pnpm: { + overrides: { + '@codemirror/view': '<6.39.0', + }, + }, dependencies: { '@codemirror/commands': '^6.10.0', '@codemirror/lang-cpp': '^6.0.3', @@ -61,7 +66,7 @@ '@codemirror/lang-xml': '^6.1.0', '@codemirror/lang-yaml': '^6.1.2', '@codemirror/state': '^6.5.2', - '@codemirror/view': '^6.39.4', + '@codemirror/view': '^6.38.8', '@hpcc-js/wasm-graphviz': '^1.17.0', '@mathjax/mathjax-newcm-font': '4.1.0', codemirror: '^6.0.2', From baca5d646a55d0b56ce29b3809dc5f1726b2c7a5 Mon Sep 17 00:00:00 2001 From: "Bryan A. Jones" Date: Wed, 17 Dec 2025 07:22:08 -0600 Subject: [PATCH 03/25] Fix: use correct random funtion to avoid fractional floating-point values. --- extensions/VSCode/src/extension.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/extensions/VSCode/src/extension.ts b/extensions/VSCode/src/extension.ts index 938fd836..7e8ccf33 100644 --- a/extensions/VSCode/src/extension.ts +++ b/extensions/VSCode/src/extension.ts @@ -528,10 +528,7 @@ export const activate = (context: vscode.ExtensionContext) => { const load_file_result: null | [string, number] = doc === undefined ? null - : [ - doc.getText(), - (version = Math.random()), - ]; + : [doc.getText(), (version = rand())]; console_log( `CodeChat Editor extension: Result(LoadFile(${format_struct(load_file_result)}))`, ); From 82260b9d59aec321051e2cb376720d9c51a6b3e2 Mon Sep 17 00:00:00 2001 From: "Bryan A. Jones" Date: Wed, 17 Dec 2025 08:05:26 -0600 Subject: [PATCH 04/25] Docs: updates. --- builder/src/main.rs | 3 ++- client/readme.md | 10 ++++++++++ extensions/readme.md | 14 ++++++++++++++ extensions/universal.md | 8 -------- test_utils/src/test_macros.rs | 5 ----- test_utils/src/test_utils.rs | 5 ----- toc.md | 4 ++-- 7 files changed, 28 insertions(+), 21 deletions(-) create mode 100644 client/readme.md create mode 100644 extensions/readme.md delete mode 100644 extensions/universal.md diff --git a/builder/src/main.rs b/builder/src/main.rs index 353fb95a..bd71f67d 100644 --- a/builder/src/main.rs +++ b/builder/src/main.rs @@ -320,7 +320,8 @@ fn patch_client_libs() -> io::Result<()> { " let selectionNotFocus = !focused && !(this.view.state.facet(editable) || this.dom.tabIndex > -1) && hasSelection(this.dom, this.view.observer.selectionRange) && !(activeElt && this.dom.contains(activeElt));", &format!("{CLIENT_PATH}/node_modules/@codemirror/view/dist/index.js") - )?; // In [older + )?; + // 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. diff --git a/client/readme.md b/client/readme.md new file mode 100644 index 00000000..7a30e8b6 --- /dev/null +++ b/client/readme.md @@ -0,0 +1,10 @@ +`readme.md` - overview of the Client +================================================================================ + +Inside the client: + +* The Framework exchanges messages with the Server and loads the appropriate + Client (simple view, PDF view, editor, document-only editor). +* The editor provides basic Client services and handles document-only mode. +* The CodeMirror integration module embeds TinyMCE into CodeMirror, providing + the primary editing environment. diff --git a/extensions/readme.md b/extensions/readme.md new file mode 100644 index 00000000..43f52547 --- /dev/null +++ b/extensions/readme.md @@ -0,0 +1,14 @@ +`readme.py` - Overview of extensions +================================================================================ + +The goal of the CodeChat Editor is to provide extensions for a number of IDEs +and environments. To support this, an explicit design goal of the Editor is to +implement most of the program's functionality in the Server and Client, and to +provide generic interfaces as a part of the server to IDEs (see ide.rs). + +Currently, the system supports two IDEs: + +* Visual Studio Code. This is the primary platform for the CodeChat Editor. +* Universal -- the file watcher extension allows use with any IDE by looking for + changes made to the current file and automatically reloading it when changes + are made. diff --git a/extensions/universal.md b/extensions/universal.md deleted file mode 100644 index 2dc4a90b..00000000 --- a/extensions/universal.md +++ /dev/null @@ -1,8 +0,0 @@ -**NOTE**: This file was copied from a previous project and needs significant -editing. - -# Universal extensions/plug-ins - -The CodeChat Server offers a modes that will work with almost any text editor or IDE: - -- A `file change watcher ` which renders any file as soon as it's saved. diff --git a/test_utils/src/test_macros.rs b/test_utils/src/test_macros.rs index c0883882..b1220e8d 100644 --- a/test_utils/src/test_macros.rs +++ b/test_utils/src/test_macros.rs @@ -16,11 +16,6 @@ /// /// `test_macros.rs` -- Reusable macros 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 // ----------------------------------------------------------------------------- // diff --git a/test_utils/src/test_utils.rs b/test_utils/src/test_utils.rs index 7d05e95d..a947b3c9 100644 --- a/test_utils/src/test_utils.rs +++ b/test_utils/src/test_utils.rs @@ -16,11 +16,6 @@ /// /// `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 // ----------------------------------------------------------------------------- // diff --git a/toc.md b/toc.md index 6495932a..ee1ce65d 100644 --- a/toc.md +++ b/toc.md @@ -46,7 +46,7 @@ Implementation 5. Processing [tests.rs](server/src/processing/tests.rs) 6. [cli.rs](server/tests/cli.rs) 9. [Cargo.toml](server/Cargo.toml) -2. Client +2. [Client](client/readme.md) 1. Editor 1. [CodeChatEditorFramework.mts](client/src/CodeChatEditorFramework.mts) 2. [CodeChatEditor.mts](client/src/CodeChatEditor.mts) @@ -68,7 +68,7 @@ Implementation 1. [CodeChatEditor-test.mts](client/src/CodeChatEditor-test.mts) 1. [Run tests](README.md?test) 2. [HTML to Markdown conversion test document](docs/Markdown_HTML.js) -3. Extensions +3. [Extensions](extensions/) 1. Visual Studio Code 1. [extension.ts](extensions/VSCode/src/extension.ts) 2. [lib.rs](extensions/VSCode/src/lib.rs) From 523ca4e881cc00ccf1fdbadd0b0d6576c42ce94a Mon Sep 17 00:00:00 2001 From: "Bryan A. Jones" Date: Wed, 17 Dec 2025 08:15:39 -0600 Subject: [PATCH 05/25] Add: include version numbers in OutOfSync message. --- client/src/CodeChatEditorFramework.mts | 7 ++++++- extensions/VSCode/src/extension.ts | 9 +++++++-- server/src/webserver.rs | 17 ++--------------- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/client/src/CodeChatEditorFramework.mts b/client/src/CodeChatEditorFramework.mts index 69b7634e..5e590d2b 100644 --- a/client/src/CodeChatEditorFramework.mts +++ b/client/src/CodeChatEditorFramework.mts @@ -175,7 +175,12 @@ class WebSocketComm { report_error( `Out of sync: Client version ${this.version} !== incoming version ${contents.source.Diff.version}.`, ); - this.send_result(id, "OutOfSync"); + this.send_result(id, { + OutOfSync: [ + this.version, + contents.source.Diff.version, + ], + }); return; } } diff --git a/extensions/VSCode/src/extension.ts b/extensions/VSCode/src/extension.ts index 7e8ccf33..93f173c2 100644 --- a/extensions/VSCode/src/extension.ts +++ b/extensions/VSCode/src/extension.ts @@ -360,7 +360,12 @@ export const activate = (context: vscode.ExtensionContext) => { // If this diff was not made against the // text we currently have, reject it. if (source.Diff.version !== version) { - await sendResult(id, "OutOfSync"); + await sendResult(id, { + OutOfSync: [ + version, + source.Diff.version, + ], + }); // Send an `Update` with the full text to // re-sync the Client. console_log( @@ -514,7 +519,7 @@ export const activate = (context: vscode.ExtensionContext) => { const result_contents = value as MessageResult; if ("Err" in result_contents) { show_error( - `Error in message ${id}: ${result_contents.Err}`, + `Error in message ${id}: ${JSON.stringify(result_contents.Err)}`, ); } break; diff --git a/server/src/webserver.rs b/server/src/webserver.rs index 32d05a35..e0d18b8c 100644 --- a/server/src/webserver.rs +++ b/server/src/webserver.rs @@ -254,8 +254,8 @@ pub enum ResultOkTypes { #[derive(Debug, Serialize, Deserialize, TS, PartialEq, thiserror::Error)] pub enum ResultErrTypes { - #[error("File out of sync; update rejected")] - OutOfSync, + #[error("File out of sync; update rejected. Expected version {0} but saw version {1}")] + OutOfSync(f64, f64), #[error("IDE must not send this message")] IdeIllegalMessage, #[error("Client not allowed to send this message")] @@ -426,19 +426,6 @@ pub const INITIAL_IDE_MESSAGE_ID: f64 = INITIAL_CLIENT_MESSAGE_ID + 1.0; /// assuming an average of 1 message/second.) pub const MESSAGE_ID_INCREMENT: f64 = 3.0; -/// Synchronization state between the Client, Server, and IDE. -#[derive(PartialEq)] -pub enum SyncState { - /// Indicates the Client, IDE, and server's documents are identical. - InSync, - /// An Update message is in flight; the documents are out of sync until the - /// response to the Update is received. - Pending(f64), - /// A CurrentFile message was sent, guaranteeing that documents are out of - /// sync. - OutOfSync, -} - const MATHJAX_TAGS: &str = concatdoc!( r#"