Пожалуйста, перестаньте использовать таблицы в Markdown, особенно если они большие и сложные.

В пятницу ко мне подошел @abogdanov37 и показал новую утилиту, которую он разработал. Она генерирует документацию в Markdown на основе .env файла, включая переменные, их значения и комментарии. Я, конечно, поздравил коллегу с успехом и попросил посмотреть на результат. И тут меня ждал шок — таблица в Markdown! Вы только представьте себе это!

Так начался холивар...

Введение

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

Ключевое слово здесь — читаемость, причем речь идет не о конечном рендере, а о самом исходном документе. Иначе мы бы продолжали использовать HTML или LaTeX для разметки.

Markdown хорош именно тем, что его можно использовать начиная для создания документации в репозитории проекта, которая затем:

  • Используется в описании готового образа контейнера в реестре контейнеров,

  • Публикуется с помощью MkDocs, Jekyll или другого решения как статичный HTML сайт,

  • Конвертируется в PDF с помощью Puppeteer или Prince,

  • При помощи Pandoc может превращаться в PDF или DOC в соответствии с ГОСТ стандартами,

  • И прочие сценарии жизненного цикла ваших документов.

И во всех этих случаях документы могут выглядеть совершенно по-разному.

А всё потому, что Markdown не является стандартом, хотя так и кажется. Есть CommonMark — это сейчас основа, с четкой спецификацией, но в ней нет таблиц! Там предлагается использовать только: <table><tr><td><pre>**Hello world**</pre></td></tr></table> - где здесь читаемость?

Именно поэтому появилось множество различных стандартов, поддерживающих таблицы вот в таком виде:

| Item       | In Stock | Price |
| :--------- | :------: | ----: |
| Python Hat |   True   | 23.99 |
| SQL Hat    |   True   | 23.99 |

Это пожалуй кажется читаемым...

Альтернативных стандартов и расширений у Markdown множество. Вот лишь небольшая часть популярных:

Причем не все из этих стандартов одинаково работают с таблицами.

А в чем проблема?

Андрей показывает мне, как работает его утилита и какой результат она выдает.

На входе у нас такой .env файл:

# Section 1
ENV_A=a # Описние a
ENV_B=b # Описние b
# Section 2
LOG_LEVEL=info # Описние log

А на выходе такой Markdown

|Наименование переменной|Значение по умолчанию|Описание|
|:---|:---|:---|
|**Section 1**|||
|ENV_A|a|Описние a|
|ENV_B|b|Описние b|
|**Section 2**|||
|LOG_LEVEL|info|Описние log|

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

Вводный реальный пример
Вводный реальный пример

После чего, попросил отрисовать готовый Markdown документ на основании моего .env. Утилита прекрасно справилась с поставленной задачей:

Результат работы утилиты
Результат работы утилиты

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

Мы долго спорили, доказывая друг другу, почему таблица — это хорошо или плохо. Я не буду вдаваться в детали (они не пройдут цензуру), но далее — сухой остаток, почему таблицы, на мой взгляд, это плохо.

Проблемы

Как мы выяснили, CommonMark — это основной стандарт, на котором базируются и который расширяют другие стандарты. Иногда они даже нарушают его. В самом CommonMark нет поддержки таблиц с помощью внутренней разметки, только HTML, и это не случайно. Таблицы — зло, и вот почему:

Читаемость исходных файлов

Здесь всё просто, просто сравните два приведенных ниже блока кода.

# Кусочек огромного списка переменных

* **`NGINX_GZIP`**=`on` —
  Разрешает или запрещает сжатие ответа методом gzip.
* **`NGINX_GZIP_COMP_LEVEL`**=`1` —
  Устанавливает степень сжатия ответа методом gzip.
  Допустимые значения находятся в диапазоне от 1 до 9.
* **`NGINX_GZIP_MIN_LENGTH`**=`20` —
  Устанавливает минимальную длину ответа, который будет сжиматься методом gzip.
  Длина определяется только из поля `Content-Length` заголовка ответа.
* **`NGINX_GZIP_PROXIED`**=`expired no-cache no-store private auth` —
  Разрешает или запрещает сжатие ответа методом gzip для проксированных запросов
  в зависимости от запроса и ответа. То, что запрос проксированный,
  определяется на основании наличия поля `Via` в заголовке запроса.
  В директиве можно указать одновременно несколько параметров:
  * **`on`** — запрещает сжатие для всех проксированных запросов, игнорируя
    остальные параметры;
  * **`expired`** — разрешает сжатие, если в заголовке ответа есть поле
    `Expires` со значением, запрещающим кэширование;
  * **`no-cache`** — разрешает сжатие, если в заголовке ответа есть поле
    `Cache-Control` с параметром `no-cache`;
  * **`no-store`** — разрешает сжатие, если в заголовке ответа есть поле
    `Cache-Control` с параметром `no-store`;
  * **`private`** — разрешает сжатие, если в заголовке ответа есть поле
    `Cache-Control` с параметром `private`;
  * **`no_last_modified`** — разрешает сжатие, если в заголовке ответа нет
    поля `Last-Modified`;
  * **`no_etag`** — разрешает сжатие, если в заголовке ответа нет поля `ETag`;
  * **`auth`** — разрешает сжатие, если в заголовке запроса есть поле
    `Authorization`;
  * **`any`** — разрешает сжатие для всех проксированных запросов.
