Статьи

Обработка уценки в Ruby

Markdown знак

Markdown — это фантастический язык разметки, который компилируется в HTML. Хотя его первоначальная реализация была написана на Perl, Markdown был портирован на несколько языков с различными функциями. Мы собираемся сосредоточиться на 4 реализациях Markdown в Ruby: kramdown , maruku , rdiscount и redcarpet .

Обработка уценки в Ruby

Очевидно, что сначала мы должны установить эти драгоценные камни, поэтому gem install kramdown maruku rdiscount redcarpet . Это может занять немного времени, потому что и RDiscount, и Redcarpet используют расширения C для более быстрой скорости обработки.
Это также означает, что если ваш интерпретатор Ruby не поддерживает расширения C, вы не сможете использовать RDiscount или Redcarpet. Я смотрю на тебя, JRuby.

Для наших нужд обработки мы будем использовать страницу синтаксиса Markdown от Markdown от John Gruber, сохраненную в markup.md .

В каждой реализации мы можем обрабатывать этот файл Markdown в одной строке кода.

 markdown = File.read('markup.md') # kramdown require 'kramdown' Kramdown::Document.new(markdown).to_html # maruku require 'maruku' Maruku.new(markdown).to_html # rdiscount require 'rdiscount' RDiscount.new(markdown).to_html # redcarpet require 'redcarpet' Redcarpet::Markdown.new(Redcarpet::Render::HTML.new).render(markdown) 

Сладкий! Мы видим, что каждый фреймворк (за исключением Redcarpet) имеет простой API для обработки Markdown.

Характеристики

Первоначальная реализация Markdown была великолепна в свое время, но люди решили, что хотят большего. Например, оригинальная реализация Markdown включает в себя поддержку изображений и кодовых блоков, но многие пользователи хотели использовать другой синтаксис и / или лучшую расширяемость этих функций. Таким образом, возможности различных реализаций Markdown сильно различаются.

Давайте рассмотрим несколько популярных дополнений и их поддержку в наших реализациях Ruby.

Кодовые блоки

Синтаксис блока кода Markdown изначально включал использование отступа кода следующим образом:

 if foo == bar "Markdown is awesome." end 

Улучшенный синтаксис называется блоками изолированного кода . Это написано так:

 ```ruby if foo == bar "Markdown is awesome." end ``` 

Обратите внимание на спецификацию Ruby как языка в конце первого набора «заборов». Это необязательно, но позволяет реализации Markdown делать подсветку синтаксиса для конкретного языка.

Зачеркнутый

Зачеркнутый — это добавленная функция в Markdown. Это написано, оборачивая слово (или слова) в тильды следующим образом:

 ~~Something outdated~~ 

таблицы

Таблицы являются дополнительной функцией в Markdown. Они созданы аналогично тому, как они выглядят в HTML.

 | Header 1 | Header 2 | Header 3 | |----------|----------|----------| | Foo | Bar | Baz | 

Это выводит таблицу HTML, которая выглядит очень похожей. Хотя этот синтаксис удобен для простых таблиц, я нахожу его неудобным при редактировании таблиц, поскольку трудно поддерживать равномерную ширину ячейки в простом тексте. Тем не менее, это не имеет значения, потому что следующее также будет отображать то же, что и выше (это просто делает ваш Markdown более уродливым):

 | Header 1 | Header 2|Header 3 | |-------|----|----------| |Foo|Bar|Baz| 

ID заголовка

