Skip to content

Conversation

aaryan610
Copy link
Member

@aaryan610 aaryan610 commented Jun 18, 2025

Description

This PR refactors the types structure of the editor package-

  1. Created a base types for editor and read only editor components.
  2. All the other types extend from the base types.
  3. Created base types for hooks.

Type of Change

  • Code refactoring

Summary by CodeRabbit

  • New Features

    • Introduced support for "flaggedExtensions" across all editor components, enabling finer control over extension states alongside disabled extensions.
  • Refactor

    • Updated prop types and interfaces for editor and read-only components to consistently include both "disabledExtensions" and "flaggedExtensions".
    • Simplified and unified type definitions and imports for editor props and hooks, enhancing maintainability and type safety.
    • Refactored editor extension logic to incorporate flagged extensions in enablement and creation processes.
  • Chores

    • Improved internal type organization, renaming, and import consistency for clearer and scalable code.
    • Enhanced the editor flagging hook to return structured disabled and flagged extension arrays per editor type.

Copy link
Contributor

coderabbitai bot commented Jun 18, 2025

Walkthrough

This change introduces a new flaggedExtensions property throughout the editor codebase, updating type definitions, component props, and hook signatures to support both disabledExtensions and flaggedExtensions. Type management is refactored for consistency, and extension enablement logic is updated to consider flagged extensions alongside disabled ones across all editor variants.

Changes

Files/Paths Change Summary
.../core/types/editor.ts, .../core/types/hook.ts, .../core/types/config.ts, .../core/types/index.ts Refactored and reorganized editor prop types, introduced flaggedExtensions to core interfaces, consolidated and extended hook prop types, and added new config/user types.
.../ce/extensions/core/extensions.ts, .../ce/extensions/core/read-only-extensions.ts, .../ce/extensions/document-extensions.tsx, .../ce/extensions/rich-text/extensions.tsx, .../ce/extensions/rich-text/read-only-extensions.tsx, .../ce/extensions/slash-commands.tsx Updated extension prop types and logic to use flaggedExtensions in addition to disabledExtensions, refactored type imports and function signatures accordingly.
.../core/extensions/extensions.ts, .../core/extensions/read-only-extensions.ts, .../core/extensions/utility.ts, .../core/extensions/slash-commands/root.tsx, .../core/extensions/slash-commands/command-items-list.tsx Updated extension utility and registry logic to support and forward flaggedExtensions, refactored type usage and function signatures.
.../core/components/editors/document/collaborative-editor.tsx, .../core/components/editors/document/page-renderer.tsx, .../core/components/editors/document/read-only-editor.tsx, .../core/components/editors/editor-wrapper.tsx, .../core/components/editors/lite-text/editor.tsx, .../core/components/editors/lite-text/read-only-editor.tsx, .../core/components/editors/read-only-editor-wrapper.tsx, .../core/components/editors/rich-text/editor.tsx, .../core/components/editors/rich-text/read-only-editor.tsx Updated editor and read-only editor components to use new prop types and pass flaggedExtensions throughout, refactored type annotations and prop destructuring.
.../core/hooks/use-collaborative-editor.ts, .../core/hooks/use-editor.ts, .../core/hooks/use-read-only-editor.ts Updated editor hooks to use new prop types, added support for flaggedExtensions in their logic and extension composition.
.../core/types/collaboration.ts Removed obsolete collaborative editor prop types, retaining only server handler type.
.../index.ts Removed export of obsolete CustomEditorProps type.
web/ce/hooks/use-editor-flagging.ts Refactored flagging hook to return both disabled and flagged arrays for each editor type, updated return type accordingly.
web/core/components/editor/lite-text-editor/lite-text-editor.tsx, web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx, web/core/components/editor/rich-text-editor/rich-text-editor.tsx, web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx, web/core/components/editor/sticky-editor/editor.tsx Updated wrapper components to use new flagging structure and pass both disabledExtensions and flaggedExtensions to editors.
web/core/components/pages/editor/editor-body.tsx, web/core/components/pages/version/editor.tsx Updated usage to split flagging props into disabledExtensions and flaggedExtensions when passing to document editor/read-only editor components.
space/core/components/editor/lite-text-editor.tsx, space/core/components/editor/lite-text-read-only-editor.tsx, space/core/components/editor/rich-text-editor.tsx, space/core/components/editor/rich-text-read-only-editor.tsx Updated wrapper components to support and pass flaggedExtensions alongside disabledExtensions in editor props and components.