* **`NGINX_GZIP_TYPES`** — `text/plain text/css application/json`
  `application/javascript application/x-javascript text/javascript`
  `application/xml text/xml application/xml+rss` —
  Разрешает сжатие ответа методом gzip для указанных MIME-типов в дополнение к
  `text/html`. Специальное значение `*` соответствует любому MIME-типу.
  Ответы с типом `text/html` сжимаются всегда.
* **`NGINX_GZIP_DISABLE`** — `msie6` —
  Запрещает сжатие ответа методом gzip для запросов с полями заголовка
  `User-Agent`, совпадающими с заданными регулярными выражениями.
  Специальная маска `msie6` соответствует регулярному выражению `MSIE [4-6]\.`,
  но работает быстрее.
# Кусочек огромного списка переменных

|Наименование переменной|Значение по умолчанию|Описание|
|:---|:---|:---|
|NGINX_GZIP|on|Разрешает или запрещает сжатие ответа методом gzip.|
|NGINX_GZIP_COMP_LEVEL|1|Устанавливает степень сжатия ответа методом gzip. Допустимые значения находятся в диапазоне от 1 до 9.|
|NGINX_GZIP_MIN_LENGTH|20|Устанавливает минимальную длину ответа, который будет сжиматься методом gzip. Длина определяется только из поля `Content-Length` заголовка ответа.|
|NGINX_GZIP_PROXIED|expired no-cache no-store private auth|Разрешает или запрещает сжатие ответа методом gzip для проксированных запросов в зависимости от запроса и ответа. То, что запрос проксированный, определяется на основании наличия поля `Via` в заголовке запроса.<br>В директиве можно указать одновременно несколько параметров:<br> <ul> <li> **`on`** — запрещает сжатие для всех проксированных запросов, игнорируя<br>  остальные параметры;<br> <li> **`expired`** — разрешает сжатие, если в заголовке ответа есть поле<br>  `Expires` со значением, запрещающим кэширование;<br> <li> **`no-cache`** — разрешает сжатие, если в заголовке ответа есть поле<br>  `Cache-Control` с параметром `no-cache`;<br> <li> **`no-store`** — разрешает сжатие, если в заголовке ответа есть поле<br>  `Cache-Control` с параметром `no-store`;<br> <li> **`private`** — разрешает сжатие, если в заголовке ответа есть поле<br>  `Cache-Control` с параметром `private`;<br> <li> **`no_last_modified`** — разрешает сжатие, если в заголовке ответа нет<br>  поля `Last-Modified`;<br> <li> **`no_etag`** — разрешает сжатие, если в заголовке ответа нет поля `ETag`;<br> * **`auth`** — разрешает сжатие, если в заголовке запроса есть поле<br>  `Authorization`;<br> <li> **`any`** — разрешает сжатие для всех проксированных запросов. </ul>|
|NGINX_GZIP_TYPES|text/plain text/css application/json application/javascript application/x-javascript text/javascript application/xml text/xml application/xml+rss|Разрешает сжатие ответа методом gzip для указанных MIME-типов в дополнение к `text/html`. Специальное значение `*` соответствует любому MIME-типу. Ответы с типом `text/html` сжимаются всегда.|
|NGINX_GZIP_DISABLE|msie6|Запрещает сжатие ответа методом gzip для запросов с полями заголовка `User-Agent`, совпадающими с заданными регулярными выражениями. Специальная маска `msie6` соответствует егулярному выражению `MSIE [4-6]\.`, но работает быстрее.|

Теперь представьте себе, что это огромный файл с сотнями строк, а что если потребуется изменить что-то вручную в этой таблице.

Не думаю, что найдется кто-то, кто сможет убедить меня, что второй вариант читается проще. Особенно это поймут те, кто хоть раз открывал markdown в терминале, особенно на виртуальной консоли с разрешением 640x480.

Таблица может не отобразиться

Если утилита, отображающая Markdown, поддерживает только CommonMark, вы не получите красивой таблицы на выходе.

Не буду специально искать примеры, но приведу один из памяти. В реестре контейнеров Quay используется CommonMark (по крайней мере, так было два года назад). При сборке и публикации образа многие автоматически заливают туда README.md, который теряет форматирование, если в нем есть таблицы в стиле GFM. Проблема решалась конвертацией Markdown в HTML, который затем публиковался как Markdown.

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

Ячейки неудобно форматировать

Если нужно разместить в ячейке таблицы список, переносы строк, блоки кода или другое форматирование, всё может нарушиться. В таких случаях приходится использовать HTML, что делает текст трудночитаемым и неудобным для редактирования. Просто обратите внимание, каким путём собран список в рамках одной из ячеек таблицы, сплошные <ul>, <li> и <br>, ведь переносы строк там делать нельзя, всё сломается.

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

Это не стандарт

На вкус и цвет, как говорится, все фломастеры разные. Я никого не заставляю использовать линтеры для проверки Markdown на соответствие стандартам. Однако просто оставлю здесь отчёт от MarkdownLint

Предупреждения MarkdownLint
Предупреждения MarkdownLint

Для варианта со списком у меня нет картинок, потому что там просто не было замечаний.

Форматирование таблицы

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

Форматирование таблиц
Форматирование таблиц

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

