Особенности синтаксиса kramdown: часть 1
Kramdown это один из четырех конвертеров Markdown, доступных в Jekyll по умолчанию (в принципе уже трех — maruku официально объявлен устаревшим и в версии 3.0 не будет поддерживаться), но с 2016 года это единственный конвертер поддерживаемый в версии Jekyll на Github. Kramdown уступает в скорости Redcarpet и rDiscount, но предлагает больше возможностей по разметке текста. В первую очередь это, конечно, возможность добавлять id, классы и прочие атрибуты прямо в разметке Markdown. За счет этого он и является наиболее популярным парсером Markdown в Jekyll (нет, конечно же, на самом деле kramdown наиболее популярен только потому, что является в Jekyll дефолтным парсером).
В рунете хватает статей о синтаксисе Markdown и практически ничего нет о его разновидностях. Поэтому я написал большой текст о kramdown, который пришлось разбить на три части — первые две посвящены особенностям kramdown при парсинге базовых тегов, третья будет о сносках, оглавлениях, добавлении атрибутов и опциях. Что-то из основ синтаксиса Markdown здесь будет повторяться, что-то нет; ознакомиться с основами Markdown можно прочитав любую из указанных ниже статей:
Пустые строки и отступы
Пустая строка обрабатывается как пустая строка, несколько пустых строк — как одна пустая строка. Пустые строки используются для разделения блочных элементов.
Поэтому пустая строка обязательна перед заголовками, блоками кода, списками и таблицами!
Отступы в табуляции предполагаются равными 4. Это важно учитывать, особенно при отступах во вложенных списках. Табы не стоит использовать после пробелов, это может привести к неожиданным результатам.
Параграфы
Основной блочный элемент. Одна или несколько строк текста подряд обрабатываются как параграф.
Перенос строки внутри параграфа делается двумя пробелами перед переводом строки, при этом вставляется тег <br>
.
Как и все остальные блоки, параграф отделяется от других блоков пустой строкой.
Цитаты
Содержимое цитаты является блочным элементом. Это значит, что текст будет обернут параграфом. На примере цитата с двумя параграфами.
> This is a blockquote.
> on multiple lines
that may be lazy.
>
> This is the second paragraph.
This is a blockquote. on multiple lines that may be lazy.
This is the second paragraph.
Так как контентом цитат являются блочные элементы, то вы можете вкладывать в них другие цитаты и прочие блочные элементы:
> Параграф.
>
> > Вложенная цитата.
>
> ## Заголовок
>
> * Список
>
> И любые другие блочные элементы
Параграф.
Вложенная цитата.
Заголовок
- Список
И любые другие блочные элементы
Заголовки
Для заголовков в Markdown есть два вида синтаксиса — Setext и atx. Обе формы можно использовать в одном документе. Но лучше этого не делать, так как использование единого стиля улучшает читаемость исходников.
Стиль Setext предусматривает выделение заголовков подчеркиванием.Заголовки первого уровня подчеркиваются знаками равенства (=
), второго уровня — дефисами (-
). Заголовки других уровней не предусмотрены
Стиль atx позволяет выделять заголовок хэшами (#
) и следующим за ними пробелом, количество хэшей соответствует уровню заголовка, от одного до шести. Этот стиль поддерживается плагинами Markdown в текстовых редакторах, у него больше возможностей, в общем, используйте atx и не используйте Setext.
Пустая строка перед заголовком в kramdown обязательна.
Списки
Список начинается с маркера (любой на выбор: -
, +
или *
), за ним должен быть, как минимум, один пробел или таб и контент. Пробел или таб при конвертации удаляются, все элементы неупорядоченного списка попадают в один список независимо от используемых маркеров. Числа для упорядоченных списков не имеют значения, они всегда начинаются с 1 и нумеруются автоматически. Перед списком обязательна пустая строка.
* kram
+ down
- now
1. kram
2. down
3. now
- kram
- down
- now
- kram
- down
- now
В обычном Markdown можно смешивать маркеры упорядоченного и неупорядоченного списков, тип списка определяется первым маркером. Вышеприведенный пример даст вам два списка (неупорядоченный и упорядоченный) в kramdown и один неупорядоченный в Markdown.
Первый маркер списка можно отделять не более, чем тремя пробелами; отступ перед маркерами в последующих элементах может быть меньше, но не больше.
1. kram
3. down
2. now
- kram
- down
- now
Но лучше так не делать.
Между элементами списка возможно любое количество пустых строк. Если после элемента списка есть пустая строка, его содержимое оборачивается в параграф. Последний элемент списка оборачивается параграфом с помощью установки маркера окончания блока ^
:
1. kram
2. down
3. now
4. !!!
^
- kram
-
down
-
now
-
!!!
Если вам нужно принудительно разделить списки, также используйте маркер окончания блока ^
:
* первый элемент списка
* второй элемент списка
-
первый элемент списка
-
второй элемент списка
* первый список
^
* второй список
- первый список
- второй список
Вложенность списков
В списки можно вкладывать другие блочные элементы — параграфы, списки, цитаты. Это делается с помощью отступа в 4 пробела.
* Первый элемент списка
```markdown
1. Вложенный
2. код
3. с указанием языка
```
* вложенный список
###### с вложенным заголовком
* второй элемент вложенного списка
> цитата
* Второй элемент списка
-
Первый элемент списка
1. Вложенный 2. код 3. с указанием языка
с вложенным заголовком
- вложенный список
- второй элемент вложенного списка
цитата
-
Второй элемент списка
Списки определений
Списки определений не являются частью оригинального Markdown, идея и синтаксис позаимствованы из PHP Markdown Extra .
Списки определений также, как и остальные списки отделяются пустой строкой сверху. На первой строке идет термин, а на второй после двоеточия — определение.
kramdown
: Конвертер Markdown
Maruku
: Еще один конвертер Markdown
- kramdown
- Конвертер Markdown
- Maruku
- Еще один конвертер Markdown
Таблицы
Таблицы также не являются частью оригинального Markdown, но это расширение из PHP Markdown Extra реализовано в большинстве современных парсеров. Синтаксис интуитивно понятный, но если возникают сложности, можно использовать генератор таблиц Markdown (на том же сайте можно автоматически создавать таблицы в HTML, Latex, Wiki и в простом тексте).
Отличия таблиц kramdown от традиционного синтаксиса PHP Markdown Extra:
В таблицах не нужен заголовок. Таблицы структурируются разделителями. В таблицу можно вставить футер. Таблицы необходимо отделять пустыми строками от других блочных элементов.
Ряд таблицы должен содержать как минимум одну вертикальную черту, вертикальные черты разделяют ряд на ячейки, закрывающая черта игнорируется. При экранировании вертикальная линия внутри таблицы не выводится совсем, ее надо обернуть в code
. Текст внутри ячеек парсится как строчный контент, многострочный текст в ячейках не поддерживается.
| Первая ячейка|Вторая ячейка|Третья ячейка
| Первая | Вторая | Третья|
Первая | Вторая | | Четвертая |
Первая | Вторая | | Четвертая
Первая ячейка | Вторая ячейка | Третья ячейка |
Первая | Вторая | Третья |
Первая | Вторая | Четвертая | |
Первая | Вторая | Четвертая |
В этом примере построены самые простые таблицы — в тег table
вложены tr
и td
. Для разделения таблицы на отдельные элементы используются разделители: они создают внутри таблицы thead
, tbody
и tfoot
. В разделителе можно использовать вертикальные черты, дефисы, плюсы, двоеточия и пробелы. Вертикальные черты и плюсы визуально отделяют колонки. Образцы разделителей:
|----+----|
1 | 2
----|----
3 |4
|---------|
5 | 6
|-
7 |8
|:-----:|
9 |10
1 | 2 |
3 | 4 |
5 | 6 |
7 | 8 |
9 | 0 |
Первый разделитель в таблице создает в предшествующих строках таблицы тег thead
. Следующая горизонтальная черта в таблице отделит группу строк дополнительным тегом tbody
(количество tbody
в таблице не ограничено), знаки равенства отделяют tfoot
— футер в таблице должен быть один.
T | H | E | A | D
----|----|----|----|----
| | | |
T |B |O | D | Y
| | 1 | |
----|----|----|----|----
| | | |
T |B |O | D | Y
| | 2 | |
====|====|====|====|====
T |F | O |O |T
Разметка таблицы с длинными разделителями:
T | H | E | A | D |
---|---|---|---|---|
T | B | O | D | Y |
1 | ||||
T | B | O | D | Y |
2 | ||||
T | F | O | O | T |
Вертикальная черта слева позволяет разделять таблицу короткими линиями — для отделения tbody
или tfoot
достаточно одного дефиса или знака равно соответственно. Использование сокращенных разделителей при отсутствии черты слева вызовет ошибку.
|T | H | E | A | D |
|-
| | | | | |
|T |B |O | D | Y |
| | | 1 | | |
|-
| | | | | |
|T |B |O | D | Y |
| | | 2 | | |
|=
|T |F | O |O |T |
Разметка таблицы с вертикальной чертой слева и короткими разделителями:
T | H | E | A | D |
---|---|---|---|---|
T | B | O | D | Y |
1 | ||||
T | B | O | D | Y |
2 | ||||
T | F | O | O | T |
Особый интерес представляет первый разделитель, кроме отделения заголовка, он также задает выравнивание всей таблицы. Для задания выравнивания используются двоеточия, при их отсутствии используется выравнивание по умолчанию. Если двоеточие стоит перед дефисами текст в колонке будет выравниваться слева, если после дефисов — справа, если двоеточия стоят с обоих краев — по центру.
|---
| выравнивание по умолчанию | выравнивание слева | выравнивание по центру | выравнивание справа
|-|:-|:-:|-:
| First body part | Second cell | Third cell | fourth cell
выравнивание по умолчанию | выравнивание слева | выравнивание по центру | выравнивание справа |
---|---|---|---|
First body part | Second cell | Third cell | fourth cell |
Это была первая статья о kramdown, темой следущей будут ссылки, блоки кода и улучшение типографики.
Серия статей: "Особенности синтаксиса kramdown":
- Особенности синтаксиса kramdown: часть 1
- Особенности синтаксиса kramdown: часть 2
- Дополнительные возможности kramdown