Repository navigation
fix(desktop): keep title bar path segments in order under the Bidi algorithm - #5317
Conversation
Jocs
left a comment
There was a problem hiding this comment.
Thanks for tracking this down, @dronov-dmitry. The reordering is real, but replacing direction: rtl with text-align: right introduces two layout regressions. I measured each variant in Chromium using the title bar's markup and CSS.
Regressions
- Long paths now hide the filename (GH#339 is back). When inline content overflows its line box, CSS aligns it to the start edge and it overflows at the end edge, whatever
text-alignis set to (CSS Text 3,text-align). With LTR, the end edge is on the right. The leading folders stay visible, while the filename and the unsaved dot are clipped (in my test the filename's right edge was 248px past the clip edge).direction: rtlwas there to put the overflow on the left. - Titles are no longer centered. The span used to inherit
text-align: centerfrom.title.text-align: rightoverrides that, so every title (including theMarkTextplaceholder) is pushed against the right padding. - The unsaved dot now touches the filename. Under RTL the dot was drawn to the left of the title, and
margin-right: .25remprovided the gap. In LTR it follows the filename, and the margin ends up on its far side.
Root cause
This isn't a DirectWrite/FreeType difference. It's the standard Unicode bidi algorithm, and Chrome on macOS renders report.md_003 too. In an RTL paragraph, the digits 003 only stay in place if a strong LTR character comes before them. Otherwise they resolve as RTL, _ stays at the paragraph level, and the runs swap.
It only shows up on Windows because the breadcrumb segments never render there. window.path.sep comes from pathe, which is always /, and titleBar/index.vue:217 splits the raw Windows pathname on it. C:\Users\me\Desktop\003_report.md produces no segments, so nothing precedes the digits. On Linux, e.g. Desktop › comes first and keeps them in order. That split is a separate bug and should be fixed on its own.
The PR also doesn't handle RTL folder names. With a Hebrew folder (Users › מסמכים › 003_report.md), this version still renders the segments out of order.
Suggested fix
Keep the RTL box for the left-side clipping, and isolate the LTR content inside it:
<span v-else>
<bdi dir="ltr">
<span v-for="(path, index) of paths" :key="index">…</span>
<span class="filename" …>{{ filename }}</span>
<span class="save-dot" :class="{ show: !isSaved }" />
</bdi>
</span>div.title > span {
/* Workaround for GH#339 */
display: block;
direction: rtl;
overflow: hidden;
text-overflow: clip;
white-space: nowrap;
}
div.title > span > bdi > span {
unicode-bidi: isolate;
}
.active .save-dot {
margin-left: 0.25rem; /* instead of margin-right */
}Measured in Chromium:
| Case | current develop |
this PR | suggested |
|---|---|---|---|
003_report.md, no breadcrumbs |
report.md_003 ❌ |
order OK, right-aligned ❌ | order OK, centered ✅ |
Users › me › Desktop › 003_report.md |
OK, centered | right-aligned ❌ | centered ✅ |
Hebrew folder + 003_report.md |
reordered ❌ | reordered ❌ | correct ✅ |
| long path overflow | clipped left, filename visible | filename clipped ❌ | clipped left, filename visible ✅ |
| unsaved dot on long path | clipped (drawn on the left) | clipped | visible ✅ |
Other notes
- Please drop
bag_windows_0.19.1.pngfrom the commit. It's a binary at the repo root (committed with mode 100755) that's only used by the PR description. A PR comment attachment works for that. - The new CSS comment describes the change ("replaced … with …") and gives the Windows explanation. Once the fix above is in, the original
/* Workaround for GH#339 */is enough.
2adbfb5 to
8c79b4c
Compare
…indows Wrap the title bar filename and breadcrumb spans inside a `<bdi dir=ltr>` element to isolate LTR content from the outer RTL container. This prevents the Unicode Bidi Algorithm from reordering characters in filenames (e.g. "003_report.md" was displayed as "report.md_003" on Windows where breadcrumb segments don't render). - Keep `direction: rtl` on the outer span for GH#339 left-side clipping - Add `unicode-bidi: isolate` on inner spans to prevent RTL inheritance - Move save-dot margin from right to left (correct positioning in LTR) Co-Authored-By: dronov-dmitry <dronov-dmitry@users.noreply.github.com>
The branch predates marktext#5318, whose lint-staged config still ran `prettier --write` over .ts/.vue on commit. The hook reflowed the whole template, burying a fifteen-line fix in sixty lines of churn and leaving this component as the only one not using one attribute per line. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Without a note, `unicode-bidi: isolate` reads as belt-and-braces next to the `<bdi>` and invites removal. It is load-bearing: drop it and a Hebrew or Arabic folder name pulls its separator across the segments beside it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8c79b4c to
5c667fa
Compare
|
Thanks @dronov-dmitry — this revision is the right fix, and I've verified it in the real app on macOS before merging. It isn't Windows-onlyWorth recording, because it changes how the bug should be described: Measured on macOS by launching the built app and sorting the title bar's characters by their rendered x position:
Row 2 is the interesting one: the filename contains no digits at all, yet the breadcrumbs still render backwards. Row 4 is the control — its first segment The parts of the fix I checked
Two commits pushed on top
Follow-up, not this PRWindows renders no breadcrumbs at all, which is why it always lacks a strong LTR character: |
…ath (#5467) (#5468) * fix(desktop): put the unsaved dot back on the left of the title bar path (#5467) `div.title > span` carries `direction: rtl` so that an over-long path clips from the left and leaves the filename readable (the GH#339 workaround). The save dot used to be the last child of that RTL block, and an empty atomic inline is a neutral: under an RTL base direction a trailing neutral resolves to the paragraph level, which laid the dot out at the visual left of the line. #5317 wrapped the breadcrumb in `<bdi dir="ltr">` to stop the Bidi algorithm reordering numeric path segments, and carried the dot into the isolate with it. Inside an LTR isolate the dot is simply the last item in logical order, so it moved to the right of the filename — a user-visible change that was never the point of that PR. Lay the title out with flexbox instead: the dot becomes a flex item preceding the breadcrumb, and the RTL clip context moves onto the `.path` box alone. The dot is back on the left, #5317's isolation is untouched, and because the dot now sits outside the clip box an over-long path can no longer swallow it — as it did before #5317. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test(desktop): pin the title bar dot position and breadcrumb order (#5467) Neither property had a guard: #5317 could move the dot without a test going red, and the Bidi ordering it fixed was never pinned either. Geometry is the only honest assertion here — the layout falls out of the Unicode Bidi Algorithm and of overflow clipping, neither of which jsdom computes — so these specs drive the real app under Playwright and compare boxes: the dot left of the first path segment, the dot still inside the clip box when a long path is truncated, and numeric segments in path order. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

Problem
When opening a file named
003_report.mdin MarkText on Windows x64, the filename in the window title bar was displayed asreport.md_003instead of003_report.md. Characters in the filename were reordered.Root cause
The CSS property
direction: rtlon the outer<span>container in the title bar activates the Unicode Bidi Algorithm. On Windows, breadcrumb segments never render (becausePATH_SEPARATORfrompatheis always/, so Windows paths likeC:\Users\me\Desktop\003_report.mddon't split). Without a preceding strong LTR character, the Bidi Algorithm reorders neutral characters — digits003resolve as RTL, and the runs swap.On Linux, breadcrumb segments (e.g.
Desktop ›) render first, providing a strong LTR context that keeps digits in order.Fix
Isolate LTR content inside the RTL container using
<bdi dir=ltr>:direction: rtlon the outer<span>for GH#339 left-side clipping (long paths are clipped from the left, filename stays visible)<bdi dir=ltr>to prevent the Bidi Algorithm from reordering charactersunicode-bidi: isolateon inner spans to prevent RTL context inheritancemargin-righttomargin-left(correct positioning in LTR context)Screenshot
Testing
pnpm run lintpnpm run typecheck003_report.mdRelated
direction: rtlwas originally added for GH#339 (clip long paths from the left)