Эта функция позволяет использовать привязки HTML ( например, http://something.com/document.html#id-ref ) в сгенерированных документах Markdown. Это делается автоматически в заголовках и подзаголовках. Каждая реализация Markdown генерирует их по-своему, поэтому лучше проверить документацию по этому вопросу.

Типографская замена (стиль «SmartyPants»)

Оказывается, пользователям Markdown также нравится еще один проект Daring Fireball под названием SmartyPants. Эта программа заменяет обычную ASCII-пунктуацию на «умный» типографский HTML-вывод. Например:

 "Ruby", the programming language. Becomes:Ruby, the programming language. 

Также выполняются другие типографские замены, такие как --- to — (em-dash) и-to — (en-dash).

Сравнение

Давайте посмотрим на поддержку этих функций в наших реализациях Ruby Markdown.

Огороженный код Зачеркнутый таблицы ID заголовка Типографская замена
Kramdown да нет да да да
Maruku да нет да да да
Красный ковер да да да да да
RDiscount да да да нет да

Из этих данных довольно очевидно, что Redcarpet — это путь. Redcarpet не только расширяем, но и удивительно быстр (мы займемся этим дальше).

Ориентиры

Я решил проверить скорость каждого процессора Markdown, сравнив скорость обработки этого файла . Оказывается, что сделать это на удивление легко в Ruby с помощью модуля Benchmark . Вот как я это настроил:

 require 'benchmark' markdown = File.read('TestDoc.md') Benchmark.bm(15) do |x| x.report('Kramdown') { require 'kramdown' Kramdown::Document.new(markdown.dup).to_html } x.report('Maruku') { require 'maruku' Maruku.new(markdown.dup).to_html } x.report('RDiscount') { require 'rdiscount' RDiscount.new(markdown.dup).to_html } x.report('RedCarpet') { require 'redcarpet' Redcarpet::Markdown.new(Redcarpet::Render::HTML.new).render(markdown.dup) } end 

Из-за различий во времени выполнения я выполнил этот тест 5 раз (в конце 2013 года MacBook Pro: Intel Core i5 с частотой 2,4 ГГц и Ruby 2.2.0) и усреднил результаты:

Avg. Время (в секундах)
Kramdown .1054152
Maruku .1226444
RDiscount .0131436
Красный ковер 0,007233

Эти цифры крутые, но для того, чтобы действительно получить эффект, нам нужен график: (чем короче планка, тем она быстрее)

Вау. Очевидно, что Redcarpet действительно быстр, с RDiscount в ближайшее время. Учитывая особенности Redcarpet, я очень рекомендую это.

Давайте рассмотрим эти цифры в перспективе. В следующей таблице указано количество документов, которые RedCarpet может обработать за время, которое требуется другим процессорам для обработки одного .

процессор Количество обработанных документов
Maruku 17 документов
Kramdown 15 документов
RDiscount 2 документа

Так что да, Redcarpet довольно чертовски быстр.

Расширенное использование Redcarpet

Redcarpet не только быстр, но и очень расширяем. Давайте посмотрим, сможем ли мы создать самую классную настройку Redcarpet.

Прежде всего мы должны решить, какие дополнительные функции мы хотим от нашей Markdown. Давайте составим список того, что мы хотим: (вы можете ссылаться на эти функции здесь )

  • Таблицы ( :tables )
  • Блоки огороженного кода ( :fenced_code_blocks )
  • Автолинк ( :autolink )
  • Зачеркнутый ( :strikethrough )

Потрясающие. Далее нам нужно получить небольшую мету с нашим HTML и решить, какие атрибуты мы хотим, чтобы он имел. Эти параметры будут помещены в сам рендерер, а не в процессор Markdown. Это только часть удивительной расширяемости Redcarpet. Однако большинство из этих опций являются функциями безопасности (такими как :safe_links_only и :filter_html ), поэтому нам на самом деле не нужно использовать их в нашем случае, но о них полезно знать.

Итак, используя наш список, давайте создадим наш процессор Markdown!

 # our markdown extensions md_options = { tables: true, fenced_code_blocks: true, autolink: true, strikethrough: true } # our markdown processor processor = Redcarpet::Markdown.new(Redcarpet::Render::HTML, md_options) 

Теперь мы можем проанализировать нашу Markdown с помощью простого processor.render(some_markdown_string) .

Вывод

Markdown — очень полезный язык разметки. Даже эта статья написана на уценке.

Поскольку его синтаксис становится все более и более вездесущим, возможность разбирать его на разных языках также будет. Когда дело доходит до производительности и расширяемости, Redcarpet не может быть лучше, но не позволяйте этому помешать вам попробовать и другие процессоры Ruby Markdown. Удачного рендеринга!