vuejs / vuepress

📝 Minimalistic Vue-powered static site generator
https://vuepress.vuejs.org
MIT License
22.52k stars 4.76k forks source link

[[TOC]] links broken with Badges #1985

Open brindosch opened 4 years ago

brindosch commented 4 years ago

Bug report

If [[TOC]] is used in a page where a header has a badge, the link contains also the badge content.

Steps to reproduce

What is expected?

abernov commented 4 years ago

Problem in markdown-it-table-of-contents plugin.

It needs to be replaced with a new one! It’s not difficult to develop such a plugin

kefranabg commented 4 years ago

@abernov The problem is that VuePress and markdown-it-table-of-contents are not applying the slugify function on the same header link.

VuePress will use TEXT and markdown-it-table-of-contents will use TEXT <Badge text="TBA 2.1+"/>

kefranabg commented 4 years ago

As a workaround, you can use a custom markdown slugify function.

abernov commented 4 years ago

@kefranabg Vuepress passes to markdown-it-table-of-content its own slugify function.

It is possible to rewrite this function so that it removes the badge.

kefranabg commented 4 years ago

@abernov yes this is what I suggested in the last comment, but this is a workaround, not a fix.

Rewrite the slugify function we pass to markdown-it-table-of-content to remove badges will work, but later we'll have a new bug report saying it's not working with headers containing emojis and probably other things (so it will be hard to maintain).

The clean way to fix this would be to standardize the way vuepress and markdown-it-table-of-contents parse a header title.

dlecan commented 4 years ago

Here is the code I've used to fix this issue on my site:

In your config.js:

const { slugify: vuePressSlugify } = require("@vuepress/shared-utils");

function customSlugifyToHandleBadges(str) {
 // Remove badges and use original slugify function
  return vuePressSlugify(str.replace(/<Badge[^>]*\/>/, ""));
}
...
module.exports = {
...
  markdown: {
    slugify: customSlugifyToHandleBadges,
    toc: {
      slugify: customSlugifyToHandleBadges,
    },
  },
}