Coder Social home page Coder Social logo

slugify's Introduction

slugify

Slugify a string

Useful for URLs, filenames, and IDs.

It handles most major languages, including German (umlauts), Vietnamese, Arabic, Russian, and more.

Install

$ npm install @sindresorhus/slugify

Usage

import slugify from '@sindresorhus/slugify';

slugify('I ♥ Dogs');
//=> 'i-love-dogs'

slugify('  Déjà Vu!  ');
//=> 'deja-vu'

slugify('fooBar 123 $#%');
//=> 'foo-bar-123'

slugify('я люблю единорогов');
//=> 'ya-lyublyu-edinorogov'

API

slugify(string, options?)

string

Type: string

String to slugify.

options

Type: object

separator

Type: string
Default: '-'

import slugify from '@sindresorhus/slugify';

slugify('BAR and baz');
//=> 'bar-and-baz'

slugify('BAR and baz', {separator: '_'});
//=> 'bar_and_baz'

slugify('BAR and baz', {separator: ''});
//=> 'barandbaz'
lowercase

Type: boolean
Default: true

Make the slug lowercase.

import slugify from '@sindresorhus/slugify';

slugify('Déjà Vu!');
//=> 'deja-vu'

slugify('Déjà Vu!', {lowercase: false});
//=> 'Deja-Vu'
decamelize

Type: boolean
Default: true

Convert camelcase to separate words. Internally it does fooBarfoo bar.

import slugify from '@sindresorhus/slugify';

slugify('fooBar');
//=> 'foo-bar'

slugify('fooBar', {decamelize: false});
//=> 'foobar'
customReplacements

Type: Array<string[]>
Default: [ ['&', ' and '], ['🦄', ' unicorn '], ['♥', ' love '] ]

Add your own custom replacements.

The replacements are run on the original string before any other transformations.

This only overrides a default replacement if you set an item with the same key, like &.

import slugify from '@sindresorhus/slugify';

slugify('Foo@unicorn', {
	customReplacements: [
		['@', 'at']
	]
});
//=> 'fooatunicorn'

Add a leading and trailing space to the replacement to have it separated by dashes:

import slugify from '@sindresorhus/slugify';

slugify('foo@unicorn', {
	customReplacements: [
		['@', ' at ']
	]
});
//=> 'foo-at-unicorn'

Another example:

import slugify from '@sindresorhus/slugify';

slugify('I love 🐶', {
	customReplacements: [
		['🐶', 'dogs']
	]
});
//=> 'i-love-dogs'
preserveLeadingUnderscore

Type: boolean
Default: false

If your string starts with an underscore, it will be preserved in the slugified string.

Sometimes leading underscores are intentional, for example, filenames representing hidden paths on a website.

import slugify from '@sindresorhus/slugify';

slugify('_foo_bar');
//=> 'foo-bar'

slugify('_foo_bar', {preserveLeadingUnderscore: true});
//=> '_foo-bar'
preserveTrailingDash

Type: boolean
Default: false

If your string ends with a dash, it will be preserved in the slugified string.

For example, using slugify on an input field would allow for validation while not preventing the user from writing a slug.

import slugify from '@sindresorhus/slugify';

slugify('foo-bar-');
//=> 'foo-bar'

slugify('foo-bar-', {preserveTrailingDash: true});
//=> 'foo-bar-'
preserveCharacters

Type: string[]
Default: []

Preserve certain characters.

It cannot contain the separator.

For example, if you want to slugify URLs, but preserve the HTML fragment # character.

import slugify from '@sindresorhus/slugify';

slugify('foo_bar#baz', {preserveCharacters: ['#']});
//=> 'foo-bar#baz'

slugifyWithCounter()

Returns a new instance of slugify(string, options?) with a counter to handle multiple occurrences of the same string.

Example

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'

Use-case example of counter

If, for example, you have a document with multiple sections where each subsection has an example.

## Section 1

### Example

## Section 2

### Example

You can then use slugifyWithCounter() to generate unique HTML id's to ensure anchors will link to the right headline.

