# Идентичные заголовки приводят к одинаковым id и якорям

**URL:** https://meta.discourse.org/t/having-identical-titles-leads-to-identical-ids-and-anchors/270649
**Category:** Feature
**Tags:** pr-welcome, disco-toc
**Created:** [21.Июнь.2023 08:00:08 UTC](https://meta.discourse.org/t/having-identical-titles-leads-to-identical-ids-and-anchors/270649 "2023-06-21T08:00:08Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![anderer](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/anderer/32/310458_2.png) [@anderer](https://meta.discourse.org/u/anderer)
#### Post date: [21.Июнь.2023 08:00:08 UTC](https://meta.discourse.org/t/having-identical-titles-leads-to-identical-ids-and-anchors/270649/1 "2023-06-21T08:00:08Z")

</div>

Привет,

Я обнаружил ошибку (?) или техническое ограничение. Ссылки в оглавлении, а также подсветка при прокрутке работают некорректно, если заголовки имеют одинаковые названия. Думаю, это связано с тем, что генерируется не уникальный ID, а ID совпадает с названием заголовка.

В моём случае оглавление выглядит так — благодаря педагогическому образованию структура наших учебных модулей всегда одинакова, например:

- H1 - Обзор
- H1 - 0:00 \> 0:15 - Пленарное заседание и введение
  - H2 - Цель
  - H2 - Содержание
  - H2 - Методика
  - H2 - Советы
  - H2 - Слайды

- H1 - 0:15 \> 0:45 - Работа в группах
  - H2 - Цель
  - H2 - Содержание
  - H2 - Методика
  - H2 - Советы
  - H2 - Слайды

- H1 - 0:45 \> 0:60 - Индивидуальная работа
  - H2 - Цель
  - H2 - Содержание
  - H2 - Методика
  - H2 - Советы
  - H2 - Слайды

- H1 - 0:60 \> 0:90 - Пленарное обсуждение
  - H2 - Цель
  - H2 - Содержание
  - H2 - Методика
  - H2 - Советы
  - H2 - Слайды

Думаю, можно было бы сделать заголовки H2 более информативными, но это противоречит идее единой структуры для всех учебных модулей. Особенно в случаях «Советы» и «Слайды» добавить больше информации сложно.

Возможно, вся эта проблема связана с упомянутым выше вопросом, но я не настолько эксперт.

> [@topological](#):
>
> Если в посте несколько заголовков на китайском языке (включая отсутствие символов ASCII), то при клике на элемент навигации справа переход осуществляется только к первому заголовку данного уровня. Я полагаю, что это происходит потому, что DiscoTOC генерирует элементы навигации с одинаковыми ID (так как все заголовки на китайском языке).

---

<div class="post-metadata">

### Author: ![Canapin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/canapin/32/119591_2.png) [@Canapin](https://meta.discourse.org/u/Canapin)
#### Post date: [05.Июль.2023 18:22:07 UTC](https://meta.discourse.org/t/having-identical-titles-leads-to-identical-ids-and-anchors/270649/2 "2023-07-05T18:22:07Z")

</div>

Это не ошибка, а особенность самого HTML, поэтому это техническое ограничение.

Видео, демонстрирующее такое поведение с использованием компонента темы, как вы описали:

Я считаю, что это задача с низким приоритетом, но изменения были бы кстати, поэтому я добавлю тег #pr-welcome, если кто-то захочет этим заняться. 🙂

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [05.Июль.2023 18:33:11 UTC](https://meta.discourse.org/t/having-identical-titles-leads-to-identical-ids-and-anchors/270649/3 "2023-07-05T18:33:11Z")

</div>

> [@Canapin](#):
>
> Это не ошибка, а особенность самого HTML, то есть техническое ограничение.

Хм, нет, у якорей генерируются уникальные атрибуты `name`

```plaintext
# Заголовок уровня A
foo

## Заголовок уровня B
bar

## Заголовок уровня B
bar

# Заголовок уровня A
foo

## Заголовок уровня B
bar

## Заголовок уровня B
bar

```

генерирует: (обратите внимание на -1 -2 -3 и т.д.)

```html
<h1 dir="ltr">
  <a name="heading-level-a-1" class="anchor" href="#heading-level-a-1"></a>Заголовок уровня A
</h1>
<p dir="ltr">foo</p>
<h2 dir="ltr">
  <a name="heading-level-b-2" class="anchor" href="#heading-level-b-2"></a>Заголовок уровня B
</h2>
<p dir="ltr">bar</p>
<h2 dir="ltr">
  <a name="heading-level-b-3" class="anchor" href="#heading-level-b-3"></a>Заголовок уровня B
</h2>
<p dir="ltr">bar</p>
<h1 dir="ltr">
  <a name="heading-level-a-4" class="anchor" href="#heading-level-a-4"></a>Заголовок уровня A
</h1>
<p dir="ltr">foo</p>
<h2 dir="ltr">
  <a name="heading-level-b-5" class="anchor" href="#heading-level-b-5"></a>Заголовок уровня B
</h2>
<p dir="ltr">bar</p>
<h2 dir="ltr">
  <a name="heading-level-b-6" class="anchor" href="#heading-level-b-6"></a>Заголовок уровня B
</h2>
<p dir="ltr">bar</p>

```

---

<div class="post-metadata">

### Author: ![Canapin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/canapin/32/119591_2.png) [@Canapin](https://meta.discourse.org/u/Canapin)
#### Post date: [05.Июль.2023 18:46:08 UTC](https://meta.discourse.org/t/having-identical-titles-leads-to-identical-ids-and-anchors/270649/4 "2023-07-05T18:46:08Z")

</div>

> [@Richard - Communiteq](#):
>
> Хм, нет, у якорей появляются уникальные атрибуты `name`.

Значения атрибутов основаны на содержании заголовков, поэтому одинаковые заголовки будут иметь идентичные атрибуты `id` и `data-d-toc`:

Последний заголовок «Aim»:

 ![image](https://global.discourse-cdn.com/meta/original/4X/3/8/a/38a439bdf25466234e7de47acd2c7aa70efb9cd7.png)

Приводит к первому элементу «Aim», у которого атрибуты `id` и `data-d-toc` имеют то же значение, что и последний элемент оглавления:

 ![image](https://global.discourse-cdn.com/meta/original/4X/c/5/c/c5c591adb94ce71118d67ac0b415b8a275794151.png)

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [05.Июль.2023 19:14:52 UTC](https://meta.discourse.org/t/having-identical-titles-leads-to-identical-ids-and-anchors/270649/5 "2023-07-05T19:14:52Z")

</div>

> [@Canapin](#):
>
> Значения атрибутов основаны на содержимом заголовков, поэтому идентичные заголовки будут иметь идентичные атрибуты `id` и `data-d-toc`:

Верно, поэтому это не является внутренним ограничением HTML (на самом деле наличие идентичных `id` в одном документе нарушает [спецификацию](https://www.w3.org/TR/2015/WD-html51-20151008/dom.html#the-id-attribute)), а представляет собой ошибку в компоненте темы.

Полагаю, что [этот код](https://github.com/discourse/DiscoTOC/blob/main/javascripts/discourse/initializers/disco-toc-main.js#L50-L52)

```js
const suffix = slugify(h.textContent) || index;
const id = h.getAttribute("id") || slugify(`toc-${h.nodeName}-${suffix}`);

```

должен быть изменён на что-то вроде

```js
const suffix = slugify(h.textContent) || '';
const id = h.getAttribute("id") || slugify(`toc-${h.nodeName}-${suffix}-${index}`);

```
