Is there a slugify-with-counter helper? How does it work?
Is there a slugify-with-counter helper? How does it work?
About sindresorhus/slugify · 2 messages · last activity 7/27/2026
Yes — slugifyWithCounter() is exported from index.js and provides a stateful version of slugify that appends numeric suffixes to disambiguate repeated slugs.
How it works
Creation and state
It's a factory function that creates a fresh occurrences map (a Map) to track how many times each slugged string has been seen, then returns a countable function closing over that map [index.js:L112-L114].
Per-call logic [index.js:L116-L128]
- The input string is first run through the normal
slugify(string, options). - If the result is empty, it returns
''immediately. - It lowercases the slug (
stringLower) to use as the map key, so counting is case-insensitive. - It checks
numberless— the count previously recorded for the "base" version of the string (with any trailing-<number>suffix stripped via the regex/(?:-\d+?)+?$/). This guards against edge cases where a string naturally already ends in-<digits>. - It looks up
counter, the existing recorded count for this exact lowercased string. - It increments/sets the occurrence count in the map: if there's a numeric counter already, increment it; otherwise set it to
1. newCounteris read back from the map (defaulting to2if unset).- If
newCounter >= 2ornumberless > 2, the counter is appended to the slug as${string}-${newCounter}. - Returns the (possibly suffixed) slug.
Reset
The returned function also has a .reset() method that simply clears the occurrences map, letting you restart counting from scratch [index.js:L130-L132].
Example usage
import {slugifyWithCounter} from '@sindresorhus/slugify';
const slugify = slugifyWithCounter();
slugify('foo bar');
//=> 'foo-bar'
slugify('foo bar');
//=> 'foo-bar-2'
slugify.reset();
slugify('foo bar');
//=> 'foo-bar'
This is documented in the readme [readme.md:L245-L266] and typed in index.d.ts as the CountableSlugify type, which declares both the callable signature and the reset(): void method [index.d.ts:L220-L241, index.d.ts:L286-L287].
Use case
The readme calls out a specific motivating scenario: generating unique HTML ids for repeated headings (e.g., multiple "Example" subsections across different sections in a document), so anchor links resolve to the correct heading instead of colliding [readme.md:L266-L272].
FOLLOW_UPS:
- What does the base
slugifyfunction's options object support? - How does
customReplacementsinteract with decamelization? - What test cases cover
slugifyWithCounterbehavior?
Want to ask your own question?
Open chat for sindresorhus/slugifyPublic Q&A. Generated by RepoPilot from the actual source of sindresorhus/slugify. AI answers can be incomplete or stale — verify before relying on them.