glugify/anchor

GitHub-compatible heading anchors, matching the github-slugger JavaScript library (and therefore GitHub’s own markdown rendering). Use this when generating anchors for tables of contents, static site generators or anything that must agree with GitHub about which #id a heading gets.

This is a different algorithm from glugify.slugify: GitHub keeps underscores, keeps every Unicode letter (no transliteration), turns each space into exactly one hyphen without collapsing, and does not trim. "Hello, _World_!" anchors to "hello-_world_" but slugifies to "hello-world".

import glugify/anchor

anchor.to_anchor("Hello, World!")
// -> "hello-world"

let a = anchor.new()
let #(a, first) = anchor.anchor(a, "Intro")
let #(_, second) = anchor.anchor(a, "Intro")
// first -> "intro"
// second -> "intro-1"

The character classes come from the host’s Unicode tables (Erlang’s re module or the JavaScript regex engine), so behavior can differ for characters from recently added scripts. In particular, OTP 27 and earlier bundle a regex engine with Unicode 7.0 tables, so letters from scripts added later (Osage, Adlam, Cherokee lowercase, …) are stripped there but kept on OTP 28+ and JavaScript. Common scripts are unaffected.

Types

Tracks anchors handed out so far, so duplicate headings get unique ids (intro, intro-1, intro-2, …) with the same counting behavior as github-slugger. Create one with new and thread it through anchor calls.

pub opaque type Anchorer

Values

pub fn anchor(
  anchorer: Anchorer,
  text: String,
) -> #(Anchorer, String)

Converts text to a GitHub-style anchor and makes it unique against everything this anchorer has produced before.

Examples

let a = new()
let #(a, first) = anchor(a, "Intro")
let #(_, second) = anchor(a, "Intro")
// first -> "intro"
// second -> "intro-1"
pub fn anchor_maintaining_case(
  anchorer: Anchorer,
  text: String,
) -> #(Anchorer, String)

Like anchor, but keeps the original case.

pub fn new() -> Anchorer

Creates a fresh anchorer with no anchors taken.

pub fn to_anchor(text: String) -> String

Converts text to a GitHub-style anchor: lowercased, with every character GitHub strips removed and each space turned into a hyphen.

Unlike glugify.slugify, consecutive spaces produce consecutive hyphens and underscores are kept, exactly as GitHub renders heading ids.

Examples

to_anchor("Hello, World!")
// -> "hello-world"

to_anchor(":ok_hand: Single")
// -> "ok_hand-single"

to_anchor("I ♥ unicode")
// -> "i--unicode"
pub fn to_anchor_maintaining_case(text: String) -> String

Like to_anchor, but keeps the original case, matching github-slugger’s maintainCase option.

Examples

to_anchor_maintaining_case("Hello, World!")
// -> "Hello-World"
Search Document