Rouge

Статус сборки Версия Gem Документы YARD

Rouge - это чистый синтаксический текстовыделитель Ruby. Он может выделять более 200 различных языков, и выводить HTML или ANSI 256-цветный текст. Его HTML-вывод совместим с таблицами стилей, разработанными для Pygments.

Установка

Добавьте в свой Gemfile:

gem 'rouge'

или

gem install rouge

Использование

Наиболее часто Rouge используется как библиотека Ruby, как часть Jekyll и как инструмент командной строки.

Библиотека

Вот краткий пример использования Rouge, как и любой другой обычной библиотеки Ruby:

require 'rouge'

# make some nice lexed html
source = File.read('/etc/bashrc')
formatter = Rouge::Formatters::HTML.new
lexer = Rouge::Lexers::Shell.new
formatter.format(lexer.lex(source))

# Get some CSS
Rouge::Themes::Base16.mode(:light).render(scope: '.highlight')
# Or use Theme#find with string input
Rouge::Theme.find('base16.light').render(scope: '.highlight')

Jekyll

Rouge - это подсветка синтаксиса по умолчанию в Jekyll. Из коробки Rouge будет использоваться для выделения текста, обернутого в теги шаблона {% highlight %}. Тег {% highlight %} предоставляет минимальные опции: вы можете указать используемый язык и включить или не включить нумерацию строк. Более подробную информацию можно найти в документации Jekyll.

Командная строка

Rouge поставляется с командой rougify, которая позволяет вам легко выделять файлы в терминале:

rougify foo.rb
rougify style monokai.sublime > syntax.css

Конфигурация

Форматировщики

Rouge поставляется с несколькими встроенными форматерами, но начиная с Rouge 2.0, вам предлагается написать свой собственный форматер, если вам нужно что-то индивидуальное.

К встроенным форматерам относятся:

  • Rouge::Formatters::HTML.new будет отображать ваш код со стандартными именами классов для лексем, без div-обертывания и прочих прелестей.

  • Rouge::Formatters::HTMLInline.new(theme) отобразит ваш код без имен классов, но вместо этого встроит параметры стиля в атрибут style=. Это хорошо подходит для электронной почты и других систем, где поддержка CSS минимальна.

  • Rouge::Formatters::HTMLLinewise.new(formatter, class: 'line-%i') разделит ваш код на строки, каждая из которых содержится в собственном div. Опция class будет использоваться для добавления имени класса к div, учитывая номер строки.

  • Rouge::Formatters::HTMLLineHighlighter.new(formatter, highlight_lines: [3, 5]) разделит ваш код на строки и обернет строки, указанные опцией highlight_lines, в span с именем класса, указанным опцией highlight_line_class (по умолчанию: hll).

  • Rouge::Formatters::HTMLLineTable.new(formatter, opts={}) выводит HTML-таблицу, содержащую пронумерованные строки, каждая из которых находится в отдельной строке таблицы. Варианты:

    • start_line: 1 - номер первой строки
    • line_id: 'line-%i' - шаблон sprintf для атрибута id с текущим номером строки
    • line_class: 'lineno' - класс CSS для каждой строки таблицы
    • table_class: 'rouge-line-table' - CSS-класс для таблицы
    • gutter_class: 'rouge-gutter' - CSS-класс для ячейки с номером строки
    • code_class: 'rouge-code' - CSS-класс для ячейки кода
  • Rouge::Formatters::HTMLPygments.new(formatter, css_class='codehilite') оборачивает данный форматтер с обертками div, обычно ожидаемыми от таблиц стилей, разработанных для Pygments.

  • Rouge::Formatters::HTMLTable.new(formatter, opts={}) выводит HTML-таблицу, содержащую пронумерованные строки, подобно Rouge::Formatters::HTMLLineTable, за исключением того, что таблица, созданная с помощью этого форматтера, имеет только одну строку. Поэтому, хотя таблица более удобна в DOM для сценариев JavaScript, длинные строки кода будут нарушать выравнивание столбцов. Варианты:

    • start_line: 1 - номер первой строки
    • line_format: '%i' - шаблон sprintf для номера самой строки
    • table_class: 'rouge-table' - CSS-класс для таблицы
    • gutter_class: 'rouge-gutter' - CSS-класс для водостока
    • code_class: 'rouge-code' - класс CSS для колонки кода
  • Rouge::Formatters::HTMLLegacy.new(opts={}) - класс обратной совместимости, предназначенный для пользователей Rouge 1.x, с опциями, которые поддерживались тогда. Варианты:

    • inline_theme: nil - использовать HTMLInline форматер с заданной темой
    • line_numbers: false - использовать форматтер HTMLTable
    • wrap: true - использовать обертку HTMLPygments
    • css_class: 'codehilite' - CSS-класс для использования обертки Pygments
  • Rouge::Formatters::Terminal256.new(theme) - форматер для генерации выделенного текста для использования в терминале. theme должен быть экземпляром Rouge::Theme, или структурой Hash с входом :theme.

