Skip to content

Commit 9d04bf5

Browse files
authored
fix: Rich Text Editor: Prevent pasting links when inside an existing link (#4374)
## Description closes #2887 ## Steps for reproduction See Issue ## Code Review - [ ] hi @kof, I need you to do - conceptual review (architecture, feature-correctness) - detailed review (read every line) - test it on preview ## Before requesting a review - [ ] made a self-review - [ ] added inline comments where things may be not obvious (the "why", not "what") ## Before merging - [ ] tested locally and on preview environment (preview dev login: 5de6) - [ ] updated [test cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md) document - [ ] added tests - [ ] if any new env variables are added, added them to `.env` file
1 parent a71190a commit 9d04bf5

File tree

1 file changed

+28
-0
lines changed

1 file changed

+28
-0
lines changed

apps/builder/app/canvas/features/text-editor/text-editor.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
$normalizeSelection__EXPERIMENTAL,
3333
type LexicalEditor,
3434
type SerializedEditorState,
35+
$createTextNode,
3536
} from "lexical";
3637
import { LinkNode } from "@lexical/link";
3738
import { LexicalComposer } from "@lexical/react/LexicalComposer";
@@ -802,6 +803,32 @@ const InitialJSONStatePlugin = ({
802803
return null;
803804
};
804805

806+
/**
807+
* Removes link nodes and converts them to text nodes inside <a> elements.
808+
* Solves the issue with pasting from external sources that contain links.
809+
*/
810+
const LinkSanitizePlugin = (): null => {
811+
const [editor] = useLexicalComposerContext();
812+
813+
useEffect(() => {
814+
const rootElement = editor.getRootElement();
815+
if (rootElement === null) {
816+
return;
817+
}
818+
819+
if (!(rootElement instanceof HTMLAnchorElement)) {
820+
return;
821+
}
822+
823+
return editor.registerNodeTransform(LinkNode, (linkNode) => {
824+
linkNode.insertBefore($createTextNode(linkNode.getTextContent()));
825+
linkNode.remove();
826+
});
827+
}, [editor]);
828+
829+
return null;
830+
};
831+
805832
export const TextEditor = ({
806833
rootInstanceSelector,
807834
instances,
@@ -985,6 +1012,7 @@ export const TextEditor = ({
9851012
placeholder={<></>}
9861013
/>
9871014
<LinkPlugin />
1015+
<LinkSanitizePlugin />
9881016
<HistoryPlugin />
9891017

9901018
<SwitchBlockPlugin onNext={handleNext} />

0 commit comments

Comments
 (0)