Skip to content

feat(editor): add optional auto text direction per block - #17931

Open
Nishef1 wants to merge 1 commit into
siyuan-note:devfrom
Nishef1:feat/auto-text-direction-per-block
Open

feat(editor): add optional auto text direction per block#17931
Nishef1 wants to merge 1 commit into
siyuan-note:devfrom
Nishef1:feat/auto-text-direction-per-block

Conversation

@Nishef1

@Nishef1 Nishef1 commented Jun 24, 2026

Copy link
Copy Markdown

New edit:

Summary

Adds an optional automatic per-block text-direction mode for mixed RTL/LTR writing in the Protyle editor.

Automatic direction is applied at runtime only. It does not write detected dir, inline styles, or custom direction markers into block data, so enabling the feature does not persist automatically detected direction into .sy documents or affect undo/redo history.

Behavior

  • Adds editor.autoTextDirection, disabled by default.
  • Detects direction for paragraph, heading, and list-item blocks.
  • Counts Unicode letters rather than ASCII-only characters, supporting RTL scripts while correctly handling Latin, Cyrillic, Greek, CJK, and other non-RTL scripts.
  • Ignores numbers, punctuation, symbols, and combining marks when determining base direction.
  • Uses balanced detection with a minimum of 2 RTL letters and an RTL ratio threshold of 0.35.
  • Keeps inline code, kbd, samp, and inline math LTR-isolated inside automatically RTL content.
  • Keeps text alignment independent from text direction.
  • Uses a Protyle-scoped MutationObserver with requestAnimationFrame batching.
  • Cleans up the observer and generated runtime styles when the Protyle instance is destroyed.
  • Global RTL and automatic direction are mutually exclusive; explicit/manual direction takes precedence.

Implementation

  • kernel/conf/editor.go — persists the AutoTextDirection preference.
  • app/src/types/autoTextDirection.d.ts — extends Config.IEditor.
  • app/src/protyle/util/autoDirection.ts — Unicode-aware classifier and scoped runtime.
  • app/src/protyle/util/autoDirection.test.ts — classifier tests covering RTL/LTR scripts, mixed content, numbers, and balanced detection thresholds.
  • app/src/config/tabs/autoDirectionSetting.ts — registers the Appearance setting and RTL mutual-exclusion behavior.
  • app/src/protyle/util/reload.ts — synchronizes the runtime across editor reloads, including preview mode.
  • app/src/protyle/util/destroy.ts — disposes the automatic-direction runtime.

No new locale keys are introduced in this version.

Validation

  • 20/20 targeted classifier cases passed.
  • autoDirection.ts passed an isolated TypeScript 5.8 + DOM type-check.
  • pnpm build was not run, following the repository's AGENTS.md guidance.

Copilot AI 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.

Pull request overview

Adds an optional per-block auto text-direction mode to the Protyle editor to better support mixed RTL/LTR writing, including a new config flag, runtime application hooks (render/paste/input), and UI + i18n wiring.

Changes:

  • Added autoTextDirection to kernel editor config and frontend Config.IEditor typing.
  • Introduced app/src/protyle/util/autoDirection.ts and invoked auto-direction application during document render, paste, and input.
  • Added a settings switch (mutually exclusive with global RTL) and updated gutter/shortcuts to mark manual direction overrides; added new i18n keys across locales.

Reviewed changes

Copilot reviewed 30 out of 31 changed files in this pull request and generated 20 comments.

Show a summary per file
File Description
kernel/conf/editor.go Adds AutoTextDirection config flag with default false.
app/src/types/config.d.ts Extends Config.IEditor with autoTextDirection.
app/src/protyle/util/autoDirection.ts New detection + apply/clear logic for per-block direction.
app/src/config/tabs/appearanceTab.ts Adds settings toggle and RTL mutual-exclusion behavior.
app/src/config/tabs/editorRuntime.ts Clears auto markers when disabling auto direction.
app/src/protyle/util/onGet.ts Applies auto direction on document render when enabled.
app/src/protyle/util/paste.ts Applies auto direction after paste rendering.
app/src/protyle/wysiwyg/input.ts Applies auto direction after input updates.
app/src/protyle/gutter/index.ts Marks manual overrides and re-applies auto direction after clearing styles.
app/src/protyle/wysiwyg/keydown.ts Marks manual overrides for RTL/LTR shortcuts.
app/appearance/langs/zh-TW.json Adds autoTextDirection i18n keys (needs Traditional Chinese wording fixes).
app/appearance/langs/zh-CN.json Adds autoTextDirection i18n keys.
app/appearance/langs/en.json Adds autoTextDirection i18n keys.
app/appearance/langs/uk.json Adds autoTextDirection i18n keys (currently English text).
app/appearance/langs/tr.json Adds autoTextDirection i18n keys (currently English text).
app/appearance/langs/th.json Adds autoTextDirection i18n keys (currently English text).
app/appearance/langs/sk.json Adds autoTextDirection i18n keys (currently English text).
app/appearance/langs/ru.json Adds autoTextDirection i18n keys (currently English text).
app/appearance/langs/pt-BR.json Adds autoTextDirection i18n keys (currently English text).
app/appearance/langs/pl.json Adds autoTextDirection i18n keys (currently English text).
app/appearance/langs/nl.json Adds autoTextDirection i18n keys (currently English text).
app/appearance/langs/ko.json Adds autoTextDirection i18n keys (currently English text).
app/appearance/langs/ja.json Adds autoTextDirection i18n keys (currently English text).
app/appearance/langs/it.json Adds autoTextDirection i18n keys (currently English text).
app/appearance/langs/id.json Adds autoTextDirection i18n keys (currently English text).
app/appearance/langs/hi.json Adds autoTextDirection i18n keys (currently English text).
app/appearance/langs/he.json Adds autoTextDirection i18n keys (currently English text).
app/appearance/langs/fr.json Adds autoTextDirection i18n keys (currently English text).
app/appearance/langs/es.json Adds autoTextDirection i18n keys (currently English text).
app/appearance/langs/de.json Adds autoTextDirection i18n keys (currently English text).
app/appearance/langs/ar.json Adds autoTextDirection i18n keys (currently English text).

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

