Язык разметки Markdown

Зачем нужен ещё один язык разметки и как на нём писать.

Время чтения: 13 мин

Кратко

Скопировано

Markdown — удобочитаемый язык разметки, который прозрачно конвертируется в HTML. Его можно открывать и изменять в любом редакторе текста. Широко используется для написания документаций и README-файлов.

Пример

Скопировано

Вы можете встретить Markdown в .md или .markdown файлах. Давайте посмотрим на пример одного из таких:

        
          
          # ДокаДока — это **добрая** энциклопедия для веб-разработчиков.Вы можете [открыть её](https://doka.guide) в своём браузере.## Преимущества- Понятный материал;- Нескучные объяснения;- Удобный поиск.
          # Дока

Дока — это **добрая** энциклопедия для веб-разработчиков.
Вы можете [открыть её](https://doka.guide) в своём браузере.

## Преимущества

- Понятный материал;
- Нескучные объяснения;
- Удобный поиск.

        
        
          
        
      

Он содержит базовые элементы, которые можно найти почти в любом README.md:

  • заголовок первого уровня для названия;
  • выделение жирным шрифтом важных частей в описании;
  • ссылка с понятным текстом;
  • заголовок второго уровня для подпунктов;
  • маркированный список для перечисления преимуществ.

Несмотря на то, что Markdown достаточно удобно читать в исходном виде, его часто переводят в HTML. Результат конвертации находится ниже.

Открыть демо в новой вкладке

Синтаксис

Скопировано

Параграф

Скопировано

Параграф — это одна или несколько подряд идущих строчек текста, отделённых одной или несколькими пустыми строчками. Если строка содержит только пробелы или табы, то она всё равно считается пустой.

Подряд идущие строчки будут склеены в одну, если не добавить жёсткий перенос. Существует несколько способов, как это можно сделать:

  • добавить два (или больше) пробелов в конце строки <пробел><пробел>;
  • добавить обратную косую черту в конце строки \;
  • добавить HTML-тег переноса строки <br>.
        
          
          Привет,мир!Привет,<пробел><пробел>пробел!Привет,\косая черта!Привет,<br>тег бр-р-р!
          Привет,
мир!

Привет,<пробел><пробел>
пробел!

Привет,\
косая черта!

Привет,<br>
тег бр-р-р!

        
        
          
        
      
Открыть демо в новой вкладке

Заголовки

Скопировано

Markdown предлагает два стиля написания заголовков: через решётки (#) и через подчёркивания (====). Можно использовать до шести уровней заголовков, но подчёркивания позволяют создавать только первые два (<h1> и <h2>).

Решётки (Atx-style)

Скопировано

Для того чтобы выделить заголовок, необходимо поставить от 1 до 6 решёток (#) и пробел в самом начале строки. Уровень заголовка зависит только от количества решёток.

        
          
          # Заголовок 1 уровня## Заголовок 2 уровня### Заголовок 3 уровня#### Заголовок 4 уровня##### Заголовок 5 уровня###### Заголовок 6 уровня
          # Заголовок 1 уровня
## Заголовок 2 уровня
### Заголовок 3 уровня
#### Заголовок 4 уровня
##### Заголовок 5 уровня
###### Заголовок 6 уровня

        
        
          
        
      
Открыть демо в новой вкладке

Подчёркивания (Setext-style)

Скопировано

«Подчёркивание» параграфа знаками равно (=) или дефисами (-) делает его заголовком первого или второго уровня соответственно. Уровень заголовка зависит только от типа «чёрточек», их количество значения не имеет.

Между текстом и «подчёркиванием» не должно быть пустых строк.

        
          
          Заголовок 1 уровня==================Заголовок 2 уровня------------------Заголовок, который подчеркнули одним символом-Заголовок второгоуровня из несколькихстрочек текста------------------
          Заголовок 1 уровня
==================

Заголовок 2 уровня
------------------

Заголовок, который подчеркнули одним символом
-

Заголовок второго
уровня из нескольких
строчек текста
------------------

        
        
          
        
      
Открыть демо в новой вкладке

Списки

Скопировано

Маркированные

Скопировано

Для создания маркированных (ненумерованных) списков перед каждым пунктом нужно поставить минус (-), плюс (+) или звёздочку (*). Маркер и текст пункта необходимо разделять пробелом.

        
          
          - Помидор- Огурец+ Бублик+ Ватрушка* Молоко* Кефир
          - Помидор
- Огурец

+ Бублик
+ Ватрушка

* Молоко
* Кефир

        
        
          
        
      
Открыть демо в новой вкладке

Если перед подряд идущими пунктами будут стоять разные маркеры, то после конвертации мы получим разные списки.

        
          
          - Помидор+ Бублик* Молоко
          - Помидор
+ Бублик
* Молоко

        
        
          
        
      
Открыть демо в новой вкладке

Упорядоченные

Скопировано

Если в качестве маркеров использовать цифры c точкой на конце (1., 2. и т. д.), то мы получим упорядоченный (нумерованный) список.

        
          
          1. Хлеб2. Молоко3. Помидоры
          1. Хлеб
2. Молоко
3. Помидоры

        
        
          
        
      
Открыть демо в новой вкладке

Номера пунктов в итоговой разметке будут идти по порядку (1, 2, 3), даже если в Markdown будут стоять 1., 4., 9.. Такая особенность позволяет нам использовать «ленивую нумерацию», когда перед каждым пунктом ставится одно и то же число.

        
          
          1. Хлеб1. Молоко1. Помидоры
          1. Хлеб
1. Молоко
1. Помидоры

        
        
          
        
      
Открыть демо в новой вкладке

Число перед первым пунктом показывает с чего нужно начинать нумеровать элементы списка, поэтому если в Markdown поставить 99., 1., 2., то в итоговой разметки пункты будут стоять под номерами 99, 100, 101.

        
          
          99. Хлеб1. Молоко2. Помидоры
          99. Хлеб
1. Молоко
2. Помидоры

        
        
          
        
      
Открыть демо в новой вкладке

Вложенность

Скопировано

Любые списки можно вкладывать друг в друга, для этого перед маркером нужно поставить таб или несколько пробелов.

        
          
          + Хлеб+ Молочные продукты  1. Кефир  2. Ряженка1. Молоко2. Хлебобулочные изделия    + Бублик    + Ватрушка
          + Хлеб
+ Молочные продукты
  1. Кефир
  2. Ряженка

1. Молоко
2. Хлебобулочные изделия
    + Бублик
    + Ватрушка

        
        
          
        
      
Открыть демо в новой вкладке

Количество пробелов, которое нужно использовать, чтобы вложить один список в другой, может варьироваться. Оно зависит от количества символов в родительском маркере (L):

  • + — 1 символ (L = 1)
  • 1. — 2 символа (L = 2)
  • 99. — 3 символа (L = 3)

Перед вложенным списком нужно поставить от L + 1 до L + 4 пробелов.

Отступы вложенных списков
Открыть демо в новой вкладке

Цитаты

Скопировано

Если в начале строки поставить треугольную скобку (>), то Markdown превратит текст после неё в цитату. Внутри могут быть любые блоки: параграфы, заголовки или даже другие цитаты.

        
          
          > Одна треугольная скобкапревращает в цитату несколько строк,идущих друг за другом.
          > Одна треугольная скобка
превращает в цитату несколько строк,
идущих друг за другом.

        
        
          
        
      
Открыть демо в новой вкладке
        
          
          > # Цитаты великих людей> Ваша работа заполнит большую часть жизни и единственный способ быть> полностью довольным — делать то, что по-вашему является великим делом.> И единственный способ делать великие дела — любить то, что вы делаете.>> *— Стив Джобс, Речь в Стенфорде*
          > # Цитаты великих людей
> Ваша работа заполнит большую часть жизни и единственный способ быть
> полностью довольным — делать то, что по-вашему является великим делом.
> И единственный способ делать великие дела — любить то, что вы делаете.
>
> *— Стив Джобс, Речь в Стенфорде*

        
        
          
        
      
Открыть демо в новой вкладке
        
          
          > Первая, родительская цитата> > А это уже вторая,\> > дочерняя цитата
          > Первая, родительская цитата
> > А это уже вторая,\
> > дочерняя цитата

        
        
          
        
      
Открыть демо в новой вкладке

Исходный код

Скопировано

Markdown позволяет специальным образом размечать исходный код, все символы внутри будут автоматически экранированы. Есть 3 способа, как это можно сделать:

  • Обернуть код одной-двумя парами бэктиков (`код`)
  • Обернуть код тремя и более парами бэктиков (```код```)
  • Поставить таб или 4 пробела перед каждой строчкой кода

Одна-две пары бэктиков

Скопировано

Этот способ позволяет вставлять исходный код как строчный элемент. Даже если фактически у нас будет несколько строчек кода, обёрнутых бэктиками, мы всё равно получим одну строку после конвертации в HTML.

        
          
          Функция `alert()`вызывает диалоговое окно.Сумму двух переменныхможно вывести так:``const a = 1const b = 2alert(a + b)``
          Функция `alert()`
вызывает диалоговое окно.

Сумму двух переменных
можно вывести так:
``const a = 1
const b = 2
alert(a + b)``

        
        
          
        
      
Открыть демо в новой вкладке

Три и более пары бэктиков

Скопировано

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

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

        
          
          Функция ```console.log()```выводит текст в консоль.Сумму двух переменныхможно вывести так:```javascriptconst a = 1const b = 2console.log(a + b)```
          Функция ```console.log()```
выводит текст в консоль.

Сумму двух переменных
можно вывести так:
```javascript
const a = 1
const b = 2

console.log(a + b)
```

        
        
          
        
      
Открыть демо в новой вкладке

Отступ

Скопировано

Другой способ выделить код — поставить перед ним таб или 4 пробела. Исходный код необходимо отделять пустой строкой от предыдущего блока.

        
          
          Метод ```.toString()```превращает числа в строку.Его можно использовать так:    const a = 1    const b = 2    (a + b).toString()
          Метод ```.toString()```
превращает числа в строку.

Его можно использовать так:

    const a = 1
    const b = 2

    (a + b).toString()

        
        
          
        
      
Открыть демо в новой вкладке

Выделение текста

Скопировано

Если обернуть текст звёздочками (*) или нижними подчёркиваниями (_), то он станет жирным или курсивным. Оба символа работают одинаково, стиль выделения зависит только от их количества:

  • одна пара * или _ сделает текст *курсивным*;
  • две пары * или _ сделают текст **жирным**;
  • три пары * или _ применят ***оба стиля***.
        
          
          Обычный текст*Курсивный текст*<br>_Другой курсивный текст_**Жирный текст**<br>__Другой жирный текст__***Оба стиля***<br>___Оба стиля___<br>
          Обычный текст

*Курсивный текст*<br>
_Другой курсивный текст_

**Жирный текст**<br>
__Другой жирный текст__

***Оба стиля***<br>
___Оба стиля___<br>

        
        
          
        
      
Открыть демо в новой вкладке

Для экранирования служебных символов Markdown нужно поставить обратную косую черту перед каждым из них (\*, \_, \*\*).

        
          
          **_Оба стиля из \* и \__**<br>__*Оба стиля из \* и \_*__\*\*Экранирование звёзд\*\*<br>\_\_\_Экранирование подчёркиваний\_\_\_
          **_Оба стиля из \* и \__**<br>
__*Оба стиля из \* и \_*__

\*\*Экранирование звёзд\*\*<br>
\_\_\_Экранирование подчёркиваний\_\_\_

        
        
          
        
      
Открыть демо в новой вкладке

Ссылки

Скопировано

Markdown предлагает 3 стиля разметки ссылок: строчный, справочный и автоматический.

Строчные

Скопировано

Для вставки ссылки в строчном стиле необходимо воспользоваться следующей конструкцией: [Текст ссылки](URL). Есть возможность добавить подсказку, для этого нужно после URL дописать текст в кавычках: [Текст ссылки](URL "Подсказка").

        
          
          Привет, [Дока](https://doka.guide "Энциклопедия про web-dev")!
          Привет, [Дока](https://doka.guide "Энциклопедия про web-dev")!

        
        
          
        
      
Открыть демо в новой вкладке

Справочные

Скопировано

Для вставки ссылки в справочном стиле нужно написать [Текст ссылки][Ключ] в том месте, где вы хотите её поместить, а где-нибудь выше или ниже добавить сноску [Ключ]: URL "Подсказка".

        
          
          У [Доки][1] есть свой [репозиторий][repo].[1]: https://doka.guide "Энциклопедия про web-dev"[repo]: https://github.com/doka-guide "Репозиторий Доки"
          У [Доки][1] есть свой [репозиторий][repo].


[1]: https://doka.guide "Энциклопедия про web-dev"
[repo]: https://github.com/doka-guide "Репозиторий Доки"

        
        
          
        
      
Открыть демо в новой вкладке

Автоматические

Скопировано

Markdown позволяет использовать упрощённый вариант для вставки ссылок, для этого нужно просто обернуть URI треугольными скобками (<URI>).

Можно вставлять адреса электронной почты (<hi@doka.guide>), тогда мы автоматически получим ссылку типа mailto:.

        
          
          Заходите на <https://doka.guide>или присылайте нам письма на <hi@doka.guide>
          Заходите на <https://doka.guide>
или присылайте нам письма на <hi@doka.guide>

        
        
          
        
      
Открыть демо в новой вкладке

Изображения

Скопировано

Конструкции для вставки изображений очень похожи на те, что используются для ссылок. Предлагается 2 стиля разметки: строчный и справочный.

Строчные

Скопировано

Для вставки изображения в строчном стиле необходимо воспользоваться конструкцией !⁠[Alt текст](URL картинки). При желании можно добавить подсказку: !⁠[Alt текст](URL картинки "Подсказка").

        
          
          ![Одна собака](dog.png "Собака смотрит влево")
          ![Одна собака](dog.png "Собака смотрит влево")

        
        
          
        
      
Открыть демо в новой вкладке

Справочные

Скопировано

Для вставки изображения в справочном стиле нужно написать !⁠[Alt текст][Ключ] в том месте, где вы хотите его поместить, а где-нибудь выше или ниже описать картинку по ключу [Ключ]: URL картинки "Подсказка".

        
          
          ![Одна собака][1][1]: dog.png "Собака смотрит влево"
          ![Одна собака][1]

[1]: dog.png "Собака смотрит влево"

        
        
          
        
      
Открыть демо в новой вкладке

Горизонтальный разделитель

Скопировано

Для разделения смысловых блоков можно использовать горизонтальную черту (<hr>). Чтобы это сделать, необходимо поставить на одной строке три (или более) дефиса (-), подчёркивания (_) или звёздочки (*). Они не обязательно должны идти друг за другом, между ними могут быть табы или пробелы.

        
          
          ---***_	_	_*  * *  *------------
          ---

***

_	_	_

*  * *  *

------------

        
        
          
        
      
Открыть демо в новой вкладке

Стандартизация

Скопировано

У Markdown есть оригинальная спецификация от одного из создателей языка — Джона Грубера. К сожалению, она не всегда однозначно описывает синтаксис, из-за чего многие конвертеры Markdown работают по-разному. Чтобы исправить эту ситуацию, группа разработчиков «поклонников Markdown» создала CommonMarkспецификацию, которая описывает многие частные случаи, и эталонную реализацию парсера Markdown на JS.

Диалекты

Скопировано

Простой Markdown не всегда подходит для тех или иных проектов, поэтому существуют спецификации, которые расширяют или сужают его.

GitHub Flavored Markdown

Скопировано

GFM — один из диалектов Markdown, который, как можно догадаться из названия, используется на GitHub. Он основан на спецификации CommonMark и расширяет её дополнительными элементами: таблицами, списками задач и зачёркиваниями.

Таблицы

Скопировано

Колонки таблицы размечаются с помощью вертикальных черт (|), а заголовок отделяется дефисами (-).

        
          
          | Место | Участник | Рейтинг ||-------|----------|---------|| 1     | Саша     | 118     || 2     | Юля      | 92      || 3     | Даниил   | 36      |
          | Место | Участник | Рейтинг |
|-------|----------|---------|
| 1     | Саша     | 118     |
| 2     | Юля      | 92      |
| 3     | Даниил   | 36      |

        
        
          
        
      
Открыть демо в новой вкладке

Можно поставить двоеточие (:) рядом с дефисами для выравнивания текста:

  • по левой стороне (|:----|)
  • по центру (|:----:|)
  • по правой стороне (|----:|)
        
          
          | Место | Участник | Рейтинг ||------:|:--------:|:--------|| 1     | Саша     | 118     || 2     | Юля      | 92      || 3     | Даниил   | 36      |
          | Место | Участник | Рейтинг |
|------:|:--------:|:--------|
| 1     | Саша     | 118     |
| 2     | Юля      | 92      |
| 3     | Даниил   | 36      |

        
        
          
        
      
Открыть демо в новой вкладке

Ячейки таблицы могут не соответствовать друг другу по размеру.

        
          
          |Место|Участник|Рейтинг||-:|:-:|:-||1|Саша|118||2|Юля|92||3|Даниил|36|
          |Место|Участник|Рейтинг|
|-:|:-:|:-|
|1|Саша|118|
|2|Юля|92|
|3|Даниил|36|

        
        
          
        
      
Открыть демо в новой вкладке

Список задач

Скопировано

Для создания списка задач используется синтаксис маркированного списка, но с добавлением чекбоксов ([ ] или [x]) после маркеров.

        
          
          - [x] Выйти на улицу- [x] Зайти в магазин- [ ] Купить продукты  - [x] Молоко  - [x] Хлеб  - [ ] Помидоры- [ ] Вернуться домой
          - [x] Выйти на улицу
- [x] Зайти в магазин
- [ ] Купить продукты
  - [x] Молоко
  - [x] Хлеб
  - [ ] Помидоры
- [ ] Вернуться домой

        
        
          
        
      
Открыть демо в новой вкладке

Зачёркивание

Скопировано

Если необходимо зачеркнуть текст, то можно поставить по две тильды (~~) в начале и в конце фрагмента.

        
          
          ~~Привет, Вова!~~\Здравствуйте, Владимир!
          ~~Привет, Вова!~~\
Здравствуйте, Владимир!

        
        
          
        
      
Открыть демо в новой вкладке

Stack Exchange Additions

Скопировано

Популярный среди разработчиков сайт Stack Overflow и все остальные сайты, входящие в группу Stack Exchange, используют в редакторе вопросов Markdown, основанный на спецификации CommonMark. Он расширен следующим образом:

Теги

Скопировано

Ссылка на вопросы по определённому тегу пишется просто в квадратных скобках с префиксом tag:

        
          
          Все вопросы по тегу [tag:javascript] на нашем сайте.
          Все вопросы по тегу [tag:javascript] на нашем сайте.

        
        
          
        
      

Спойлер

Скопировано

Если после символа цитирования поставить восклицательный знак (>!), то цитата выведется свёрнутой, и развернуть её пользователь сможет, кликнув по ней.

        
          
          В конце пятого эпизода выясняется, что>! он его отец.
          В конце пятого эпизода выясняется, что
>! он его отец.

        
        
          
        
      

Другие отличия

Скопировано

Stack Exchange использует тот же синтаксис для создания таблиц, что и GitHub Flavored Markdown, а также некоторые HTML-теги из числа безопасных.

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

Мессенджеры

Скопировано

Многие мессенджеры, например Telegram или Discord, используют упрощённую версию Markdown. Там отсутствует разметка заголовков, списков и цитат, но поддерживается расширенный синтаксис выделения текста: жирный шрифт, курсив, зачёркивания, ссылки, разметка исходного кода.

На практике

Скопировано

Саша Беспоясов советует

Скопировано

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

        
          
          [Ковариантность](https://ru.wikipedia.org/wiki/Ковариантность_и_контравариантность_(математика))
          [Ковариантность](https://ru.wikipedia.org/wiki/Ковариантность_и_контравариантность_(математика))

        
        
          
        
      

Код выше выведет «Ковариантность)», потому что ссылка закончится на первой закрывающей скобке.

Чтобы таких проблем не возникало, можно обернуть адрес в угловые скобки:

        
          
          [Ковариантность](<https://ru.wikipedia.org/wiki/Ковариантность_и_контравариантность_(математика)>)
          [Ковариантность](<https://ru.wikipedia.org/wiki/Ковариантность_и_контравариантность_(математика)>)

        
        
          
        
      

Так, например, автоматически делает Prettier, когда работает с Markdown-файлами.

Сергей Минаков советует

Скопировано

Не стоит использовать два пробела для жёсткого переноса строк в параграфе, потому что во многих проектах для IDE включена опция trim_trailing_whitespace, которая стирает все пробелы, стоящие в конце строки.

Лучше всего использовать тег <br>, потому что перенос с помощью обратной косой черты (\) может поддерживаться не всеми Markdown-конвертерами, так как её описание есть в CommonMark, но отсутствует в оригинальной спецификации.

Илья Таратухин советует

Скопировано

Markdown не предполагает специального синтаксиса для встраивания видео, но и использование HTML-тегов тоже не запрещает. Есть два основных пути добавить видео в Markdown:

  1. Использовать обложку видео со ссылкой на внешнюю платформу. 100% рабочий и допустимый на сторонних площадках вроде GitHub способ.
        
          
          [![Обложка к видео «Дока — как добавить пулреквест со статьёй»](https://i3.ytimg.com/vi/y-_nXfKkI3w/hqdefault.jpg)](https://www.youtube.com/watch?v=y-_nXfKkI3w)
          [![Обложка к видео «Дока — как добавить пулреквест со статьёй»](https://i3.ytimg.com/vi/y-_nXfKkI3w/hqdefault.jpg)](https://www.youtube.com/watch?v=y-_nXfKkI3w)

        
        
          
        
      

Обложка к видео «Дока — как добавить пулреквест со статьёй»

  1. Использовать HTML-разметку и вставить <iframe>, например тот, что генерирует YouTube в диалоге «поделиться».
        
          
          <iframe width="560" height="315"  src="https://www.youtube.com/embed/y-_nXfKkI3w"  title="YouTube video player" frameborder="0"  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"  allowfullscreen></iframe>
          <iframe width="560" height="315"
  src="https://www.youtube.com/embed/y-_nXfKkI3w"
  title="YouTube video player" frameborder="0"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
  allowfullscreen></iframe>