Conversation
🚀 Locadex i18n StartedLocadex is now analyzing your changes and generating localizations for this pull request. What's happening:
Estimated time: 2-10 minutes depending on the size of your changes. You'll receive another comment when the localization is complete. |
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
WalkthroughThis update refactors the text editor component and its associated plugins for improved modularity and maintainability. Key changes include introducing new plugin factories, extracting inline suggestion and save logic into reusable functions, adding new plugins for diffing and formatting, and reorganizing event handling. Several utility functions and a React renderer class were removed. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Editor
participant Plugins
participant Backend
User->>Editor: Interacts (type, format, etc.)
Editor->>Plugins: Dispatch transactions
Plugins->>Plugins: Track formatting, suggestions, diff, etc.
Plugins->>Backend: (Optional) Save content, request suggestions
Backend-->>Plugins: Returns save status or suggestion
Plugins->>Editor: Update state/UI
Editor->>User: Reflects changes
Possibly related PRs
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (12)
apps/snow-leopard/lib/editor/placeholder-plugin.ts (2)
2-2: Use import type for type-only imports.
EditorViewis only used as a type parameter and should be imported withimport type.-import { Decoration, DecorationSet, EditorView } from 'prosemirror-view'; +import { Decoration, DecorationSet } from 'prosemirror-view'; +import type { EditorView } from 'prosemirror-view';
30-59: Consider handling multiple editor instances.The current implementation could create duplicate style elements if multiple editors use the placeholder plugin. Consider checking if the style already exists or using a more isolated approach.
view(editorView: EditorView) { + // Check if style already exists + const existingStyle = document.querySelector('[data-placeholder-style="true"]'); + if (existingStyle) { + return { destroy() {} }; + } + const style = document.createElement('style'); style.setAttribute('data-placeholder-style', 'true');Alternatively, consider using inline styles or CSS-in-JS approaches for better isolation between editor instances.
apps/snow-leopard/lib/editor/suggestion-plugin.ts (2)
2-2: Use import type for type-only imports.
EditorViewis only used as a type parameter and should be imported withimport type.-import { EditorView, Decoration, DecorationSet } from 'prosemirror-view'; +import { Decoration, DecorationSet } from 'prosemirror-view'; +import type { EditorView } from 'prosemirror-view';
93-147: Improve type safety for event handler.Instead of using type assertions, properly type the event handler to avoid potential runtime issues.
- const handleApplySuggestion = (event: CustomEvent) => { + const handleApplySuggestion = (event: Event) => { + if (!(event instanceof CustomEvent)) return; if (!event.detail) return; const { state, dispatch } = editorView; const { from, to, suggestion, documentId: suggestionDocId, } = event.detail;- window.addEventListener("apply-suggestion", handleApplySuggestion as EventListener); + window.addEventListener("apply-suggestion", handleApplySuggestion); return { destroy() { - window.removeEventListener("apply-suggestion", handleApplySuggestion as EventListener); + window.removeEventListener("apply-suggestion", handleApplySuggestion); }, };apps/snow-leopard/lib/editor/editor-plugins.ts (1)
3-3: Use import type for type-only imports.
Pluginis only used as a type in the return signature and should be imported withimport type.-import { Plugin } from 'prosemirror-state'; +import type { Plugin } from 'prosemirror-state';apps/snow-leopard/lib/editor/format-plugin.ts (1)
1-2: Useimport typefor type-only importsThese imports are only used as type annotations and should be imported using
import typeto ensure they are removed during compilation.-import { Plugin, PluginKey, EditorState } from 'prosemirror-state'; -import { EditorView } from 'prosemirror-view'; +import { Plugin, PluginKey } from 'prosemirror-state'; +import type { EditorState } from 'prosemirror-state'; +import type { EditorView } from 'prosemirror-view';apps/snow-leopard/lib/editor/save-plugin.ts (1)
29-32: Consider more robust document ID validationThe current validation checks for specific string values which could be fragile. Consider using a more robust approach or extracting this validation logic.
- if (!docId || docId === "init" || docId === "undefined" || docId === "null") { - console.warn("[Save Function] Attempted to save with invalid or init documentId:", docId); - throw new Error("Cannot save with invalid or initial document ID."); - } + const isValidDocumentId = (id: string): boolean => { + return Boolean(id) && id !== "init" && !["undefined", "null"].includes(id); + }; + + if (!isValidDocumentId(docId)) { + console.warn("[Save Function] Attempted to save with invalid or init documentId:", docId); + throw new Error("Cannot save with invalid or initial document ID."); + }apps/snow-leopard/lib/editor/diff-plugin.ts (3)
2-2: Useimport typefor type-only import
EditorViewis only used as a type annotation and should be imported usingimport type.-import { EditorView } from 'prosemirror-view'; +import type { EditorView } from 'prosemirror-view';
11-11: Remove redundant type annotationThe type annotation
: booleanis redundant as it can be inferred from the initialization value.- let previewActiveRef: boolean = false; + let previewActiveRef = false;
71-71: Useconstinstead ofletfor non-reassigned variableThe
trvariable is never reassigned, only mutated. Useconstfor better code clarity.- let tr = state.tr; + const tr = state.tr;apps/snow-leopard/components/document/text-editor.tsx (2)
19-19: Useimport typefor type-only import
FormatStateis only used as a type annotation and should be imported usingimport type.-import { type FormatState } from "@/lib/editor/format-plugin"; +import type { FormatState } from "@/lib/editor/format-plugin";
251-251: Remove unnecessary type castingThe type casting
as unknown as Record<string, boolean>appears unnecessary. IfEditorToolbarexpectsRecord<string, boolean>andFormatStatehas all boolean properties, they should be compatible without casting.- <EditorToolbar activeFormats={activeFormats as unknown as Record<string, boolean>} /> + <EditorToolbar activeFormats={activeFormats} />If this causes a type error, consider updating the
EditorToolbarprop types to acceptFormatStatedirectly for better type safety.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
apps/snow-leopard/components/document/text-editor.tsx(8 hunks)apps/snow-leopard/components/suggestion-overlay-provider.tsx(1 hunks)apps/snow-leopard/lib/editor/config.ts(0 hunks)apps/snow-leopard/lib/editor/diff-plugin.ts(1 hunks)apps/snow-leopard/lib/editor/editor-plugins.ts(1 hunks)apps/snow-leopard/lib/editor/format-plugin.ts(1 hunks)apps/snow-leopard/lib/editor/functions.tsx(1 hunks)apps/snow-leopard/lib/editor/inline-suggestion-plugin.ts(2 hunks)apps/snow-leopard/lib/editor/placeholder-plugin.ts(2 hunks)apps/snow-leopard/lib/editor/react-renderer.tsx(0 hunks)apps/snow-leopard/lib/editor/save-plugin.ts(3 hunks)apps/snow-leopard/lib/editor/suggestion-plugin.ts(5 hunks)
💤 Files with no reviewable changes (2)
- apps/snow-leopard/lib/editor/react-renderer.tsx
- apps/snow-leopard/lib/editor/config.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
apps/snow-leopard/lib/editor/placeholder-plugin.ts (2)
apps/snow-leopard/lib/editor/inline-suggestion-plugin.ts (1)
decorations(171-227)apps/snow-leopard/lib/editor/suggestion-plugin.ts (1)
decorations(67-90)
apps/snow-leopard/lib/editor/diff-plugin.ts (2)
apps/snow-leopard/lib/editor/functions.tsx (2)
buildContentFromDocument(26-26)buildDocumentFromContent(10-16)apps/snow-leopard/lib/editor/config.ts (1)
documentSchema(27-33)
🪛 Biome (1.9.4)
apps/snow-leopard/lib/editor/placeholder-plugin.ts
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
apps/snow-leopard/lib/editor/suggestion-plugin.ts
[error] 2-2: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
apps/snow-leopard/lib/editor/editor-plugins.ts
[error] 3-3: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.
(lint/style/useImportType)
apps/snow-leopard/lib/editor/format-plugin.ts
[error] 1-1: Some named imports are only used as types.
This import is only used as a type.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Add inline type keywords.
(lint/style/useImportType)
[error] 2-2: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.
(lint/style/useImportType)
apps/snow-leopard/lib/editor/diff-plugin.ts
[error] 11-11: This type annotation is trivially inferred from its initialization.
Safe fix: Remove the type annotation.
(lint/style/noInferrableTypes)
[error] 2-2: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.
(lint/style/useImportType)
[error] 71-71: This let declares a variable that is only assigned once.
'tr' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
apps/snow-leopard/components/document/text-editor.tsx
[error] 19-19: All these imports are only used as types.
Importing the types with import type ensures that they are removed by the compilers and avoids loading unnecessary modules.
Safe fix: Use import type.
(lint/style/useImportType)
🔇 Additional comments (4)
apps/snow-leopard/components/suggestion-overlay-provider.tsx (1)
12-12: Import source update looks good.The constants have been correctly moved to their new location in the suggestion plugin module, aligning with the modular plugin architecture.
apps/snow-leopard/lib/editor/functions.tsx (1)
22-22: Correct handling of diffMark in serializer.Adding
diffMarkwith empty open/close strings ensures diff marks are properly stripped when serializing to markdown.apps/snow-leopard/lib/editor/inline-suggestion-plugin.ts (1)
124-124: Good use of optional callback patternMaking the
requestSuggestioncallback optional with safe invocation using optional chaining improves the plugin's flexibility and robustness.Also applies to: 252-252
apps/snow-leopard/components/document/text-editor.tsx (1)
71-78: Excellent refactoring to use plugin factory patternThe use of
createEditorPluginsfactory significantly improves code organization and maintainability. The component is now much cleaner and focused on its core responsibilities.Also applies to: 134-141
| export interface EditorPluginOptions { | ||
| documentId: string; | ||
| initialLastSaved: Date | null; | ||
| placeholder?: string; | ||
| performSave: (content: string) => Promise<any>; | ||
| requestInlineSuggestion: (state: any) => void; | ||
| setActiveFormats: (formats: any) => void; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Replace 'any' types with more specific types.
Using any reduces type safety. Consider defining proper types for these parameters.
+import type { EditorState } from 'prosemirror-state';
+
+interface SaveResult {
+ // Define the expected save result structure
+ success: boolean;
+ error?: string;
+}
+
+interface ActiveFormats {
+ // Define the format structure based on your format plugin
+ bold?: boolean;
+ italic?: boolean;
+ // ... other formats
+}
+
export interface EditorPluginOptions {
documentId: string;
initialLastSaved: Date | null;
placeholder?: string;
- performSave: (content: string) => Promise<any>;
- requestInlineSuggestion: (state: any) => void;
- setActiveFormats: (formats: any) => void;
+ performSave: (content: string) => Promise<SaveResult>;
+ requestInlineSuggestion: (state: EditorState) => void;
+ setActiveFormats: (formats: ActiveFormats) => void;
}Would you like me to help define the proper types based on your plugin implementations?
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export interface EditorPluginOptions { | |
| documentId: string; | |
| initialLastSaved: Date | null; | |
| placeholder?: string; | |
| performSave: (content: string) => Promise<any>; | |
| requestInlineSuggestion: (state: any) => void; | |
| setActiveFormats: (formats: any) => void; | |
| } | |
| import type { EditorState } from 'prosemirror-state'; | |
| interface SaveResult { | |
| // Define the expected save result structure | |
| success: boolean; | |
| error?: string; | |
| } | |
| interface ActiveFormats { | |
| // Define the format structure based on your format plugin | |
| bold?: boolean; | |
| italic?: boolean; | |
| // ... other formats | |
| } | |
| export interface EditorPluginOptions { | |
| documentId: string; | |
| initialLastSaved: Date | null; | |
| placeholder?: string; | |
| performSave: (content: string) => Promise<SaveResult>; | |
| requestInlineSuggestion: (state: EditorState) => void; | |
| setActiveFormats: (formats: ActiveFormats) => void; | |
| } |
🤖 Prompt for AI Agents
In apps/snow-leopard/lib/editor/editor-plugins.ts around lines 15 to 22, the
EditorPluginOptions interface uses 'any' for the types of the parameters in
requestInlineSuggestion and setActiveFormats, which reduces type safety. To fix
this, analyze the actual data structures or types used in your plugin
implementations for these parameters and replace 'any' with those specific types
or interfaces. This will improve type safety and code clarity.
Summary by CodeRabbit
New Features
Refactor
Bug Fixes
Chores