[WIKI-345] chore: pass disabled and flagged extensions to block menu (#7152)

* chore: refactor editor

* sync changes

* feat: api service update

* refactor : update sync

* fix : package sync

* fix: requested changes

* fix : embedhandler type

* fix : remove commands

* refactor : space

* refactor : rich lite editors

* refactor : minor ce changes

* chore : minor ui fix

* package: tldjs

* refactor : remove tldjs

* refactor: flagged

* refactor: flagged

* chore : remove disbaled check in menu

* refactor: fix space

* refactor: NodeViewProps

* refactor: type

* refactor : update community types

* refactor : remove external embed CE

* remove : external embed config from ce

* refactor : update disabled

* chore: pass disabled

* chore : update utils
This commit is contained in:
Vipin Chaudhary 2025-08-26 02:23:50 +05:30 committed by GitHub
parent 8801ab0081
commit 0fe7da6265
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 53 additions and 11 deletions

View File

@ -14,6 +14,7 @@ export abstract class APIService {
this.axiosInstance = axios.create({
baseURL,
withCredentials: true,
timeout: 20000,
});
}

View File

@ -71,7 +71,7 @@ export const isCommentEmpty = (comment: string | undefined): boolean => {
return (
comment?.trim() === "" ||
comment === "<p></p>" ||
isEmptyHtmlString(comment ?? "", ["img", "mention-component", "image-component"])
isEmptyHtmlString(comment ?? "", ["img", "mention-component", "image-component", "embed-component"])
);
};

View File

@ -1,6 +1,7 @@
import React, { useState } from "react";
// plane imports
// plane constants
import { EIssueCommentAccessSpecifier } from "@plane/constants";
// plane imports
import { type EditorRefApi, type ILiteTextEditorProps, LiteTextEditorWithRef, type TFileHandler } from "@plane/editor";
import { useTranslation } from "@plane/i18n";
import type { MakeOptional } from "@plane/types";
@ -87,7 +88,6 @@ export const LiteTextEditor = React.forwardRef<EditorRefApi, LiteTextEditorWrapp
// derived values
const isEmpty = isCommentEmpty(props.initialValue);
const editorRef = isMutableRefObject<EditorRefApi>(ref) ? ref.current : null;
return (
<div
className={cn(

View File

@ -59,7 +59,6 @@ export const StickyEditor = React.forwardRef<EditorRefApi, StickyEditorWrapperPr
}
// derived values
const editorRef = isMutableRefObject<EditorRefApi>(ref) ? ref.current : null;
return (
<div
className={cn("relative border border-custom-border-200 rounded", parentClassName)}

View File

@ -12,7 +12,7 @@ const nextConfig = {
return [
{
source: "/(.*)?",
headers: [{ key: "X-Frame-Options", value: "SAMEORIGIN" }],
headers: [{ key: "X-Frame-Options", value: "DENY" }],
},
];
},

View File

@ -108,6 +108,8 @@ const CollaborativeDocumentEditor: React.FC<ICollaborativeDocumentEditorProps> =
isTouchDevice={!!isTouchDevice}
isLoading={!hasServerSynced && !hasServerConnectionFailed}
tabIndex={tabIndex}
flaggedExtensions={flaggedExtensions}
disabledExtensions={disabledExtensions}
/>
);
};

View File

@ -82,6 +82,7 @@ const DocumentEditor = (props: IDocumentEditorProps) => {
initialValue: value,
mentionHandler,
onChange,
embedHandler,
});
const editorContainerClassName = getEditorClassNames({
@ -98,6 +99,8 @@ const DocumentEditor = (props: IDocumentEditorProps) => {
editorContainerClassName={cn(editorContainerClassName, "document-editor")}
id={id}
isTouchDevice={!!isTouchDevice}
flaggedExtensions={flaggedExtensions}
disabledExtensions={disabledExtensions}
/>
);
};

View File

@ -5,7 +5,7 @@ import { cn } from "@plane/utils";
import { DocumentContentLoader, EditorContainer, EditorContentWrapper } from "@/components/editors";
import { AIFeaturesMenu, BlockMenu, EditorBubbleMenu } from "@/components/menus";
// types
import { TAIHandler, TDisplayConfig } from "@/types";
import { IEditorProps, TAIHandler, TDisplayConfig } from "@/types";
type Props = {
aiHandler?: TAIHandler;
@ -18,6 +18,8 @@ type Props = {
isLoading?: boolean;
isTouchDevice: boolean;
tabIndex?: number;
flaggedExtensions?: IEditorProps["flaggedExtensions"];
disabledExtensions?: IEditorProps["disabledExtensions"];
};
export const PageRenderer = (props: Props) => {
@ -32,6 +34,8 @@ export const PageRenderer = (props: Props) => {
isLoading,
isTouchDevice,
tabIndex,
flaggedExtensions,
disabledExtensions,
} = props;
return (
@ -54,7 +58,11 @@ export const PageRenderer = (props: Props) => {
{editor.isEditable && !isTouchDevice && (
<div>
{bubbleMenuEnabled && <EditorBubbleMenu editor={editor} />}
<BlockMenu editor={editor} />
<BlockMenu
editor={editor}
flaggedExtensions={flaggedExtensions}
disabledExtensions={disabledExtensions}
/>
<AIFeaturesMenu menu={aiHandler?.menu} />
</div>
)}

View File

@ -41,6 +41,7 @@ export const EditorWrapper: React.FC<Props> = (props) => {
placeholder,
tabIndex,
value,
embedHandler,
} = props;
const editor = useEditor({
@ -65,6 +66,7 @@ export const EditorWrapper: React.FC<Props> = (props) => {
placeholder,
tabIndex,
value,
embedHandler,
});
const editorContainerClassName = getEditorClassNames({

View File

@ -1,8 +1,12 @@
import { autoUpdate, flip, hide, shift, useDismiss, useFloating, useInteractions } from "@floating-ui/react";
import { Editor, useEditorState } from "@tiptap/react";
import { FC, useCallback, useEffect, useRef, useState } from "react";
// components
import { LinkView, LinkViewProps } from "@/components/links";
import { CORE_EXTENSIONS } from "@/constants/extension";
// components
import { getExtensionStorage } from "@/helpers/get-extension-storage";
type Props = {
editor: Editor;
@ -18,7 +22,7 @@ export const LinkViewContainer: FC<Props> = ({ editor, containerRef }) => {
const editorState = useEditorState({
editor,
selector: ({ editor }: { editor: Editor }) => ({
linkExtensionStorage: editor.storage.link,
linkExtensionStorage: getExtensionStorage(editor, CORE_EXTENSIONS.CUSTOM_LINK),
}),
});

View File

@ -4,9 +4,12 @@ import { useCallback, useEffect, useRef } from "react";
import tippy, { Instance } from "tippy.js";
// constants
import { CORE_EXTENSIONS } from "@/constants/extension";
import { IEditorProps } from "@/types";
type Props = {
editor: Editor;
flaggedExtensions?: IEditorProps["flaggedExtensions"];
disabledExtensions?: IEditorProps["disabledExtensions"];
};
export const BlockMenu = (props: Props) => {

View File

@ -81,6 +81,7 @@ declare module "@tiptap/core" {
export type CustomLinkStorage = {
isPreviewOpen: boolean;
posToInsert: { from: number; to: number };
isBubbleMenuOpen: boolean;
};
export const CustomLinkExtension = Mark.create<LinkOptions, CustomLinkStorage>({

View File

@ -29,7 +29,7 @@ import {
// plane editor extensions
import { CoreEditorAdditionalExtensions } from "@/plane-editor/extensions";
// types
import type { IEditorProps } from "@/types";
import type { IEditorProps, TEmbedConfig } from "@/types";
// local imports
import { CustomImageExtension } from "./custom-image/extension";
import { EmojiExtension } from "./emoji/extension";
@ -45,9 +45,11 @@ type TArguments = Pick<
| "mentionHandler"
| "placeholder"
| "tabIndex"
| "embedHandler"
> & {
enableHistory: boolean;
editable: boolean;
embedHandler?: TEmbedConfig;
};
export const CoreEditorExtensions = (args: TArguments): Extensions => {
@ -60,6 +62,7 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => {
mentionHandler,
placeholder,
tabIndex,
embedHandler,
editable,
} = args;
@ -115,6 +118,7 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => {
disabledExtensions,
flaggedExtensions,
fileHandler,
embedHandler,
}),
];

View File

@ -80,6 +80,7 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorHookProps) =>
);
const editor = useEditor({
embedHandler,
disabledExtensions,
id,
editable,

View File

@ -32,6 +32,7 @@ export const useEditor = (props: TEditorHookProps) => {
onAssetChange,
onChange,
onEditorFocus,
embedHandler,
onTransaction,
placeholder,
provider,
@ -63,6 +64,7 @@ export const useEditor = (props: TEditorHookProps) => {
mentionHandler,
placeholder,
tabIndex,
embedHandler,
}),
...extensions,
],

View File

@ -21,6 +21,7 @@ const generalSelectors = [
".image-component",
".image-upload-component",
".editor-callout-component",
".editor-embed-component",
].join(", ");
const maxScrollSpeed = 20;
@ -103,6 +104,11 @@ export const nodeDOMAtCoords = (coords: { x: number; y: number }) => {
continue;
}
// Skip elements inside .editor-embed-component
if (elem.closest(".editor-embed-component") && !elem.matches(".editor-embed-component")) {
continue;
}
// apply general selector
if (elem.matches(generalSelectors)) {
return elem;

View File

@ -2,6 +2,7 @@ import type { Content, Extensions, JSONContent, RawCommands } from "@tiptap/core
import type { MarkType, NodeType } from "@tiptap/pm/model";
import type { Selection } from "@tiptap/pm/state";
import type { EditorProps, EditorView } from "@tiptap/pm/view";
import type { NodeViewProps as TNodeViewProps } from "@tiptap/react";
// extension types
import type { TTextAlign } from "@/extensions";
// types
@ -48,7 +49,8 @@ export type TEditorCommands =
| "text-align"
| "callout"
| "attachment"
| "emoji";
| "emoji"
| "external-embed";
export type TCommandExtraProps = {
image: {
@ -138,6 +140,7 @@ export type IEditorProps = {
editorClassName?: string;
editorProps?: EditorProps;
extensions?: Extensions;
embedHandler?: TEmbedConfig;
flaggedExtensions: TExtensions[];
fileHandler: TFileHandler;
forwardedRef?: React.MutableRefObject<EditorRefApi | null>;
@ -191,3 +194,5 @@ export type EditorEvents = {
destroy: never;
ready: { height: number };
};
export type NodeViewProps = TNodeViewProps;

View File

@ -13,6 +13,7 @@ type TCoreHookProps = Pick<
| "handleEditorReady"
| "isTouchDevice"
| "onEditorFocus"
| "embedHandler"
>;
export type TEditorHookProps = TCoreHookProps &

View File

@ -174,7 +174,7 @@ export const isCommentEmpty = (comment: string | undefined): boolean => {
return (
comment?.trim() === "" ||
comment === "<p></p>" ||
isEmptyHtmlString(comment ?? "", ["img", "mention-component", "image-component"])
isEmptyHtmlString(comment ?? "", ["img", "mention-component", "image-component", "embed-component"])
);
};