slugify.reset()

Reset the counter

Example

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'

Related

  • slugify-cli - CLI for this module
  • transliterate - Convert Unicode characters to Latin characters using transliteration
  • filenamify - Convert a string to a valid safe filename

slugify's People

Contributors

aegatlin avatar alisonmonteiro avatar arfatsalman avatar arnovsky avatar bendingbender avatar canrau avatar codekonami avatar dgaussr avatar duruld avatar hanneskuettner avatar joshuajabbour avatar lagden avatar mhm5000 avatar richienb avatar sindresorhus avatar tiagodanin avatar tniessen avatar vhpoet avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

slugify's Issues

Truncate string input?

Is it possible to truncate the output of the "slugified" string if it's way too long? Thanks!

Can't install?

Hey! I'm probably too much of a newb here, but I can install all of your node modules so far, except this one ;-)

I'm using node v8.10.0, and npm 5.6.0. Thanks!

$ npm install @sindresorhus/slugify
npm ERR! code E404
npm ERR! 404 Not Found: @sindresorhus/slugify@latest

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/bparks/.npm/cache/_logs/2018-04-27T11_36_52_196Z-debug.log

and that log file has this in it

0 info it worked if it ends with ok
1 verbose cli [ '/Users/bparks/.nvm/versions/node/v8.10.0/bin/node',
1 verbose cli   '/Users/bparks/.nvm/versions/node/v8.10.0/bin/npm',
1 verbose cli   'install',
1 verbose cli   '@sindresorhus/slugify' ]
2 info using [email protected]
3 info using [email protected]
4 verbose npm-session 1b1c4188ad8951d9
5 silly install loadCurrentTree
6 silly install readLocalPackageData
7 http fetch GET 404 https://nexus.dev.ca3.sfmc.co/nexus/content/repositories/npm-all/@sindresorhus%2fslugify 859ms
8 silly fetchPackageMetaData error for @sindresorhus/slugify@latest 404 Not Found: @sindresorhus/slugify@latest
9 verbose stack Error: 404 Not Found: @sindresorhus/slugify@latest
9 verbose stack     at fetch.then.res (/Users/bparks/.nvm/versions/node/v8.10.0/lib/node_modules/npm/node_modules/pacote/lib/fetchers/registry/fetch.js:42:19)
9 verbose stack     at tryCatcher (/Users/bparks/.nvm/versions/node/v8.10.0/lib/node_modules/npm/node_modules/bluebird/js/release/util.js:16:23)
9 verbose stack     at Promise._settlePromiseFromHandler (/Users/bparks/.nvm/versions/node/v8.10.0/lib/node_modules/npm/node_modules/bluebird/js/release/promise.js:512:31)
9 verbose stack     at Promise._settlePromise (/Users/bparks/.nvm/versions/node/v8.10.0/lib/node_modules/npm/node_modules/bluebird/js/release/promise.js:569:18)
9 verbose stack     at Promise._settlePromise0 (/Users/bparks/.nvm/versions/node/v8.10.0/lib/node_modules/npm/node_modules/bluebird/js/release/promise.js:614:10)
9 verbose stack     at Promise._settlePromises (/Users/bparks/.nvm/versions/node/v8.10.0/lib/node_modules/npm/node_modules/bluebird/js/release/promise.js:693:18)
9 verbose stack     at Async._drainQueue (/Users/bparks/.nvm/versions/node/v8.10.0/lib/node_modules/npm/node_modules/bluebird/js/release/async.js:133:16)
9 verbose stack     at Async._drainQueues (/Users/bparks/.nvm/versions/node/v8.10.0/lib/node_modules/npm/node_modules/bluebird/js/release/async.js:143:10)
9 verbose stack     at Immediate.Async.drainQueues (/Users/bparks/.nvm/versions/node/v8.10.0/lib/node_modules/npm/node_modules/bluebird/js/release/async.js:17:14)
9 verbose stack     at runCallback (timers.js:794:20)
9 verbose stack     at tryOnImmediate (timers.js:752:5)
9 verbose stack     at processImmediate [as _immediateCallback] (timers.js:729:5)
10 verbose cwd /Users/bparks/bin/node_scripts
11 verbose Darwin 17.5.0
12 verbose argv "/Users/bparks/.nvm/versions/node/v8.10.0/bin/node" "/Users/bparks/.nvm/versions/node/v8.10.0/bin/npm" "install" "@sindresorhus/slugify"
13 verbose node v8.10.0
14 verbose npm  v5.6.0
15 error code E404
16 error 404 Not Found: @sindresorhus/slugify@latest
17 verbose exit [ 1, true ]

