From 0d66eabb102aceaf863bbb8cbd009014ad88c111 Mon Sep 17 00:00:00 2001 From: Asim M Al Twijry <3624441+AsimNet@users.noreply.github.com> Date: Sat, 15 Aug 2026 20:27:25 +0000 Subject: [PATCH 01/31] fix(web): read Arabic and Hebrew messages in the right direction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A message renders under the app's direction rather than its own, so Arabic prose comes out with its trailing punctuation on the wrong end, inline code and file paths displaced inside the sentence, and list bullets and quote bars on the side opposite the text they belong to. Each block of message markdown now carries dir="auto", so the browser takes that block's base direction from its own first strong character — one Arabic paragraph and one English paragraph in the same message each read correctly. Code and tables opt out and stay left-to-right, since identifiers, paths, and column order are not prose. Only the outermost block of a run is marked, because dir="auto" skips descendants that carry their own dir: marking a list and its items both would leave the list with no text to judge and paint its bullets into a gutter that had moved. The list, quote, and task-list gutters in the stylesheet become logical so they follow the marker. Thread titles and project names get the same treatment: they are generated from the user's own prompt, and truncating them needs the ellipsis on the correct end. Written by Claude Opus 5 in Claude Code. --- apps/web/src/components/ChatMarkdown.test.tsx | 46 +++++++++++++- apps/web/src/components/ChatMarkdown.tsx | 63 +++++++++++++++++++ apps/web/src/components/LegacySidebar.tsx | 7 ++- apps/web/src/components/Sidebar.tsx | 22 +++++-- apps/web/src/components/chat/ChatHeader.tsx | 18 ++++-- .../components/chat/MessagesTimeline.test.tsx | 4 +- .../src/components/chat/MessagesTimeline.tsx | 12 +++- apps/web/src/index.css | 15 +++-- 8 files changed, 166 insertions(+), 21 deletions(-) diff --git a/apps/web/src/components/ChatMarkdown.test.tsx b/apps/web/src/components/ChatMarkdown.test.tsx index 9499ee5a6915..c2b4004a7b25 100644 --- a/apps/web/src/components/ChatMarkdown.test.tsx +++ b/apps/web/src/components/ChatMarkdown.test.tsx @@ -1,6 +1,7 @@ +import { renderToStaticMarkup } from "react-dom/server"; import { describe, expect, it } from "vite-plus/test"; -import { orderedListGutterStyle } from "./ChatMarkdown"; +import ChatMarkdown, { orderedListGutterStyle } from "./ChatMarkdown"; describe("orderedListGutterStyle", () => { it("leaves the default gutter alone for single-digit lists", () => { @@ -34,3 +35,46 @@ describe("orderedListGutterStyle", () => { expect(orderedListGutterStyle(0, undefined)).toBeUndefined(); }); }); + +describe("chat markdown text direction", () => { + function render(text: string) { + return renderToStaticMarkup(); + } + + it("lets each block pick its own direction from its own text", () => { + const html = render("English first.\n\nمرحبا بالعالم."); + expect(html).toContain('

English first.

'); + expect(html).toContain('

مرحبا بالعالم.

'); + }); + + it("marks headings, lists, and quotes so their markers follow the text", () => { + const html = render("# عنوان\n\n- عنصر\n\n> اقتباس"); + expect(html).toContain('

'); + expect(html).toContain('