Git Product home page Git Product logo

dobidi / markdown-it-bidi Goto Github PK

View Code? Open in Web Editor NEW
9.0 2.0 1.0 171 KB

A plugin for adding bidi support to markdown-it project. This plugin can help JS projects to add support for mixed RTL and LTR markdown document to parse into better readable HTML files.

Home Page: https://www.npmjs.com/package/markdown-it-bidi

License: GNU Lesser General Public License v3.0

JavaScript 100.00%
markdown markdown-it markdown-it-plugin bidi bidirectional rtl

markdown-it-bidi's Introduction

Markdown-it-bidi

This is a plugin for Markdown-it to add bidi (bidirectinal text) support to its Markdown to HTML parser.

Usage

Install dependencies

npm i markdown-it
npm i markdown-it-bidi

Use the package to add bidi support. For example:

const markdownit = require('markdown-it')
const mdBidi = require('markdown-it-bidi')

const md = markdownit().use(mdBidi)

const inputText = `
# Heading 1
## Heading 2

Some text
in two lines!

- unordered list 1
    - unordered list 2

1. ordered list 1
    1. ordered list 2

> blockquote
`;

const result = md.render(inputText)
console.log(result)

Output:

<h1 dir="auto">Heading 1</h1>
<h2 dir="auto">Heading 2</h2>
<p dir="auto">Some text
in two lines!</p>
<ul dir="auto">
<li>unordered list 1
<ul dir="auto">
<li>unordered list 2</li>
</ul>
</li>
</ul>
<ol dir="auto">
<li>ordered list 1
<ol dir="auto">
<li>ordered list 2</li>
</ol>
</li>
</ol>
<blockquote dir="auto">
<p dir="auto">blockquote</p>
</blockquote>

License:

This plugin is released under LGPL v3 or later

markdown-it-bidi's People

Contributors

ahangarha avatar imrdjai avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

mtashackori

markdown-it-bidi's Issues

Handle JS version

  • Prepare development environment for writing code in ES6 and compile and bundle them in ES5.

Add linter

  • Add Eslint
  • Config git action to run linter on PR

Make sure we have enough feedback

We need to have this code run on at least 10 different real world projects and get feedback from them. This way we will make sure there is no issue of adding bidi support for real world use cases.

This is not only for this plugin but for our proposition to CommonMark.

Decide what to do with blockquotes

Blockquotes are exceptional, we need to define exactly how they should behave with bidirectional text.

Usually, developers add extra CSS to give blockquotes that border on the left, but when the text direction is right to left, the border should be on the right instead, and that looks problematic 🤔. Thankfully, we don't have to write a script that handles that for us 😌! There is a pure CSS solution that makes the border follow the direction of the first strong character: border-inline-start!

However, the current design of the plugin prevents border-inline-start from working as we give every block element the dir attribute. Keep in mind that the blockquote element isn't a direct parent to the text, instead, there is a paragraph element that contains the text inside, and as it also has dir="auto", the text is isolated from the blockquote causing the CSS trick to be unfunctional.

We have multiple options and we need to decide which one to choose (suggestions are welcome):

Markdown:

> عربية1 عربية2 English عربية3 عربية4
>
> > عربية1 عربية2 English عربية3 عربية4 
>
> > English1 English2 عربية English3 English4
>
> English1 English2 عربية English3 English4

Option 1: No dir="auto" for the first child of the blockquote element:

image

<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>

Option 2: No dir="auto" for every non-blockquote element (e.g. p, table...):

image

<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>English1 English2 عربية English3 English4</p>
</blockquote>

Option 3: No dir="auto" for every nested element (Gitlab Approach):

image

<blockquote dir="auto">
  <p>عربية1 عربية2 English عربية3 عربية4</p>
  <blockquote>
    <p>عربية1 عربية2 English عربية3 عربية4</p>
  </blockquote>
  <blockquote>
    <p>English1 English2 عربية English3 English4</p>
  </blockquote>
  <p>English1 English2 عربية English3 English4</p>
</blockquote>

Edit: Here is the CSS I used:

blockquote {
  border-inline-start: .25em solid #bbbbbb;
  padding: 0 .25em;
}

Edit 2: (Just for reference)

Option 4: No dir="auto" for blockquote elements (Github Approach):

This approach has one bug: The blockquote element itself doesn't get any direction based on its content. there is one workaround which is to give the style to child elements of a blockquote which results in horrible outcomes with lists and tables.

Bidi support for lists

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:

image

<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:

image

<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

image

<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:

image

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

I see no other solutions for lists, we should go ahead and implement this one.

List of mixed RTL/LTR markdown documents for test

Please share the link to any markdown documents which contain both RTL and LTR text. This way we can make sure we have tested this plugin with more and more real case scenarios.

اگر پرونده مارک‌داونی را می‌شناسید که حاوی متن راست به چپ و چپ به راست است، لطفا نشانی‌اش را در این‌جا با ما هم‌رسانی کنید تا بتوانیم اطمینان حاصل کنیم که افزونهٔ ما حالت‌های مختلفی از موارد استفاده در دنیای واقی را به درستی و مطابق انتظار تجزیه می‌کند.

Add test

  • Make test to make sure we are getting expected result after each change.
  • Add npm script for test
  • Add test to github workflow to check the test on PR

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.