Conversation
- Updated ModelManager to use strict mode for better validation in parseMarkdownTemplate. - Improved error handling in parseMarkdownTemplate to avoid unnecessary logging during editing. - Modified Vite configuration to set process.browser and process.env for better compatibility. - Added end-to-end tests for the TipTap Template Editor, covering rich editor features and interactions. - Introduced theme utilities for managing light/dark mode in the application. - Created CSS styles for the TipTap Template Editor wrapper, handling layout and error/loading states. - Defined constants for TemplateMark and CommonMark node classes to avoid typos and improve IDE support. - Implemented converters for transforming TipTap nodes to TemplateMark format and vice versa. - Added type guards for runtime type checking of TemplateMark and CommonMark nodes. Signed-off-by: Matt Roberts <code@rbrts.uk>
❌ Deploy Preview for ap-template-playground failed.
|
There was a problem hiding this comment.
Pull request overview
Introduces a TipTap-based rich TemplateMark editor (opt-in “Beta”) alongside the existing Monaco markdown editor, and refactors theme handling to a boolean dark-mode flag while upgrading the Vite/Vitest toolchain.
Changes:
- Add
src/tiptap-editor/package (components, extensions, serializers, utils) plus wrapper integration into the existing editor container and settings toggle. - Refactor theme state from
backgroundColor/textColortoisDarkModeand apply Ant Design theming viaConfigProvider. - Upgrade build/test tooling (Vite/Vitest, polyfills, coverage) and add new unit + e2e coverage for the rich editor.
Reviewed changes
Copilot reviewed 106 out of 108 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| vite.config.ts | Switch node polyfill plugin and enable Vitest coverage configuration. |
| package.json | Add TipTap/ProseMirror deps and upgrade Vite/Vitest-related tooling. |
| .gitignore | Ignore coverage output and Dolt database artifacts. |
| e2e/tiptap-editor.spec.ts | Add Playwright coverage for rich editor enabled/disabled flows. |
| src/store/store.ts | Add isDarkMode, useRichEditor, and store modelManager from rebuild. |
| src/App.tsx | Apply Ant Design dark/light algorithms via ConfigProvider; set data-theme. |
| src/pages/MainContainer.tsx | Integrate “Beta” tag display + hide old toolbar when rich editor enabled; adapt to isDarkMode. |
| src/styles/pages/MainContainer.css | Apply typography variables to agreement preview container. |
| src/components/SettingsModal.tsx | Add “Rich Template Editor (Beta)” toggle; migrate to isDarkMode. |
| src/components/ProblemPanel.tsx | Migrate theme usage to isDarkMode and remove inline color styling. |
| src/components/ErrorBoundary.tsx | Migrate theme usage to isDarkMode and simplify inline styling. |
| src/components/AIChatPanel.tsx | Migrate theme usage to isDarkMode and remove inline color styling. |
| src/components/ResizableContainer.tsx | Remove store-driven background color styling. |
| src/components/FullScreenModal.tsx | Remove dynamic style injection based on theme colors. |
| src/AgreementHtml.tsx | Remove inline background/text color styling from preview wrapper. |
| src/constants/theme.ts | Add helper to convert isDarkMode to `'light' |
| src/editors/editorsContainer/TemplateMarkdown.tsx | Route Template editor to TipTap wrapper when useRichEditor enabled. |
| src/editors/TiptapTemplateEditor.tsx | New wrapper syncing markdown string state ↔ TemplateMark JSON, using store modelManager. |
| src/editors/TiptapTemplateEditor.css | Wrapper styles for loading/error states. |
| src/editors/MarkdownEditor.tsx | Migrate editor theme selection to isDarkMode (light/dark Monaco themes). |
| src/editors/JSONEditor.tsx | Migrate editor theme selection to isDarkMode. |
| src/editors/ConcertoEditor.tsx | Migrate editor theme selection to isDarkMode. |
| src/tests/components/ProblemPanel.test.tsx | Update tests for new theme state shape. |
| src/tests/components/ErrorBoundary.test.tsx | Update tests for new theme state shape. |
| src/tests/tiptap-editor/mocks/styleMock.js | Add style mock for TipTap editor test environment. |
| src/tests/tiptap-editor/helpers/createTestEditor.ts | Add headless TipTap editor factory for unit tests. |
| src/tests/tiptap-editor/utils/serializeTemplate.test.ts | Add unit tests for TemplateMark → markdown serialization. |
| src/tests/tiptap-editor/utils/parseTemplate.test.ts | Add unit tests for markdown → TemplateMark parsing helpers. |
| src/tests/tiptap-editor/utils/generateConcertoModel.test.ts | Add unit tests for generating CTO from TemplateMark JSON. |
| src/tests/tiptap-editor/components/TemplateEditor.test.tsx | Add basic render-level tests for the new TemplateEditor component. |
| src/tests/tiptap-editor/components/conditional-nodeview.test.tsx | Add node-level tests for conditional nodes round-tripping. |
| src/tests/tiptap-editor/components/optional-nodeview.test.tsx | Add node-level tests for optional nodes round-tripping. |
| src/tests/tiptap-editor/components/enum-variable-nodeview.test.tsx | Add node-level tests for enum variable nodes round-tripping. |
| src/tiptap-editor/index.ts | Export new editor package API surface (components/hooks/utils/types). |
| src/tiptap-editor/types/index.ts | Define public props + validation error types for the editor package. |
| src/tiptap-editor/types/TemplateMark.ts | Add TemplateMark/CommonMark TS model mirrors for editor logic. |
| src/tiptap-editor/types/guards.ts | Add runtime type guards for TemplateMark/CommonMark nodes. |
| src/tiptap-editor/constants/nodeClasses.ts | Centralize $class string constants for TemplateMark/CommonMark. |
| src/tiptap-editor/constants/types.ts | Add supported type lists + friendly/FQN mapping helpers. |
| src/tiptap-editor/utils/serializeTemplate.ts | Serialize TemplateMark JSON to markdown with UI-prop stripping + formula fixups. |
| src/tiptap-editor/utils/parseTemplate.ts | Parse markdown to TemplateMark JSON using token pass + synthesized CTO. |
| src/tiptap-editor/utils/generateConcertoModel.ts | Generate CTO model from TemplateMark document variable declarations. |
| src/tiptap-editor/utils/validateTemplate.ts | Validate TemplateMark by round-tripping through transformer with generated model. |
| src/tiptap-editor/utils/branchMarkdown.ts | Convert conditional/optional branch JSON ↔ editable markdown strings. |
| src/tiptap-editor/hooks/useTemplateEditor.ts | Create TipTap editor instance with extensions/plugins and external sync behavior. |
| src/tiptap-editor/hooks/useMarkdownSync.ts | Provide rich/markdown view toggle and markdown synchronization. |
| src/tiptap-editor/hooks/useValidation.ts | Debounced validation hook calling TemplateMark validation utility. |
| src/tiptap-editor/components/TemplateEditor.tsx | New editor UI wiring toolbar, rich/markdown view, and validation panel. |
| src/tiptap-editor/components/ValidationPanel.tsx | Display validation errors/warnings in-panel. |
| src/tiptap-editor/components/dialogs/Popover.tsx | Reusable popover component + class-name exports. |
| src/tiptap-editor/components/dialogs/Modal.tsx | Shared modal/branch-modal/insert-dialog UI. |
| src/tiptap-editor/components/dialogs/index.ts | Barrel export for dialog components. |
| src/tiptap-editor/styles/editor.css | Rich editor layout and validation panel styles. |
| src/tiptap-editor/styles/toolbar.css | Toolbar layout styles including responsive breakpoints. |
| src/tiptap-editor/styles/popover.css | Themed popover styles. |
| src/tiptap-editor/styles/modal.css | Themed modal styles. |
| src/tiptap-editor/extensions/* | TipTap node extensions for TemplateMark/CommonMark constructs. |
| src/tiptap-editor/nodeViews/* | React NodeViews for variable/formula/block constructs and editing UI. |
| src/tiptap-editor/plugins/VariableSyncPlugin.ts | ProseMirror plugin to sync variable text within clause scope. |
| src/tiptap-editor/plugins/FormulaDependencyPlugin.ts | ProseMirror decorations for highlighting formula dependencies. |
| src/tiptap-editor/serializer/nodeConverters.ts | Compatibility re-export layer for serializer converter modules. |
| src/tiptap-editor/serializer/converters/index.ts | Barrel export for converter functions. |
| src/tiptap-editor/serializer/TemplateMarkToTipTap.ts | TemplateMark JSON → TipTap JSON conversion entrypoint. |
| src/tiptap-editor/serializer/TipTapToTemplateMark.ts | TipTap JSON → TemplateMark JSON conversion entrypoint. |
| src/content/intro.md | Expand tutorial introduction content and update links/descriptions. |
| src/content/module1.md | Expand Concerto tutorial module content and examples. |
| src/content/module2.md | Expand TemplateMark tutorial module content and examples. |
| const switchToRich = useCallback(() => { | ||
| if (!editor) { setView('rich'); return; } | ||
| const parsed = parseMarkdownTemplate(markdownText, nameRefRef.current.current, modelManagerRef.current); | ||
| if (parsed) { | ||
| const content = templateMarkToTipTap(parsed); | ||
| // emitUpdate=true so onUpdate fires → currentDoc and parent onChange are synced | ||
| editor.commands.setContent(content, true); | ||
| } | ||
| setView('rich'); | ||
| }, [editor, markdownText]); |
There was a problem hiding this comment.
switchToRich always calls setView('rich') even when parseMarkdownTemplate(...) returns null. This will kick the user back into the rich editor without applying their markdown changes, and makes it hard to fix invalid/partial markdown. Prefer keeping the view in markdown mode (and optionally surface a parse error) when parsing fails.
| async function rebuild(template: string, model: string, dataString: string): Promise<{ html: string; modelManager: ModelManager }> { | ||
| // Validate inputs before expensive operations | ||
| // This fails fast on invalid JSON or CTO syntax without running network calls | ||
| await validateBeforeRebuild(template, model, dataString); | ||
|
|
There was a problem hiding this comment.
rebuild() now returns { html, modelManager }, but not all call sites in this file have been updated. For example, setData still assigns the return value directly to agreementHtml (treating it as a string), which will set agreementHtml to an object and break preview rendering. Update remaining callers to destructure { html, modelManager } and store modelManager consistently.
| const { editor, nameRef, currentDoc } = useTemplateEditor(props); | ||
| const { view, markdownText, setMarkdownText, toggleView } = useMarkdownSync(editor, nameRef, props.modelManager); | ||
| const showValidation = props.showValidation ?? true; | ||
| const errors = useValidation(currentDoc.current, showValidation, props.onValidation, props.modelManager); | ||
|
|
There was a problem hiding this comment.
useValidation is invoked with currentDoc.current, which is a mutable ref. Updating a ref does not trigger a React re-render, so errors can become stale unless the parent re-renders the component on every editor update (e.g., via a controlled value/onChange loop). Consider storing the current TemplateMark document in component state (updated in onUpdate) and passing that state into useValidation, or have useValidation subscribe to editor updates directly.
* fix(editor): retarget pr878 follow-up to mr-template-editor Retry TipTap template parsing when external sample or shared-link loads receive the rebuilt modelManager, so the rich editor does not get stuck on stale model state. Also store rebuilt html/modelManager after JSON data edits and split Vitest config from vite.config.ts so CI can load the production Vite config cleanly. Signed-off-by: Rishabh060105 <rishabhj2005@email.com> * test(playground): add regression coverage for pr881 fixes Signed-off-by: Rishabh060105 <rishabhj2005@email.com> --------- Signed-off-by: Rishabh060105 <rishabhj2005@email.com> Co-authored-by: Rishabh060105 <rishabhj2005@email.com>
Closes #
Introduces a TipTap-based rich TemplateMark editor (opt-in “Beta”) alongside the existing Monaco markdown editor, and refactors theme handling to a boolean dark-mode flag while upgrading the Vite/Vitest toolchain.
Changes:
Screenshots or Video
Related Issues
Author Checklist
--signoffoption of git commit.mainfromfork:branchname