Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
71 changes: 36 additions & 35 deletions src/editors/TiptapTemplateEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ function TiptapTemplateEditor() {
const isSyncingRef = useRef(false);
// Track the last markdown we sent to the store to detect external changes
const lastMarkdownRef = useRef(editorValue);
// External template loads can be parsed before rebuild provides the matching model.
const pendingModelRetryRef = useRef<string | null>(editorValue);
const lastModelManagerRef = useRef(modelManager);

// Parse markdown into TemplateMarkDocument for the editor
// Initialize as null - parsing is deferred to useEffect to ensure libraries are ready
Expand All @@ -40,45 +43,41 @@ function TiptapTemplateEditor() {
// Determine theme based on isDarkMode
const theme = getThemeName(isDarkMode);

// Capture initial values in refs to avoid re-running the initial parse effect
// when these values change (the sync effect handles subsequent changes)
const initialEditorValue = useRef(editorValue);
const initialModelManager = useRef(modelManager);

// Parse initial markdown after mount (runs once)
useEffect(() => {
if (doc === null && !parseError) {
const parsed = parseMarkdownTemplate(
initialEditorValue.current,
undefined,
initialModelManager.current
);
if (parsed) {
setDoc(parsed);
lastMarkdownRef.current = initialEditorValue.current;
} else {
setParseError("Could not parse template markdown");
}
}
}, [doc, parseError]);

// Sync from store to editor when editorValue changes externally
// (e.g., loading a sample, loading from shareable link)
useEffect(() => {
// Skip if doc hasn't been initialized yet
if (doc === null) return;

// Only sync if the change came from outside (not from our own onChange)
if (editorValue !== lastMarkdownRef.current && !isSyncingRef.current) {
const parsed = parseMarkdownTemplate(editorValue, undefined, modelManager);
if (parsed) {
setDoc(parsed);
setParseError(null);
} else {
setParseError("Could not parse template markdown");
if (isSyncingRef.current) return;

const needsInitialParse = doc === null;
const markdownChanged = editorValue !== lastMarkdownRef.current;
const modelChanged = modelManager !== lastModelManagerRef.current;
const shouldRetryWithModel =
modelChanged && pendingModelRetryRef.current === editorValue;

Comment thread
Rishabh060105 marked this conversation as resolved.
if (!needsInitialParse && !markdownChanged && !shouldRetryWithModel) {
if (modelChanged) {
lastModelManagerRef.current = modelManager;
}
lastMarkdownRef.current = editorValue;
return;
}

const parsed = parseMarkdownTemplate(editorValue, undefined, modelManager);
if (parsed) {
setDoc(parsed);
setParseError(null);
} else {
setParseError("Could not parse template markdown");
}

if (markdownChanged || needsInitialParse) {
pendingModelRetryRef.current = editorValue;
}
if (shouldRetryWithModel) {
pendingModelRetryRef.current = null;
}

lastMarkdownRef.current = editorValue;
lastModelManagerRef.current = modelManager;
}, [editorValue, doc, modelManager]);

// Handle changes from the TipTap editor
Expand All @@ -90,6 +89,8 @@ function TiptapTemplateEditor() {
// Serialize back to markdown
const markdown = serializeToMarkdown(newDoc);
lastMarkdownRef.current = markdown;
pendingModelRetryRef.current = null;
lastModelManagerRef.current = modelManager;

// Update store (this triggers rebuild)
isSyncingRef.current = true;
Expand All @@ -107,7 +108,7 @@ function TiptapTemplateEditor() {
isSyncingRef.current = false;
});
},
[setEditorValue, setTemplateMarkdown]
[modelManager, setEditorValue, setTemplateMarkdown]
);

// Handle validation errors from the TipTap editor
Expand Down
4 changes: 2 additions & 2 deletions src/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,12 +320,12 @@ const useAppStore = create<AppState>()(
setData: async (data: string) => {
set(() => ({ data }));
try {
const result = await rebuildDeBounce(
const { html, modelManager } = await rebuildDeBounce(
get().templateMarkdown,
get().modelCto,
data
);
set(() => ({ agreementHtml: result, error: undefined }));
set(() => ({ agreementHtml: html, modelManager, error: undefined }));
} catch (error: unknown) {
Comment thread
Rishabh060105 marked this conversation as resolved.
set(() => ({
error: formatError(error),
Expand Down
33 changes: 3 additions & 30 deletions vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { defineConfig as defineViteConfig, mergeConfig } from "vite";
import { defineConfig as defineVitestConfig, configDefaults } from "vitest/config";
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { nodePolyfills } from "vite-plugin-node-polyfills";
import { visualizer } from "rollup-plugin-visualizer";

// https://vitejs.dev/config/
const viteConfig = defineViteConfig({
export default defineConfig({
plugins: [nodePolyfills(), react(), visualizer({
emitFile: true,
filename: "stats.html",
Expand All @@ -18,30 +18,3 @@ const viteConfig = defineViteConfig({
needsInterop: ['@accordproject/template-engine'],
},
});


// https://vitest.dev/config/
const vitestConfig = defineVitestConfig({ test: {
globals: true,
environment: "jsdom",
setupFiles: "./src/utils/testing/setup.ts",
exclude: [...configDefaults.exclude, "**/e2e/**"],
server: {
deps: {
inline: ["monaco-editor"],
},
},
coverage: {
provider: 'v8',
reporter: ['text'],
include: ['src/**/*.{ts,tsx}'],
},
},
resolve: {
alias: process.env.VITEST ? {
"monaco-editor": "monaco-editor/esm/vs/editor/editor.api",
} : {},
},
});

export default mergeConfig(viteConfig, vitestConfig);
28 changes: 28 additions & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { mergeConfig } from "vite";
import { configDefaults, defineConfig } from "vitest/config";
import viteConfig from "./vite.config";

// https://vitest.dev/config/
export default mergeConfig(viteConfig, defineConfig({
test: {
globals: true,
environment: "jsdom",
setupFiles: "./src/utils/testing/setup.ts",
exclude: [...configDefaults.exclude, "**/e2e/**"],
server: {
deps: {
inline: ["monaco-editor"],
},
},
coverage: {
provider: "v8",
reporter: ["text"],
include: ["src/**/*.{ts,tsx}"],
},
},
resolve: {
alias: process.env.VITEST ? {
"monaco-editor": "monaco-editor/esm/vs/editor/editor.api",
} : {},
},
}));