diff --git a/app/components/Editor.tsx b/app/components/Editor.tsx index c80702d38f..19f6a7c4f0 100644 --- a/app/components/Editor.tsx +++ b/app/components/Editor.tsx @@ -6,7 +6,9 @@ import * as React from "react"; import { mergeRefs } from "react-merge-refs"; import { Optional } from "utility-types"; import insertFiles from "@shared/editor/commands/insertFiles"; +import EditorContainer from "@shared/editor/components/Styles"; import { AttachmentPreset } from "@shared/types"; +import { ProsemirrorHelper } from "@shared/utils/ProsemirrorHelper"; import { getDataTransferFiles } from "@shared/utils/files"; import { AttachmentValidation } from "@shared/validations"; import ClickablePadding from "~/components/ClickablePadding"; @@ -183,22 +185,46 @@ function Editor(props: Props, ref: React.RefObject | null) { [updateComments] ); + const paragraphs = React.useMemo(() => { + if (props.readOnly && typeof props.value === "object") { + return ProsemirrorHelper.getPlainParagraphs(props.value); + } + return undefined; + }, [props.readOnly, props.value]); + return ( <> - + {paragraphs ? ( + +
+ {paragraphs.map((paragraph, index) => ( +

+ {paragraph.content.map((content) => content.text)} +

+ ))} +
+
+ ) : ( + + )} {props.editorStyle?.paddingBottom && !props.readOnly && ( .ProseMirror-yjs-cursor { display: none; } diff --git a/shared/utils/ProsemirrorHelper.test.ts b/shared/utils/ProsemirrorHelper.test.ts index 55c6d3d0f7..3974785c01 100644 --- a/shared/utils/ProsemirrorHelper.test.ts +++ b/shared/utils/ProsemirrorHelper.test.ts @@ -1,3 +1,4 @@ +import { ProsemirrorData } from "../types"; import { CommentMark, ProsemirrorHelper } from "./ProsemirrorHelper"; describe("ProsemirrorHelper", () => { @@ -87,4 +88,131 @@ describe("ProsemirrorHelper", () => { expect(returnedAnchorText).toBeUndefined(); }); }); + + describe("getPlainParagraphs", () => { + it("should return an array of plain paragraphs", async () => { + const data = { + type: "doc", + content: [ + { + type: "paragraph", + content: [ + { + type: "text", + text: "some content in a paragraph", + }, + ], + }, + { + type: "paragraph", + content: [ + { + type: "text", + text: "some content in another paragraph", + }, + ], + }, + ], + } as ProsemirrorData; + + const paragraphs = ProsemirrorHelper.getPlainParagraphs(data); + + expect(paragraphs).toEqual([ + { + type: "paragraph", + content: [ + { + type: "text", + text: "some content in a paragraph", + }, + ], + }, + { + type: "paragraph", + content: [ + { + type: "text", + text: "some content in another paragraph", + }, + ], + }, + ]); + }); + + it("should return undefined when data contains inline nodes", async () => { + const data = { + type: "doc", + content: [ + { + type: "paragraph", + content: [ + { + type: "text", + text: "some content in a paragraph", + }, + { + type: "emoji", + attrs: { + "data-name": "😆", + }, + }, + ], + }, + ], + } as ProsemirrorData; + + const paragraphs = ProsemirrorHelper.getPlainParagraphs(data); + expect(paragraphs).toBeUndefined(); + }); + + it("should return undefined when data contains block nodes", async () => { + const data = { + type: "doc", + content: [ + { + type: "blockquote", + content: [ + { + type: "paragraph", + content: [ + { + type: "text", + text: "some content in a paragraph", + }, + ], + }, + ], + }, + ], + } as ProsemirrorData; + + const paragraphs = ProsemirrorHelper.getPlainParagraphs(data); + expect(paragraphs).toBeUndefined(); + }); + + it("should return undefined when data contains marks", async () => { + const data = { + type: "doc", + content: [ + { + type: "paragraph", + content: [ + { + type: "text", + text: "some content in a paragraph", + marks: [ + { + type: "bold", + }, + ], + }, + ], + }, + ], + } as ProsemirrorData; + + const paragraphs = ProsemirrorHelper.getPlainParagraphs(data); + expect(paragraphs).toBeUndefined(); + }); + }); }); diff --git a/shared/utils/ProsemirrorHelper.ts b/shared/utils/ProsemirrorHelper.ts index ea2e2c554d..9b77644135 100644 --- a/shared/utils/ProsemirrorHelper.ts +++ b/shared/utils/ProsemirrorHelper.ts @@ -346,4 +346,29 @@ export class ProsemirrorHelper { return replace(data); } + + /** + * Returns the paragraphs from the data if there are only plain paragraphs + * without any formatting. Otherwise returns undefined. + * + * @param data The ProsemirrorData object + * @returns An array of paragraph nodes or undefined + */ + static getPlainParagraphs(data: ProsemirrorData) { + const paragraphs = []; + for (const node of data.content) { + if ( + node.type === "paragraph" && + !node.content.some( + (item) => + item.type !== "text" || (item.marks && item.marks.length > 0) + ) + ) { + paragraphs.push(node); + } else { + return undefined; + } + } + return paragraphs; + } }