mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-11 05:11:49 +01:00
Handle advisory html images in markdown editor
This commit is contained in:
1 parent
f8132bfd26
commit
8ed2a939df
2 files changed
+21
-2
No files matched your search
@@ -19,6 +19,7 @@ const mdxEditorMockState = vi.hoisted(() => ({
|
||||
emitMountParseError: false,
|
||||
emitMountSilentEmptyState: false,
|
||||
markdownValues: [] as string[],
|
||||
suppressHtmlProcessingValues: [] as boolean[],
|
||||
}));
|
||||
|
||||
vi.mock("@mdxeditor/editor", async () => {
|
||||
@@ -41,16 +42,20 @@ vi.mock("@mdxeditor/editor", async () => {
|
||||
onChange,
|
||||
onError,
|
||||
className,
|
||||
suppressHtmlProcessing,
|
||||
}: {
|
||||
markdown: string;
|
||||
placeholder?: string;
|
||||
onChange?: (value: string) => void;
|
||||
onError?: (error: unknown) => void;
|
||||
className?: string;
|
||||
suppressHtmlProcessing?: boolean;
|
||||
className?: string;
|
||||
},
|
||||
forwardedRef: React.ForwardedRef<{ setMarkdown: (value: string) => void; focus: () => void } | null>,
|
||||
) {
|
||||
mdxEditorMockState.markdownValues.push(markdown);
|
||||
mdxEditorMockState.suppressHtmlProcessingValues.push(Boolean(suppressHtmlProcessing));
|
||||
const [content, setContent] = React.useState(markdown);
|
||||
const editableRef = React.useRef<HTMLDivElement>(null);
|
||||
const handle = React.useMemo(() => ({
|
||||
@@ -59,8 +64,16 @@ vi.mock("@mdxeditor/editor", async () => {
|
||||
}), []);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!suppressHtmlProcessing && markdown.includes("<img ")) {
|
||||
setContent("");
|
||||
onError?.({
|
||||
message: "Error parsing markdown: HTML-like formatting requires suppressHtmlProcessing",
|
||||
source: markdown,
|
||||
});
|
||||
return;
|
||||
}
|
||||
setContent(markdown);
|
||||
}, [markdown]);
|
||||
}, [markdown, onError, suppressHtmlProcessing]);
|
||||
|
||||
React.useEffect(() => {
|
||||
setForwardedRef(forwardedRef, null);
|
||||
@@ -114,6 +127,8 @@ vi.mock("@mdxeditor/editor", async () => {
|
||||
markdownShortcutPlugin: () => ({}),
|
||||
quotePlugin: () => ({}),
|
||||
realmPlugin: (plugin: unknown) => plugin,
|
||||
jsxPlugin: () => ({}),
|
||||
GenericJsxEditor: () => null,
|
||||
tablePlugin: () => ({}),
|
||||
thematicBreakPlugin: () => ({}),
|
||||
};
|
||||
@@ -165,6 +180,7 @@ describe("MarkdownEditor", () => {
|
||||
mdxEditorMockState.emitMountParseError = false;
|
||||
mdxEditorMockState.emitMountSilentEmptyState = false;
|
||||
mdxEditorMockState.markdownValues = [];
|
||||
mdxEditorMockState.suppressHtmlProcessingValues = [];
|
||||
});
|
||||
|
||||
it("applies async external value updates once the editor ref becomes ready", async () => {
|
||||
@@ -238,6 +254,7 @@ describe("MarkdownEditor", () => {
|
||||
await flush();
|
||||
expect(mdxEditorMockState.markdownValues.at(-1)).toContain("");
|
||||
expect(mdxEditorMockState.markdownValues.at(-1)).not.toContain("<img");
|
||||
expect(mdxEditorMockState.suppressHtmlProcessingValues).toContain(true);
|
||||
expect(container.textContent).toContain("Before");
|
||||
expect(container.textContent).toContain("After");
|
||||
|
||||
@@ -309,7 +326,6 @@ describe("MarkdownEditor", () => {
|
||||
root.unmount();
|
||||
});
|
||||
});
|
||||
|
||||
it("anchors the mention menu inside the visual viewport when mobile offsets are present", () => {
|
||||
expect(
|
||||
computeMentionMenuPosition(
|
||||
|
||||
@@ -505,6 +505,7 @@ export const MarkdownEditor = forwardRef<MarkdownEditorRef, MarkdownEditorProps>
|
||||
const [isDragOver, setIsDragOver] = useState(false);
|
||||
const [richEditorError, setRichEditorError] = useState<string | null>(null);
|
||||
const dragDepthRef = useRef(0);
|
||||
const suppressHtmlProcessing = /<img\s/i.test(value);
|
||||
|
||||
// Stable ref for imageUploadHandler so plugins don't recreate on every render
|
||||
const imageUploadHandlerRef = useRef(imageUploadHandler);
|
||||
@@ -1055,9 +1056,11 @@ export const MarkdownEditor = forwardRef<MarkdownEditorRef, MarkdownEditorProps>
|
||||
onPasteCapture={handlePasteCapture}
|
||||
>
|
||||
<MDXEditor
|
||||
key={suppressHtmlProcessing ? "mdxeditor-no-html" : "mdxeditor-default"}
|
||||
ref={setEditorRef}
|
||||
markdown={editorValue}
|
||||
placeholder={placeholder}
|
||||
suppressHtmlProcessing={suppressHtmlProcessing}
|
||||
onChange={(next) => {
|
||||
const echo = echoIgnoreMarkdownRef.current;
|
||||
if (echo !== null && next === echo) {
|
||||
|
||||
Reference in new issue
Block a user