You can use Jekyll plugins to override the standard behaviour. I put this in _plugins/header.rb
:
class Jekyll::MarkdownHeader < Jekyll::Converters::Markdown
def convert(content)
super.gsub(/<h(\d) id="(.*?)">/, '<h\1 id="\2"><a href="#\2">§</a>')
end
end
The regexp replaces all headers with an ID tag with one that also adds a link. This is not a fool-proof way to do this in a generic case (e.g. <h2 class="foo" id="x")
won't work), but the Kramdown output is fairly reliable and consistent, so it should be okay. I added this with Jekyll 3.8.4 and Kramdown 1.17.0.
If you want/need a more robust solution then you can use a HTML parser. Shouldn't be that much harder.
The advantage of this is that it doesn't require JavaScript on the client side.
Or if you want to link the actual heading instead of prepending a link:
class Jekyll::MarkdownHeader < Jekyll::Converters::Markdown
def convert(content)
super.gsub(/<h(\d) id="(.*?)">(.*)<\/h(\d)>/, '<h\1 id="\2"><a href="#\2">\3</a></h\1>')
end
end