Skip to content

fix: force LTR direction and layout for code elements in RTL/Arabic l… #141#142

Merged
DataDave-Dev merged 1 commit into
DataDave-Dev:mainfrom
YasserYG8:fix/arabic_code
Jun 28, 2026
Merged

fix: force LTR direction and layout for code elements in RTL/Arabic l… #141#142
DataDave-Dev merged 1 commit into
DataDave-Dev:mainfrom
YasserYG8:fix/arabic_code

Conversation

@YasserYG8

@YasserYG8 YasserYG8 commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Title

fix: force LTR direction and layout for code elements in RTL/Arabic locales

Description

This PR resolves the issue where programming code blocks, colons, brackets, and text editor layout get corrupted/reversed when switching the site locale to Arabic (or any Right-to-Left language).

Changes Made:

  1. Targeted CSS Rules: Added global styles in globals.css to force all code elements (pre, code, and monospace textareas) to render Left-to-Right (direction: ltr !important) and disabled the browser's Unicode Bidirectional re-ordering algorithm on code tags (unicode-bidi: plaintext !important). This ensures punctuation (like :() vs ():) is rendered in the correct position.
  2. Editor Layout Direction: Injected dir="ltr" into the editor container inside CodeWorkspace.tsx to guarantee that the line-number gutter stays on the left and the textarea on the right, even when the rest of the page flows Right-to-Left.

How to test / verify

  1. Run pnpm typecheck to confirm type compiling.
  2. Run pnpm test to verify unit tests pass.
  3. Switch the site locale to Arabic (/ar/app) and verify that:
    • The editor gutter (line numbers) stays on the left.
    • Entered code (such as Python def main():) renders LTR without brackets or punctuation flipping.
    • Non-code textareas (such as testimonials) still correctly flow RTL.

Summary by CodeRabbit

  • Bug Fixes

    • Improved layout handling for code blocks and editor areas so they display left-to-right consistently across languages.
    • Fixed alignment issues in code-like text fields and monospaced content for better readability.
  • Style

    • Adjusted global text direction and alignment rules for code-related content.
    • Updated page rendering so theme setup runs in a more reliable place without changing the visible page structure.

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The root layout now injects the theme bootstrap script at the start of the body instead of in the head. Global styles and the code workspace editor now force code-like content to render left-to-right.

Changes

Rendering placement and direction updates

Layer / File(s) Summary
Theme script relocation
src/app/[lang]/layout.tsx
The root layout changes the inline theme script from <head> to a hidden body element while keeping the nonce.
LTR code surfaces
src/app/globals.css, src/components/ui/CodeWorkspace.tsx
Global rules force pre, code, and mono textareas to render LTR, and the code workspace wrapper sets dir="ltr".

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

  • DataDave-Dev/weftmap issue 141 — The CSS and editor direction changes match the reported code-alignment problem for RTL locales.

Possibly related PRs

  • DataDave-Dev/weftmap#135 — This also changes src/app/[lang]/layout.tsx’s inline theme handling and body-level rendering setup.

Poem