Но что случится с нашей таблицей из примера?

Очень широко ...
Очень широко ...

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

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

Да, это меня не оправдывает, но такая ситуация заслуживает обсуждения.

Ширина строк

Для меня это, пожалуй, одна из главных причин, почему я против использования широких строк в Markdown. Это касается как таблиц, так и общего форматирования документа. Я стремлюсь укладываться в ширину 72/80 символов на строку, а в крайнем случае — 132 символа.

Некоторые могут возразить, мол, эпоха перфокарт давно прошла, и с современными 8K мониторами нет никаких проблем писать строки длиной от начала до конца экрана. Но мой аргумент простой: это создает лишний шум в коммитах и увеличивает нагрузку на ревьюера.

Вот пример тех же двух документов, где в теле изменился всего один параметр с on на off. Посмотрите на этот дифф, какой из вариантов экономит время на ревью?

diff --git a/list.md b/list.md
index 617c5b2..30b25ad 100644
--- a/list.md
+++ b/list.md
@@ -13,7 +13,7 @@
   в зависимости от запроса и ответа. То, что запрос проксированный,
   определяется на основании наличия поля `Via` в заголовке запроса.
   В директиве можно указать одновременно несколько параметров:
-  * **`on`** — запрещает сжатие для всех проксированных запросов, игнорируя
+  * **`off`** — запрещает сжатие для всех проксированных запросов, игнорируя
     остальные параметры;
   * **`expired`** — разрешает сжатие, если в заголовке ответа есть поле
     `Expires` со значением, запрещающим кэширование;
diff --git a/table.md b/table.md
index 4c53d05..843eb02 100644
--- a/table.md
+++ b/table.md
@@ -5,6 +5,6 @@
 |NGINX_GZIP|on|Разрешает или запрещает сжатие ответа методом gzip.|
 |NGINX_GZIP_COMP_LEVEL|1|Устанавливает степень сжатия ответа методом gzip. Допустимые значения находятся в диапазоне от 1 до 9.|
 |NGINX_GZIP_MIN_LENGTH|20|Устанавливает минимальную длину ответа, который будет сжиматься методом gzip. Длина определяется только из поля `Content-Length` заголовка ответа.|
-|NGINX_GZIP_PROXIED|expired no-cache no-store private auth|Разрешает или запрещает сжатие ответа методом gzip для проксированных запросов в зависимости от запроса и ответа. То, что запрос проксированный, определяется на основании наличия поля `Via` в заголовке запроса.<br>В директиве можно указать одновременно несколько параметров:<br> <ul> <li> **`on`** — запрещает сжатие для всех проксированных запросов, игнорируя<br>  остальные параметры;<br> <li> **`expired`** — разрешает сжатие, если в заголовке ответа есть поле<br>  `Expires` со значением, запрещающим кэширование;<br> <li> **`no-cache`** — разрешает сжатие, если в заголовке ответа есть поле<br>  `Cache-Control` с параметром `no-cache`;<br> <li> **`no-store`** — разрешает сжатие, если в заголовке ответа есть поле<br>  `Cache-Control` с параметром `no-store`;<br> <li> **`private`** — разрешает сжатие, если в заголовке ответа есть поле<br>  `Cache-Control` с параметром `private`;<br> <li> **`no_last_modified`** — разрешает сжатие, если в заголовке ответа нет<br>  поля `Last-Modified`;<br> <li> **`no_etag`** — разрешает сжатие, если в заголовке ответа нет поля `ETag`;<br> * **`auth`** — разрешает сжатие, если в заголовке запроса есть поле<br>  `Authorization`;<br> <li> **`any`** — разрешает сжатие для всех проксированных запросов. </ul>|
+|NGINX_GZIP_PROXIED|expired no-cache no-store private auth|Разрешает или запрещает сжатие ответа методом gzip для проксированных запросов в зависимости от запроса и ответа. То, что запрос проксированный, определяется на основании наличия поля `Via` в заголовке запроса.<br>В директиве можно указать одновременно несколько параметров:<br> <ul> <li> **`off`** — запрещает сжатие для всех проксированных запросов, игнорируя<br>  остальные параметры;<br> <li> **`expired`** — разрешает сжатие, если в заголовке ответа есть поле<br>  `Expires` со значением, запрещающим кэширование;<br> <li> **`no-cache`** — разрешает сжатие, если в заголовке ответа есть поле<br>  `Cache-Control` с параметром `no-cache`;<br> <li> **`no-store`** — разрешает сжатие, если в заголовке ответа есть поле<br>  `Cache-Control` с параметром `no-store`;<br> <li> **`private`** — разрешает сжатие, если в заголовке ответа есть поле<br>  `Cache-Control` с параметром `private`;<br> <li> **`no_last_modified`** — разрешает сжатие, если в заголовке ответа нет<br>  поля `Last-Modified`;<br> <li> **`no_etag`** — разрешает сжатие, если в заголовке ответа нет поля `ETag`;<br> * **`auth`** — разрешает сжатие, если в заголовке запроса есть поле<br>  `Authorization`;<br> <li> **`any`** — разрешает сжатие для всех проксированных запросов. </ul>|
 |NGINX_GZIP_TYPES|text/plain text/css application/json application/javascript application/x-javascript text/javascript application/xml text/xml application/xml+rss|Разрешает сжатие ответа методом gzip для указанных MIME-типов в дополнение к `text/html`. Специальное значение `*` соответствует любому MIME-типу. Ответы с типом `text/html` сжимаются всегда.|
 |NGINX_GZIP_DISABLE|msie6|Запрещает сжатие ответа методом gzip для запросов с полями заголовка `User-Agent`, совпадающими с заданными регулярными выражениями. Специальная маска `msie6` соответствует егулярному выражению `MSIE [4-6]\.`, но работает быстрее.|

