From 2c2d462694b0e87a9ed70a0ecfed63d475b89833 Mon Sep 17 00:00:00 2001 From: Eran Krakovsky Date: Fri, 3 Jul 2026 16:05:05 +0300 Subject: [PATCH] fix: support RTL chat message rendering --- apps/web/src/components/ChatMarkdown.test.tsx | 74 ++++++++++++ apps/web/src/components/ChatMarkdown.tsx | 110 +++++++++++++++++- .../src/components/ComposerPromptEditor.tsx | 23 +++- .../src/components/chat/MessagesTimeline.tsx | 11 +- apps/web/src/index.css | 39 ++++++- apps/web/src/lib/rtl.test.ts | 62 ++++++++++ apps/web/src/lib/rtl.ts | 60 ++++++++++ 7 files changed, 368 insertions(+), 11 deletions(-) create mode 100644 apps/web/src/components/ChatMarkdown.test.tsx create mode 100644 apps/web/src/lib/rtl.test.ts create mode 100644 apps/web/src/lib/rtl.ts diff --git a/apps/web/src/components/ChatMarkdown.test.tsx b/apps/web/src/components/ChatMarkdown.test.tsx new file mode 100644 index 00000000000..c650dc11f04 --- /dev/null +++ b/apps/web/src/components/ChatMarkdown.test.tsx @@ -0,0 +1,74 @@ +import { EnvironmentId } from "@t3tools/contracts"; +import { renderToStaticMarkup } from "react-dom/server"; +import { describe, expect, it, vi } from "vite-plus/test"; + +import ChatMarkdown from "./ChatMarkdown"; + +vi.mock("@effect/atom-react", () => ({ + useAtomValue: () => ({ availableEditors: [] }), +})); + +vi.mock("../hooks/useTheme", () => ({ + useTheme: () => ({ resolvedTheme: "light" }), +})); + +vi.mock("../editorPreferences", () => ({ + useOpenInPreferredEditor: () => () => {}, +})); + +vi.mock("../state/assets", () => ({ + assetEnvironment: { createUrl: {} }, +})); + +vi.mock("../state/entities", () => ({ + useActiveEnvironmentId: () => EnvironmentId.make("environment-local"), +})); + +vi.mock("../state/preview", () => ({ + previewEnvironment: { open: {} }, +})); + +vi.mock("../state/server", () => ({ + serverEnvironment: { configValueAtom: () => ({}) }, +})); + +vi.mock("../state/session", () => ({ + usePreparedConnection: () => ({ _tag: "None" }), +})); + +vi.mock("../state/use-atom-command", () => ({ + useAtomCommand: () => () => {}, +})); + +vi.mock("../state/use-atom-query-runner", () => ({ + useAtomQueryRunner: () => () => "", +})); + +describe("ChatMarkdown bidi list rendering", () => { + it("renders code-prefixed Hebrew unordered lists as RTL", () => { + const markup = renderToStaticMarkup( + , + ); + + expect(markup).toContain('