Revert "Fix markdown editor escaped list markers"

This reverts commit fbcd80948e.
This commit is contained in:
Dotta
2026-03-07 10:09:04 -06:00
parent f85f2fbcc2
commit a4d0901e89
4 changed files with 8 additions and 83 deletions

View File

@@ -4,7 +4,6 @@ import remarkGfm from "remark-gfm";
import { parseProjectMentionHref } from "@paperclipai/shared";
import { cn } from "../lib/utils";
import { useTheme } from "../context/ThemeContext";
import { normalizeMarkdownArtifacts } from "../lib/markdown";
interface MarkdownBodyProps {
children: string;
@@ -115,7 +114,6 @@ function MermaidDiagramBlock({ source, darkMode }: { source: string; darkMode: b
export function MarkdownBody({ children, className }: MarkdownBodyProps) {
const { theme } = useTheme();
const normalizedMarkdown = normalizeMarkdownArtifacts(children);
return (
<div
className={cn(
@@ -156,7 +154,7 @@ export function MarkdownBody({ children, className }: MarkdownBodyProps) {
},
}}
>
{normalizedMarkdown}
{children}
</Markdown>
</div>
);

View File

@@ -29,7 +29,6 @@ import {
} from "@mdxeditor/editor";
import { buildProjectMentionHref, parseProjectMentionHref } from "@paperclipai/shared";
import { cn } from "../lib/utils";
import { normalizeMarkdownArtifacts } from "../lib/markdown";
/* ---- Mention types ---- */
@@ -204,7 +203,7 @@ export const MarkdownEditor = forwardRef<MarkdownEditorRef, MarkdownEditorProps>
}: MarkdownEditorProps, forwardedRef) {
const containerRef = useRef<HTMLDivElement>(null);
const ref = useRef<MDXEditorMethods>(null);
const latestValueRef = useRef(normalizeMarkdownArtifacts(value));
const latestValueRef = useRef(value);
const [uploadError, setUploadError] = useState<string | null>(null);
const [isDragOver, setIsDragOver] = useState(false);
const dragDepthRef = useRef(0);
@@ -282,10 +281,9 @@ export const MarkdownEditor = forwardRef<MarkdownEditorRef, MarkdownEditorProps>
}, [hasImageUpload]);
useEffect(() => {
const normalizedValue = normalizeMarkdownArtifacts(value);
if (normalizedValue !== latestValueRef.current) {
ref.current?.setMarkdown(normalizedValue);
latestValueRef.current = normalizedValue;
if (value !== latestValueRef.current) {
ref.current?.setMarkdown(value);
latestValueRef.current = value;
}
}, [value]);
@@ -556,15 +554,11 @@ export const MarkdownEditor = forwardRef<MarkdownEditorRef, MarkdownEditorProps>
>
<MDXEditor
ref={ref}
markdown={normalizeMarkdownArtifacts(value)}
markdown={value}
placeholder={placeholder}
onChange={(next) => {
const normalizedNext = normalizeMarkdownArtifacts(next);
latestValueRef.current = normalizedNext;
if (normalizedNext !== next) {
ref.current?.setMarkdown(normalizedNext);
}
onChange(normalizedNext);
latestValueRef.current = next;
onChange(next);
}}
onBlur={() => onBlur?.()}
className={cn("paperclip-mdxeditor", !bordered && "paperclip-mdxeditor--borderless")}

View File

@@ -1,20 +0,0 @@
import { describe, expect, it } from "vitest";
import { normalizeMarkdownArtifacts } from "./markdown";
describe("normalizeMarkdownArtifacts", () => {
it("normalizes escaped unordered list markers and space entities", () => {
const input = "Here is a list:\n\n\\* foo&#x20;\n\\- bar&#x20;";
const output = normalizeMarkdownArtifacts(input);
expect(output).toBe("Here is a list:\n\n* foo \n- bar ");
});
it("does not rewrite escaped markers inside fenced code blocks", () => {
const input = "```md\n\\* keep literal&#x20;\n\\- keep literal&#x20;\n```";
expect(normalizeMarkdownArtifacts(input)).toBe(input);
});
it("keeps escaped non-list syntax intact", () => {
const input = "\\*not-a-list";
expect(normalizeMarkdownArtifacts(input)).toBe(input);
});
});

View File

@@ -1,47 +0,0 @@
const FENCE_RE = /^\s*(`{3,}|~{3,})/;
const SPACE_ENTITY_RE = /&#x20;/gi;
const ESCAPED_UNORDERED_LIST_RE = /^(\s{0,3})\\([*+-])([ \t]+)/;
/**
* Normalize markdown artifacts emitted by rich-text serialization so
* plain markdown list syntax remains usable in Paperclip editors.
*/
export function normalizeMarkdownArtifacts(markdown: string): string {
if (!markdown) return markdown;
const lines = markdown.split(/\r?\n/);
let inFence = false;
let fenceMarker: "`" | "~" | null = null;
let fenceLength = 0;
let changed = false;
const normalized = lines.map((line) => {
const fenceMatch = FENCE_RE.exec(line);
if (fenceMatch) {
const marker = fenceMatch[1];
if (!inFence) {
inFence = true;
fenceMarker = marker[0] as "`" | "~";
fenceLength = marker.length;
} else if (marker[0] === fenceMarker && marker.length >= fenceLength) {
inFence = false;
fenceMarker = null;
fenceLength = 0;
}
return line;
}
if (inFence) return line;
let next = line;
if (next.includes("&#x20;")) {
next = next.replace(SPACE_ENTITY_RE, " ");
}
const unescaped = next.replace(ESCAPED_UNORDERED_LIST_RE, "$1$2$3");
if (unescaped !== line) changed = true;
return unescaped;
});
if (!changed) return markdown;
return normalized.join("\n");
}