Я разрабатываю редактор Markdown под названием Inkdrop, который обеспечивает красивую подсветку синтаксиса в блоках кода. Чтобы реализовать эту функцию, я проверил множество выделителей синтаксиса, но в итоге сделал еще один. Он отлично работает с React и не требует dangerouslySetInnerHTML. Он поддерживает множество языков из коробки. Я хотел бы представить его, потому что это был бы небольшой совет для тех, у кого со мной схожие требования.

Две проблемы с CodeMirror и highlight.js

Редактор Markdown Inkdrop основан на CodeMirror, который представляет собой универсальный компонент текстового редактора, созданный для браузеров. Он предоставляет встроенную подсветку синтаксиса, поэтому пользователи могут редактировать текст в красивом интерфейсе. С другой стороны, Inkdrop использовал highlight.js для панели предварительного просмотра Markdown. Эта композиция отлично сработала, но с двумя проблемами.

Первая причина в том, что highlight.js не поддерживает некоторые языки, которые поддерживает CodeMirror (и наоборот). Иногда пользователей смущала эта разница между редактором и предварительным просмотром, и они думали: «Почему он не отображает Markdown одинаково?»

Во-вторых, для highlight.js и других подобных библиотек требуется функция рендеринга с использованием dangerouslySetInnerHTML в React или просто ручное изменение DOM с помощью собственного javascript. Это не так эффективно, потому что при каждом изменении текста требуется полностью перестраивать DOM. Эту проблему можно решить с помощью lowlight - фантастической работы, проделанной Titus, который выводит виртуальные модели DOM и совместим с highlight.js. Это сработало отлично, но первая проблема все еще существовала.

Поэтому я решил сделать такое решение, как тусклый свет, но совместимое с CodeMirror.

CodeMirror как средство выделения синтаксиса

Я заметил, что CodeMirror предоставляет средство запуска режима, которое позволяет запускать его как средство выделения синтаксиса. Вы можете посмотреть демо здесь. CodeMirror.runMode - это функция, которая принимает следующие аргументы:

  • text (строка): документ, который нужно просмотреть с помощью маркера.
  • mode (спецификация режима): используемый режим. например, javascript
  • output (функция или узел DOM): если это функция, она будет вызываться для каждого токена с двумя аргументами: текстом токена и классом стиля токена (может быть null для токенов без стиля). Если это узел DOM, токены будут преобразованы в span элементы, как в редакторе, и вставлены в узел (через innerHTML).

Третий аргумент принимает функцию, которая позволяет создавать виртуальные модели DOM из текста! Это хорошие новости. Вы можете создать компонент React, используя runMode следующим образом:

Затем вы можете использовать его следующим образом:

Это прекрасно работает. Я сделал простую библиотеку с некоторыми функциями, которые сделали бы ее более удобной для использования в ваших приложениях React, например theme prop. Эта библиотека сейчас используется в Inkdrop: D

Надеюсь, эта статья будет вам полезна!

  • Craftzdog / react-codemirror-runmode - выделение синтаксиса для реакции с использованием парсера CodeMirror.
  • Lowlight - Виртуальная подсветка синтаксиса для виртуальных DOM и не-HTML вещей.