Skip to content

fix: detect static text direction per block - #569

Open
CodeinScrubs wants to merge 1 commit into
vercel:mainfrom
CodeinScrubs:agent/fix-static-bidi-blocks
Open

fix: detect static text direction per block#569
CodeinScrubs wants to merge 1 commit into
vercel:mainfrom
CodeinScrubs:agent/fix-static-bidi-blocks

Conversation

@CodeinScrubs

@CodeinScrubs CodeinScrubs commented Jul 30, 2026

Copy link
Copy Markdown

Description

Static mode currently resolves dir=auto once for the complete Markdown string. A mixed Hebrew/Arabic/Persian and English response therefore gives every block the same base direction, while code can inherit RTL.

This change keeps static content as one Markdown document but adds a rehype pass that assigns direction to each semantic block. Keeping one parse preserves cross-block references and footnotes. The public detector now uses strong-character content majority, with first-strong as the tie-breaker, so RTL-majority technical prose such as an answer beginning with an English identifier is not forced LTR. Rendered code-block containers are explicitly LTR.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality not to work as expected)
  • Documentation update
  • Performance improvement
  • Refactoring (no functional changes)

Related Issues

Fixes #509

Changes Made

  • Detect static Markdown direction per heading, paragraph, list item, quote, definition, caption, and table cell.
  • Use content-majority direction with first-strong tie-breaking and exclude inline/fenced code from prose evidence.
  • Keep code LTR at both HAST and custom code-block rendering layers.
  • Add Hebrew, Persian/English, English, and fenced-code regression coverage.

Testing

  • All existing tests pass
  • Added new tests for the changes
  • Manually tested the changes

Test Coverage

  • pnpm --filter streamdown test: 73 files, 985 tests passed
  • pnpm --filter streamdown build: ESM and declaration build passed
  • Ultracite check on all six touched TypeScript/TSX files: passed
  • git diff --check: passed

Screenshots/Demos

Not included. The regression is asserted against the rendered DOM: no document-level auto direction in static mode, per-block dir values, and an LTR code-block container.

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
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings or errors
  • I have added tests that prove my fix is effective
  • 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

I maintain the MIT-licensed BidiLens project and used its per-semantic-block/content-majority model as design input. This PR intentionally implements the small policy natively instead of adding BidiLens as a dependency: Streamdown supports Node 18, while BidiLens 0.3 declares Node 22.12+, so a direct dependency would unnecessarily raise the host's runtime floor.

The Vercel preview check requires authorization from a Vercel team member because this PR comes from an external fork. Socket security and Vercel Agent Review passed; the preview authorization state is not a build or test failure in this patch.

@vercel

vercel Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Someone is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

@CodeinScrubs
CodeinScrubs marked this pull request as ready for review July 30, 2026 09:16
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