И вот представьте, что мы обсуждали автоматическую генерацию документации с описанием переменных, которая запускается как пред-коммитный хук. Если мы меняем префикс переменной с NGINX_ на ANGIE_ или корректируем значения по умолчанию в нескольких местах, какой из вариантов форматирования документа вам было бы удобнее рассматривать как ревьюеру?

Кстати, в IDE это выглядит не намного лучше.

Diff в IDE
Diff в IDE

Восприятие документа

К сожалению, невозможно напрямую управлять шириной колонок в таблицах Markdown. Конечно, можно применять CSS и <style> для достижения нужного вида, но ведь мы пишем документацию для людей, которые будут её читать. Важно, чтобы документ был удобен для восприятия.

Восприятие документа
Восприятие документа

А как будет выглядеть такая же таблица, но с большим количеством колонок? Или кто-то действительно считает использование пользовательского CSS в Markdown нормальной практикой?

Конвертация документа

Одной из целей Markdown является упрощение конвертации в различные форматы. Рассмотрим, как Markdown преобразуется в PDF — один из наиболее распространенных форматов. Чаще всего итоговый PDF будет иметь стандартный размер шрифта и формат листа A4.

Ниже представлены примеры PDF-документов, созданных с помощью Puppeteer (Chrome).

Список в PDF, 1 лист
Список в PDF, 1 лист
Таблица в PDF, 3 листа
Таблица в PDF, 3 листа

Как видно, восприятие таблицы в PDF значительно ухудшается: три страницы против одной. Если вам нужно создать документ, соответствующий ГОСТу или брендбуку, вы, вероятно, будете использовать Pandoc с множеством LaTeX-конструкций и параметров для достижения требуемого результата. Какова вероятность того, что вы не столкнетесь с проблемами при работе с таблицами? Если в документе используется HTML, шансы на успешное преобразование уменьшаются, и это может стать настоящей головной болью, даже без учета проблем с CSS, изменяющим ширину колонок.

Переносимость

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

И даже Хабр ломает таблицы

Это бонусная проблема, которая всплыла при публикации статьи на Хабр. Изначально документ был написан в Markdown и загружен на GitHub. В разделе "Конвертация документа" я создал таблицу с двумя PDF файлами, расположив их в колонках "Список" и "Таблица". Каково же было моё удивление, когда Хабр отказался отображать изображения, находящиеся в этой таблице.

Ожидаемый результат и суровая реальность
Ожидаемый результат и суровая реальность

Выводы

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

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

По итогам нашего обсуждения Андрей реализовал в своей утилите возможность генерации как списков, так и таблиц, сделав это настраиваемой опцией. Однако он так и не сообщил, какое значение по умолчанию будет у этой опции: список или таблица ?

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

Послесловие

Зачем я написал эту статью? Всё просто: чтобы в случае очередного холивара я мог просто сослаться на этот документ и не тратить часы на бессмысленные обсуждения.

