В первый раз, когда мой README пересек тысячу строк, я сделал то, что делают все: я прокрутил. Затем я прокрутил еще немного. Где-то около четвертого прохода в поисках раздела "Развертывание и квота; Я сдался и начал писать от руки оглавление в верхней части файла. Это работало до тех пор, пока я не переименовал заголовок, не забыл обновить ссылку и не отправил README, где "Конфигурация и квотирование; ни на что не указал. Неработающая ссылка на странице в вашей собственной документации - это мелочь, но это своего рода мелочь, которая говорит читателю, что никто не возражает против магазина.
Я создаю [Toolz.dev](/, коллекцию утилит для разработчиков на основе браузера, и я поддерживаю много Markdown: руководства по инструментам, файлы README, внутренние спецификации и документы, которые вы читаете прямо сейчас. оглавление, которое я должен поддерживать вручную, - это оглавление, которое в конечном итоге ляжет. Поэтому я построил Генератор TOC Markdown чтобы сделать скучную часть правильно каждый раз, и это руководство все, что я узнал о якорных звеньях во время его строительства.
TL;DR: Оглавление Markdown - это вложенный список ссылок, которые переходят к заголовкам на одной странице.Ссылки работают, потому что каждый заголовок получает автоматический идентификатор привязки, а slug, который назначает GitHub, следует определенному правилу: строчные строки текста, выпадают из пунктуации, отличной от дефисов, и превращаются пробелы в дефисы. вставьте свою разметку в генератор, выберите, какие уровни заголовков включить, и скопируйте список. инструмент вычисляет точные рендеры slugs GitHub, включая
-1суффикс для дублирующих заголовков, поэтому при вставке ничего не сломается.
Что такое оглавление Markdown?
Оглавление в Markdown не является специальным синтаксисом. общая метка не определяет такую конструкцию, как и GitHub Flavored Markdown. Это обычный список, в котором каждый элемент является ссылкой, и каждая ссылка указывает на привязку внутри одного документа. Когда рендерер Markdown, такой как GitHub, превращает заголовок в HTML, он также дает этому заголовку ан id атрибут. Заголовок, написанный как ## Getting Started становится грубо <h2 id="getting-started">Getting Started</h2>. Как только этот идентификатор существует, ссылка записывается как [Getting Started](#getting-started) прокручивает страницу до него.
Таким образом, оглавление - это просто набор этих ссылок с отступом, отражающим иерархию заголовков:
- [Getting Started](#getting-started)
- [Installation](#installation)
- [Configuration](#configuration)
- [Usage](#usage)
Весь трюк живет в одном слове из этого примера: якорь. Получить якорь неправильно и ссылка бесшумно отказывает, прокрутка нигде.Get it right и блок содержимого работает на GitHub, в большинстве статических генераторов сайта, и внутри платформ документации, которые следуют тому же соглашению. жесткая часть не пишет список.Жесткая часть предсказывает точный идентификатор, который каждый рендерер назначит, поэтому делать это вручную является проигрышной игрой на любом документе, который меняется.
Как на самом деле генерируются якоря заголовков?
GitHub's Алгоритм slug является детерминированным и заслуживает запоминания, потому что, как только вы его узнаете, вы можете предсказать каждый якорь на странице. Шаги по порядку: преобразовать текст заголовка в строчный регистр, удалить любой символ, который не является буквой, числом, пробелом или дефисом, а затем заменить каждое пространство дефисом. Это все правило.
Последствия - это то, куда люди спотыкаются. Рассмотрим заголовок, как ## Set Up & Config. Нижний регистр дает set up & config. Удаление амперсанда (но оставление пространств вокруг него) дает set up config с двумя пробелами, где & раньше было Превращение пространств в дефисы производит set-up--config, с двойным дефисом. этот двойной дефис выглядит как ошибка, но это именно то, что визуализирует GitHub, так что это именно то, что нужно вашей ссылке. инструмент, который "очищает up" двойной дефис произвел бы ссылку, которая не разрешается.
Заголовки с высоким значением пунктуации рушатся дальше, чем вы ожидаете. ## C++ Guide становиться c-guide, потому что оба знака плюс удаляются, а оставшееся пространство становится одним дефисом. ## What's New? становиться whats-newпотому что апостроф и вопросительный знак исчезают. Эмодзи и большинство символов полностью исчезают.The Генератор TOC Markdown применяет этот символ правила для символа, поэтому slug он показывает, что вы являетесь идентификатором, который будет строить GitHub, без каких-либо угадываний.
Что происходит, когда два заголовка одинаковы?
Документы повторяют заголовки. Журнал изменений может состоять из трех разделов, все из которых озаглавлены ### Fixed. Если бы каждый из них произвел slug fixed, только первая ссылка будет работать.GitHub решает это, нумеруя дубликаты: первый Fixed получает fixed, второй получает fixed-1, третий получает fixed-2, и так далее в порядке документов Суффикс добавляется после основания slug дефисом.
Это одна из самых распространенных причин, по которой рукописный оглавление выпадает из синхронизации. вы добавляете второй раздел с именем, которое уже использовали, якорь незаметно становится -1, и ваша старая ссылка теперь указывает не в том месте или вообще нигде Генератор отслеживает каждый slug, который он издал, и применяет один и тот же числовой суффикс, поэтому повторяющиеся заголовки ссылаются на правильное вхождение.
Какие заголовки читает инструмент?
Markdown имеет два стиля заголовков, и полный генератор должен читать оба. Распространенным является ATX, где строка начинается с одного до шести # символы, за которыми следует текст заголовка. счет хешей - это уровень, так что # является H1 и ###### это H6. Второй стиль - Setext, где строка текста подчеркнута в следующей строке знаками, равными знакам H1 или дефисам для H2:
Document Title
==============
A Section
---------
Оба стиля производят заголовки с идентификаторами якоря, поэтому оба принадлежат оглавлению. сложная часть с Setext - это сказать реальный подчеркнутый заголовок отдельно от горизонтального правила, потому что строка дефисов может означать либо Правило, которое использует генератор, заключается в том, что подчеркивание дефиса считается только заголовком, когда строка непосредственно над ним представляет собой обычный текст абзаца, а не пустую строку, элемент списка, блок-цитату или другую конструкцию блока. А --- сидеть один с пустыми линиями вокруг - это тематический перерыв, и он правильно игнорируется.
Есть еще одна категория, с которой нужно справиться, и это та, которая тихо портит наивные инструменты: заголовки внутри кода. если ваш документ содержит огороженный блок кода, который показывает команды оболочки, некоторые из этих строк начнутся с # как комментарии. это не заголовки, и они никогда не должны появляться в содержимом. Генератор отслеживает огороженные блоки кода (те, которые ограничены тройными обратными тисками или тройными тильдами) и пропускает любые # строка внутри них. shell комментарий как # install dependencies в примере остается там, где ему место, в примере.
Как мне контролировать глубину оглавления?
Оглавление, в котором перечислен каждый заголовок вниз к H6, не является оглавлением, это второй экземпляр документа Большинство README читают лучше всего, когда содержимое охватывает только H2 и H3, давая читателям основные разделы и их непосредственных детей, не топя их в деталях. генератор позволяет установить минимальный и максимальный уровень, и он включает только заголовки, которые попадают в этот диапазон.
Тонкое поведение здесь отступы. если вы включаете H2 через H4, самый мелкий заголовок, который вы держали, это H2, и он должен располагаться заподлицо с левым краем, а не с отступом, как если бы над ним находился невидимый H1. Генератор измеряет глубину вложенности относительно самого мелкого заголовка, который он на самом деле включает, поэтому блок содержимого, который начинается с H2, начинается без отступа. В этом разница между списком, который выглядит намеренно, и списком, который выглядит так, будто потерял свой первый столбец.
Вы также можете выбрать маркер списка. неупорядоченный список использует пулю для каждой записи, что является обычным поиском для README. упорядоченный список нумерует записи, и генератор перезапускает счет в пределах каждого уровня вложения, поэтому нумерованный контур читается правильно, а не подсчитывается прямо от одного до пятидесяти. Вдавливание может быть двумя пробелами, четырьмя пробелами или вкладкой, в зависимости от того, что использует остальная часть вашего документа.
А как насчет акцентированных и нелатинских заголовков?
Не каждый заголовок является простым английским, и правило slug должно соответствовать требованиям. GitHub сохраняет буквы из других алфавитов, а не удаляет их, поэтому заголовок нравится ## Configuración сохраняет акцентированные характеры и становится configuración, и заголовок на кириллице или греческом языке сохраняет эти буквы тоже. удаляется пунктуация и символы, а не буквы, независимо от сценария. генератор следует тому же принципу, рассматривая любую букву или цифру Юникода как действительный символ slug, поэтому многоязычный документ создает якоря, соответствующие тому, что отображает GitHub, а не ряд пустых ссылок.
Это имеет большее значение, чем кажется на первый взгляд. команды, которые пишут документацию на испанском, немецком или японском языках, часто обнаруживают, что наивные инструменты slug искажают свои заголовки в непригодные для использования якоря, потому что эти инструменты предполагают ASCII. Если ваши ссылки когда-либо не указывали ни на что на переведенном README, slug, который молча отбрасывал буквы, отличные от ASCII, почти наверняка является причиной. Создание блока содержимого с помощью инструмента, поддерживающего Unicode, удаляет весь класс неработающих ссылок, и это означает, что один и тот же документ может содержать заголовки более чем на одном языке, при этом ни один из них не теряет своих якорей.
Когда мне следует использовать сгенерированный TOC по сравнению с автоматическим?
Некоторые платформы создают для вас оглавление. GitLab поддерживает a [[_TOC_]] токена, некоторые вики вводят окно содержимого автоматически, и рамки документации, как Docusaurus, отображают на странице контур из ваших заголовков, не пишу ничего Когда вы работаете внутри одной из этих систем, используйте встроенную функцию Он остается актуальным с нулевым усилием, потому что платформа регенерирует его на каждом рендере.
Генератор зарабатывает свое место везде, и & quot;везде & quot; является большим местом.GitHub README не автоматически генерируют блок содержимого, поэтому целевой странице репозитория нужен реальный список Markdown, записанный в файл. Markdown, который преобразуется в что-то другое, отправляется по электронной почте, вставляется в проблему или визуализируется минимальным зрителем, нуждается в статическом блоке содержимого, потому что нет движка, чтобы построить его на лету. В таблице ниже указано, где каждый подход подходит.
| положение | Лучший подход | почему |
|---|---|---|
| GitHub README | Сгенерированный статический список | GitHub отображает идентификаторы заголовков, но не вставляет автоматически TOC |
| GitLab вики или документы | [[_TOC_]] жетон |
Родной, всегда актуальный |
| Страница Докузавра/MkDocs | Встроенный контур | Framework отображает это из заголовков |
| Обычный файл Markdown для экспорта | Сгенерированный статический список | Нет рендерера, который мог бы создать его во время просмотра |
| Описание запроса на выпуск или извлечение | Сгенерированный статический список | Якоря работают, но ничто не создает список автоматически |
Эмпирическое правило: если вещь, которая отображает вашу Markdown может построить содержимое самостоятельно, пусть это. Если ваша Markdown может быть прочитана где-то, что не может, сгенерируйте список и зафиксируйте его. Когда вы конвертируете между форматами, Markdown в HTML-конвертер и тот Конвертер HTML в Markdown естественным образом соединяются с блоком сгенерированного содержимого, поскольку якоря переживают путешествие туда и обратно.
Как это соответствует остальной части рабочего процесса Markdown?
Оглавление - это одна часть, позволяющая читать длинные документы, и она лучше всего работает наряду с несколькими привычками. Сохраняйте стабильность текста заголовка после публикации ссылок на него, поскольку переименование заголовка меняет его slug и разрывает каждую ссылку, которая указывает на него. Когда вы все-таки переименовываете, восстанавливайте содержимое, а не редактируете одну ссылку, которую вы помните, поскольку переименование часто смещает нумерацию дубликатов суффиксов дальше по файлу.
Структурированный контент извлекает выгоду из других инструментов того же семейства. Когда документ опирается на табличные данные, Генератор таблиц Markdown строит правильно выровненные таблицы трубы, что вручную типизированная таблица почти никогда не получает правильно Когда вы наследуете беспорядочный HTML, который должен стать чистым Markdown, или чистая Markdown, который должен стать HTML, конвертеры обрабатывают перевод, сохраняя структуру заголовка, И если вы проверяете документ на длину или баланс ключевых слов, счетчик слов дает вам цифры, не вставляя черновик в что-либо облачное.
Все работает в браузере, что имеет большее значение, чем звучит. README часто содержит неизданные имена функций, внутренние URL-адреса или данные клиента, и все это не должно быть загружено на сторонний сервер только для того, чтобы построить список ссылок. Генератор анализирует вашу Markdown с помощью JavaScript на стороне клиента, поэтому документ никогда не покидает вашу машину. Если конфиденциальность в инструментах разработчика - это то, о чем вы думаете, запись на Конфиденциальность данных и онлайн-инстру охватывает, почему локальная обработка является правильным по умолчанию, и Набор инструментов для веб-разработчиков ежедневно собирает остальные коммунальные услуги, к которым я обращаюсь.
Быстро сработавший пример
Предположим, у вас есть этот документ:
# Payment Service
## Getting Started
### Requirements
### Local Setup
## API Reference
### Authentication
### Errors
## Deployment
Установите диапазон от H2 до H3, выберите список с пулеметами и оставьте якорные ссылки включенными Генератор производит
- [Getting Started](#getting-started)
- [Requirements](#requirements)
- [Local Setup](#local-setup)
- [API Reference](#api-reference)
- [Authentication](#authentication)
- [Errors](#errors)
- [Deployment](#deployment)
Заголовок H1 исключен, потому что он находится выше диапазона, разделы H2 расположены заподлицо слева, а их дети H3 имеют отступы на один уровень. Вставьте этот блок прямо под заголовком в свой README, и каждая запись перейдет в его раздел на GitHub. Это вся работа, выполненная за время, необходимое для чтения этого предложения, и она остается правильной, потому что машина вычислила slugs вместо вас.
Часто задаваемые вопросы
Как работает оглавление Markdown?
Оглавление Markdown - это список ссылок, указывающих на привязки заголовков на одной странице. Каждому заголовку документа Markdown присвоен автоматический идентификатор и ссылка, записанная как Раздел переходим к нему. этот инструмент считывает ваши заголовки, строит соответствующие якоря и собирает для вас вложенный список.
Как генерируются якорные ссылки?
Якоря следуют правилу GitHub slug: текст заголовка имеет нижний регистр, пунктуация, отличная от дефисов, удаляется, а пробелы становятся дефисами. "Установить & amp; Config" становится настройкой идентификатора-config. Когда два заголовка производят один и тот же slug, второй получает суффикс -1, третий -2 и так далее, соответствующий тому, как GitHub их отображает.
Работает ли он с файлами GitHub README?
Да. Алгоритм slug отражает тот, который GitHub использует для рендеринга идентификаторов заголовков, поэтому ссылки на оглавление правильно разрешаются внутри README на github.com. Вставьте свой README, выберите уровни заголовков и опустите сгенерированный список под заголовок.
Могу ли я выбрать, какие уровни заголовков появятся?
Да. Установите минимальный и максимальный уровень, например от H2 до H4, и включены только заголовки в этом диапазоне. Глубина гнездования измеряется относительно самого мелкого включенного заголовка, поэтому контур никогда не начинается с большого пустого отступа.
Включены ли заголовки внутри блоков кода?
Нет. Строки, начинающиеся с # внутри огороженного кодового блока (ограниченные тройными обратными тильдами или тройными тильдами), рассматриваются как код, а не заголовки, поэтому фрагменты примеров и комментарии оболочки никогда не появляются в оглавлении.
В чем разница между заказанным и незаказанным ТОС?
В неупорядоченном оглавлении для каждой записи используются маркеры бюллетеней, такие как дефис, а в упорядоченном - числа, увеличивающиеся в пределах каждого уровня вложения. выбирайте упорядоченный, когда читателям выгоден пронумерованный контур, и неупорядоченный для более легкого и традиционного блока содержимого.
Поддерживает ли инструмент заголовки Setext?
Да. Он читает оба заголовка ATX, которые начинаются с заголовков # и Setext, где строка текста подчеркнута знаками равенства для H1 или дефисами для H2. Оба стиля преобразуются в якорные ссылки одинаково.
Генератор Markdown TOC бесплатный и приватный?
Да. Это совершенно бесплатно без регистрации и ограничений. Весь анализ происходит в вашем браузере с использованием JavaScript на стороне клиента, поэтому вставка Markdown никогда не покидает ваше устройство, и инструмент продолжает работать в автономном режиме после загрузки страницы.