A bunny hops through bytes tonight 🐇
LTR code blocks now sit just right
The theme script tucked where bodies grow
With whiskers twitching, onward I go

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the fix and verification steps, but it doesn't follow the required template sections or checklist. Reformat it to the repository template: add 'Qué hace', 'Tipo' with one selected option, and the full checklist (lint/typecheck/test/build).
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: forcing LTR layout for code elements in RTL/Arabic locales.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/`[lang]/layout.tsx:
- Around line 54-58: The layout’s inline theme bootstrap is currently
string-interpolating nonce into raw HTML, which can emit nonce="undefined" when
the value is missing. Update the logic in the layout component that builds the
bootstrap script so it renders an actual script element and passes nonce={nonce}
directly, ensuring the attribute is omitted when absent and keeping CSP behavior
correct.

In `@src/components/ui/CodeWorkspace.tsx`:
- Line 425: The current LTR fix in CodeWorkspace only covers snippet mode, while
the project-mode uploaded path list still renders under RTL. Update
CodeWorkspace so the file list around the f.path rendering is wrapped in an LTR
container like the existing snippet view, or otherwise ensure those monospace
path items inherit dir="ltr". Keep the fix targeted to the project file list
elements and verify the relevant JSX block in CodeWorkspace uses the same LTR
handling for both modes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 15b2e4f8-a664-4b22-a541-58e502135e02

📥 Commits

Reviewing files that changed from the base of the PR and between 656cd67 and b850597.

📒 Files selected for processing (3)
  • src/app/[lang]/layout.tsx
  • src/app/globals.css
  • src/components/ui/CodeWorkspace.tsx

Comment thread src/app/[lang]/layout.tsx
Comment on lines +54 to +58
<div
suppressHydrationWarning
style={{ display: "none" }}
dangerouslySetInnerHTML={{
__html: `(function(){try{var t=localStorage.getItem('theme');var d=t?t==='dark':matchMedia('(prefers-color-scheme:dark)').matches;if(d)document.documentElement.classList.add('dark');}catch(e){}})();`,
__html: `<script nonce="${nonce}">(function(){try{var t=localStorage.getItem('theme');var d=t?t==='dark':matchMedia('(prefers-color-scheme:dark)').matches;if(d)document.documentElement.classList.add('dark');}catch(e){}})();</script>`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Avoid emitting nonce="undefined" here.

nonce is optional in this layout, but string interpolation always writes an attribute. If x-nonce is ever missing, this becomes nonce="undefined" and the bootstrap script no longer satisfies CSP. Render a real <script> node and pass nonce={nonce} so the attribute is omitted when absent.

Suggested fix
-        <div
-          suppressHydrationWarning
-          style={{ display: "none" }}
-          dangerouslySetInnerHTML={{
-            __html: `<script nonce="${nonce}">(function(){try{var t=localStorage.getItem('theme');var d=t?t==='dark':matchMedia('(prefers-color-scheme:dark)').matches;if(d)document.documentElement.classList.add('dark');}catch(e){}})();</script>`,
-          }}
-        />
+        <script
+          nonce={nonce}
+          suppressHydrationWarning
+          dangerouslySetInnerHTML={{
+            __html:
+              "(function(){try{var t=localStorage.getItem('theme');var d=t?t==='dark':matchMedia('(prefers-color-scheme:dark)').matches;if(d)document.documentElement.classList.add('dark');}catch(e){}})();",
+          }}
+        />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div
suppressHydrationWarning
style={{ display: "none" }}
dangerouslySetInnerHTML={{
__html: `(function(){try{var t=localStorage.getItem('theme');var d=t?t==='dark':matchMedia('(prefers-color-scheme:dark)').matches;if(d)document.documentElement.classList.add('dark');}catch(e){}})();`,
__html: `<script nonce="${nonce}">(function(){try{var t=localStorage.getItem('theme');var d=t?t==='dark':matchMedia('(prefers-color-scheme:dark)').matches;if(d)document.documentElement.classList.add('dark');}catch(e){}})();</script>`,
<script
nonce={nonce}
suppressHydrationWarning
dangerouslySetInnerHTML={{
__html:
"(function(){try{var t=localStorage.getItem('theme');var d=t?t==='dark':matchMedia('(prefers-color-scheme:dark)').matches;if(d)document.documentElement.classList.add('dark');}catch(e){}})();",
}}
/>
🧰 Tools
🪛 ast-grep (0.44.0)

[warning] 56-56: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation

(react-unsafe-html-injection)

🪛 React Doctor (0.5.8)

[error] 57-57: dangerouslySetInnerHTML is an XSS hole that runs attacker-controlled HTML in your users' browsers.

Render trusted content as React children so attacker-controlled HTML cannot run in users' browsers.

(no-danger)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`[lang]/layout.tsx around lines 54 - 58, The layout’s inline theme
bootstrap is currently string-interpolating nonce into raw HTML, which can emit
nonce="undefined" when the value is missing. Update the logic in the layout
component that builds the bootstrap script so it renders an actual script
element and passes nonce={nonce} directly, ensuring the attribute is omitted
when absent and keeping CSP behavior correct.

{/* Body */}
{mode === "snippet" ? (
<div className="relative flex flex-1 overflow-hidden font-mono text-[13px] leading-[1.7]">
<div dir="ltr" className="relative flex flex-1 overflow-hidden font-mono text-[13px] leading-[1.7]">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

This only fixes snippet mode; project file paths still render under RTL.

The uploaded path list below (f.path at Lines 483-490) is still outside any dir="ltr" container, and the new globals.css rule does not cover those monospace list items. Arabic locale users can still see reordered / and [] there. Please extend the LTR wrapper or add a dedicated LTR container for the project-mode file list too.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/ui/CodeWorkspace.tsx` at line 425, The current LTR fix in
CodeWorkspace only covers snippet mode, while the project-mode uploaded path
list still renders under RTL. Update CodeWorkspace so the file list around the
f.path rendering is wrapped in an LTR container like the existing snippet view,
or otherwise ensure those monospace path items inherit dir="ltr". Keep the fix
targeted to the project file list elements and verify the relevant JSX block in
CodeWorkspace uses the same LTR handling for both modes.

@YasserYG8 YasserYG8 changed the title fix: force LTR direction and layout for code elements in RTL/Arabic l… fix: force LTR direction and layout for code elements in RTL/Arabic l… #141 Jun 28, 2026
@DataDave-Dev DataDave-Dev merged commit 12b5ae1 into DataDave-Dev:main Jun 28, 2026
2 of 3 checks passed
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.

2 participants