Написание собственного HTML-форматера

Если описанных выше форматеров недостаточно, и вы хотите настроить макет HTML-документа, мы предлагаем написать свой собственный HTML-форматер. Это можно сделать, создав подкласс Rouge::Formatters::HTML и переопределив определенные методы:

class MyFormatter < Rouge::Formatters::HTML

  # this is the main entry method. override this to customize the behavior of
  # the HTML blob as a whole. it should receive an Enumerable of (token, value)
  # pairs and yield out fragments of the resulting html string. see the docs
  # for the methods available on Token.
  def stream(tokens, &block)
    yield "<div class='my-outer-div'>"

    tokens.each do |token, value|
      # for every token in the output, we render a span
      yield span(token, value)
    end

    yield "</div>"
  end

  # or, if you need linewise processing, try:
  def stream(tokens, &block)
    token_lines(tokens).each do |line_tokens|
      yield "<div class='my-cool-line'>"
      line_tokens.each do |token, value|
        yield span(token, value)
      end
      yield "</div>"
    end
  end

  # Override this method to control how individual spans are rendered.
  # The value `safe_value` will already be HTML-escaped.
  def safe_span(token, safe_value)
    # in this case, "text" tokens don't get surrounded by a span
    if token == Token::Tokens::Text
      safe_value
    else
      "<span class=\"#{token.shortname}\">#{safe_value}</span>"
    end
  end
end

Параметры лексера

  • debug: false выводит трассировку лексера на stdout.

  • parent: '' позволяет указать, на каком языке написан шаблон.

Параметры CSS

  • scope: '.highlight' задает CSS-селектор, к которому применяются стили, например:

    Rouge::Themes::MonokaiSublime.render(scope: 'code')

Документация

Документация Rouge доступна по адресу rouge-ruby.github.io/docs/.

Требования

Ruby

Rouge совместим со всеми версиями Ruby, начиная с 2.0.0. У него нет внешних зависимостей.

Кодировки

Rouge поддерживает только строки в кодировке UTF-8. Если вы хотите выделить строку с другой кодировкой, пожалуйста, сначала преобразуйте ее в UTF-8.

Интеграции

Вклад

Мы всегда рады приветствовать новых участников проекта Rouge. По своей природе, синтаксический анализатор зависит от вклада пользователей языков, на которых он работает. Вы можете помочь Rouge, отправляя сообщения об ошибках или разрабатывая новые лексеры.

Сообщения об ошибках

Rouge использует GitHub's Issues для сообщения об ошибках. Вы можете выбрать один из наших шаблонов или создать собственный вопрос. Вопросы, которые не были активны в течение года, автоматически закрываются Probot на GitHub.

Разработка лексем

NOTE: Пожалуйста, не присылайте лексеры, скопированные из других файлов. Они будут отклонены, а мы не хотим, чтобы вы тратили свое время.

Мы хотим сделать так, чтобы каждый мог внести свой лексер в Rouge как можно проще. Чтобы помочь вам начать, у нас есть новое блестящее руководство по разработке лексера в документации. Лучше всего начать с него.

Если вы застряли и вам нужна помощь, отправьте запрос на pull request с тем, что у вас есть, и уточните в своём запросе, что лексер ещё не закончен. Мы постараемся ответить на любые ваши вопросы, и иногда лучший способ сделать это - реальный код.

Тестирование Rouge

После клонирования репозитория с GitHub вы можете протестировать ядро Rouge, просто запустив rake (не требуется bundle exec). Вы также можете запустить один файл теста, установив переменную окружения TEST на путь к нужному тесту. Например, для тестирования только ruby lexer (расположенного по пути spec/lexers/ruby_spec.rb) просто выполните следующее:

TEST=spec/lexers/ruby_spec.rb rake

Для визуального тестирования лексера запустите rackup из рабочего каталога верхнего уровня, и у вас должен быть запущен и готов к работе веб-сервер. Посетите http://localhost:9292, чтобы посмотреть полный список лексеров Rouge.

Выбрав определенный лексер, вы можете добавить ?debug=1 в строку URL, чтобы увидеть много полезной отладочной информации, выводимой на stdout.

Версионирование

Rouge использует Semantic Versioning 2.0.0.

Мейнтейнеры

Rouge в значительной степени является результатом тяжелой работы неоплачиваемых добровольцев. Он был первоначально разработан Жанин Адкиссон (@jneen) и в настоящее время поддерживается Жанин Адкиссон, Дрю Блессингом (@dblessing), Горо Фуджи (@gfx) и Тан Ле (@tancnle).

Лицензия

Rouge выпускается под лицензией MIT. Дополнительную информацию см. в файле LICENSE.