fix: force LTR direction and layout for code elements in RTL/Arabic l… #141#142
Conversation
📝 WalkthroughWalkthroughThe 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. ChangesRendering placement and direction updates
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
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
📒 Files selected for processing (3)
src/app/[lang]/layout.tsxsrc/app/globals.csssrc/components/ui/CodeWorkspace.tsx
| <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>`, |
There was a problem hiding this comment.
🎯 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.
| <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]"> |
There was a problem hiding this comment.
🎯 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.
Title
fix: force LTR direction and layout for code elements in RTL/Arabic localesDescription
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:
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.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
pnpm typecheckto confirm type compiling.pnpm testto verify unit tests pass./ar/app) and verify that:def main():) renders LTR without brackets or punctuation flipping.Summary by CodeRabbit
Bug Fixes
Style