Option disabling `transliterate`

Heya, great one.

Can we add options.transliterate so we can disable transliteration? Defaulting to true if you will so.

string = transliterate(string, {customReplacements});

to

string = options.transliterate ? transliterate(string, {customReplacements}) : string;

dot "." is legal in a URL but it is replaced with "-"

HI Sindre
I have been using your slugify and I find it very useful. So thank you for offering it.

I discovered that a url containing a dot is converted. Eg:
version3.1 is converted to version3-1

This created problems when I'm creating slugs for URLs like https://api.insightly.com/v3.1/Help

According to the spec of url written by Tim Berners-Lee back in 1994 it is legal to have a dot "." (punktum) in a url.
https://www.w3.org/Addressing/URL/url-spec.txt

Is there a way to instruct slugify to not convert "." to "-" ?

Using with create-react-app

Trying to use it with create-react-app, it fails the minification:

Failed to minify the code from this file:

 	./node_modules/@sindresorhus/slugify/index.js:7

Read more here: http://bit.ly/2tRViJ9

Incorrect dashes

slugify('XBOX360'); returns "xbo-x360". But I expected the value to be "xbox360"

Improve docs: add a notice that the module is not transpiled to ES5 and requires an additional built-tool setup.

I've just noticed that the module is not transpiled to ES5, so Webpack requires additional setup:

module: {
  rules: [
    {
      test: /\.js$/,
      exclude: /node_modules\/(?!(@sindresorhus)\/).*/,
      loader: 'babel-loader',
    },
    // ... other loaders
  ],
},

Otherwise, the module will not be transpiled by babel-loader which is not what the majority of users would expect.

If, for any reason, you don't want to ship the transpiled module, then I would, at least, add an info to the documentation that such setup is required.

The library doesn't support IE 11

We got the following errors in IE11:

  1. Target is not iterable + TypeError
  2. Object does not support property or method "Symbol(Symbol.iterator
  3. Object does not support property or method "normalize""

Transpiling to ES5

First of all thanks for the great package. I am wondering whether it is possible to transpile the package into ES5 so it can be used in older browsers as well. For example, if the package is used in IE11 the arrow function is not supported and therefore results in an error. Edge 18 does not support spread syntax so also results in an error.

Of course the app that uses the package can transpile the package itself but that feels more like an overhead. Compiling the package to ES5 in the first place should not bring any problems on the other hand.

Removing of '/' character

Hi,

Does the library remove / character from the path? I want to move certain pages as a sub-directory of main path, like integrations/abc and then have an original integrations page as well.

Is it possible with slufigy?

Custom replacements don't work as expected

... Or at least don't work as I would expect them to work :)

Example:

import slugify from '@sindresorhus/slugify';

const customSlugify = string => slugify(string, {
  customReplacements: [
    ['.', ''],
  ],
});

const slugified = customSlugify('x.y.z'); // Expected `xyz`, received `x-y-z`

I expected all dots to be converted into empty strings, so the expected result was xyz but I received x-y-z


I suppose that it's not a bug, but it would be good if the documentation explained how custom replacements really work.

Make patternSlug customizable

Hello,

Would it be possible to make the patternSlug configurable, so for example if we want to have # in our slug, we could do something like slugify('foo#bar hello$123', {patternSlug: /[^a-zA-Z#\d]+/g}); to get foo#bar-hello-123.