Comment thread app/src/protyle/util/autoDirection.ts Outdated
Comment on lines +1 to +2
const RTL_RE = /[\u0590-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]/u;
const LTR_RE = /[A-Za-z]/u;
Comment thread app/appearance/langs/zh-TW.json Outdated
Comment on lines +929 to +930
"autoTextDirection": "自动检测每个块的文字方向",
"autoTextDirectionTip": "根据首个强字符自动为每个文本块应用 RTL 或 LTR 方向。手动设置的块方向会覆盖此设置。",
Comment thread app/appearance/langs/uk.json Outdated
Comment on lines +929 to +930
"autoTextDirection": "Auto-detect text direction per block",
"autoTextDirectionTip": "Automatically applies RTL or LTR direction to each text block based on its first strong character. Manual block direction overrides this setting.",
Comment thread app/appearance/langs/tr.json Outdated
Comment on lines +929 to +930
"autoTextDirection": "Auto-detect text direction per block",
"autoTextDirectionTip": "Automatically applies RTL or LTR direction to each text block based on its first strong character. Manual block direction overrides this setting.",
Comment thread app/appearance/langs/th.json Outdated
Comment on lines +929 to +930
"autoTextDirection": "Auto-detect text direction per block",
"autoTextDirectionTip": "Automatically applies RTL or LTR direction to each text block based on its first strong character. Manual block direction overrides this setting.",
Comment thread app/appearance/langs/he.json Outdated
Comment on lines +929 to +930
"autoTextDirection": "Auto-detect text direction per block",
"autoTextDirectionTip": "Automatically applies RTL or LTR direction to each text block based on its first strong character. Manual block direction overrides this setting.",
Comment thread app/appearance/langs/fr.json Outdated
Comment on lines +929 to +930
"autoTextDirection": "Auto-detect text direction per block",
"autoTextDirectionTip": "Automatically applies RTL or LTR direction to each text block based on its first strong character. Manual block direction overrides this setting.",
Comment thread app/appearance/langs/es.json Outdated
Comment on lines +929 to +930
"autoTextDirection": "Auto-detect text direction per block",
"autoTextDirectionTip": "Automatically applies RTL or LTR direction to each text block based on its first strong character. Manual block direction overrides this setting.",
Comment thread app/appearance/langs/de.json Outdated
Comment on lines +929 to +930
"autoTextDirection": "Auto-detect text direction per block",
"autoTextDirectionTip": "Automatically applies RTL or LTR direction to each text block based on its first strong character. Manual block direction overrides this setting.",
Comment thread app/appearance/langs/ar.json Outdated
Comment on lines +929 to +930
"autoTextDirection": "Auto-detect text direction per block",
"autoTextDirectionTip": "Automatically applies RTL or LTR direction to each text block based on its first strong character. Manual block direction overrides this setting.",
@Nishef1 Nishef1 closed this Jul 21, 2026
@Nishef1
Nishef1 force-pushed the feat/auto-text-direction-per-block branch from c3b4a0e to eef1056 Compare July 21, 2026 06:48
@Nishef1 Nishef1 reopened this Jul 21, 2026
@88250

88250 commented Aug 9, 2026

Copy link
Copy Markdown
Member

Thanks for the implementation. I found two issues that should be addressed before merging:

  1. syncAutoDirectionRuntime() is called only by reloadProtyle(). Newly created editors load through getDoc() / onGet() without calling it. Therefore, the feature works for editors open when the setting is toggled, but not for editors opened afterward or after restarting SiYuan. Please initialize the runtime for every new Protyle and add a regression test.

  2. The setting exists under Settings - Appearance - Content, but its label only combines A↔א with the existing LTR / RTL strings. It does not explain automatic per-block detection. Please add dedicated, properly translated title and description keys to every language file, then run python scripts/check-lang-keys.py.

The existing tests, type check, ESLint checks, Go formatting, and git diff --check pass locally.

@Nishef1
Nishef1 force-pushed the feat/auto-text-direction-per-block branch from 4714d54 to f9d6f06 Compare August 9, 2026 07:27
@Nishef1

Nishef1 commented Aug 9, 2026

Copy link
Copy Markdown
Author

Thanks for the review. Both issues have been addressed:

  • Auto-direction is now initialized for every new Protyle via onGet(), with a regression test.
  • Dedicated title/description keys were added and properly translated for all language files.

I also rebased the PR onto the current dev. Tests, lint/typecheck, check-lang-keys.py, gofmt, and git diff --check all pass.

Please take another look when you have a chance. Thanks!

@88250

88250 commented Aug 9, 2026

Copy link
Copy Markdown
Member

Thanks, I rechecked the latest commit. The localization issue is resolved, and initialization now works for normal documents loaded through onGet().

However, it still does not cover every new Protyle. When options.backlinkData is provided, the constructor calls renderBacklink() and returns without going through onGet(), so a backlink editor created after startup still does not start the runtime.

Please initialize the runtime from a common construction path after protyle.wysiwyg is available, or explicitly cover the backlink rendering path. The current regression test only checks the source text of onGet.ts, so it does not cover this case.

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.

3 participants