Skip to content

Conversation

@djedi
Copy link
Owner

@djedi djedi commented Dec 12, 2025

Summary

  • Add right-to-left (RTL) language support with three modes: LTR, RTL, and Auto-detect
  • Create direction service following the theme service pattern with localStorage persistence
  • Add direction selector in Settings modal with matching UI style
  • Convert physical CSS properties to logical properties (margin-inline-start/end, etc.)
  • Integrate auto-detection with editor to detect RTL content (Arabic, Hebrew, Persian, Syriac)

Test plan

  • Verify LTR mode works as default
  • Test RTL mode flips UI layout correctly
  • Test Auto mode detects Arabic/Hebrew text and switches direction
  • Verify setting persists across page reloads
  • Test on mobile viewport

Add right-to-left (RTL) language support with three modes:
- LTR: Left-to-right (default)
- RTL: Right-to-left for Arabic, Hebrew, etc.
- Auto: Automatically detect based on content

Changes:
- Create direction service with auto-detection using Unicode ranges
- Add direction selector in Settings (matching theme selector style)
- Convert physical CSS properties to logical properties throughout
  (margin-inline-start/end, padding-inline-start/end, etc.)
- Integrate auto-detection with editor content changes
Copilot AI review requested due to automatic review settings December 12, 2025 23:28
@djedi djedi mentioned this pull request Dec 12, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds comprehensive right-to-left (RTL) language support to the application, enabling proper display and interaction for languages like Arabic, Hebrew, Persian, and Syriac. The implementation follows the existing theme service pattern, creating a direction service with three modes: LTR (left-to-right), RTL (right-to-left), and Auto-detect. The auto-detect mode intelligently analyzes editor content using Unicode character ranges to determine the appropriate text direction.

Key changes:

  • Created a DirectionService singleton following the ThemeService pattern with reactive state, localStorage persistence, and Vue watchers
  • Integrated direction auto-detection into the Editor component with debounced updates during content changes
  • Converted physical CSS properties (left/right, margin-left/right) to logical properties (inline-start/end, margin-inline) across all Vue components for bidirectional layout support

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
client/src/services/direction.ts New direction service implementing state management, auto-detection algorithm for RTL languages, frontmatter stripping, and DOM manipulation
client/src/main.ts Imports direction service to initialize it at application startup
client/src/components/Settings.vue Adds direction selector UI matching theme selector pattern with three button options
client/src/components/Editor.vue Integrates debounced direction auto-detection on content changes and initial mount
client/src/App.vue Adds CSS variables for direction support (though currently unused)
client/src/views/Search.vue Converts autocomplete dropdown and syntax help table positioning to logical properties
client/src/views/Note.vue Converts editor split border from physical to logical property
client/src/views/Home.vue Converts center-columns margin to logical property shorthand
client/src/views/Day.vue Converts editor split border from physical to logical property
client/src/components/NestedTags.vue Converts padding and margin properties for nested tag indentation to logical properties
client/src/components/MarkdownPreview.vue Converts multiple spacing properties (margins, padding, borders) and text-align from physical to logical properties
client/src/components/Header.vue Converts header spacing and dropdown positioning to logical properties, removes obsolete float property

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 91 to 95
this.state.autoDetectedDirection = detected;

if (this.state.preference === 'auto') {
this.state.resolved = detected;
this.applyDirection();
Copy link

Copilot AI Dec 12, 2025

Choose a reason for hiding this comment

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

The updateAutoDirection method updates the resolved direction and applies it even when preference is 'auto', but it doesn't prevent race conditions. If multiple rapid content changes occur, the debounced calls could update autoDetectedDirection out of order. Consider checking if the detected direction has actually changed before calling applyDirection to avoid unnecessary DOM manipulations.

Suggested change
this.state.autoDetectedDirection = detected;
if (this.state.preference === 'auto') {
this.state.resolved = detected;
this.applyDirection();
if (this.state.autoDetectedDirection !== detected) {
this.state.autoDetectedDirection = detected;
if (this.state.preference === 'auto') {
this.state.resolved = detected;
this.applyDirection();
}

Copilot uses AI. Check for mistakes.
* Strip YAML frontmatter from text
*/
private stripFrontmatter(text: string): string {
const frontmatterRegex = /^---\s*\n[\s\S]*?\n---\s*\n/;
Copy link

Copilot AI Dec 12, 2025

Choose a reason for hiding this comment

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

The frontmatter regex pattern /^---\s*\n[\s\S]*?\n---\s*\n/ requires a newline after the closing ---, but valid YAML frontmatter can end with --- at the end of the file without a trailing newline. This could cause frontmatter to not be stripped in some cases. Consider making the trailing newline optional: /^---\s*\n[\s\S]*?\n---\s*\n?/

Suggested change
const frontmatterRegex = /^---\s*\n[\s\S]*?\n---\s*\n/;
const frontmatterRegex = /^---\s*\n[\s\S]*?\n---\s*\n?/;

Copilot uses AI. Check for mistakes.
Comment on lines 234 to 241
--text-direction: ltr;
}
/* RTL mode */
.dir-rtl {
--text-direction: rtl;
}
Copy link

Copilot AI Dec 12, 2025

Choose a reason for hiding this comment

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

The CSS variable --text-direction is defined but never used in the codebase. Since the direction service already applies the dir attribute to the document element (which provides native browser RTL support), this CSS variable appears to be unnecessary. Consider removing it unless there are plans to use it for custom direction-aware styling.

Suggested change
--text-direction: ltr;
}
/* RTL mode */
.dir-rtl {
--text-direction: rtl;
}
}
/* RTL mode */
.dir-rtl {
}

Copilot uses AI. Check for mistakes.
(value: string) => {
directionService.updateAutoDirection(value);
},
300,
Copy link

Copilot AI Dec 12, 2025

Choose a reason for hiding this comment

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

The debounce delay of 300ms for direction updates is shorter than the 500ms throttle delay for content emission. Since direction detection involves regex matching on content, consider using a delay equal to or longer than the throttledEmit delay (500ms) to reduce unnecessary processing, especially during rapid typing.

Suggested change
300,
500,

Copilot uses AI. Check for mistakes.
- Prevent race condition in direction auto-detection by only updating
  when the detected direction has actually changed
- Make trailing newline optional in frontmatter regex to handle files
  ending with frontmatter
- Remove unused --text-direction CSS variable (dir attribute suffices)
- Align direction detection debounce to 500ms to match content throttle
@djedi djedi merged commit 63e0faa into master Dec 12, 2025
1 check passed
@djedi djedi deleted the feature/rtl-support branch December 12, 2025 23:50
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