RepoPilot

Is there a slugify-with-counter helper? How does it work?

About sindresorhus/slugify · 2 messages · last activity 8/1/2026

Question

Is there a slugify-with-counter helper? How does it work?

RepoPilot

Yes — it's called slugifyWithCounter(), exported from the main module.

How it works:

slugifyWithCounter() is a factory function that returns a stateful slugify function (typed as CountableSlugify) which keeps track of how many times each slug has been generated so it can append a numeric suffix to duplicates [index.js:L112-L140].

Internally:

  1. It creates a Map called occurrences to track how many times each base slug has been seen [index.js:L113].
  2. The returned function countable(string, options) first runs the normal slugify(string, options) to get the base slug [index.js:L115].
  3. If the result is an empty string, it returns '' immediately [index.js:L117-L119].
  4. It lowercases the slug and strips any existing trailing -<number> suffix to compute a "numberless" occurrence count via stringLower.replace(/(?:-\d+?)+?$/, '') [index.js:L121].
  5. It looks up the current counter for the exact lowercased string, increments it (or initializes it to 1 if it doesn't exist yet), and stores it back in the map [index.js:L122-L124].
  6. If the new counter is >= 2, or if the numberless count exceeds 2, it appends -${newCounter} to the slug [index.js:L125-L127].
  7. It returns the (possibly suffixed) slug [index.js:L129].

There's also a .reset() method attached to the returned function, which clears the occurrences map so counting starts fresh [index.js:L132-L134].

Example usage [readme.md:L245-L272]:

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 useful for generating unique HTML ids, e.g. when a document has repeated section names (like multiple "Example" subsections), so anchor links point to the correct headline instead of colliding [index.d.ts:L266-L283].

The TypeScript types for this are declared in [index.d.ts:L220-L285] (the CountableSlugify type, including the callable signature and reset method) and the factory itself is declared at [index.d.ts:L286-L287].

FOLLOW_UPS:

  • What options does the base slugify() function accept?
  • How does customReplacements interact with counting?
  • What does preserveLeadingUnderscore do exactly?

Want to ask your own question?

Open chat for sindresorhus/slugify

Public Q&A. Generated by RepoPilot from the actual source of sindresorhus/slugify. AI answers can be incomplete or stale — verify before relying on them.