CommonMark: формальная спецификация для Markdown

Опубликовано: 2022-03-10
Краткое резюме ↬ Markdown — это мощный язык разметки, который позволяет редактировать и форматировать в формате обычного текста, который затем можно анализировать и отображать как HTML. Он имеет декларативный синтаксис, который является одновременно мощным и простым в освоении как техническими, так и нетехническими людьми. Однако из-за последовавших неоднозначностей в его исходной спецификации было несколько различных разновидностей (или пользовательских версий), направленных на устранение этих неоднозначностей, а также на расширение поддержки исходного синтаксиса. Это привело к резкому расхождению между тем, что можно разобрать, и тем, что визуализируется. CommonMark стремится предоставить стандартизированную спецификацию Markdown, которая отражает его реальное использование.

CommonMark — это рационализированная версия синтаксиса Markdown со спецификацией, целью которой является устранение двусмысленностей и несоответствий, связанных с исходной спецификацией Markdown. Он предлагает стандартизированную спецификацию, которая определяет общий синтаксис языка, а также набор всесторонних тестов для проверки реализаций Markdown на соответствие этой спецификации.

GitHub использует Markdown в качестве языка разметки для своего пользовательского контента.

«CommonMark — это амбициозный проект по формальному определению синтаксиса Markdown, используемого многими веб-сайтами в Интернете, таким образом, чтобы он отражал его реальное использование [...] Он позволяет людям продолжать использовать Markdown так же, как они всегда использовали, предлагая разработчикам всеобъемлющая спецификация и эталонные реализации для согласованного взаимодействия и отображения Markdown между платформами».

— «Официальная спецификация для GitHub Flavored Markdown», блог GitHub.

В 2012 году GitHub приступил к созданию своего собственного варианта Markdown — GitHub Flavored Markdown (GFM) — для борьбы с отсутствием стандартизации Markdown и расширения синтаксиса в соответствии со своими потребностями. GFM был построен на основе Sundown, синтаксического анализатора, специально созданного GitHub для устранения некоторых недостатков существующих в то время парсеров Markdown. Пять лет спустя, в 2017 году, было объявлено об отказе от Sundown в пользу библиотеки синтаксического анализа и рендеринга CommonMark, cmark в официальной спецификации для GitHub Flavored Markdown.

В разделе «Общие вопросы» кода Markdown и Visual Studio задокументировано, что Markdown в VSCode нацелен на спецификацию CommonMark Markdown с использованием библиотеки markdown-it, которая сама по себе следует спецификации CommonMark.

CommonMark получил широкое распространение и реализован (см. Список реализаций CommonMark) для использования на различных языках, таких как C (например, cmark), C# (например, CommonMark.NET), JavaScript (например, markdown-it) и т. д. Это хорошая новость для разработчиков. и авторы постепенно переходят на новый уровень использования Markdown с согласованным синтаксисом и стандартизированной спецификацией.

Краткое примечание о парсерах Markdown

Парсеры Markdown лежат в основе прямого или косвенного преобразования текста Markdown в HTML.

Такие синтаксические анализаторы, как cmark и commonmark.js, не преобразуют Markdown в HTML напрямую, вместо этого они преобразуют его в абстрактное синтаксическое дерево (AST), а затем визуализируют AST как HTML, делая процесс более детализированным и подверженным манипуляциям. Например, между синтаксическим анализом — в AST — и рендерингом — в HTML текст Markdown можно расширить.

Еще после прыжка! Продолжить чтение ниже ↓

Поддержка синтаксиса CommonMark Markdown

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

Поддержка синтаксиса CommonMark может быть ограничена поначалу, например, он не поддерживает синтаксис этой таблицы, но важно знать, что это сделано специально, как показывает этот комментарий в этой ветке обсуждения: что поддерживаемый синтаксис является строгим и сказал быть основным синтаксисом самого языка — таким же, как указано его создателем Джоном Грубером в Markdown: Syntax.

На момент написания, вот несколько поддерживаемых синтаксисов:

  1. Абзацы и разрывы строк,
  2. Заголовки,
  3. Акцент и сильный акцент,
  4. Горизонтальные правила,
  5. списки,
  6. Ссылки,
  7. Картинки,
  8. котировки,
  9. Код,
  10. Кодовые блоки.

Чтобы следовать примерам, рекомендуется использовать редактор dingus commonmark.js, чтобы опробовать синтаксис и получить обработанный предварительный просмотр, сгенерированный HTML и AST.

Абзацы и разрывы строк

В Markdown абзацы представляют собой непрерывные строки текста, разделенные как минимум пустой строкой.