Sequence Diagram(s)

sequenceDiagram
    participant Parent as Parent Component
    participant Flagging as useEditorFlagging
    participant Editor as Editor Component
    participant Hook as useEditor/useReadOnlyEditor
    participant Extensions as CoreEditorExtensions

    Parent->>Flagging: useEditorFlagging()
    Flagging-->>Parent: {disabled, flagged} arrays for editor type
    Parent->>Editor: Pass disabledExtensions, flaggedExtensions
    Editor->>Hook: Pass disabledExtensions, flaggedExtensions
    Hook->>Extensions: Pass disabledExtensions, flaggedExtensions
    Extensions-->>Hook: Compose extensions using both arrays
    Hook-->>Editor: Editor instance with configured extensions
Loading

Possibly related PRs

  • makeplane/plane#7158: Refactors extension handling to support flaggedExtensions alongside disabledExtensions in editor extension logic and type definitions.

Suggested labels

ready to merge

Suggested reviewers

  • anmolsinghbhatia
  • prateekshourya29

Poem

In fields of code where editors hop,
A new flag appears—let the changes not stop!
Both disabled and flagged, extensions in line,
Types refactored, the logic refined.
Now bunnies can edit with options galore,
With flaggedExtensions, we’re ready for more!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🔭 Outside diff range comments (6)
packages/editor/src/ce/extensions/rich-text/read-only-extensions.tsx (1)

13-18: isEnabled should accept flaggedExtensions as well

The new extension-flagging feature is ignored here—isEnabled only receives disabledExtensions. As a result, a “flagged” extension might still be enabled in read-only mode.

-  isEnabled: (disabledExtensions: TExtensions[]) => boolean;
+  isEnabled: (
+    disabledExtensions: TExtensions[],
+    flaggedExtensions: TExtensions[]
+  ) => boolean;

You’ll also need to update every registry entry and the filter call at lines 25-28:

-  .filter((config) => config.isEnabled(disabledExtensions))
+  .filter((config) => config.isEnabled(disabledExtensions, props.flaggedExtensions ?? []))
packages/editor/src/core/extensions/extensions.ts (1)

192-196: Guard .includes against empty disabledExtensions

After applying the previous change, this is safe. If you choose not to default, wrap the check:

