RepoPilot

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

About sindresorhus/slugify · 2 messages · last activity 7/27/2026

Question

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

RepoPilot

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]

  1. The input string is first run through the normal slugify(string, options).
  2. If the result is empty, it returns '' immediately.
  3. It lowercases the slug (stringLower) to use as the map key, so counting is case-insensitive.
  4. 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>.
  5. It looks up counter, the existing recorded count for this exact lowercased string.
  6. It increments/sets the occurrence count in the map: if there's a numeric counter already, increment it; otherwise set it to 1.
  7. newCounter is read back from the map (defaulting to 2 if unset).
  8. If newCounter >= 2 or numberless > 2, the counter is appended to the slug as ${string}-${newCounter}.
  9. 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 slugify function's options object support?
  • How does customReplacements interact with decamelization?
  • What test cases cover slugifyWithCounter behavior?

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.