Skip to content
Merged

Dev #70

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions builder/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion builder/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ fn run_update() -> io::Result<()> {
cargo update --manifest-path=../builder/Cargo.toml;
cargo update;
)?;
// Simply display outdated dependencies, but don't considert them an error.
// Simply display outdated dependencies, but don't consider them an error.
run_script("npm", &["outdated"], "../client", false)?;
run_script("npm", &["outdated"], "../extensions/VSCode", false)?;
run_cmd!(
Expand Down
41 changes: 28 additions & 13 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 7 additions & 5 deletions client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "codechat-editor-client",
"version": "0.1.24",
"version": "0.1.26",
"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",
Expand All @@ -17,6 +17,7 @@
"@types/js-beautify": "^1",
"@types/mocha": "^10",
"@types/node": "^24",
"@types/toastify-js": "^1.12.4",
"@typescript-eslint/eslint-plugin": "^8",
"@typescript-eslint/parser": "^8",
"chai": "^5",
Expand All @@ -41,14 +42,15 @@
"@codemirror/lang-rust": "^6",
"@codemirror/lang-xml": "^6",
"@codemirror/view": "^6",
"codemirror": "^6",
"graphviz-webcomponent": "^2",
"@mathjax/mathjax-newcm-font": "4.0.0-rc.4",
"@mathjax/src": "4.0.0-rc.4",
"codemirror": "^6",
"graphviz-webcomponent": "^2",
"mermaid": "^11",
"npm-check-updates": "^18",
"pdfjs-dist": "^5",
"tinymce": "^8"
"pdfjs-dist": "~5 < 5.4.54 || ~5.4.55",
"tinymce": "^8",
"toastify-js": "^1"
},
"repository": {
"type": "git",
Expand Down
124 changes: 77 additions & 47 deletions client/src/CodeChatEditor.mts
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ import {
CodeMirror_save,
mathJaxTypeset,
mathJaxUnTypeset,
scroll_to_line,
set_CodeMirror_positions,
} 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,
// 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";
Expand All @@ -70,6 +72,7 @@ import {
UpdateMessageContents,
CodeMirror,
} from "./shared_types.mjs";
import { show_toast } from "./show_toast.mjs";

// ### CSS
import "./css/CodeChatEditor.css";
Expand Down Expand Up @@ -113,8 +116,13 @@ declare global {
interface Window {
CodeChatEditor: {
// Called by the Client Framework.
open_lp: (code_chat_for_web: CodeChatForWeb) => Promise<void>;
open_lp: (
codechat_for_web: CodeChatForWeb,
cursor_position?: number,
) => Promise<void>;
on_save: (_only_if_dirty: boolean) => Promise<void>;
scroll_to_line: (line: number) => void;
show_toast: (text: string) => void;
allow_navigation: boolean;
};
CodeChatEditor_test: any;
Expand Down Expand Up @@ -180,6 +188,8 @@ export const page_init = () => {
window.CodeChatEditor = {
open_lp,
on_save,
scroll_to_line,
show_toast,
allow_navigation: false,
};
});
Expand Down Expand Up @@ -210,10 +220,17 @@ const is_doc_only = () => {
};

// Wait for the DOM to load before opening the file.
const open_lp = async (code_chat_for_web: CodeChatForWeb) =>
on_dom_content_loaded(() => _open_lp(code_chat_for_web));

// Store the HTML sent for CodeChat Editor documents. We can't simply use TinyMCE's [getContent](https://www.tiny.cloud/docs/tinymce/latest/apis/tinymce.editor/#getContent), since this modifies the content based on cleanup rules before returning it -- which causes applying diffs to this unexpectedly modified content to produce incorrect results. This text is the unmodified content sent from the IDE.
const open_lp = async (
codechat_for_web: CodeChatForWeb,
cursor_position?: number,
) => on_dom_content_loaded(() => _open_lp(codechat_for_web, cursor_position));

// Store the HTML sent for CodeChat Editor documents. We can't simply use
// TinyMCE's
// [getContent](https://www.tiny.cloud/docs/tinymce/latest/apis/tinymce.editor/#getContent),
// since this modifies the content based on cleanup rules before returning it --
// which causes applying diffs to this unexpectedly modified content to produce
// incorrect results. This text is the unmodified content sent from the IDE.
let doc_content = "";

// This function is called on page load to "load" a file. Before this point, the
Expand All @@ -223,7 +240,8 @@ let doc_content = "";
const _open_lp = async (
// A data structure provided by the server, containing the source and
// associated metadata. See[`AllSource`](#AllSource).
code_chat_for_web: CodeChatForWeb,
codechat_for_web: CodeChatForWeb,
cursor_position?: number,
) => {
// Use[URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)
// to parse out the search parameters of this window's URL.
Expand All @@ -238,16 +256,18 @@ const _open_lp = async (
const editorMode = EditorMode[urlParams.get("mode") ?? "edit"];

// Get the<code><a href="#current_metadata">current_metadata</a></code> from
// the provided `code_chat_for_web` struct and store it as a global variable.
current_metadata = code_chat_for_web["metadata"];
const source = code_chat_for_web["source"];
// the provided `code_chat_for_web` struct and store it as a global
// variable.
current_metadata = codechat_for_web["metadata"];
const source = codechat_for_web["source"];
const codechat_body = document.getElementById(
"CodeChat-body",
) as HTMLDivElement;
// Disable autosave when updating the document.
autosaveEnabled = false;
clearAutosaveTimer();
// Before calling any MathJax, make sure it's fully loaded and the initial render is finished.
// Before calling any MathJax, make sure it's fully loaded and the initial
// render is finished.
await window.MathJax.startup.promise;
// Per
// the[docs](https://docs.mathjax.org/en/latest/web/typeset.html#updating-previously-typeset-content),
Expand Down Expand Up @@ -299,7 +319,12 @@ const _open_lp = async (
}
mathJaxTypeset(codechat_body);
} else {
await CodeMirror_load(codechat_body, source, current_metadata.mode, []);
await CodeMirror_load(
codechat_body,
codechat_for_web,
[],
cursor_position,
);
}
autosaveEnabled = true;

Expand All @@ -312,45 +337,48 @@ const _open_lp = async (
}
};

const save_lp = () => {
/// @ts-expect-error
let code_mirror_diffable: CodeMirrorDiffable = {};
if (is_doc_only()) {
// Untypeset all math before saving the document.
const codechat_body = document.getElementById(
"CodeChat-body",
) as HTMLDivElement;
mathJaxUnTypeset(codechat_body);
// To save a document only, simply get the HTML from the only Tiny MCE
// div.
tinymce.activeEditor!.save();
const html = tinymce.activeEditor!.getContent();
(
code_mirror_diffable as {
Plain: CodeMirror;
}
).Plain = {
doc: turndownService.turndown(html),
doc_blocks: [],
};
// Retypeset all math after saving the document.
mathJaxTypeset(codechat_body);
} else {
code_mirror_diffable = CodeMirror_save();
assert("Plain" in code_mirror_diffable);
codechat_html_to_markdown(code_mirror_diffable.Plain.doc_blocks);
}

const save_lp = (is_dirty: boolean) => {
let update: UpdateMessageContents = {
// The Framework will fill in this value.
file_path: "",
contents: {
};
set_CodeMirror_positions(update);

// Add the contents only if the document is dirty.
if (is_dirty) {
/// @ts-expect-error
let code_mirror_diffable: CodeMirrorDiffable = {};
if (is_doc_only()) {
// Untypeset all math before saving the document.
const codechat_body = document.getElementById(
"CodeChat-body",
) as HTMLDivElement;
mathJaxUnTypeset(codechat_body);
// To save a document only, simply get the HTML from the only Tiny MCE
// div.
tinymce.activeEditor!.save();
const html = tinymce.activeEditor!.getContent();
(
code_mirror_diffable as {
Plain: CodeMirror;
}
).Plain = {
doc: turndownService.turndown(html),
doc_blocks: [],
};
// Retypeset all math after saving the document.
mathJaxTypeset(codechat_body);
} else {
code_mirror_diffable = CodeMirror_save();
assert("Plain" in code_mirror_diffable);
codechat_html_to_markdown(code_mirror_diffable.Plain.doc_blocks);
}
update.contents = {
metadata: current_metadata,
source: code_mirror_diffable,
},
scroll_position: null,
cursor_position: null,
};
};
}

return update;
};

Expand All @@ -373,7 +401,9 @@ const on_save = async (only_if_dirty: boolean = false) => {
const webSocketComm = parent.window.CodeChatEditorFramework.webSocketComm;
console.log("Sent Update - saving document.");
await new Promise(async (resolve) => {
webSocketComm.send_message({ Update: save_lp() }, () => resolve(0));
webSocketComm.send_message({ Update: save_lp(is_dirty) }, () =>
resolve(0),
);
});
is_dirty = false;
};
Expand Down
Loading
Loading