Комментарии (71)


  1. aborouhin
    16.08.2024 22:17
    +10

    В этом плане у AsciiDoc синтаксис для таблиц гораздо гибче и читаемей (ну и стандарт единый). Сам AsciiDoc, увы, куда менее распространён, но если нам надо просто выгружать HTML/PDF/etc. - то вполне заслуживающий рассмотрения вариант.


    1. slonopotamus
      16.08.2024 22:17
      +14

      Это будет следующая статья, "прекратите использовать Markdown".


    1. nuald
      16.08.2024 22:17
      +1

      AsciiDoc нативно поддерживается всеми публичными репозитариями (github, gitlab), намного более гибкий и продуманный чем markdown + нормальное форматирование таблиц. Мы работали с бюрократами из PCI DSS, вся оригинальная документация была в AsciiDoc, и нормально конвертировалась в PDF включая сложные графики (использовали Mermaid). В markdown даже графику вставить нельзя. Весьма позорный формат, который должен уйти на свалку истории.


      1. inkelyad
        16.08.2024 22:17
        +1

        Весьма позорный формат, который должен уйти на свалку истории.

        У них же область применения разная. Markdown - это для случаев, когда минимального форматирования хочется. А AsciiDoc - оно 'semantically equivalent to DocBook'. (Вот интересно, про существование этого самого DocBook еще кто-нибудь помнит, кроме узких специалистов?) И делать его полноценную поддержку (чтобы все, что по спецификации положено, могло) - наверняка сильно сложно.


        1. aborouhin
          16.08.2024 22:17
          +1

          Зачем DocBook, если есть DITA, если уж мы про XML-based форматы? А DITA прекрасна, если нет острой потребности писать руками именно текстовый исходник и есть немного денежек на Oxygen XML Editor. Я часто думаю, насколько бы лучше были документы и светлее мозги у типичного офисного гуманитария, если бы все документы он вместо Word'а в чём-то подобном создавал...


          1. inkelyad
            16.08.2024 22:17
            +1

            Зачем DocBook, если есть DITA, если уж мы про XML-based форматы?

            Если склероз мне ни изменяет - у них тоже слегка разная область применения. DocBook - оно именно для книжек, которые сплошной текст с оглавлением в начале и представляет из себя 'законченное произведение', про которое подразумевается, что его таки можно прочитать от начала до конца, не спотыкаясь. И средства там, соответственно, больше на такой формат подачи материала заточены.

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


            1. aborouhin
              16.08.2024 22:17
              +1

              DITA никто не мешает использовать и в режиме "законченного произведения", а вот у DocBook с "компонованием кусочков" возможности как раз ограниченные, да. AsciiDoc тут вполне тягается с DITA, кстати, и превосходит DocBook.

              А вот есть ли настолько функциональный и удобный нетехническому пользователю редактор для AsciiDoc, как Oxygen для DITA, - вопрос интересный... Пока что я вижу, что для таких пользователей массово пилят свои велосипеды под конкретную задачу там, где что DITA, что AsciiDoc справились бы из коробки (пример - всяческие конструкторы договоров, составляющие оные на основе типовых форм, заполняемых полей и опросников с выбором условий).


    1. McGrog
      16.08.2024 22:17
      +2

      Сам AsciiDoc, увы, куда менее распространён

      На самом деле распространен. Его любят как разрабы, так и аналитики и техписы.

      но если нам надо просто выгружать HTML/PDF/etc

      Да и для хостинга бложиков или публичных спек к фреймворку - тоже пойдет.
      Загляните на https://docs.spring.io/spring-framework/reference/integration/rest-clients.html#rest-message-conversion (там табличка) и у нее вполне человеколюбивые исходники https://github.com/spring-projects/spring-framework/blob/v6.1.12/framework-docs/modules/ROOT/pages/integration/rest-clients.adoc?plain=1#L380.

      Благодаря анторе, акциидоктор получил второе дыхание. Что бы проникнуться, можно полистать https://antora.org/ и ее документацию. Аккуратнее, там тяжеловато в спеках.

      Про таблицы и asciidoc.
      Как бе, если таблица не очень широкая или не очень длинная, она вполне неплохо разворачивается в "одну колонку". Пример выше как раз такое содержит.
      Но делать на нем скоринг для выбора либы/решения/платформы - не очень подходит, эксель лучше справится.

      Прискорбно, что ни adoc ни rst до сих пор не завезли ни в joplin ни в obsidian. Так бы этот богомерзкий md быстрее бы ушел в забытие)


  1. dyadyaSerezha
    16.08.2024 22:17
    +5

    А вообще-то, если env-file переименовать в txt-file (или в исходом виде вставить в любой документ), то и так будет очень читаемо и никуда не надо преобразовывать.


  1. santjagocorkez
    16.08.2024 22:17
    +37

    1. Если маркдаун генерируется, то нечего ему делать в репозитории; отложи его генерацию на этап сборки проекта

    2. Таблица — хорошо там, где представляются табличные данные; если по каким-то причинам в табличные данные пролез кусок, к ним не относящийся, оформи его отдельным блоком под таблицей, а в ячейке проставь ссылку-сноску

    3. Генерируемый файл следует сопровождать именованием вида filename.g.ext; PullRequest pipeline должен строго следить, чтобы никто не мог смержить файлы, имеющие .g. в имени, чтобы любой разработчик, посмотрев на готовый билд, знал, взглянув на имя файла, что его содержимое не подлежит ручной правке, то есть, сгенерировано автоматически, а, следовательно, править надо не этот файл, а генератор (а в файле можно проставить ссылку на этот самый генератор и другую информацию, например, исходник, из которого сгенерировано, чтобы долго не искать)


    1. baldr
      16.08.2024 22:17
      +6

      "Любое категоричное утверждение ошибочно, включая и это" (с).

      • Если маркдаун генерируется, то нечего ему делать в репозитории; отложи его генерацию на этап сборки проекта

      Контрпримеры навскидку - "README.md", "CHANGELOG.md" файлы в репозитории. Вполне нужны прямо в репозитории, причём changelog вполне может быть сгенерированным (на основе закрытых тасков и тп).

      Генерируемый файл следует сопровождать именованием вида filename.g.ext;

      Это если у вас весь тулинг в проекте свой. А если какой-то внешний инструмент использует эти файлы?

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


      1. youngmysteriouslight
        16.08.2024 22:17
        +1

        Контрпримеры навскидку - "README.md", "CHANGELOG.md" файлы в репозитории. Вполне нужны прямо в репозитории, причём changelog вполне может быть сгенерированным (на основе закрытых тасков и тп).

        В репозитории должны быть исходные файлы, а артефакты сборки/обработки/генерации на основе исходников следует версионировать отдельно (не абсолютное правило, но рекомендация на уровне «не устанавливайте туалет на кухне»).

        README.md не является артефактом.

        CHANGELOG.md может быть результатом генерации, но не на основе исходников.

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

        Это если у вас весь тулинг в проекте свой. А если какой-то внешний инструмент использует эти файлы?

        Та же ситуация, что и с любыми другими артефактами сборки. Собственно, как было замечено на примере статики, вопрос шире обсуждаемой здесь темы. От себя скажу, что у нас сейчас ещё нет достаточно продвинутой системы версионирования, чтобы единообразно и систематически решать подобные задачи.


  1. voldemar_d
    16.08.2024 22:17
    +5

    Таблица может не отобразится

    tsya.ru


    1. navferty
      16.08.2024 22:17
      +5

      Для подобных замечаний на хабре есть удобная фича - выделяете фрагмент и нажимаете Ctrl-Enter, чтобы отправить информацию об опечатке в ЛС автору.


      1. voldemar_d
        16.08.2024 22:17
        +18

        Как нажать Ctrl+Enter в смартфоне?


        1. navferty
          16.08.2024 22:17
          +3

          Не знаю, есть ли аналогичная возможность. Возможно, придётся потрудиться чуть больше и вручную открыть диалог с автором.


          1. voldemar_d
            16.08.2024 22:17
            +17

            То есть, автору чуть больше трудиться не обязательно, а мне придётся?

            Впрочем, я свой выбор уже сделал. Захочет ли автор - его дело.


    1. voldemar_d
      16.08.2024 22:17

      Все минусующие поддерживают незнание правил русского языка?


      1. DaneSoul
        16.08.2024 22:17
        +9

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


        1. voldemar_d
          16.08.2024 22:17
          +6

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


          1. dartraiden
            16.08.2024 22:17
            +8

            А мне не плевать

            Вы поинтересовались, ставят ли вам минусы за исправление ошибок - вам пояснили, что не за исправление, а за форму, в которую облечено это исправление. Дальше есть лишь четыре варианта решения проблемы по убыванию оптимальности:

            • изменить канал, по которому отправляются сообщения об ошибках (сообщать в личку)

            • ничего не менять и забить на минусы

            • прекратить сообщать об ошибках вовсе

            • перейти на какой-то иной ресурс, где все ваши действия будут вызывать лишь коллективный одобрямс


            1. voldemar_d
              16.08.2024 22:17

              Форма максимально лаконичная и нейтральная. Кто как хочет, пусть реагирует на своё усмотрение.

              решения проблемы

              Спасибо за советы.


          1. nin-jin
            16.08.2024 22:17
            +5

            Ну а всем плевать что вас там раздражает. Вам бы ко психологу подлечить раздражительность.


          1. Rorg
            16.08.2024 22:17
            +2

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

            Лично для меня такие ошибки — своеобразный измеритель интересности текста. Если статья интересна, я их просто не замечаю. А если начинаю считать запятые или проверять правильность слов, то, видимо, статья не очень (по крайней мере для меня), и на нее не стоит тратить время.


        1. sergey-kuznetsov
          16.08.2024 22:17

          плевать на ошибки, не меняющие смысл текста

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


    1. WoozyMasta Автор
      16.08.2024 22:17
      +3

      Спасибо, исправил.
      Сожалею, что раньше не смог добраться добраться с ответом и это породило столько волнений.


  1. vikarti
    16.08.2024 22:17
    +5

    И как быть если нужна именно таблица? Показывать какие то табличные данные. Оформлять просто списком? оформлять отступами?


    1. Alexufo
      16.08.2024 22:17

      Маркдаун же ест и html


      1. ritorichesky_echpochmak
        16.08.2024 22:17

        И, совершенно внезапно, в том html будет точно такая же нечитаемая для простых людей лапша на больших автогенерённых таблицах. А если они не большие, то и проблемы я всё ещё не вижу.


        1. Alexufo
          16.08.2024 22:17

          Зависит от контента. Если много много строчек в ячейке и они короткие то норм


      1. vikarti
        16.08.2024 22:17

        И это еще хуже выглядит при вводе. Думать на html сложно.


        1. Alexufo
          16.08.2024 22:17

          его думать не обязательно, его можно копипастить из доступного WYSIWYG


  1. N-Cube
    16.08.2024 22:17
    +11

    Если разработчики не знают pandoc и просто холиварят про TeX и markdown, это профнепригодность.

    В командной строке набираем:

    pandoc README.md -t plain
    


  1. CBET_TbMbI
    16.08.2024 22:17
    +20

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


    1. JerryI
      16.08.2024 22:17
      +16

      А ведь стоит просто следовать стандартам и делать таблицу как table а не кучкой div


      1. morijndael
        16.08.2024 22:17
        +1

        Но ведь верстать на таблицах это древний устаревший и не модный путь!!!! /sarcasm


  1. baldr
    16.08.2024 22:17
    +17

    Пфф.. Markdown... Таблицы...

    Это вы ещё не видели как "таблица" может выглядеть внутри pdf ! И не пытались вытащить этот текст оттуда (потому что прайс опубликован на сайте в pdf, а надо их тащить с разных сайтов). Две внешне рядом стоящие буквы одного слова могут относиться к разным блокам, в которых ориентация текста вертикальная. Почему? Ну вот так документ решил сохраниться. И все попытки вытащить текст через "стандартное" API pdf приводят к кровавым слезам, в итоге проще перевести документ в картинку и загнать в OCR.

    Если уж на то пошло - давайте запретим и csv-файлы. Вот у меня pandas читает файл: 30 колонок, 6k+ строк с float числами. Вроде и текстовый файл, но открывать лучше всё равно экселем.

    Отступы в табличке Markdown вам не нравятся? А вы неформатированный json больше хотя бы 500 байт видели? Быстро сможете найти там вторую запись в массиве строк? Меж тем, форматированный вид - всего лишь опция.

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


  1. siberianlaika
    16.08.2024 22:17
    +4

    Выравнивать не пробовали? Например GNU/Emacs столбцы при редактировании автоматически выравнивает пробелами и так сохраняет:

    | header 1 | header 2 |
    |----------+----------|
    | text 1   | text 2   |
    | text 3   | text 4   |
    

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

    Если приведенная автором статьи утилита это не умеет, то это вопрос к утилите, не к формату.


    1. WoozyMasta Автор
      16.08.2024 22:17

      Вы совершенно верно подметили, в разделе "Форматирование таблицы" я как раз писал про автоматическое форматирование таблиц, а также о негативных последствиях.


  1. dartraiden
    16.08.2024 22:17
    +1

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

    Поэтому я завёл полезную привычку просматривать дифф с внесёнными изменениями перед коммитом.


    1. Chupaka
      16.08.2024 22:17

      `git commit -p` уже много лет пальцы набирают автоматически


    1. WoozyMasta Автор
      16.08.2024 22:17

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


  1. zabanen2
    16.08.2024 22:17

    поздравил коллегу с успехом

    да уж, богданов в следующий раз 100 раз подумает, прежде чем делать мир лучше

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


    1. WoozyMasta Автор
      16.08.2024 22:17

      Я уверен, что это ни как не скажется на Андрее, и он по прежнему будет делать мир лучше.
      Статья всё же не про утилиту, а про таблицы. Да, можно конечно добавить и 4й столбец, но лучше от этого не станет, а вот проблем от этого новых добавит. Как минимум, это потребует описать некий стандарт комментария, что бы описать данные 4-го столбца, и прочие вытекающие последствия.


  1. Alexufo
    16.08.2024 22:17

    Есть как минимум три расширения vscode для форматирования таблиц md.

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

    Если таблица очень сложная, ее нужно хранить отдельно где-то.


  1. s-a-u-r-o-n
    16.08.2024 22:17

    Самый кошмар начинается, когда нужно сделать вложенную таблицу. Как известно, средствами Markdown это сделать нельзя, а значит — придётся прибегать к HTML, использование которого сведёт все преимущества Markdown к нулю (а также не факт, что на конкретном сайте такая таблица будет корректно отображена).


    1. slonopotamus
      16.08.2024 22:17
      +2

      Поэтому первый коммент под этим постом говорит об AsciiDoc.


  1. serafims
    16.08.2024 22:17

    Я просто оставлю здесь... Табулятор.

    Символ, кнопка, про который почему-то забыли.

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

    Сложности только с объединенными ячейками...


  1. nin-jin
    16.08.2024 22:17

    Используйте нормальные форматы и не будет всех этих проблем. https://marked.hyoo.ru/


    1. slonopotamus
      16.08.2024 22:17
      +4

      Чем оно лучше AsciiDoc'а?


      1. nin-jin
        16.08.2024 22:17

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


        1. inkelyad
          16.08.2024 22:17
          +1

          (поглядывая на LaTeX) Он тоже простой, да...

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


          1. nin-jin
            16.08.2024 22:17

            Лучше бы вы по ссылке сходили, да поглядели, как делается простое и читаемое текстовое представление вложенных таблиц.


            1. inkelyad
              16.08.2024 22:17
              +4

              Ну да, конечно. Вот это(Отсюда, по ссылке ниже.):

              ! Dimensions
                ! 2
                  ! 3
              ! Rotation
                ! " ! ;;cos A;;
                ! "   ! ;;sin A;;
                ! " ! ;;- sin A;;
                ! "   ! ;;cos A;;
                  ! " ! ;;cos A;;
                  ! "   ! ;;sin A;;
                  ! "     ! 0
                  ! " ! ;;- sin A;;
                  ! "   ! ;;cos A;;
                  ! "     ! 0
                  ! " ! 0
                  ! "   ! 0
                  ! "     ! 1
              

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


              1. nin-jin
                16.08.2024 22:17

                Однако ux исследования показывают, что люди прекрасно справляются с чтением и редактированием таких таблиц. Глаза боятся - руки делают.


                1. inkelyad
                  16.08.2024 22:17

                  Люди, скорее всего, плохо справляются в любом случае. Возмем случай попроще.

                  ! 
                    ! table
                      ! header
                  ! a
                    ! There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable.
                      ! row
                  ! b
                    ! table 
                      ! row
                  
                  
                  

                  Как тут просто найти, где находится ячейка на пересечении header и b? Особенно если таблица - побольше и на экране оно все сразу не помещается.


                  1. nin-jin
                    16.08.2024 22:17

                    Поставил курсор на хедер и поехал вниз по восклицательным знакам.


      1. baldr
        16.08.2024 22:17
        +1

        Чем оно лучше AsciiDoc'а?

        Очевидно, у AsciiDoc'а есть фатальный недостаток.


        1. nin-jin
          16.08.2024 22:17

          У вас ссылка битая. Вот правильная: https://page.hyoo.ru/#!=6lqg5m_deygy0


          1. slonopotamus
            16.08.2024 22:17

            Почитал.

            Вы там много аппелируете к "не только английским" раскладкам, но что-то мне подсказывает, что речь исключительно про кириллицу, да? И точно ли это проблема формата разметки что на вашей клавиатуре нет []<>#?

            P.S. В AsciiDoc в таблицы тоже можно вкладывать всё что угодно.


            1. nin-jin
              16.08.2024 22:17

              Я много к чему апеллирую.

              Это решение проблемы. Можете предложить лучшее.

              Можно пример, как в аскидоке вложить таблицу в таблицу?


              1. inkelyad
                16.08.2024 22:17

                Отсюда

                [cols="1,2a"]
                |===
                | Col 1 | Col 2
                
                | Cell 1.1
                | Cell 1.2
                
                | Cell 2.1
                | Cell 2.2
                
                [cols="2,1"]
                !===
                ! Col1 ! Col2
                
                ! C11
                ! C12
                
                !===
                
                |===

                То, что начинается с '|' - это внешняя таблица. То, что '!' - вложенная.


                1. nin-jin
                  16.08.2024 22:17

                  Прекрасная читаемость. А для 3 уровня вложенности какой символ?


                  1. inkelyad
                    16.08.2024 22:17
                    +1

                    Ну написано же: 'you can choose another character by defining the separator attribute on the table.'

                    А про читаемость - мой тезис в том, что читабельность таких конструкций будет никакая в любом формате.


                    1. alextretyak
                      16.08.2024 22:17

                      Раз уж тут начали рекламировать свои языки разметки, позвольте и мне вставить 5 коп. Вот так данная «таблица в таблице» выглядит в пк-разметке:

                      T‘
                      H‘‘Col 1’     ‘Col 2’’
                       ‘‘Cell 1.1’  ‘Cell 1.2’’
                       ‘‘Cell 2.1’  ‘Cell 2.2
                      [[[    ]]]T‘H‘‘Col1’ ‘Col2’’
                                   ‘‘C11’  ‘C12’’’’’
                      ’
                      

                      Да, набирать такое не очень удобно, но читаемость вполне себе неплоха.


                      1. WoozyMasta Автор
                        16.08.2024 22:17
                        +1

                        Не согласен, выше приведенные примеры как раз решают проблему с отображением длинных строк, размещая их в виде списка.
                        А в pq, мы всё также вынуждены все ячейки одной строки, разместить в одной исходной строке. Большой объем содержимого здесь так же нарушит читаемость исходника.


                      1. alextretyak
                        16.08.2024 22:17
                        +1

                        А в pq, мы всё также вынуждены все ячейки одной строки, разместить в одной исходной строке.

                        Это ещё почему?

                        Хотите, всю таблицу вообще в одну строку, а хотите, в виде списка вот так:

                        T‘
                        H‘‘Col 1’
                          ‘Col 2’’
                        
                         ‘‘Cell 1.1’
                          ‘Cell 1.2’’
                        
                         ‘‘Cell 2.1’
                          ‘Cell 2.2
                        T‘H‘‘Col1’ ‘Col2’’
                           ‘‘C11’  ‘C12’’’’’
                        ’
                        

                        Я уж не говорю про возможность куда угодно вставлять [[[комментарии]]]. (Может быть полезно, чтобы давать подписи строкам или ячейкам таблицы.)


                      1. WoozyMasta Автор
                        16.08.2024 22:17

                        Тогда да, спасибо за пояснение, из беглого обзора приведенной выше статьи подумал об обратном.


  1. Yuuri
    16.08.2024 22:17

    Некоторые могут возразить, мол, эпоха перфокарт давно прошла, и с современными 8K мониторами нет никаких проблем писать строки длиной от начала до конца экрана. Но мой аргумент простой: это создает лишний шум в коммитах и увеличивает нагрузку на ревьюера.

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


  1. whocoulditbe
    16.08.2024 22:17

    На мой взгляд рендер для документации куда важнее, чем исходник. Результат будут видеть намного чаще, чем страшную сгенерированную таблицу в markdown. Раз она сгенерированная из какого-то там исходника - в чём проблема редактировать исходник и из него готовить рендер?

    Вообще беда конкретно вашего примера с конфигом nginx - это ширина второй колонки с дефолтным значением. Посмотрите, как Яндекс решает эту проблему:

    Картинка

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

    На каждую ситуацию свой инструмент. Я бы не стал отказываться от таблиц только потому, что в IDE писателю-ревьюверу будет тяжело пару минут, а вместо этого почитал бы книжки от типографов, редакторов текста, гайдлайны интерфейсов в конце концов, где точно что-нибудь будет по этому поводу.


  1. romastra
    16.08.2024 22:17

    Да, любопытный холивар. Но смысла воевать не вижу. Первое, что пришло в голову — зачем понадобится лезть в исходник автоматически сгенерированного markdown документа?

    Если его назначение — либо отобразиться в готовом виде, либо преобразоваться в PDF —генериться такое должно при сборке и не подразумевать рукопашку.

    Ещё интересно было бы посмотреть, как вы управляетесь с этим "кусочком ограмного списка переменных" в самом env-файле. Для автогенерации все эти тексты со всей разметкой изначально должны храниться именно в нём? Тогда здесь, на мой взгляд, и заключается ваша болезненная рукопашка.