Would be really amazing feature :-)

Decamelization should ignore plurals of acronyms

A plural of an acronym with decamelization enabled currently results in:

slugify('Util APIs'); // util-api-s

It would be nicer if plurals were detected and ignored during decamelization so that it can produce util-apis slug instead.

Extract transliteration into it's own library

Hello!

Thank you for this great library!

However, would you consider to extract the transliteration part into it's own library? I believe this functionality could be very much useful on it's own.

Why CLI is not included?

Why the CLI for this module is not included in the repo? It could be useful to have both interfaces in one place and doesn't really increase the module size.

You may need an appropriate loader to handle this file type

I'm getting an error when trying to import this into a Sanity project. I'm not sure whether there's something wrong with my config or whether theres something incompatible in the code.

I tried reinstalling v2.1.0, v2.0.0, `v1.1.0 but with the same results. Ended up using another package for now, but could help investigate. Have you had any other reports of something similar?

On node v14.17.6

Error in ./node_modules/@sindresorhus/slugify/index.js
Module parse failed: Unexpected token (35:2)
You may need an appropriate loader to handle this file type.
| 		preserveLeadingUnderscore: false,
| 		preserveTrailingDash: false,
| 		...options
| 	};

Cannot use Slugify inside Jest tests

Slugify seems natively incompatible with jest. I get the following error when I run jest test where slugify is used in one of the test:

Test suite failed to run

    Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
     • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    /home/runner/slug/node_modules/@sindresorhus/slugify/index.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import escapeStringRegexp from 'escape-string-regexp';
                                                                                      ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      1 | 'use strict'
      2 |
    > 3 | const slugify = require('@sindresorhus/slugify');
        |                 ^
      4 |
      5 | describe('slugify', () => {
      6 |   test('test 1', () => {

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1728:14)
      at Object.<anonymous> (slug.test.js:3:17)

My files:

// slug.test.js
'use strict'

const slugify = require('@sindresorhus/slugify');

describe('slugify', () => {
  test('test 1', () => {
    expect(slugify('démocratie')).toBe('democratie');
  });
});
// package.json
{
  "name": "slug",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "test": "jest"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@sindresorhus/slugify": "^2.1.0"
  },
  "dependencies": {
    "jest": "^27.4.7"
  }
}

Here is a repo that reproduces the error when you run jest or yarn test: https://replit.com/@PierreNoel/slug#slug.test.js

How to not remove brackets?

I tried

customReplacements: [
                ['[', '['],
                [']', ']']
            ]

to force not remove brackets [] but still removed in my slugified string...

Contractions/possessions removal causes unwanted behavior

The contractions/possessions removal (PR #71) causes unwanted behavior when it is invoked with a partial string which happens to end on a -s or -t.

In that case the - is removed which might be unwanted if this library is used for live input transformation, eg in directus/directus#18352
For example the user starts to type article title which gets transformed to article-t as soon as the user types the t, which then incorrectly gets turned into articlet.

More builtin custom replacements

For popular things that makes sense. Suggestions welcome, but I'm not going to add more than maybe 30. So make it worth it.

Don't do a PR. I'll add them all at once when we've decided on what to include.

All Caps cause incorrect dashes!

I am well aware of , {decamelize: false}.

Wanted to report an edge case.

slugify('JAMstack Conf London 2019') 
// ja-mstack-conf-london-2019

I think it should do jam-stack-conf-london-2019 in case, where all the caps are considered one single word.

Run custom replacements before anything else

What I expected:

slugify('Zürich', {
      customReplacements: [["ä", "ae"], ["ö", "oe"], ["ü", "ue"], ["ß", "ss"]]
    })

// -> result: zuerich

What I got instead:

// -> result: zurich

Reason:

string = deburr(string);  <- will replace ü with u
string = decamelize(string);
string = doCustomReplacements(string, customReplacements);

Possible solution:

Run doCustomReplacements first.

string = doCustomReplacements(string, customReplacements);
string = deburr(string);
string = decamelize(string);

What do you think?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.