Skip to content

fix: per-block direction detection in static mode with dir="auto"#510

Open
shloimy-wiesel wants to merge 1 commit into
vercel:mainfrom
shloimy-wiesel:fix/rtl-static-mode-per-block-direction
Open

fix: per-block direction detection in static mode with dir="auto"#510
shloimy-wiesel wants to merge 1 commit into
vercel:mainfrom
shloimy-wiesel:fix/rtl-static-mode-per-block-direction

Conversation

@shloimy-wiesel
Copy link
Copy Markdown
Contributor

@shloimy-wiesel shloimy-wiesel commented Apr 16, 2026

Description

Fix dir="auto" in static mode to detect text direction per-block instead of once for the entire content. Previously, mixed RTL/LTR markdown (e.g., Hebrew headings + English paragraphs + code blocks) would all receive a single direction, causing incorrect text alignment. This PR aligns static mode behavior with streaming mode, which already handled per-block direction correctly.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Related Issues

Fixes #509

Changes Made

  • Per-block direction in static mode (packages/streamdown/index.tsx): When mode="static" and dir="auto", the component now uses parseMarkdownIntoBlocks + per-block detectTextDirection, matching the streaming mode behavior
  • Strip fenced code blocks from direction detection (packages/streamdown/lib/detect-direction.ts): detectTextDirection now strips fenced code blocks (```...```) before analyzing text direction, preventing code content from skewing the result
  • Force code blocks to LTR (packages/streamdown/lib/code-block/body.tsx): Added dir="ltr" to the CodeBlockBody root div - code is universally LTR regardless of surrounding content direction
  • Fix Block wrapper styling (packages/streamdown/index.tsx): Replaced display: contents with unicodeBidi: "isolate" on the Block dir wrapper to preserve space-y-4 spacing between blocks
  • Add dir config to playground (apps/website/.../playground-editor.tsx): Added a configurable Dir dropdown (Auto / LTR / RTL) to the playground settings panel, defaulting to Auto, replacing the previous hardcoded dir="auto"

Testing

  • All existing tests pass (988/988)
  • Added new tests for the changes
  • Manually tested the changes
  • Ultracite lint check passes (0 errors on changed files)

Test Coverage

detect-direction.test.ts - 3 new tests:

  • Strips fenced code blocks before direction detection
  • Detects RTL when fenced code block contains LTR code
  • Handles multiple fenced code blocks with different languages

rtl-support.test.tsx - 4 updated/new tests:

  • Updated: Block wrapper uses unicodeBidi: isolate (not display: contents)
  • New: Static mode with dir="auto" renders different directions per block
  • New: Static mode with dir="auto" renders English blocks as LTR within Hebrew content
  • New: Code blocks always render with dir="ltr"

Screenshots/Demos

Before Fix (Bug)

Static mode applies a single direction to the entire content - English section inherits RTL from Hebrew context

image

After Fix

Static mode now detects direction per-block - Hebrew blocks are RTL, English blocks are LTR, code blocks always LTR

image

Checklist

  • My code follows the project's code style
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings or errors
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I have created a changeset (pnpm changeset)

Changeset

  • I have created a changeset for these changes

Additional Notes

  • The fix reuses the existing parseMarkdownIntoBlocks + detectTextDirection pipeline that streaming mode already uses - no new direction detection logic was introduced
  • display: contents was replaced with unicodeBidi: "isolate" because display: contents makes the element invisible to CSS layout, which broke space-y-4 margins between blocks
  • Code blocks are forced to dir="ltr" at the component level (not via detection) because marked's Lexer treats a list item with a nested code block as a single token, making per-block detection insufficient for embedded code

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 16, 2026

@shloimy-wiesel is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

@shloimy-wiesel shloimy-wiesel force-pushed the fix/rtl-static-mode-per-block-direction branch from f44335c to 0c37738 Compare April 16, 2026 19:41
When mode="static" and dir="auto", Streamdown now detects text direction
per-block (same as streaming mode) instead of once for the entire content.

- Static mode with dir="auto" uses parseMarkdownIntoBlocks and per-block
  detectTextDirection, matching streaming mode behavior
- detectTextDirection strips fenced code blocks before detection
- Code blocks always render LTR via dir="ltr" on CodeBlockBody
- Block dir wrapper uses unicodeBidi:"isolate" instead of display:contents
  to preserve space-y-4 spacing between blocks
@shloimy-wiesel shloimy-wiesel force-pushed the fix/rtl-static-mode-per-block-direction branch from 0c37738 to a46c37f Compare April 16, 2026 19:47
Copy link
Copy Markdown
Contributor

@vercel vercel Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Suggestion:

Missing closing parentheses in CSS var() expressions cause broken background color on the <pre> element of code blocks.

Fix on Vercel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug Report: dir="auto" in static mode applies single direction to all content

1 participant