-if (!disabledExtensions.includes("image")) {
+if (!disabledExtensions?.includes("image")) {
packages/editor/src/core/hooks/use-editor.ts (1)

46-81: Stale closure risk: dependency array only contains editable.

useTiptapEditor will not recreate the editor when flaggedExtensions, disabledExtensions, placeholder, fileHandler, etc. change at runtime.
If any of those props are expected to change (e.g. after a feature-flag fetch) the editor will keep the old values, leading to inconsistent UI.

-  const editor = useTiptapEditor(
+  const editor = useTiptapEditor(
     { /* config */ },
-    [editable]
+    [
+      editable,
+      disabledExtensions?.join(),
+      flaggedExtensions?.join(),
+      placeholder,
+      enableHistory,
+      fileHandler,          // handlers are objects – consider memoising before passing
+    ]
   );
web/core/components/editor/rich-text-editor/rich-text-editor.tsx (1)

28-38: flaggedExtensions is forwarded twice – later spread overrides the calculated value.

Because flaggedExtensions is not plucked out of props, it remains inside ...rest.
The explicit prop you pass on line 54 will be silently overwritten by whatever the caller supplied.

-    uploadFile,
-    disabledExtensions: additionalDisabledExtensions,
+    uploadFile,
+    disabledExtensions: additionalDisabledExtensions,
+    // hoist and discard to keep it out of `...rest`
+    flaggedExtensions: _ignoredFlaggedExtensions,

This guarantees that the editor always receives the union computed from the flagging hook.
Duplicate removal also prevents hard-to-trace bugs when the two arrays diverge.

web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx (1)

28-34: Same double-prop collision as in the writable editor.

flaggedExtensions survives inside ...props and will overwrite the computed value below.
Apply the same extraction pattern:

-  ({ workspaceId, workspaceSlug, projectId, disabledExtensions: additionalDisabledExtensions, ...props }, ref) => {
+  (
+    {
+      workspaceId,
+      workspaceSlug,
+      projectId,
+      disabledExtensions: additionalDisabledExtensions,
+      flaggedExtensions: _ignoredFlaggedExtensions,
+      ...props
+    },
+    ref,
+  ) => {
web/core/components/editor/lite-text-editor/lite-text-editor.tsx (1)

96-115: Duplicate flaggedExtensions prop passed – remove one

You explicitly pass flaggedExtensions and then spread ...rest, which (see comment above) may contain another flaggedExtensions.
Removing it from rest or re-ordering the spread avoids accidental overrides and React warnings about duplicate props.

♻️ Duplicate comments (1)
packages/editor/src/ce/extensions/document-extensions.tsx (1)

19-27: Same isEnabled parameter mismatch as in rich-text registry

Align the function signature with the declared type to avoid type-checking failures.

-    isEnabled: (disabledExtensions) => !disabledExtensions.includes("slash-commands"),
+    isEnabled: (disabledExtensions, _flaggedExtensions) =>
+      !disabledExtensions.includes("slash-commands"),
🧹 Nitpick comments (24)
packages/editor/src/core/types/config.ts (1)

37-47: Prefer marking DTO-like types as readonly and consider optional queryParams.

TUserDetails and TRealtimeConfig look fine, but these value objects are typically treated as immutable once created. Adding readonly to each property communicates that intent at the type level and prevents accidental mutation.

-export type TUserDetails = {
-  color: string;
-  id: string;
-  name: string;
-  cookie?: string;
-};
+export type TUserDetails = {
+  readonly color: string;
+  readonly id: string;
+  readonly name: string;
+  readonly cookie?: string;
+};
 
-export type TRealtimeConfig = {
-  url: string;
-  queryParams: TWebhookConnectionQueryParams;
-};
+export type TRealtimeConfig = {
+  readonly url: string;
+  /** optional: some consumers may not need extra params */
+  readonly queryParams?: TWebhookConnectionQueryParams;
+};

A tiny improvement, but promotes safer code.

packages/editor/src/core/extensions/slash-commands/command-items-list.tsx (1)

292-294: Pass a default empty array to avoid undefined propagation.

coreEditorAdditionalSlashCommandOptions likely expects arrays. Passing undefined forces the callee to null-check each time.

-        disabledExtensions,
-        flaggedExtensions,
+        disabledExtensions: disabledExtensions ?? [],
+        flaggedExtensions: flaggedExtensions ?? [],

A minor guard that reduces branching down-stream.

web/core/components/pages/version/editor.tsx (1)

35-36: Variable naming avoids shadowing but consider documentExtensions.

Destructuring as { document: documentEditorExtensions } is clear, yet the intermediate name still contains “Editor”. To stay concise and avoid redundancy you could rename to documentExtensions.

Not blocking, just a readability tweak.

packages/editor/src/core/components/editors/document/page-renderer.tsx (1)

8-16: Consider in-place destructuring to remove double handling of props

The component currently declares a Props type and then immediately re-destructures inside the body. In small renderers this extra indirection is noise and slightly harms readability.

-export const PageRenderer = (props: Props) => {
-  const { aiHandler, bubbleMenuEnabled, displayConfig, editor, editorContainerClassName, id, tabIndex } = props;
+export const PageRenderer = ({
+  aiHandler,
+  bubbleMenuEnabled,
+  displayConfig,
+  editor,
+  editorContainerClassName,
+  id,
+  tabIndex,
+}: Props) => {

This removes one object allocation and makes the parameter list self-documenting. No functional change.

packages/editor/src/core/components/editors/read-only-editor-wrapper.tsx (1)

20-33: Provide a default for flaggedExtensions to avoid extra undefined checks downstream

flaggedExtensions is optional here but many extension filters expect an array. Supplying [] by default keeps call-sites simpler and eliminates the need for repeated ?? [] guards in hooks.

-    flaggedExtensions,
+    flaggedExtensions = [],

Same default can be passed into useReadOnlyEditor.

packages/editor/src/core/components/editors/editor-wrapper.tsx (1)

29-49: Align the new flaggedExtensions prop with the existing defaulting pattern

Elsewhere props such as displayConfig and editorClassName carry sensible defaults. For consistency, default flaggedExtensions to an empty array before forwarding to useEditor; that hook can then rely on an array type.

-    fileHandler,
-    flaggedExtensions,
+    fileHandler,
+    flaggedExtensions = [],

This avoids potential undefined checks inside the hook and extension factories.

packages/editor/src/ce/extensions/core/read-only-extensions.ts (1)

5-8: Unused parameter indicates dead code path

CoreReadOnlyEditorAdditionalExtensions receives disabledExtensions and flaggedExtensions but immediately discards them:

const {} = props;
return [];

Either remove the parameter or implement the filtering logic; leaving it empty is misleading and may confuse future readers.

-export const CoreReadOnlyEditorAdditionalExtensions = (props: Props): Extensions => {
-  const {} = props;
+export const CoreReadOnlyEditorAdditionalExtensions = (_: Props): Extensions => {

or flesh out the extension filtering if that is still planned.

packages/editor/src/ce/extensions/slash-commands.tsx (1)

8-11: Props are accepted but never used – consider trimming API surface or implementing the logic
disabledExtensions / flaggedExtensions are passed in, yet we immediately discard them and always return an empty array. If this is intentional, drop the parameter (or prefix it with _) and inline-return [] to avoid dead code; otherwise wire the flags into the filtering logic.

-export const coreEditorAdditionalSlashCommandOptions = (props: Props): TSlashCommandAdditionalOption[] => {
-  const {} = props;
-  const options: TSlashCommandAdditionalOption[] = [];
-  return options;
-};
+export const coreEditorAdditionalSlashCommandOptions = (): TSlashCommandAdditionalOption[] => {
+  return [];
+};
packages/editor/src/ce/extensions/core/extensions.ts (1)

7-9: Same pattern: unused props argument hides missing implementation
fileHandler, disabledExtensions, and now flaggedExtensions are collected but ignored. Either (1) implement the extension composition here, or (2) drop the argument to keep the public contract honest.

-export const CoreEditorAdditionalExtensions = (props: Props): Extensions => {
-  const {} = props;
-  return [];
-};
+export const CoreEditorAdditionalExtensions = (): Extensions => {
+  return [];
+};
web/core/components/pages/editor/editor-body.tsx (1)

216-218: Ensure arrays are always defined
documentEditorExtensions.disabled / .flagged should default to [] to avoid passing undefined into the editor which may expect an array.

-disabledExtensions={documentEditorExtensions.disabled}
-flaggedExtensions={documentEditorExtensions.flagged}
+disabledExtensions={documentEditorExtensions.disabled ?? []}
+flaggedExtensions={documentEditorExtensions.flagged ?? []}
packages/editor/src/core/components/editors/rich-text/read-only-editor.tsx (1)

12-20: getExtensions() creates a new array on every render – memoise to prevent unnecessary re-initialisation

Passing a freshly created extensions array each render can cause the underlying editor to think its extension set changed, triggering costly reconfiguration. Cache the result with useMemo.

-const getExtensions = useCallback(() => {
-  const extensions = RichTextReadOnlyEditorAdditionalExtensions({
-    disabledExtensions,
-    fileHandler,
-    flaggedExtensions,
-  });
-  return extensions;
-}, [disabledExtensions, fileHandler, flaggedExtensions]);
+const extensions = useMemo(
+  () =>
+    RichTextReadOnlyEditorAdditionalExtensions({
+      disabledExtensions,
+      fileHandler,
+      flaggedExtensions,
+    }),
+  [disabledExtensions, fileHandler, flaggedExtensions],
+);

Then pass extensions={extensions} to ReadOnlyEditorWrapper.

packages/editor/src/core/hooks/use-collaborative-editor.ts (1)

19-25: Default flaggedExtensions to an empty array for safety

flaggedExtensions is optional, yet downstream helpers may call .includes on it. Defaulting it to [] in the parameter destructuring keeps the contract consistent with disabledExtensions and prevents accidental TypeError: cannot read properties of undefined.

-    flaggedExtensions,
+    flaggedExtensions = [],
packages/editor/src/core/hooks/use-read-only-editor.ts (1)

19-25: Provide a default for flaggedExtensions

Same rationale as other hooks—avoid undefined dereference.

-    flaggedExtensions,
+    flaggedExtensions = [],
packages/editor/src/core/components/editors/rich-text/editor.tsx (1)

22-38: useMemo is a better fit than useCallback here

getExtensions returns a value, not a function reference consumers call later. Recompute it only when its dependencies change:

-  const getExtensions = useCallback(() => {
+  const extensions = useMemo(() => {
     const extensions = [
       ...
     ];
-    return extensions;
-  }, [dragDropEnabled, disabledExtensions, externalExtensions, fileHandler, flaggedExtensions]);
+    return extensions;
+  }, [dragDropEnabled, disabledExtensions, externalExtensions, fileHandler, flaggedExtensions]);

Then pass extensions directly to EditorWrapper. This avoids an unnecessary function allocation every render.

packages/editor/src/core/components/editors/lite-text/editor.tsx (2)

12-20: Consider flaggedExtensions when generating the local extensions array.

flaggedExtensions is part of ILiteTextEditorProps, yet the memo completely ignores it and may therefore re-add an extension that upstream code only wants to flag (e.g. highlight, warn, etc.).
If the semantics of “flagged” require the extension still to be mounted then this is fine, otherwise you may want to honour that list the same way you do for disabledExtensions.


12-20: externalExtensions mutability caveat

useMemo only re-runs when the reference of externalExtensions changes. If callers mutate the array in-place (not uncommon when extensions are accumulated imperatively) the memo will stay stale.
A defensive copy in the dependency array solves this cheaply:

-  }, [externalExtensions, disabledExtensions, onEnterKeyPress]);
+  }, [externalExtensions?.length, disabledExtensions, onEnterKeyPress]);
web/core/components/editor/sticky-editor/editor.tsx (1)

68-70: Potential duplicate / conflicting extension flags

"enter-key" is forcibly appended to disabledExtensions, while the same id could also be present in liteTextEditorExtensions.flagged.
Down-stream logic should clarify the precedence (disabled vs flagged). To avoid accidental duplication you can dedupe before passing:

-        disabledExtensions={[...liteTextEditorExtensions.disabled, "enter-key"]}
+        disabledExtensions={[...new Set([...liteTextEditorExtensions.disabled, "enter-key"])]}
packages/editor/src/core/hooks/use-editor.ts (1)

108-111: Effect dependency on nested property can thrash renders

useEffect depends on fileHandler.assetsUploadStatus. Because this is a non-stable primitive nested inside an object, every parent re-render that recreates fileHandler will trigger the effect even if assetsUploadStatus is unchanged.

Consider lifting assetsUploadStatus out into its own prop or memoising fileHandler.

web/ce/hooks/use-editor-flagging.ts (1)

22-34: workspaceSlug parameter is unused

The hook signature suggests workspace-specific flagging, but the argument is ignored. Either:

  1. Remove the parameter from both caller & definition, or
  2. Implement the logic that actually varies the returned flags per workspace.

This avoids misleading future maintainers.

web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx (1)

38-40: Guard against duplicate ids in combined disabledExtensions

When merging liteTextEditorExtensions.disabled with additionalDisabledExtensions, duplicates can slip in, increasing array length and uselessly re-running extension disabling logic.

-        disabledExtensions={[...liteTextEditorExtensions.disabled, ...(additionalDisabledExtensions ?? [])]}
+        disabledExtensions={[...new Set([...liteTextEditorExtensions.disabled, ...(additionalDisabledExtensions ?? [])])]}
web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx (1)

40-42: De-duplicate disabled extensions before forwarding.

Mirror the improvement suggested for the writable editor to keep look-ups O(n).

-        disabledExtensions={[...richTextEditorExtensions.disabled, ...(additionalDisabledExtensions ?? [])]}
+        disabledExtensions={[
+          ...new Set([
+            ...richTextEditorExtensions.disabled,
+            ...(additionalDisabledExtensions ?? []),
+          ]),
+        ]}
packages/editor/src/core/extensions/read-only-extensions.ts (1)

38-41: Guard against undefined flaggedExtensions to simplify downstream checks.

-  const { disabledExtensions, fileHandler, flaggedExtensions, mentionHandler } = props;
+  const {
+    disabledExtensions = [],
+    flaggedExtensions = [],
+    fileHandler,
+    mentionHandler,
+  } = props;

This ensures CoreReadOnlyEditorAdditionalExtensions never receives undefined.

packages/editor/src/core/components/editors/document/read-only-editor.tsx (1)

25-28: Default flaggedExtensions to an empty array.

-    flaggedExtensions,
+    flaggedExtensions = [],

Keeps behaviour consistent with other editors and avoids extra nil-checks in useReadOnlyEditor.

packages/editor/src/core/types/hook.ts (1)

26-31: Redundant value/initialValue duo – clarify intent

TEditorHookProps exposes both value (picked) and initialValue (added manually).
Having two sources of truth for the same concept often leads to stale data or divergent behaviours. Consider keeping only one of them or documenting the difference explicitly.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9cdfb22 and d3f4786.

📒 Files selected for processing (37)
  • packages/editor/src/ce/extensions/core/extensions.ts (1 hunks)
  • packages/editor/src/ce/extensions/core/read-only-extensions.ts (1 hunks)
  • packages/editor/src/ce/extensions/document-extensions.tsx (1 hunks)
  • packages/editor/src/ce/extensions/rich-text/extensions.tsx (1 hunks)
  • packages/editor/src/ce/extensions/rich-text/read-only-extensions.tsx (1 hunks)
  • packages/editor/src/ce/extensions/slash-commands.tsx (1 hunks)
  • packages/editor/src/core/components/editors/document/collaborative-editor.tsx (4 hunks)
  • packages/editor/src/core/components/editors/document/page-renderer.tsx (2 hunks)
  • packages/editor/src/core/components/editors/document/read-only-editor.tsx (4 hunks)
  • packages/editor/src/core/components/editors/editor-wrapper.tsx (2 hunks)
  • packages/editor/src/core/components/editors/lite-text/editor.tsx (1 hunks)
  • packages/editor/src/core/components/editors/lite-text/read-only-editor.tsx (1 hunks)
  • packages/editor/src/core/components/editors/read-only-editor-wrapper.tsx (2 hunks)
  • packages/editor/src/core/components/editors/rich-text/editor.tsx (3 hunks)
  • packages/editor/src/core/components/editors/rich-text/read-only-editor.tsx (1 hunks)
  • packages/editor/src/core/extensions/extensions.ts (2 hunks)
  • packages/editor/src/core/extensions/read-only-extensions.ts (2 hunks)
  • packages/editor/src/core/extensions/slash-commands/command-items-list.tsx (2 hunks)
  • packages/editor/src/core/extensions/slash-commands/root.tsx (2 hunks)
  • packages/editor/src/core/extensions/utility.ts (2 hunks)
  • packages/editor/src/core/hooks/use-collaborative-editor.ts (2 hunks)
  • packages/editor/src/core/hooks/use-editor.ts (4 hunks)
  • packages/editor/src/core/hooks/use-read-only-editor.ts (3 hunks)
  • packages/editor/src/core/types/collaboration.ts (0 hunks)
  • packages/editor/src/core/types/config.ts (2 hunks)
  • packages/editor/src/core/types/editor.ts (3 hunks)
  • packages/editor/src/core/types/hook.ts (1 hunks)
  • packages/editor/src/core/types/index.ts (1 hunks)
  • packages/editor/src/index.ts (0 hunks)
  • web/ce/hooks/use-editor-flagging.ts (1 hunks)
  • web/core/components/editor/lite-text-editor/lite-text-editor.tsx (4 hunks)
  • web/core/components/editor/lite-text-editor/lite-text-read-only-editor.tsx (3 hunks)
  • web/core/components/editor/rich-text-editor/rich-text-editor.tsx (4 hunks)
  • web/core/components/editor/rich-text-editor/rich-text-read-only-editor.tsx (3 hunks)
  • web/core/components/editor/sticky-editor/editor.tsx (4 hunks)
  • web/core/components/pages/editor/editor-body.tsx (2 hunks)
  • web/core/components/pages/version/editor.tsx (2 hunks)
💤 Files with no reviewable changes (2)
  • packages/editor/src/core/types/collaboration.ts
  • packages/editor/src/index.ts
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (9)
packages/editor/src/core/types/index.ts (1)

7-7: Barrel export looks good.

Re-exporting ./hook here keeps the public surface consistent with the new typing modules. No issues spotted.

packages/editor/src/core/components/editors/lite-text/read-only-editor.tsx (1)

5-8: Prop type update looks correct.

Switching to ILiteTextReadOnlyEditorProps aligns with the new consolidated prop hierarchy. Implementation and ref-forwarding remain intact.

web/core/components/pages/version/editor.tsx (1)

102-104: Ensure component supports empty arrays to prevent uncontrolled behaviour.

disabledExtensions / flaggedExtensions may be undefined on first render. Verify that DocumentReadOnlyEditorWithRef treats undefined the same as [] to avoid runtime checks inside the editor wrapper. Initialising with an empty array here would be safer:

-      disabledExtensions={documentEditorExtensions.disabled}
-      flaggedExtensions={documentEditorExtensions.flagged}
+      disabledExtensions={documentEditorExtensions.disabled ?? []}
+      flaggedExtensions={documentEditorExtensions.flagged ?? []}
packages/editor/src/core/extensions/slash-commands/root.tsx (1)

109-111: TExtensionProps now mirrors editor props – good consolidation

Switching to Pick<IEditorProps, "disabledExtensions" | "flaggedExtensions"> eliminates duplication and centralises the contract. ✔️

web/core/components/pages/editor/editor-body.tsx (1)

84-85: Potential undefined-destructuring when hook returns null | undefined
If useEditorFlagging ever returns undefined (e.g. before data is loaded), destructuring will throw. Consider safe-defaulting.

-const { document: documentEditorExtensions } = useEditorFlagging(workspaceSlug);
+const { document: documentEditorExtensions } =
+  useEditorFlagging(workspaceSlug) ?? { document: { disabled: [], flagged: [] } };
packages/editor/src/core/extensions/utility.ts (1)

11-28: Type refactor looks good
Leveraging Pick<IEditorProps, "disabledExtensions"> keeps the prop contract consistent with the new base-types approach without altering run-time behaviour.

web/core/components/editor/sticky-editor/editor.tsx (1)

51-52: Unused workspaceSlug parameter inside useEditorFlagging

useEditorFlagging is invoked with workspaceSlug?.toString() but, judging from its implementation, the hook ignores the argument altogether.
Either remove the parameter here (and from the hook signature) or implement workspace-specific flagging inside the hook.

packages/editor/src/core/components/editors/document/collaborative-editor.tsx (1)

30-31: Provide a safe default for flaggedExtensions.

flaggedExtensions is optional in the type, but no default ([]) is applied.
If a downstream consumer assumes an array, an undefined may leak and trigger runtime checks or spread-operator failures.

-    flaggedExtensions,
+    flaggedExtensions = [],

(Apply the same default in the useCollaborativeEditor argument list if it expects a non-nullable array.)

web/core/components/editor/lite-text-editor/lite-text-editor.tsx (1)

67-68: Sanity-check workspaceSlug before coercion

useEditorFlagging(workspaceSlug?.toString()) will pass the literal string "undefined" when workspaceSlug is undefined, which is easy to overlook in downstream logic.
Defensively bail out or default to "" instead.

-  const { liteText: liteTextEditorExtensions } = useEditorFlagging(workspaceSlug?.toString());
+  const { liteText: liteTextEditorExtensions } = useEditorFlagging(
+    workspaceSlug ? workspaceSlug.toString() : ""
+  );

@aaryan610 aaryan610 marked this pull request as draft June 18, 2025 10:57
@aaryan610 aaryan610 marked this pull request as ready for review June 18, 2025 13:33
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
space/core/components/editor/rich-text-read-only-editor.tsx (1)

22-30: Avoid recreating default arrays on every render

disabledExtensions={disabledExtensions ?? []} and flaggedExtensions={flaggedExtensions ?? []} allocate a brand-new empty array on every render when the prop is undefined.
If the underlying editor implementation relies on referential equality (e.g., useEffect deps), this can trigger needless re-runs / re-renders.

-export const RichTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, RichTextReadOnlyEditorWrapperProps>(
-  ({ anchor, workspaceId, disabledExtensions, flaggedExtensions, ...props }, ref) => {
+const EMPTY_ARR: readonly [] = [];
+
+export const RichTextReadOnlyEditor = React.forwardRef<
+  EditorReadOnlyRefApi,
+  RichTextReadOnlyEditorWrapperProps
+>(({ anchor, workspaceId, disabledExtensions, flaggedExtensions, ...props }, ref) => {
...
-        disabledExtensions={disabledExtensions ?? []}
+        disabledExtensions={disabledExtensions ?? EMPTY_ARR}
...
-        flaggedExtensions={flaggedExtensions ?? []}
+        flaggedExtensions={flaggedExtensions ?? EMPTY_ARR}
space/core/components/editor/rich-text-editor.tsx (1)

23-41: Reuse a stable empty array for defaulted props

Same comment as for the read-only editor: defaulting to [] inline causes a new reference each render. Prefer a frozen constant to avoid unnecessary downstream effects.

-  const { anchor, containerClassName, uploadFile, workspaceId, disabledExtensions, flaggedExtensions, ...rest } = props;
+  const {
+    anchor,
+    containerClassName,
+    uploadFile,
+    workspaceId,
+    disabledExtensions,
+    flaggedExtensions,
+    ...rest
+  } = props;
+
+  const EMPTY_ARR: readonly [] = [];
...
-      disabledExtensions={disabledExtensions ?? []}
+      disabledExtensions={disabledExtensions ?? EMPTY_ARR}
...
-      flaggedExtensions={flaggedExtensions ?? []}
+      flaggedExtensions={flaggedExtensions ?? EMPTY_ARR}
space/core/components/editor/lite-text-read-only-editor.tsx (1)

22-30: Avoid creating a new empty array on every render

disabledExtensions={disabledExtensions ?? []} and likewise for flaggedExtensions produce a fresh array each render when the prop is undefined, defeating referential equality and triggering unnecessary downstream re-renders.

-        disabledExtensions={disabledExtensions ?? []}
-        flaggedExtensions={flaggedExtensions ?? []}
+        disabledExtensions={disabledExtensions ?? EMPTY_EXT_ARR}
+        flaggedExtensions={flaggedExtensions ?? EMPTY_EXT_ARR}

Add once, outside the component:

const EMPTY_EXT_ARR: never[] = [];
space/core/components/editor/lite-text-editor.tsx (1)

47-49: Reuse a stable empty array constant

Same concern as in the read-only wrapper: passing a brand-new [] each render hampers memoisation. Consider:

-        disabledExtensions={disabledExtensions ?? []}
-        flaggedExtensions={flaggedExtensions ?? []}
+        disabledExtensions={disabledExtensions ?? EMPTY_EXT_ARR}
+        flaggedExtensions={flaggedExtensions ?? EMPTY_EXT_ARR}

and declare const EMPTY_EXT_ARR: never[] = []; once per file (or share across wrappers).

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d3f4786 and e658429.

📒 Files selected for processing (9)
  • packages/editor/src/ce/extensions/core/extensions.ts (1 hunks)
  • packages/editor/src/ce/extensions/core/read-only-extensions.ts (1 hunks)
  • packages/editor/src/core/components/editors/document/collaborative-editor.tsx (4 hunks)
  • packages/editor/src/core/types/editor.ts (3 hunks)
  • packages/editor/src/core/types/hook.ts (1 hunks)
  • space/core/components/editor/lite-text-editor.tsx (4 hunks)
  • space/core/components/editor/lite-text-read-only-editor.tsx (2 hunks)
  • space/core/components/editor/rich-text-editor.tsx (3 hunks)
  • space/core/components/editor/rich-text-read-only-editor.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/editor/src/core/types/hook.ts
  • packages/editor/src/core/components/editors/document/collaborative-editor.tsx
  • packages/editor/src/ce/extensions/core/read-only-extensions.ts
  • packages/editor/src/ce/extensions/core/extensions.ts
  • packages/editor/src/core/types/editor.ts
🔇 Additional comments (7)
space/core/components/editor/rich-text-read-only-editor.tsx (1)

13-16: Type-level change looks correct

Switching to IRichTextReadOnlyEditorProps and making both disabledExtensions & flaggedExtensions optional via MakeOptional is consistent with the wider refactor. No issues spotted.

space/core/components/editor/rich-text-editor.tsx (1)

12-16: Wrapper prop typing aligns with base editor props

The updated RichTextEditorWrapperProps correctly exposes the new flaggedExtensions while still omitting handler props. Looks good.

space/core/components/editor/lite-text-read-only-editor.tsx (2)

3-3: Correct prop-type import

Switching to ILiteTextReadOnlyEditorProps keeps the wrapper in sync with the upstream refactor.


13-16: ```shell
#!/bin/bash

Show where ILiteTextReadOnlyEditorProps is imported in the wrapper file

rg -n 'ILiteTextReadOnlyEditorProps' -C2 space/core/components/editor/lite-text-read-only-editor.tsx

Locate the definition of ILiteTextReadOnlyEditorProps to inspect if disabledExtensions/flaggedExtensions are already optional

rg -n 'interface ILiteTextReadOnlyEditorProps' -C6 .


</details>
<details>
<summary>space/core/components/editor/lite-text-editor.tsx (3)</summary>

`3-3`: **Import update looks good**  

Aligns the wrapper with the new prop type introduced upstream.

---

`13-16`: **Re-assess `MakeOptional` wrapper**  

As with the read-only variant, double-optionalising props may now be superfluous and can mask future type changes.

---

`32-34`: **Destructuring change correctly surfaces `flaggedExtensions`**  

Prop now bubbles through the wrapper – good catch.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

@sriramveeraghanta sriramveeraghanta merged commit 8988cf9 into preview Jun 19, 2025
5 of 6 checks passed
@sriramveeraghanta sriramveeraghanta deleted the refactor/editor-props branch June 19, 2025 10:55
lifeiscontent pushed a commit that referenced this pull request Aug 18, 2025
* refactor: editor props structure

* chore: add missing prop

* fix: space app build

* chore: export ce types
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants