Перейти до вмісту

Markdown

звичайний текст, у якому кілька знаків задають формат

Що це таке

Markdown — це спосіб писати документ як звичайний текстовий файл, у якому кілька набраних умовностей підказують конвертеру, який HTML створити: зірочки довкола слова для виділення, знак решітки перед заголовком, дефіс перед кожним пунктом списку і квадратні дужки з круглими після них для посилання. Назва охоплює і синтаксис, і програму, у вигляді якої він з’явився, файли зазвичай мають розширення .md або .markdown, а діалекти, що з нього виросли, серед них CommonMark і GitHub Flavored Markdown (GFM), теж звуться Markdown.

Джон Грубер створив його у 2004 році разом з Аароном Шварцом і написав перший конвертер на Perl; останній випуск, Markdown 1.0.1, датовано 17 грудня 2004 року. Головною метою він називав читабельність: документ Markdown має бути придатним до публікації як є, звичайним текстом, і не виглядати так, ніби його розмітили тегами чи інструкціями форматування. Найбільше на синтаксис, за його словами, вплинуло те, як люди вже оформлювали листи електронної пошти у звичайному тексті. Усе, чого синтаксис не охоплює, пишуть як HTML посеред тексту, без перемикачів чи розділювачів, бо в його баченні Markdown — формат для письма, а HTML — формат для публікації.

Кілька рядків показують майже все:

Переїзд зайняв **один вечір**, у три кроки:

- зупинити записи
- скопіювати дані за допомогою `pg_dump`
- спрямувати [застосунок](https://example.com/app/) на новий хост

Конвертер перетворює це на абзац з елементом strong, список із трьох пунктів, фрагмент коду й посилання, а джерело й далі читається як нотатка, яку хтось просто набрав.

Чому це важливо

Джерело і є документом, а звичайний текст переживає кожен інструмент довкола нього. Файл Markdown відкривається в будь-якому редакторі, порівнюється рядок за рядком у системі контролю версій і зручно переглядається в pull request. Жоден постачальник не може скасувати цей формат, а перенесення масиву текстів з однієї системи в іншу зводиться до копіювання файлів.

Ціна — неоднозначність. Проєкт CommonMark каже про це прямо: опис Грубера не задає синтаксис однозначно, а його скрипт мав помилки й востаннє оновлювався в грудні 2004 року, тож до 2014 року існували десятки реалізацій, і кожна заповнювала прогалини по-своєму. Приклад проєкту — документ, який на вікі GitHub виглядає одним чином, а після перетворення в DocBook за допомогою Pandoc — іншим. А оскільки в Markdown немає синтаксичних помилок, розбіжність виявляється лише тоді, коли хтось дивиться на результат. Проєкт радить Babelmark 3, що проганяє той самий вхідний текст через понад двадцять реалізацій, щоб побачити, чи вони узгоджуються.

CommonMark, започаткований у 2014 році, відповідає специфікацією, яку написав Джон Макфарлейн: кожне правило в ній прив’язано до прикладів вхідного тексту й точного HTML, який з нього має вийти, — 652 приклади у версії 0.31.2 від 28 січня 2024 року. GitHub визначає свій діалект, GFM, як строгу надмножину CommonMark і додає таблиці, списки завдань, закреслення, розширені автопосилання та фільтр, що знешкоджує короткий список сирих HTML-тегів. Конвертер Markdown у Hugo, Goldmark, відповідає специфікації CommonMark і сумісний з GFM.

Markdown має й власну назву в мережі. З березня 2016 року RFC 7763 реєструє тип text/markdown для всієї родини синтаксисів з обов’язковим параметром charset і необов’язковим variant, який називає діалект файлу.

Як це виглядає на практиці

Написані вручну сторінки цього сайту — це Markdown, розкладений шаблонами Go. Сторінка подяк називає обидва серед інструментів, якими зроблено сторінки, поруч із Hugo, генератором статичних сайтів. Вона ж називає markdownlint серед лінтерів, що тримають вихідний код у порядку, а в обов’язкових перевірках якості кожне зауваження вважається помилкою, а не попередженням.

Сторінка про готовність до ШІ-агентів показує формат з іншого боку: кожна сторінка тут має Markdown-двійника за тією самою адресою, до якого можна дістатися, додавши index.md або попросивши text/markdown, а під час збірки кожного двійника перевіряють на залишки розмітки, і збірка зупиняє публікацію, коли якийсь двійник цієї перевірки не проходить. Двійник самої цієї сторінки — за один запит:

curl -sL https://engineer.company/uk/ai-ready/index.md

Близько 50 000 слів документації до програмного забезпечення лягли в Markdown у GitHub, Craft і Confluence, і значну частину з них написано вручну. Ці тексти описували архітектуру, процеси й практичні інструкції на запитання, які люди ставили раз у раз, зберігалися під контролем версій так, щоб їх легко було знайти, і допомогли новачкам швидше входити в роботу.

Де виникають проблеми

Замість жирного тексту виводяться зірочки. Читач бачить по дві зірочки з обох боків слова, яке мало бути жирним, а всі перевірки лишаються зеленими, бо HTML коректний і посилання працюють. CommonMark відкриває виділення лише на лівофланговій послідовності зірочок, а послідовність, після якої стоїть розділовий знак, як-от квадратна дужка посилання, зараховується лише тоді, коли перед нею пробіл або розділовий знак. Літера перед зірочками залишає їх буквальними, і так само діє все, що шаблонізатор ставить туди до розбору Markdown: Hugo замінює шорткод заповнювачем із літер і цифр. Шаблон Markdown-двійників цього сайту фіксує, що коли прибрали пробіл між шорткодом і жирним текстом поруч, жирне виділення зламалося на 60 пунктах списку трьома мовами. Залишайте пробіл і перевіряйте показану сторінку, а не джерело; серед обов’язкових перевірок цього сайту є та, що читає зібраний HTML у пошуках Markdown, який дійшов до читача як розділові знаки.

Той самий файл показують по-різному. Вкладений список в одній системі стає пласким, а в іншій лишається вкладеним, або решітка на початку рядка в одному конвертері робить заголовок, а в іншому лишається текстом, і ніхто про це не повідомляє, бо в Markdown немає синтаксичних помилок, про які можна повідомити. Причина — різниця діалектів: два конвертери по-різному заповнюють одну з первісних прогалин. Назвіть діалект, яким пише проєкт, здебільшого CommonMark або GFM, використовуйте лінтер, що тримає файли в його межах, і проганяйте сумнівний текст через кілька реалізацій, перш ніж на нього покладатися.

Markdown-версія сторінки містить HTML. Читач текстової версії натрапляє на сирі елементи svg або на номер телефону, що починається з числового посилання на символ там, де мав бути знак плюс. Компонент, який виводить HTML для вебсторінки, виводить той самий HTML і в усі інші формати, якщо йому не вказати інакше; Hugo шукає шаблон шорткода для кожного вихідного формату окремо й повертається до HTML-шаблону. Шаблони шорткодів цього сайту фіксують обидва випадки, 49 сирих елементів svg у Markdown-версії сторінки подяк і номер з контактної сторінки, екранований для HTML, і тепер кожен шорткод, що пише хоч якусь розмітку, має власний шаблон для Markdown. Обов’язкові перевірки також стежать, щоб Markdown-двійники не містили сирого HTML і HTML-сутностей, пропускаючи код.

Сирий HTML зникає зі сторінки. Блоку HTML, записаного в Markdown, немає на зібраній сторінці, хоча джерело виглядає гаразд. Синтаксис Грубера дозволяє HTML будь-де в тексті, але конвертер має право від нього відмовитися: налаштування unsafe для Goldmark у Hugo типово вимкнене, тож сирий HTML, змішаний з Markdown, не відображається, а GFM екранує короткий список тегів, як-от script та iframe, щоб вони виводилися як текст. Натомість беріть те, що пропонує генератор, у Hugo це шорткод або render hook, або вмикайте налаштування свідомо й погоджуйтеся з тим, що воно пропускає.

Лінтер пропускає те, що йому наказали не помічати. Файл Markdown з поламаною структурою проходить рев’ю, бо markdownlint мовчить. Правила, які мали б це впіймати, вимкнули в конфігурації й не записали чому. Правила розробки цього сайту фіксують, що markdownlint колись мав конфігурацію в JSON із шістьма вимкненими правилами без коментарів, і коли ці шість виміряли, два з них приховували справжні дефекти. Записуйте причину біля кожного вимкненого правила у форматі, який вміщує коментар, щоб наступна людина могла з нею не погодитися.

Що почитати далі

  • CommonMark Spec — специфікація, правило за правилом, кожне прив’язане до прикладів вхідного тексту й HTML, який має з нього вийти.
  • CommonMark — навіщо знадобилася специфікація, як розійшлися реалізації і хто її веде.
  • Markdown, by John Gruber — початковий опис, мета задуму і скрипт на Perl.
  • Markdown: Syntax — виклад синтаксису від самого Грубера, з правилом для HTML посеред тексту.
  • GitHub Flavored Markdown Spec — діалект GitHub як надмножина CommonMark, де позначено кожне розширення.
  • RFC 7763: The text/markdown Media Type — медіатип, його обов’язковий charset і параметр variant.

Словник