marked-ts — markdown перекладач, написаний на TypeScript

Стара добра JavaScript-бібліотека marked, призначена для перекладу markdown-текста у HTML-код, є і сьогодні кращою по швидкості, коли треба перекладати об’єм тексту до 2 МБ. На сьогоднішній день, з npmjs.com її скачують біля 3 млн. разів за місяць, вона має більше 15 тис. зірочок на github.com.

Проблема в тому, що її автор не веде активну розробку вже біля трьох років. Контрибутори теж не відзначались активністю за цей період...

Особисто я її використовував для рендерингу веб-сторінок на льоту. Мені необхідно ще було додати можливість створювати кастомні правила перекладу, щоб можна було вставляти, наприклад, відео з youtube, математичні формули і т.д.

Сьогодні представляю вам marked-ts — бібліотеку, яка вміє це робити.

npm install marked-ts --save

Для прикладу, я взяв KaTeX — JavaScript-бібліотеку для рендерінгу математичних формул.

npm install katex @types/katex --save

Отже, якщо вам не потрібні складні правила для перекладу з використанням рекурсивності, або перевіряти певні умови перед виконанням регулярних виразів, ви можете використовувати метод Marked.setBlockRule( regexp[, callback] ), що приймає в якості першого аргументу регулярний вираз, і повертає результат regexp.exec(string) в callback(execArr).

Дуже важливо щоб кожен регулярний вираз починався із символу ^.

import { Marked, escape } from 'marked-ts';
import * as katex from 'katex';


Marked.setBlockRule(/^@@@ *(\w+)\n([\s\S]+?)\[email protected]@@/, function (execArr) {

  // Don't use arrow function for this callback
  // if you need Renderer's context, for example to `this.options`.

  const channel = execArr[1];
  const content = execArr[2];

  switch(channel)
  {
    case 'youtube':
    {
      const id = escape(content);
      return `\n<iframe width="420" height="315" src="https://www.youtube.com/embed/${id}"></iframe>\n`;
    }
    case 'katex':
    {
      return katex.renderToString(escape(content));
    }
  }
});

const blockStr = `
# Example usage with embed block code

@@@ katex
c = \\pm\\sqrt{a^2 + b^2}
@@@

@@@ youtube
JgwnkM5WwWE
@@@
`;

const html = Marked.parse(blockStr);

console.log(html);

Коли я переписав цю бібліотеку, швидкість її роботи збільшилась, а споживання пам’яті зменшилось.

Бенчмарки самих популярних JavaScript markdown-перекладачів, коли вони працюють з об’ємом тексту 300 КБ:

| Lib                     | Load lib, ms | Init lib, ms | Bench work, ms | Total, ms | Memory usage, KB
| ------------------------|--------------|--------------|----------------|-----------|------------------
| marked-ts v1.0.0-beta.1 | 6            | 6            | 101            | 113       | 8 641
| marked v0.3.12          | 4            | 2            | 106            | 112       | 9 323
| remarkable v1.7.1       | 36           | 6            | 174            | 216       | 15 356
| markdown-it v8.4.0      | 29           | 10           | 227            | 266       | 18 890
| showdown v1.8.6         | 10           | 14           | 353            | 377       | 36 833
| markdown v0.5.0         | 4            | 3            | 314            | 321       | 22 664
| remark v8.0.0           | 64           | 11           | 1238           | 1313      | 71 089
👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Три зірки на github менше, ніж за тиждень — непогано =).

регулярками парсить md это ужас. почему не работать с AST?

Але, як бачите по бенчмарках — не все так погано з регулярками, особливо при об’ємі файлу до 2 МБ.

почему не работать с AST?

Що таке AST? Віка підказує мені один із варіантів Abstract syntax tree. Ви про це?

Тот же механизм как у babel- парсинг, постройка дерева, преобразование дерева, рендеринг в строку, что максимально гибко, но производительность на простых будет совсем не та.

Додав я remark до бенчмарків, можете глянути результат (самий нижній).

Підписатись на коментарі