I'm building a website with Jekyll and Github-Page written in markdown. I want to make it easy to permalink to headers, the way most online documentation does.
I want to get a URL with a hash when I click on a header. Is there an easy way to achieve this in Kramdown or in Jekyll's config?
Markdown page
#### A regular header
A regular sentence.
Ideal result
<h4 id="a-regular-header"><a href="#a-regular-header">A regular header</a></h4>
<p>A regular sentence.</p>
If you want a GitHub Pages compatible way of doing this without JavaScript, you can get crazy creative with Liquid and carefully parse your rendered HTML as strings and manipulate it as such.
Or you could just use this snippet that does exactly that: https://github.com/allejo/jekyll-anchor-headings
You can do this manually in the Markdown for each title:
#### [A regular header](#a-regular-header)
A regular sentence.
The downside there is the maintenance cost. Another option would be to create the links on the client side by adding this to the bottom of your chosen pages:
<script>
var headings = document.querySelectorAll("h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]");
for (var i = 0; i < headings.length; i++) {
headings[i].innerHTML =
'<a href="#' + headings[i].id + '">' +
headings[i].innerText +
'</a>';
}
</script>
You could look into a plugin, modified Markdown parser or task runner like gulp.js to do this at build time if the JavaScript dependency doesn't suit your audience. You can't use these alternatives if you want GitHub Pages to build your page, but you can build locally and commit the output.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With