Следующие правила определяют абзац:

  1. Абзацы Markdown отображаются в HTML как элемент Paragraph, <p>.
  2. Различные абзацы разделяются одной или несколькими пустыми строками между ними.
  3. Для разрыва строки абзац должен заканчиваться двумя пробелами (или его эквивалентом табуляции) или обратной косой чертой ( \ ).
Синтаксис Визуализированный HTML
это строка текста <p>Это строка текста</p>
это строка текста
И еще одна строка текста
И еще один, но
тот же абзац
<p>Это строка текста
И еще одна строка текста
И еще один, но
тот же абзац</p>
это абзац

И еще абзац

И другой
<p>Это абзац</p>
<p>И еще один абзац</p>
<p>И еще</p>
Два пробела после строки текста
Или обратную косую черту после фиксированной \
Оба означают разрыв строки
<p>Два пробела после строки текста<br /><br>Или обратная косая черта после фиксированной черты<br /><br>И то, и другое означает разрыв строки</p>
  • Интерактивный учебник, чтобы узнать о абзацах.
  • Постоянная ссылка Dingus: ознакомьтесь с полным примером с предварительным просмотром и AST.
  • Подробнее об абзацах.

Заголовки

Заголовки в Markdown представляют собой один из элементов заголовка HTML. Существует два способа определения заголовков:

  1. Заголовок АТХ.
  2. Заголовок сетекста.

