diff --git a/index.d.ts b/index.d.ts index 52c72df..d87933a 100644 --- a/index.d.ts +++ b/index.d.ts @@ -80,6 +80,25 @@ declare namespace slugify { ``` */ readonly customReplacements?: ReadonlyArray<[string, string]>; + + /** + 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. + + @default false + + @example + ``` + import slugify = require('@sindresorhus/slugify'); + + slugify('_foo_bar'); + //=> 'foo-bar' + + slugify('_foo_bar', {preserveLeadingUnderscore: true}); + //=> '_foo-bar' + ``` + */ + readonly preserveLeadingUnderscore?: boolean; } } diff --git a/index.js b/index.js index 5f49fa8..6a74cae 100644 --- a/index.js +++ b/index.js @@ -38,9 +38,12 @@ const slugify = (string, options) => { lowercase: true, decamelize: true, customReplacements: [], + preserveLeadingUnderscore: false, ...options }; + const shouldPrependUnderscore = options.preserveLeadingUnderscore && string.startsWith('_'); + const separator = escapeStringRegexp(options.separator); const customReplacements = new Map([ @@ -68,6 +71,10 @@ const slugify = (string, options) => { string = string.replace(/\\/g, ''); string = removeMootSeparators(string, separator); + if (shouldPrependUnderscore) { + string = `_${string}`; + } + return string; }; diff --git a/index.test-d.ts b/index.test-d.ts index 9cf8690..e6b83bf 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -8,3 +8,4 @@ expectType(slugify('fooBar', {decamelize: false})); expectType( slugify('I ♥ 🦄 & 🐶', {customReplacements: [['🐶', 'dog']]}) ); +expectType(slugify('_foo_bar', {preserveLeadingUnderscore: true})); diff --git a/readme.md b/readme.md index 59298ac..4ee157d 100644 --- a/readme.md +++ b/readme.md @@ -132,6 +132,25 @@ slugify('foo@unicorn', { //=> 'foo-at-unicorn' ``` +##### 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. + +```js +const slugify = require('@sindresorhus/slugify'); + +slugify('_foo_bar'); +//=> 'foo-bar' + +slugify('_foo_bar', {preserveLeadingUnderscore: true}); +//=> '_foo-bar' +``` + ## Related - [slugify-cli](https://github.com/sindresorhus/slugify-cli) - CLI for this module diff --git a/test.js b/test.js index 8c10156..4bab671 100644 --- a/test.js +++ b/test.js @@ -124,3 +124,10 @@ test('supports Turkish', t => { test('supports Armenian', t => { t.is(slugify('Ե ր ե ւ ա ն', {lowercase: false, separator: ' '}), 're ye v a n'); }); + +test('leading underscore', t => { + t.is(slugify('_foo bar', {preserveLeadingUnderscore: true}), '_foo-bar'); + t.is(slugify('_foo_bar', {preserveLeadingUnderscore: true}), '_foo-bar'); + t.is(slugify('__foo__bar', {preserveLeadingUnderscore: true}), '_foo-bar'); + t.is(slugify('____-___foo__bar', {preserveLeadingUnderscore: true}), '_foo-bar'); +});