simov / slugify

Slugifies a string
MIT License
1.47k stars 126 forks source link

Suggestion: add exception characters #186

Closed KevynTD closed 4 months ago

KevynTD commented 5 months ago

The suggestion is to have an extra object in the settings where I can add some characters that I don't want to be replaced.

My use case is as follows, I wanted to use it to form URLs, but I didn't want it to delete the '/' from the string. It would make it easier to have an exception option like this:

slugify('have some string/in test here', {exceptions: '/'})
// have-some-string/in-test-here
Trott commented 5 months ago

I defer to @simov on this, but I dislike extending the API further like this as it is fraught with surprises. For starters, what if exceptions collides with replacement or remove? It's not obvious which one should take precedence. And surprises like that lead to bug reports. I also don't think very many people will use this feature.

I'm not sure if there is a way to do this entirely with existing slugify APIs, but it sure seems like for this use case, using split(), map(), and join() is the way to go:

const urlPath = '//here is a string/and another/and finally one more'
const result = urlPath.split('/').map(slug).join('/')

// result === '//here-is-a-string/and-another/and-finally-one-more'

If you really want to do it inside the library, slug allows you to modify the internal charmap so you can do this:

slug.charmap['/'] = '/';
slug('have some string/in test here'); // have-some-string/in-test-here 
madebyfabian commented 4 months ago

I too would have a usecase for this feature. In my case, I have this string: Büromitarbeiter Jobs. I want to allow german umlauts in my url paths, so the generated slug should be: büromitarbeiter-jobs. But even with .extend it does not override:

slugify.extend({
  'ä': 'ä',
  'ö': 'ö',
  'ü': 'ü',
  'ß': 'ß',
})

// slugify() still returns `bueromitarbeiter-jobs`

And I cannot see a charmap option in the slugify object/method: Errors Property 'charmap' does not exist on type 'typeof slugify'

Trott commented 4 months ago

And I cannot see a charmap option in the slugify object/method: Errors Property 'charmap' does not exist on type 'typeof slugify'

charmap is in the slug module, not slugify. You'd need to switch to slug. slug and slugify are sufficiently similar that they are typically drop-in replacements for one another, but the charmap is one difference.

Trott commented 4 months ago

@madebyfabian For what it's worth, slug works the way you seem to want/expect it to with .extend().

'use strict'

const slug = require('slug')
const slugify = require('slugify')

slugify.extend({
  'ä': 'ä',
  'ö': 'ö',
  'ü': 'ü',
  'ß': 'ß',
})

console.log(slugify('Büromitarbeiter Jobs')) // Bromitarbeiter-Jobs

slug.extend({
  'ä': 'ä',
  'ö': 'ö',
  'ü': 'ü',
  'ß': 'ß',
})

console.log(slug('Büromitarbeiter Jobs')) // büromitarbeiter-jobs
Trott commented 4 months ago

@KevynTD I just noticed now that slug also works the way you would seem to want it to with .extend():

slugify.extend({'/': '/'})
slug.extend({'/': '/'})

console.log(slugify('foo/bar')) // foobar
console.log(slug('foo/bar')) // foo/bar
KevynTD commented 4 months ago

Thanks for the tip Trott!! The library simplified it to a few less lines here in my code, the slug library has a proposal that best suits for URLs (my case).

What you mentioned about being able to cause errors is really a very strong point in relation to modifying slugify with a new function.

It's closed for me!