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/20/2026
Yes — it's called slugifyWithCounter().
How it works:
slugifyWithCounter() is a factory function that returns a new stateful slugify function (typed as CountableSlugify) which keeps track of previously seen slugs so it can disambiguate repeats [index.js:L112-L140].
Internally:
- It creates a
Mapcalledoccurrencesto track how many times each slug has been generated [index.js:L113]. - The returned function
countable(string, options)first runs the normalslugify(string, options)on the input [index.js:L116]. - If the result is an empty string, it just returns
''[index.js:L118-L120]. - Otherwise, it lowercases the slug (
stringLower) for consistent lookups [index.js:L122]. - It checks
numberless— the count for the "base" version of the string with any trailing-Ncounter suffix stripped via the regex/(?:-\d+?)+?$/[index.js:L123]. - It gets the current
counterfor the exactstringLowerkey, increments it in the map (or sets it to1if it doesn't exist yet), and reads the new counter value [index.js:L124-L126]. - If
newCounter >= 2ornumberless > 2, it appends-${newCounter}to the slug to make it unique [index.js:L127-L129]. - It returns the (possibly suffixed) slug [index.js:L131].
The returned function also exposes a .reset() method that clears the occurrences map, letting you start counting fresh [index.js:L134-L136].
Example usage (from the README and type docs):
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 pattern is documented as CountableSlugify in the type definitions [index.d.ts:L220-L285] and exported as slugifyWithCounter(): CountableSlugify [index.d.ts:L286-L287].
A practical use case mentioned in the README: generating unique HTML ids for headings/anchors when a document has repeated section names (e.g., multiple "Example" subsections across different sections), so anchor links resolve to the correct heading [readme.md:L279-L283].
FOLLOW_UPS:
- What does the
decamelizeoption actually transform? - How do
customReplacementsoverride default replacements? - What transliteration languages does
@sindresorhus/transliteratesupport?
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.