GitHub Slugger generates URL-friendly slugs that exactly match GitHub's markdown heading anchor behavior. It provides both stateful and stateless slug generation, with the stateful version automatically handling duplicate slugs by appending incremental numbers.
index.d.ts) for type safetynpm install github-sluggerES Module (default export is BananaSlug class):
import GithubSlugger from "github-slugger";With named imports:
import GithubSlugger, { slug } from "github-slugger";Note: This package is ES Module only ("type": "module" in package.json). CommonJS imports are not supported.
import GithubSlugger from "github-slugger";
const slugger = new GithubSlugger();
// First occurrence returns base slug
slugger.slug('foo');
// returns 'foo'
// Subsequent occurrences get numbered suffixes
slugger.slug('foo');
// returns 'foo-1'
slugger.slug('bar');
// returns 'bar'
slugger.slug('foo');
// returns 'foo-2'
// Handles Unicode and special characters
slugger.slug('Привет non-latin 你好');
// returns 'привет-non-latin-你好'
slugger.slug('😄 emoji');
// returns '-emoji'
// Reset to start fresh
slugger.reset();
slugger.slug('foo');
// returns 'foo'GitHub Slugger is built around two complementary approaches:
GithubSlugger class tracks previously generated slugs and ensures uniquenessslug function provides consistent slug generation without trackingThe primary class for generating unique slugs that match GitHub's behavior.
/**
* Slugger class that tracks generated slugs to ensure uniqueness
* Note: The actual class name is BananaSlug, exported as default
*/
class BananaSlug {
/**
* Create a new slug class instance
*/
constructor();
/**
* Generate a unique slug, tracking previously generated slugs
* Repeated calls with the same value will result in different slugs
* @param value - String of text to slugify
* @param maintainCase - Keep the current case, otherwise make all lowercase (default: false)
* @returns A unique slug string
*/
slug(value: string, maintainCase?: boolean): string;
/**
* Reset internal state - forget all previous slugs
*/
reset(): void;
}Usage Examples:
import GithubSlugger from "github-slugger";
const slugger = new GithubSlugger();
// Basic slug generation with automatic uniqueness
const headers = ['Introduction', 'Usage', 'Introduction'];
const slugs = headers.map(header => slugger.slug(header));
// Result: ['introduction', 'usage', 'introduction-1']
// Case preservation option
slugger.reset();
const preservedCase = slugger.slug('CaMeLcAsE', true);
// Result: 'CaMeLcAsE'
const lowerCase = slugger.slug('CaMeLcAsE');
// Result: 'camelcase'Standalone function for generating consistent slugs without tracking.
/**
* Generate a slug without tracking previously generated slugs
* Repeated calls with the same value will result in the exact same slug
* @param value - String of text to slugify
* @param maintainCase - Keep the current case, otherwise make all lowercase (default: false)
* @returns A slug string (consistent for same input)
*/
function slug(value: string, maintainCase?: boolean): string;Usage Examples:
import { slug } from "github-slugger";
// Consistent results for same input
slug('foo bar baz');
// always returns 'foo-bar-baz'
slug('foo bar baz');
// still returns 'foo-bar-baz' (no tracking)
// Case handling
slug('CaMeLcAsE', true);
// returns 'CaMeLcAsE'
slug('CaMeLcAsE');
// returns 'camelcase'GitHub Slugger implements GitHub's exact character filtering behavior:
-)maintainCase is trueThe library handles edge cases gracefully:
// Default export - BananaSlug class (typically imported as GithubSlugger)
class BananaSlug {
constructor();
slug(value: string, maintainCase?: boolean): string;
reset(): void;
}
// Named export - standalone function
function slug(value: string, maintainCase?: boolean): string;
// Export structure
export default BananaSlug;
export { slug };