diff --git a/front_end/src/components/markdown_editor/__tests__/initialized_editor.test.tsx b/front_end/src/components/markdown_editor/__tests__/initialized_editor.test.tsx index 07e7fb86d4..629e5de5b7 100644 --- a/front_end/src/components/markdown_editor/__tests__/initialized_editor.test.tsx +++ b/front_end/src/components/markdown_editor/__tests__/initialized_editor.test.tsx @@ -172,6 +172,23 @@ describe("InitializedMarkdownEditor", () => { }); }); + describe("code blocks", () => { + it("renders existing code blocks in write mode when withCodeBlocks is false", async () => { + // Given + const markdown = "Before\n\n```\nconsole.log('hi');\n```\n\nAfter"; + + // When / Then — must not throw "Parsing of the following markdown + // structure failed: {type: code, name: N/A}". + await renderWithAct( + + ); + + const editor = screen.getByLabelText(EDITOR_LABEL); + expect(editor).toHaveTextContent("Before"); + expect(editor).toHaveTextContent("After"); + }); + }); + describe("html tags", () => { it("properly preserves HTML tags with custom attributes", async () => { // Given diff --git a/front_end/src/components/markdown_editor/editor.css b/front_end/src/components/markdown_editor/editor.css index fa8d7a5c16..f9706512bb 100644 --- a/front_end/src/components/markdown_editor/editor.css +++ b/front_end/src/components/markdown_editor/editor.css @@ -131,6 +131,22 @@ div:has(.prism-code) + p:has(> br:only-child) { display: none; } + +/* + * Keep fenced code blocks from stretching the editor horizontally. + * `overflow-x: auto` on the
 only clips when every ancestor up to the
+ * content-editable is width-bounded — Lexical wraps decorator blocks in
+ * intermediate spans/divs that default to intrinsic width, so we force
+ * min-width: 0 on the wrappers and cap the 
 at 100% of its container.
+ */
+.mdx-content-editable pre {
+  max-width: 100%;
+}
+.mdx-content-editable [data-lexical-decorator],
+.mdx-content-editable [data-lexical-decorator] > * {
+  min-width: 0;
+  max-width: 100%;
+}
 @media (min-width: 1024px) {
   .markdown-editor.markdown-editor-read .tweets-wrapper {
     display: block;
diff --git a/front_end/src/components/markdown_editor/initialized_editor.tsx b/front_end/src/components/markdown_editor/initialized_editor.tsx
index ef49036383..8ef5e93fa0 100644
--- a/front_end/src/components/markdown_editor/initialized_editor.tsx
+++ b/front_end/src/components/markdown_editor/initialized_editor.tsx
@@ -81,8 +81,8 @@ const PrismCodeBlock: FC<{ code?: string; language?: string }> = ({
   // Handle plain text without syntax highlighting
   if (normalizedLang === "text") {
     return (
-      
-
+      
+
           {codeTrimmed}
         
@@ -92,7 +92,7 @@ const PrismCodeBlock: FC<{ code?: string; language?: string }> = ({ const prismLang = CANONICAL_TO_PRISM[normalizedLang] ?? "tsx"; return ( -
+
= ({ > {({ className, tokens, getLineProps, getTokenProps }) => (
             {tokens.map((line, i) => (
               
@@ -258,11 +258,11 @@ const InitializedMarkdownEditor: FC< equationPlugin(), ]; - if (!withCodeBlocks) { - return common; - } - - if (mode === "read") { + // Always register codeBlockPlugin so pre-existing ``` fences in the source + // markdown parse — otherwise MDXEditor throws on unknown "code" nodes. + // `withCodeBlocks` only gates the insert-code-block toolbar affordance and + // the rich CodeMirror editing experience. + if (!withCodeBlocks || mode === "read") { return [ ...common, codeBlockPlugin({