imrdjai / bidimarkdown-spec Goto Github PK
View Code? Open in Web Editor NEWPre-defined specification for bidirectional text support in Markdown.
Pre-defined specification for bidirectional text support in Markdown.
Introduction: Bidirectional content is content that has characters in mixed directions, both LTR and RTL. Supporting bidirectional content is:
Problem: The problem with bidirectional content is that it appears broken in most implementations. For example, in the case of RTL text, the order of words would completely flip by just inserting a single LTR character within. Here is a demonstration (from google.com):
Right to left text:
Mixed text (broken):
Mixed text (Corrected):
Solution: After deep research we have concluded a general rule for supporting bidirectional content that works with (almost) every case:
dir="auto"
attribute to HTML container block elements:
By container block elements we mean HTML elements that are considered block-level (starting on a new line and taking 100% of the available width) and may contain any other content such as text or other elements. For example <p>, <table> and <video> are container block elements. However, <hr> or inline elements like <a> are not.
Adding dir="auto"
will ensure that any contained bidirectional text is rendered in the correct order by applying the correct Unicode Bidirectional Algorithm with CSS.
Example:
Markdown:
# Heading
---
**Paragraph**
HTML:
<h1 dir="auto">Heading</h1>
<hr>
<p dir="auto">
<strong>Paragraph</strong>
</p>
dir="auto"
attribute:
If we have a linked list of HTML container block elements starting at root, where each node is the direct first child of the previous one, we must only give dir="auto"
to the root node. Otherwise, the root node will be isolated from text that determines its direction. By root nodes we mean nodes with a depth of 0, or non-first child nodes.
Example:
Markdown:
> > > Quoted paragraph
>
> > فقرة مقتبسة
HTML:
<blockquote dir="auto">
<blockquote>
<blockquote>
<p>Quoted paragraph</p>
</blockquote>
</blockquote>
<blockquote dir="auto">
<p>فقرة مقتبسة</p>
</blockquote>
</blockquote>
We must not add dir="auto"
to an element if that would cause the layout to break, or UI/UX issues. For example, list items are exempt from having the attribute due to an issue with list markers. Each exception of this sort is documented separately.
Example:
Markdown:
- test
- تجربة
HTML:
<ul dir="auto">
<li>test</li>
<li>تجربة</li>
</ul>
Currently, most (if not all) Markdown standards accept only - [x]
as a checked item in a checklist. The issue is that x
is a strong character, enforcing LTR direction for the given line.
I would propose - [+]
to be accepted along with the current syntax.
As shown in the following screenshot, it becomes easy to render RTL items with a checkbox in textarea (in plain text format)
Lists (<ol>, <ul>) are container block elements, they contain list items (<li>). List items contain text. However, they are also container block elements that may contain other block elements such as nested lists.
Lists should always take a single direction, which means if the direction of the first list item is right to left, the other list items should all have a right to left direction (and the opposite is true). Otherwise, they will look ugly, messy, and will be hard to read.
Adding dir="auto"
to all block elements doesn't work well with lists. See this example:
Markdown:
RTL:
- تجربة
- test
1. تجربة
2. test
LTR:
- test
- تجربة
1. test
2. تجربة
Result:
<p dir="auto">RTL:</p>
<ul dir="auto">
<li dir="auto">تجربة</li>
<li dir="auto">test</li>
</ul>
<ol dir="auto">
<li dir="auto">تجربة</li>
<li dir="auto">test</li>
</ol>
<p dir="auto">LTR:</p>
<ul dir="auto">
<li dir="auto">test</li>
<li dir="auto">تجربة</li>
</ul>
<ol dir="auto">
<li dir="auto">test</li>
<li dir="auto">تجربة</li>
</ol>
Notice how the list markers are completely broken. To fix that, we should remove the dir
attribute from list items:
<p dir="auto">RTL:</p>
<ul dir="auto">
<li>تجربة</li>
<li>test</li>
</ul>
<ol dir="auto">
<li>تجربة</li>
<li>test</li>
</ol>
<p dir="auto">LTR:</p>
<ul dir="auto">
<li>test</li>
<li>تجربة</li>
</ul>
<ol dir="auto">
<li>test</li>
<li>تجربة</li>
</ol>
Another issue with nested lists:
Markdown:
RTL:
- تجربة
- - test
- - - test
- - - تجربة
LTR:
- test
- - تجربة
- - - تجربة
- - - test
<p dir="auto">RTL:</p>
<ul dir="auto">
<li>تجربة</li>
<li>
<ul dir="auto">
<li>test</li>
</ul>
</li>
<li>
<ul dir="auto">
<li>
<ul dir="auto">
<li>test</li>
</ul>
</li>
</ul>
</li>
<li>
<ul dir="auto">
<li>
<ul dir="auto">
<li>تجربة</li>
</ul>
</li>
</ul>
</li>
</ul>
<p dir="auto">LTR:</p>
<ul dir="auto">
<li>test</li>
<li>
<ul dir="auto">
<li>تجربة</li>
</ul>
</li>
<li>
<ul dir="auto">
<li>
<ul dir="auto">
<li>تجربة</li>
</ul>
</li>
</ul>
</li>
<li>
<ul dir="auto">
<li>
<ul dir="auto">
<li>test</li>
</ul>
</li>
</ul>
</li>
</ul>
Some list markers are aligned on the opposite side. This is a total mess! We can fix that by removing the dir
attribute from nested lists:
<p dir="auto">RTL:</p>
<ul dir="auto">
<li>تجربة</li>
<li>
<ul>
<li>test</li>
</ul>
</li>
<li>
<ul>
<li>
<ul>
<li>test</li>
</ul>
</li>
</ul>
</li>
<li>
<ul>
<li>
<ul>
<li>تجربة</li>
</ul>
</li>
</ul>
</li>
</ul>
<p dir="auto">LTR:</p>
<ul dir="auto">
<li>test</li>
<li>
<ul>
<li>تجربة</li>
</ul>
</li>
<li>
<ul>
<li>
<ul>
<li>تجربة</li>
</ul>
</li>
</ul>
</li>
<li>
<ul>
<li>
<ul>
<li>test</li>
</ul>
</li>
</ul>
</li>
</ul>
Conclusion: We should not give dir="auto"
to any child block-elements of lists. Only top-level lists should have the dir
attribute set to auto
.
Supporting bidi in tables is:
And to accomplish that we need to:
dir="auto"
to <table>
(point 2).dir="auto"
to each table cell (<th>
, <td>
), excluding the first <th>
, which its direction should not be isolated from <table>
(point 1).display: block;
to <table>
with CSS, since elements with display: table;
won't be aligned to the right when having RTL direction (point 3).Before (table aligned to the left, order of words is broken):
After (table mirrored, aligned to the right, since the first word is RTL, order of words is correct):
Markdown:
| عربية1 Eng عربية2 | Eng1 عربية Eng2 |
|--|--|
| Eng1 عربية Eng2 | عربية1 Eng عربية2 |
HTML:
<table dir="auto">
<thead>
<tr>
<th>عربية1 Eng عربية2</th>
<th dir="auto">Eng1 عربية Eng2</th>
</tr>
</thead>
<tbody>
<tr>
<td dir="auto">Eng1 عربية Eng2</td>
<td dir="auto">عربية1 Eng عربية2</td>
</tr>
</tbody>
</table>
Interesting that the text alignment in cells can be explicitly set by adding colons (:
) to delimiter rows, which provides more flexibility.
Blockquotes are exceptional, we need to precisely define how they should behave with bidirectional text.
Usually, developers add some CSS to give blockquotes that border on the left. However, in the case of right to left text, the border should be on the right instead, following the beginning of the sentence. There is a pure CSS solution that makes the border follow direction of elements: border-inline-start
!
Blockquote elements aren't direct parents to the text inside. Instead, there are nested paragraph elements that contain the text:
Markdown:
> text
HTML:
<blockquote>
<p>text</p>
</blockquote>
Giving the dir="auto"
attribute to both <blockquote>
and <p>
elements prevents the border-inline-start
trick from working because it will apply the unicode-bidi: isolate;
CSS rule to <p>
elements, which will essentially isolate the text direction from the <blockquote>
elements that rely on the direction of the first strong character to determine their own direction.
Also, the goal is when you quote existing bidirectional content, the directions should remain the same. In other words, appearance of text within a blockquote should be as close as possible to the same text unquoted. Thus, blockquote elements may have nested blockquotes or paragraphs or any other block elements taking their opposite direction.
Solution: Add dir="auto"
to all block elements except first child of another block element!
Markdown:
> عربية1 عربية2 English عربية3 عربية4
>
> > عربية1 عربية2 English عربية3 عربية4
>
> > English1 English2 عربية English3 English4
>
> English1 English2 عربية English3 English4
HTML:
<blockquote dir="auto">
<p>عربية1 عربية2 English عربية3 عربية4</p>
<blockquote dir="auto">
<p>عربية1 عربية2 English عربية3 عربية4</p>
</blockquote>
<blockquote dir="auto">
<p>English1 English2 عربية English3 English4</p>
</blockquote>
<p dir="auto">English1 English2 عربية English3 English4</p>
</blockquote>
Code blocks are consisted of block <pre>
elements wrapping inline <code>
elements. <pre>
elements provide a way to embed raw text content while preserving all white-space characters (eg. space, new line).
Bidi support for code blocks is straight forward, adding dir="auto"
to <pre>
elements will do the trick:
Markdown:
```
عربية1 عربية2 English عربية3 عربية4
English1 English2 عربية English3 English4
عربية1 عربية2 English عربية3 عربية4
English1 English2 عربية English3 English4
```
HTML:
<pre dir="auto"><code>عربية1 عربية2 English عربية3 عربية4
English1 English2 عربية English3 English4
عربية1 عربية2 English عربية3 عربية4
English1 English2 عربية English3 English4
</code></pre>
Some implementations might choose to force text alignment to the left with CSS:
While it's not mandatory, it's better to avoid this and keep the alignment automatic.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.