mirror of
https://github.com/outline/outline.git
synced 2026-06-13 19:35:02 +03:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4a6da11380 | |||
| d7565ffc1c | |||
| f2362cddba | |||
| bd75caec22 |
+39
-13
@@ -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<SharedEditor> | 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 (
|
||||
<ErrorBoundary component="div" reloadOnChunkMissing>
|
||||
<>
|
||||
<LazyLoadedEditor
|
||||
key={props.extensions?.length || 0}
|
||||
ref={mergeRefs([ref, localRef, handleRefChanged])}
|
||||
uploadFile={handleUploadFile}
|
||||
embeds={embeds}
|
||||
userPreferences={preferences}
|
||||
dictionary={dictionary}
|
||||
{...props}
|
||||
onClickLink={handleClickLink}
|
||||
onChange={handleChange}
|
||||
placeholder={props.placeholder || ""}
|
||||
defaultValue={props.defaultValue || ""}
|
||||
/>
|
||||
{paragraphs ? (
|
||||
<EditorContainer
|
||||
rtl={props.dir === "rtl"}
|
||||
grow={props.grow}
|
||||
style={props.style}
|
||||
editorStyle={props.editorStyle}
|
||||
>
|
||||
<div className="ProseMirror">
|
||||
{paragraphs.map((paragraph, index) => (
|
||||
<p key={index} dir="auto">
|
||||
{paragraph.content.map((content) => content.text)}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
</EditorContainer>
|
||||
) : (
|
||||
<LazyLoadedEditor
|
||||
key={props.extensions?.length || 0}
|
||||
ref={mergeRefs([ref, localRef, handleRefChanged])}
|
||||
uploadFile={handleUploadFile}
|
||||
embeds={embeds}
|
||||
userPreferences={preferences}
|
||||
dictionary={dictionary}
|
||||
{...props}
|
||||
onClickLink={handleClickLink}
|
||||
onChange={handleChange}
|
||||
placeholder={props.placeholder || ""}
|
||||
defaultValue={props.defaultValue || ""}
|
||||
/>
|
||||
)}
|
||||
{props.editorStyle?.paddingBottom && !props.readOnly && (
|
||||
<ClickablePadding
|
||||
onClick={props.readOnly ? undefined : focusAtEnd}
|
||||
|
||||
@@ -339,11 +339,6 @@ width: 100%;
|
||||
padding: ${props.editorStyle?.padding ?? "initial"};
|
||||
margin: ${props.editorStyle?.margin ?? "initial"};
|
||||
|
||||
.ProseMirror {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
& > .ProseMirror-yjs-cursor {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user