Следующие правила определяют заголовки ATX:

  1. Уровень заголовка 1 ( h1 ) до уровня заголовка 6 ( h6 ) поддерживается.
  2. Заголовки в стиле Atx начинаются с символа решетки ( # ).
  3. Должен быть как минимум пробел, разделяющий текст и символ решетки ( # ).
  4. Количество хэшей эквивалентно кардинальному числу заголовка. Один хэш h1 , два хеша h2 , 6 хэшей h6 .
  5. Также можно добавить произвольное количество символов решетки к заголовкам, хотя это не оказывает никакого эффекта (например, # Heading 1 # )
Синтаксис Визуализированный HTML
# Заголовок 1 <h1>Заголовок 1</h1>
## Заголовок 2 <h2>Заголовок 2</h2>
### Заголовок 3 <h3>Заголовок 3</h3>
#### Заголовок 4 <h4>Заголовок 4</h4>
##### Заголовок 5 <h5>Заголовок 5</h5>
###### Заголовок 6 <h6>Заголовок 6</h6>
## Заголовок 2 ## <h2>Заголовок 2</h2>

Следующие правила определяют заголовки Setext:

  1. Поддерживаются только уровень заголовка 1 (h1) и уровень заголовка 2 (h2).
  2. Определение стиля setext выполняется с помощью символов равенства (=) и тире соответственно.
  3. Для Setext требуется хотя бы один символ равенства или тире.
Синтаксис Визуализированный HTML
Заголовок 1
знак равно
<h1>Заголовок 1</h1>
Заголовок 2
-
<h2>Заголовок 2</h2>
  • Интерактивный учебник, чтобы узнать о заголовках.
  • Постоянная ссылка Dingus, чтобы проверить полный пример с предварительным просмотром и AST.
  • Узнайте больше о заголовках ATX.
  • Узнайте больше о заголовках Setext.

Акцент и сильный акцент

Выделение в Markdown может быть либо курсивом, либо жирным шрифтом (сильный акцент).

Следующие правила определяют акцент:

  1. Обычный и сильный акцент отображаются в HTML как элемент Emphasis, <em>, и Strong, <strong> соответственно.
  2. Текст, ограниченный одной звездочкой ( * ) или символом подчеркивания ( _ ), будет выделен.
  3. Текст, ограниченный двойными звездочками или подчеркиванием, будет выделяться.
  4. Ограничивающие символы (звездочки или подчеркивания) должны совпадать.
  5. Между символами и заключенным в них текстом не должно быть пробелов.
Синтаксис Визуализированный HTML
_Italic_ <em>Курсив</em>
*Italic* <em>Курсив</em>
__Bold__ <strong>Жирный шрифт</strong>
**Bold** <strong>Жирный шрифт</strong>
  • Интерактивный учебник, чтобы узнать об акценте.
  • Постоянная ссылка Dingus, чтобы проверить полный пример с предварительным просмотром и AST.
  • Узнайте больше об акценте и сильном акценте.

Горизонтальное правило

Горизонтальное правило <hr/> создается с тремя или более звездочками ( * ), дефисами ( - ) или символами подчеркивания ( _ ) на новой строке. Символы разделяются любым количеством пробелов или не разделяются вовсе.

Синтаксис Визуализированный HTML
*** <ч />
* * * <ч />
--- <ч />
- - - <ч />
___ <ч />
_ _ _ <ч />
  • Постоянная ссылка Dingus, чтобы проверить полный пример с предварительным просмотром и AST.
  • Узнайте больше о тематических перерывах.

Списки

Списки в Markdown представляют собой либо маркированный (неупорядоченный) список, либо упорядоченный список.

Следующие правила определяют список:

  1. Маркированные списки отображаются в HTML как элемент неупорядоченного списка <ul>.
  2. Упорядоченные списки отображаются в HTML как элемент Упорядоченный список, <ol>.
  3. В маркированных списках в качестве маркеров используются звездочки, плюсы и дефисы.
  4. Нумерованные списки используют числа, за которыми следуют точки или закрывающие скобки.
  5. Маркеры должны быть согласованными (вы должны использовать только тот маркер, с которого начинаете определение остальных элементов списка).
Синтаксис Визуализированный HTML
* один
* два
* три
<ул>
<li>один</li>
<li>два</li>
<li>три</li>
</ul>
+ один
+ два
+ три
<ул>
<li>один</li>
<li>два</li>
<li>три</li>
</ul>
- один
- два
- три
<ул>
<li>один</li>
<li>два</li>
<li>три</li>
</ul>
- один
- два
+ три
<ул>
<li>один</li>
<li>два</li>
</ul>
<ул>
<li>три</li>
</ul>
1. один
2. два
3. три
<ол>
<li>один</li>
<li>два</li>
<li>три</li>
</ol>
3. три
4. четыре
5. пять
<старт = "3">
<li>три</li>
<li>четыре</li>
<li>пять</li>
</ol>
1. один
2. два
3. три
<ол>
<li>один</li>
<li>два</li>
<li>три</li>
</ol>
  • Интерактивный учебник, чтобы узнать о списках.
  • Постоянная ссылка Dingus, чтобы проверить полный пример с предварительным просмотром и AST.
  • Подробнее об элементах списков.

Ссылки

Ссылки поддерживаются во встроенном и справочном формате.

Следующие правила определяют ссылку:

  1. Ссылки отображаются как элемент привязки HTML, <a>.
  2. Встроенный формат имеет следующий синтаксис: [value](URL "optional-title") без пробела между скобками.
  3. Формат ссылки имеет следующий синтаксис: [value][id] для ссылки и [id]: href "optional-title" для метки гиперссылки, разделенной хотя бы строкой.
  4. id является идентификатором определения и может состоять из букв, цифр, пробелов и знаков препинания.
  5. Идентификаторы определения не чувствительны к регистру.
  6. Существует также поддержка автоматических ссылок, где URL-адрес ограничен символами меньше (<) и больше (>) и отображается буквально.
 <!--Markdown--> [Google](https://google.com “Google”) <!--Rendered HTML--> <a href="https://google.com" title="Google">Google</a> <!--Markdown--> [Google](https://google.com) <!--Rendered HTML--> <a href="https://google.com">Google</a> <!--Markdown--> [Comparing Styling Methods in Next.js](/2020/09/comparing-styling-methods-next-js) <!--Rendered HTML--> <a href="/2020/09/comparing-styling-methods-next-js">Comparing Styling Methods In Next.js</a> <!--Markdown--> [Google][id] <!--At least a line must be in-between--> <!--Rendered HTML--> <a href="https://google.com" title="Google">Google</a> <!--Markdown--> <https://google.com> <!--Rendered HTML--> <a href="https://google.com">google.com</a> <!--Markdown--> <[email protected]> <!--Rendered HTML--> <a href="mailto:[email protected]">[email protected]</a>
  • Интерактивный учебник, чтобы узнать о ссылках.
  • Постоянная ссылка Dingus, чтобы проверить полный пример с предварительным просмотром и AST.
  • Узнайте больше о ссылках.

Картинки

Изображения в Markdown соответствуют встроенному и справочному формату для ссылок.

Следующие правила определяют изображения:

  1. Изображения отображаются как элемент изображения HTML, <img>.
  2. Встроенный формат имеет следующий синтаксис: ![alt text](image-url "optional-title") .
  3. Формат ссылки имеет следующий синтаксис: ![alt text][id] для ссылки и [id]: image-url "optional-title" для метки изображения. Оба должны быть разделены хотя бы пустой строкой.
  4. Название изображения не является обязательным, а URL-адрес изображения может быть относительным.
 <!--Markdown--> ![alt text](image-url "optional-title") <!--Rendered HTML--> <img src="image-url" alt="alt text" title="optional-title" /> <!--Markdown--> ![alt text][id] <!--At least a line must be in-between--> <!--Markdown--> <!--Rendered HTML--> <img src="image-url" alt="alt text" title="optional-title" />
  • Интерактивный учебник, чтобы узнать об изображениях.
  • Постоянная ссылка Dingus, чтобы проверить полный пример с предварительным просмотром и AST.
  • Узнайте больше об изображениях.

Цитаты

Элемент HTML Block Quotation, <blockquote>, можно создать, добавив перед новой строкой символ «больше» ( > ).

 <!--Markdown--> > This is a blockquote element > You can start every new line > with the greater than symbol. > That gives you greater control > over what will be rendered. <!--Rendered HTML--> <blockquote> <p>This is a blockquote element You can start every new line with the greater than symbol. That gives you greater control over what will be rendered.</p> </blockquote>

Цитаты могут быть вложенными:

 <!--Markdown--> > Blockquote with a paragraph >> And another paragraph >>> And another <!--Rendered HTML--> <blockquote> <p>Blockquote with a paragraph</p> <blockquote> <p>And another paragraph</p> <blockquote> <p>And another</p> </blockquote> </blockquote> </blockquote>

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

 <!--Markdown--> > Blockquote with a paragraph > # Heading 1 > Heading 2 > - > 1. One > 2. Two <!--Rendered HTML--> <blockquote> <p>Blockquote with a paragraph</p> <h1>Heading 1</h1> <h2>Heading 2</h2> <ol> <li>One</li> <li>Two</li> </ol> </blockquote>
  • Интерактивный учебник, чтобы узнать о блок-кавычках.
  • Постоянная ссылка Dingus, чтобы проверить полный пример с предварительным просмотром и AST.
  • Узнайте больше о блочных котировках.

Код

Элемент HTML Inline Code, <code>, также поддерживается. Чтобы создать его, разделите текст обратными галочками (`) или двойными обратными галочками, если во включающем тексте должна быть буквальная обратная галочка.

 <!--Markdown--> `inline code snippet` <!--Rendered HTML--> <code>inline code snippet</code> <!--Markdown--> `<button type='button'>Click Me</button>` <!--Rendered HTML--> <code><button type='button'>Click Me</button></code> <!--Markdown--> `` There's an inline back-tick (`). `` <!--Rendered HTML--> <code>There's an inline back-tick (`).</code>
  • Интерактивный учебник для изучения кода.
  • Постоянная ссылка Dingus, чтобы проверить полный пример с предварительным просмотром и AST.
  • Узнайте больше о диапазонах кода.

Блоки кода

Элемент предварительно отформатированного текста HTML, <pre>, также поддерживается. Это можно сделать, по крайней мере, тремя и равным количеством ограничивающих обратных галочек ( ` ) или тильд ( ~ ) — обычно называемых ограждением кода, или новой строкой, начинающейся с отступа не менее 4 пробелов.

 <!--Markdown--> ``` const dedupe = (array) => [...new Set(array)]; ``` <!--Rendered HTML--> <pre><code>const dedupe = (array) => [...new Set(array)];</code></pre> <!--Markdown--> const dedupe = (array) => [...new Set(array)]; <!--Rendered HTML--> <pre><code>const dedupe = (array) => [...new Set(array)];</code></pre>
  • Интерактивный учебник для изучения кода.
  • Постоянная ссылка Dingus, чтобы проверить полный пример с предварительным просмотром и AST.
  • Узнайте больше о блоках кода Fenced и Indented.

Использование встроенного HTML

Согласно оригинальной спецификации John Grubers для встроенного HTML, любая разметка, не охватываемая синтаксисом Markdown, вы просто используете сам HTML с единственными ограничениями в том, что HTML-элементы блочного уровня — например, <div> , <table> , <pre> , <p> и т. д. — должны быть отделены от окружающего контента пустыми строками, а начальный и конечный теги блока не должны иметь отступов с табуляцией или пробелами.

Однако, если вы, вероятно, не являетесь одним из тех, кто стоит за самим CommonMark или около того, вы, скорее всего, будете писать Markdown с разновидностью, которая уже расширена для обработки большого количества синтаксиса, в настоящее время не поддерживаемого CommonMark.

Идти вперед

CommonMark находится в постоянном развитии, его спецификация последний раз обновлялась 6 апреля 2019 года. В пуле инструментов Markdown есть ряд популярных приложений, поддерживающих его. Зная об усилиях CommonMark по стандартизации, я думаю, достаточно сделать вывод, что в простоте Markdown за кулисами выполняется много работы, и что для усилий CommonMark хорошо, что формальная спецификация GitHub Flavored Markdown основывается на спецификации.

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

Ресурсы

  • Знакомство с Markdown от Джона Грубера
  • Официальный сайт CommonMark
  • GitHub Flavored Markdown Spec
  • официальный репозиторий cmark
  • Форк GitHub cmark
  • Уценка в Википедии
  • Руководство по уценке