Handling anchors in posts created with markdown

AI-generated summary

The discussion centers around handling and hiding automatically generated anchors when posting Markdown content in Discourse. Nihokam initially sought a way to hide these anchors, as they interfere with cross-referencing in externally used Markdown documents.

Arkshine explained Discourse uses MarkdownIt, based on CommonMark, which doesn’t natively support header IDs, but Discourse generates them automatically using patterns like h-{headingId} or p-{postId}-h-{headingId} see post #2. They suggested using manual HTML anchors <a name="anchor_name"></a> as an alternative and linked to a Discourse Table of Contents component (https://meta.discourse.org/t/discotoc-automatic-table-of-contents/111143).

Nihokam decided to pre-process the Markdown before posting. Arkshine then offered a Discourse plugin (https://github.com/Arkshine/discourse-custom-anchor-id) allowing custom anchor IDs next to headings (e.g., ## My Heading {#custom_section}). Nihokam will check with their administrator about installing the plugin. Finally, mrmowji questioned the anchor generation patterns, noting discrepancies on meta.discourse.org, and asked if there are any related settings.

Hey community, I am using a discourse site to publish some specs that are primarily written in markdown, but I came to the problem that the anchors used for the headers are being rendered, while they should be hidden.

Does anyone know if there is a way to hide them?

Hey, welcome!

Is this syntax from kramdown or PHP Markdown Extra?

Discourse relies on MarkdownIt, which is based on CommonMark spec. It doesn’t support specifying a header ID.

It seems that they discussed it at some point: Anchors in markdown - Spec - CommonMark Discussion, but I don’t see any definitive conclusion.

However, Discourse generates anchor automatically.
You can see it here:

https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse-markdown-it/src/features/anchor.js

Essentially, you can expect those IDs:

  • h-{headingId} (no post ID, no slug)
  • h-{slug}-{headingId} (no post ID)
  • p-{postId}-h-{headingId} (post ID, no slug)
  • p-{postId}-h-{slug}-{headingId} (post ID, slug)

E.g.:

If you prefer, you can still create an anchor manually with HTML, e.g., <a name="anchor_name"></a>


Additional resources –
If you need to generate a Table of Contents, there is this component for you:

Thanks a lot @Arkshine!

The issue is more because we are publishing the markdowns used for other reasons in discourse as well, so the people who keep the documents use these anchors for cross-reference when merging multiple markdowns in a single document.

I think I will make some sort of script to clean up before posting the content.

I see!

The solution is also to make a plugin for Discourse with a markdown plugin to support this syntax. If you have some budget, you could ask Marketplace.

@Nihokam

If you’re still interested, I made a tiny Discourse plugin that handles specifying an anchor ID next to the heading.

https://github.com/Arkshine/discourse-custom-anchor-id

It works alongside Discourse’s automatic heading anchors.
Note that it’s basic support. There are probably a lot of variants, but this plugin supports only the following:

## My Heading {#custom_section}

will generate:

<a name="custom_section" href="#custom_section" class="custom-anchor-id"></a>

You can give it a try! Let me know if you have any issues with it.

Thanks @Arkshine!

I will check with our discourse adm about using it :grin:

@Arkshine Do you know how anchors in Discourse (the current website) are generated? Asking because they don’t seem to follow the patterns you shared. For example, see this:

https://meta.discourse.org/t/adding-a-table-to-your-post-using-markdown/66544#creating-a-simple-table-1

Is there a setting for this? I couldn’t find it. Or do they use <a>? Or your plugin?