# TOC component and header IDs

**URL:** https://meta.discourse.org/t/toc-component-and-header-ids/156601
**Category:** Support
**Created:** [July 2, 2020, 2:00pm UTC](https://meta.discourse.org/t/toc-component-and-header-ids/156601 "2020-07-02T14:00:34Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![guildai](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/guildai/32/248544_2.png) [@guildai](https://meta.discourse.org/u/guildai)
#### Post date: [July 2, 2020, 2:00pm UTC](https://meta.discourse.org/t/toc-component-and-header-ids/156601/1 "2020-07-02T14:00:34Z")

</div>

The TOC component generates header element `id` attrs based on the header text.

Here’s a header for example.

#### main outlet

The spacing comes from the styles applied to `#main-outlet`, which is a Discourse app element having nothing to do with this post.

This isn’t the end of the world if I could specify an alternative `id` for the header. The TOC component supports this:

[https://github.com/discourse/DiscoTOC/blob/master/common/header.html#L293](https://github.com/discourse/DiscoTOC/blob/master/common/header.html#L293)

Unfortunately, Discourse removes `id` attrs from post elements before the above code is run so the logic is thwarted.

Here’s a header that uses `<h4 id="alt-main-outlet">main outlet</h4>`:

#### main outlet

Note that it still uses `main-outlet` rather than `alt-main-outlet`.

I guess Discourse does this in anticipation of someone hacking a page element. But with the TOC component this is easy enough to bypass.

If there’s a solution to this or this is otherwise a well discussed problem that I’ve missed, apologies for the unsolicited opinions that follow 🙂

* * *

P.S.

Personally I think Discourse should NOT strip element `id` attrs. This is a fundamental web page construct and is used in page navigation with URL fragments. If someone wants to create a link to an element in a post, I think that’s their right as an author.

The fact that TOC opens up ID hacking suggests that this measure of stripping IDs in the first place can potentially be dropped.

If the Discourse team is that concerned about ID hijacking, all Discourse IDs should be prefixed e.g. `discourse-main-outlet` and ID stripping should apply only to those prefixed IDs.

I can appreciate the impossibility of this given existing code!

One can imagine a set of excluded IDs (e.g. main-outlet, etc.) that are stripped. This still leaves the problem of TOC being used to bypass this safeguard but it would at least let authors create useful anchors.

* * *

P.P.S.

Directly related to this is the problem of headers with the same text payload.

#### Topic One

##### Examples

#### Topic Two

##### Examples

With TOC, both **Examples** headers get the same ID, which is obviously quite broken. TOC could append incrementing indexes (e.g. `examples`, `examples-2`, etc.) — and it probably should as a default course — but still better would be a solution to the problem discussed above, which lets authors decide how to describe their content. E.g. `<h5 id="topic-one-examples">Examples</h5>`, etc.

---

<div class="post-metadata">

### Author: ![j.jaffeux](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/j.jaffeux/32/60297_2.png) [@j.jaffeux](https://meta.discourse.org/u/j.jaffeux)
#### Post date: [July 4, 2020, 7:45am UTC](https://meta.discourse.org/t/toc-component-and-header-ids/156601/2 "2020-07-04T07:45:58Z")

</div>

@Johani what do you think of this ?

---

<div class="post-metadata">

### Author: ![Johani](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/johani/32/176920_2.png) [@Johani](https://meta.discourse.org/u/Johani)
#### Post date: [July 6, 2020, 7:06am UTC](https://meta.discourse.org/t/toc-component-and-header-ids/156601/3 "2020-07-06T07:06:40Z")

</div>

> [@guildai](#):
>
> Personally I think Discourse should NOT strip element `id` attrs

> [@guildai](#):
>
> Unfortunately, Discourse removes `id` attrs from post elements before the above code is run so the logic is thwarted.
> 
> Here’s a header that uses `<h4 id="alt-main-outlet">main outlet</h4>` :

If you need to add a heading then it needs to be prefixed with `heading--` you can find more information about that here [Linking to a heading within a post or topic](https://meta.discourse.org/t/deep-linking-to-headings-anchors/47552)

ids that are not prefixed like that will be stripped, regardless of what the id value is.

> [@guildai](#):
>
> With TOC, both **Examples** headers get the same ID

Headings with duplicate text are not currently supported - and have never been - in the TOC component. The component generates the id based on the text of the heading. So, two headings with the same exact text will get the same id.

There are no plans to patch this up in the component right now since automatic id generation is on our list of features for the [next release of Discourse](https://meta.discourse.org/t/discourse-version-2-6/151394) and we plan to address the issue of duplicate headings by adding the heading’s index to its id.

> [@guildai](#):
>
> If the Discourse team is that concerned about ID hijacking, all Discourse IDs should be prefixed e.g. `discourse-main-outlet` and ID stripping should apply only to those prefixed IDs.

When we implement this in core, I think adding a prefix to the generated headings should be enough.

---

<div class="post-metadata">

### Author: ![guildai](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/guildai/32/248544_2.png) [@guildai](https://meta.discourse.org/u/guildai)
#### Post date: [July 6, 2020, 12:56pm UTC](https://meta.discourse.org/t/toc-component-and-header-ids/156601/4 "2020-07-06T12:56:57Z")

</div>

> [@Johani](#):
>
> There are no plans to patch this up in the component right now since automatic id generation is on our list of features for the [next release of Discourse](https://meta.discourse.org/t/discourse-version-2-6/151394) and we plan to address the issue of duplicate headings by adding the heading’s index to its id.

That makes sense. Thanks for the detailed explanation!
