diff --git a/_plugins/auto-anchor.rb b/_plugins/auto-anchor.rb new file mode 100644 index 00000000..627a1654 --- /dev/null +++ b/_plugins/auto-anchor.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true +# This file is based on code from https://github.com/bitcoinops/bitcoinops.github.io + +# Automatically adds id tags (anchors) to list items + +require 'digest/md5' + +def generate_slug(text) + # Remove double-quotes from titles before attempting to slugify + text.gsub!('"', '') + # Remove whitespace character from the end and use Liquid/Jekyll slugify filter + slug_text = "{{ \"#{text.rstrip}\" | slugify: 'latin' }}" + # use the digest library to create deterministic ids based on text + id = Digest::MD5.hexdigest(slug_text)[0...7] + slug = "\#b#{id}" # prefix with 'b', ids cannot start with a number + slug +end + +def generate_anchor_list_link(anchor_link, class_name='anchor-list-link') + # custom clickable bullet linking to an anchor + "" +end + +def auto_anchor(content) + # finds “bulleted” list items that start with hyphen (-) or asterisk (*) + # adds anchor and clickable bullet + content.gsub!(/^ *[\*-] .*?(?:\n\n|\z)/m) do |bulleted_paragraph| + slug = generate_slug(bulleted_paragraph) + bullet_character = bulleted_paragraph.match(/^ *([\*-])/)[1] # bullet can be '-' or '*' + id_prefix = "#{bullet_character} {:#{slug} .anchor-list} #{generate_anchor_list_link(slug)}" + bulleted_paragraph.sub!(/#{Regexp.quote(bullet_character)}/, id_prefix) + end + # finds “numbered” list items that start with number (1.) + # adds anchor only + content.gsub!(/^ *\d+\. .*?(?:\n\n|\z)/m) do |numbered_paragraph| + slug = generate_slug(numbered_paragraph) + id_prefix = "1. {:#{slug} .anchor-list .anchor-numbered}" + numbered_paragraph.sub!(/\d+\./, id_prefix) + end +end + +## Run automatically on all documents +Jekyll::Hooks.register :documents, :pre_render do |post| + ## Don't process documents if YAML headers say: "auto_id: false" + unless post.data["auto_id"] == false + auto_anchor(post.content) + end +end + +module TextFilter + # This is a custom filter used in backlinks.html to + # add anchor links to each backlink snippet + def link_to_anchor(text, url) + slug = generate_slug(text) + id_prefix = generate_anchor_list_link("#{url}#{slug}", "backlink-link") + text.sub!(/(?:-|\*|\d+\.)/, id_prefix) # this targets both “bulleted” and “numbered” list items + text + end +end + +Liquid::Template.register_filter(TextFilter) diff --git a/assets/css/all.sass b/assets/css/all.sass index d9708f53..e30faaf2 100644 --- a/assets/css/all.sass +++ b/assets/css/all.sass @@ -201,3 +201,33 @@ a font-size: 0.85em color: #828282 +@keyframes highlightfade + from + background: var(--target-color) + to + background: transparent + +.anchor-list + list-style: none + &:target + background: transparent + animation-name: highlightfade + animation-duration: 7s + +.anchor-numbered + list-style: decimal + +.anchor-list-link + color: var(--text-color) + margin-left: -14px + padding-right: 3px + font-size: 0.45em + display: inline-block + position: relative + top: -0.4em /* position the dot vertically in the middle of the container element */ + text-decoration: none + +.backlink-link + @extend .anchor-list-link + font-size: 0.7em + top: -0.25em