Skip to content

Instantly share code, notes, and snippets.

@creachadair
Last active October 10, 2023 16:35
Show Gist options
  • Save creachadair/e35cefd8e3fbdfe3cce4f6178da1cd70 to your computer and use it in GitHub Desktop.
Save creachadair/e35cefd8e3fbdfe3cce4f6178da1cd70 to your computer and use it in GitHub Desktop.
GitHub Heading Anchors and You: A Tale of Needless and Undocumented Complexity

GitHub renders Markdown in its UI according to the GitHub Flavored Markdown (GFM) spec. In addition, it adds generated link anchors for document headers. For example, a Markdown heading like:

## Fee Fie Fo Fum

is rendered with a link anchor of #fee-fie-fo-fum in the GitHub UI. Knowing this, you may wish to add links in other Markdown documents in your repository that point to those anchor targets. There are various descriptions floating around about how to do this, but all the ones I found contain subtle errors. This document attempts to clarify the rule.

Definitions

  • A word comprises a contiguous run of letters, digits, underscores (_) and hyphens (-), corresponding to the PCRE regular expression [-\w]+.
  • A space means a space (Unicode 32) or tab (Unicode 9).
  • Any character that is not a space or part of a word is punctuation.

Conversion

To convert a title t into an anchor:

  1. Translate t to lower-case.
  2. Partition the resulting string into words separated by runs of space and punctuation.
  3. Delete any space and punctuation prior to the first word and following the last word.
  4. Replace each remaining run of space and punctuation with either:
    • A single hyphen (-), if the run contains any spaces or tabs, or
    • An empty string, otherwise.
  5. After completing step (4), the resulting string is the anchor.

Example

Step Content
Input "Read it and Weep": A sordid semi-AutoBiographical tale/fantasy over 3.5 Generations!
1 "read it and weep": a sordid semi-autobiographical tale/fantasy over 3.5 generations!
2 .read.it.and.weep...a.sordid.semi-autobiographical.tale.fantasy.over.3.5.generations.
3 read.it.and.weep...a.sordid.semi-autobiographical.tale.fantasy.over.3.5.generations
4 read-it-and-weep-a-sordid-semi-autobiographical-talefantasy-over-35-generations
5 (output)

An implementation of this algorithm in the Go playground

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment