Набор регулярных выражений для MarkDown

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

Недавно столкнулся с тем, что в новом проекте надо было сделать подсветку синтаксиса для языка разметки MarkDown. В последнее время он достаточно популярен в разных местах. Долго гуглил, в результате пришлось все писать самому и долго тестировать чтобы все работало правильно.
Под катом набор регулярных выражений, которые ищут основные элементы разметки MarkDown в варианте для Objective-c.


H1
^# (.)+$ // стандартный заголовок
^.+$\n^={3,}$ // заголовок с двойным подчеркиванием

H2
^#{2,2} (.)+$ // стандартный заголовок
^.+$\n^-{3,}$ // заголовок с одинарным подчеркиванием

H3… H6
^#{3,3} (.)+$  ... ^#{6,6} (.)+$

bold ( **Текст** )
(?<!\*|\\\*)\*{2,2}[^\*\n].+?[^\*]\*{2,2}(?!\*|\\)

italic ( *Текст* или _текст_ )
((?<!\*|\\)\*[^\*\n].+?[^\*|\\]\*(?!\*))|(_.+?_)

bold italic ( ***Текст*** )
(?<!\*|\\)\*{3,3}[^\*\n].+?[^\*|\\]\*{3,3}(?!\*)

monospace ( `текст` )
`[^`]*`

Numbered list
(^\d{1,3}\. .*$)+|(^ {1,10}\d{1,3}\. .*$)+

Unnumbered list
(^(\*|\+|-) .*$)+

image ![img alt](http://image.url/img.png)
!\[[^\[\]]*?\]\(.*?\)

url [ссылка](http://site.com/)
\[[^\[\]]*?\]\(.*?\)|^\[*?\]\(.*?\)

block quotes
^>{1,4} (.)+$


Здесь кусок скриншота из приложения, в котором эти регулярные выражения применялись.

image

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 17

    +1
    А экранирование везде учитывается? То есть например вот это правильно распарсится:
    *Курс\*ив*
    

    Превратится в Курс*ив
      0
      Превратится в Кур\*сив (у меня эти выражения используются для подсветки синтаксиса, и не модифицируют строку, только её атрибуты)
      0
      Йехх… Таблиц бы.
        +2
        Какой библиотекой пользовались? Для регулярных выражений их несколько есть.
        Еще неплохо было бы пример использования привести.
        Я вот пытался здесь проверить: regexr.com?35vsn
        Не выходит.
        А еще у вас все регулярные выражения не жадные, что по идее должно привести к проблемам… короче хочу пример.
          –1
          Тот текст, который приведен на картинке — он обработан именно этими регулярками, и к ним применены стили
            0
            И все же, приведите пример исходного кода программы на Obj-C, которая работает с этими регулярками
            0
            Соглашусь, лучше показать в статье перед регексами, что собственно парсят регексы.

            *? — плохой стиль, они дублируют друг друга

            Мое видение например для img
            Имеем:
            ![Alt-текст](URL изображения «Заголовок изображения»)

            Шаг 1: Cобираем весь текст от одной скобки до другой в конструкции "[Alt-текст]" (подразумеваем, что Alt-текст обязательно хоть один символ)
            \[ [^ \] ]+ \]

            Шаг 2: Делаем выражение "[Alt-текст]" необязательным, так как может быть без Alt-текст в виде: "!(URL изображения «Заголовок изображения»)":
            ( \[ [ ^\] ]+ \] )?

            Шаг 3: Cобираем весь текст от одной круглой скобки до закрывающей ее скобки в конструкции "(URL изображения «Заголовок изображения»)" (есть непонятный нюанс, что будет, если в URL будет присутствовать закрывающая скобка )
            \( [^ \) ]+ \)

            Шаг 4: собираем вместе:
            ! ( \[ [^\]]+ \] )? \( [^\)]+ \)

            Описана общая логика, так как могут быть нюансы конкретного применения. Но выполнение по указанным шагам поможет в них разобраться.
            +3
            Меня почему то терзают смутные сомнения что данный пост, всё таки, следует занести в хаб "ненормальное программирование". Решать эту задачу, конечно, можно и регулярными выражениями, но конечные автоматы, наверное, подошли бы куда лушче. ИМХО.
              0
              Вопрос: как это реализовать на Objective-c? :-)
            • UFO just landed and posted this here
              +5
              А что мешает взять их в оригинале??? daringfireball.net/projects/markdown/
                0
                Может я не особо разобрался в том коде, но в чистом виде и для Obj-c я их там не увидел. Если я ошибаюсь, то исправьте меня.
                  +1
                  Markdown был написан Джоном Грубером на Perl. Логично, что у него на сайте варианта на Objective-C нет. Но есть целый ряд приложений и на Objective-C, и на С/С++, которые поддерживают Markdown синтакс. На GitHub не искали?

                  Вот как #{1,6} превращаются в H{1...6}:

                  $text =~ s{
                  		^(\#{1,6})	# $1 = string of #'s
                  		[ \t]*
                  		(.+?)		# $2 = Header text
                  		[ \t]*
                  		\#*		# optional closing #'s (not counted)
                  		\n+
                  	}{
                  		my $h_level = length($1);
                  		"<h$h_level>"  .  _RunSpanGamut($2)  .  "</h$h_level>\n\n";
                  	}egmx;
                  


                  Конечно, в C один-в-один так не сделать ))
                    0
                    Нюанс в том, что все что на гитхабе — это парсеры маркдауна. А мне надо было чтобы была подсветка синтаксиса в реальном времени.
                    И правктически все что есть на гитхабе на эту тему — это порты из того скрипта на перл.
                    Именно поэтому решил делать так.
                      +2
                      Так подсветка синтаксиса markdown много где есть. На регулярных выражениях она точно определена в Vim (Vim просто не умеет подсветку без регулярных выражений).

                      Просто надо смотреть более общие проекты: редакторы (Vim, katepart, Sublime, …) и библиотеки (pygments, google code prettify, …). Правда, для существующего проекта вряд ли что‐то, кроме проверенных регулярных выражений, можно оттуда выдернуть. Библиотеки подсветки для C/Objective-C вы ведь смотрели?
                      • UFO just landed and posted this here

              Only users with full accounts can post comments. Log in, please.