From 2376b7327bb97bb2b74be19048ac74d01a858d0f Mon Sep 17 00:00:00 2001 From: Marcel Gerber Date: Sat, 19 Sep 2020 14:08:56 +0200 Subject: [PATCH 1/6] Split up filenamify and filenamify-path into different files --- filenamify-path.js | 10 ++++++++++ filenamify.js | 38 ++++++++++++++++++++++++++++++++++++++ index.js | 44 ++++---------------------------------------- package.json | 5 +++++ 4 files changed, 57 insertions(+), 40 deletions(-) create mode 100644 filenamify-path.js create mode 100644 filenamify.js diff --git a/filenamify-path.js b/filenamify-path.js new file mode 100644 index 0000000..359c119 --- /dev/null +++ b/filenamify-path.js @@ -0,0 +1,10 @@ +'use strict'; +const path = require('path'); +const filenamify = require('./filenamify'); + +const filenamifyPath = (filePath, options) => { + filePath = path.resolve(filePath); + return path.join(path.dirname(filePath), filenamify(path.basename(filePath), options)); +}; + +module.exports = filenamifyPath; diff --git a/filenamify.js b/filenamify.js new file mode 100644 index 0000000..274c228 --- /dev/null +++ b/filenamify.js @@ -0,0 +1,38 @@ +'use strict'; +const trimRepeated = require('trim-repeated'); +const filenameReservedRegex = require('filename-reserved-regex'); +const stripOuter = require('strip-outer'); + +// Doesn't make sense to have longer filenames +const MAX_FILENAME_LENGTH = 100; + +const reControlChars = /[\u0000-\u001f\u0080-\u009f]/g; // eslint-disable-line no-control-regex +const reRelativePath = /^\.+/; + +const filenamify = (string, options = {}) => { + if (typeof string !== 'string') { + throw new TypeError('Expected a string'); + } + + const replacement = options.replacement === undefined ? '!' : options.replacement; + + if (filenameReservedRegex().test(replacement) && reControlChars.test(replacement)) { + throw new Error('Replacement string cannot contain reserved filename characters'); + } + + string = string.replace(filenameReservedRegex(), replacement); + string = string.replace(reControlChars, replacement); + string = string.replace(reRelativePath, replacement); + + if (replacement.length > 0) { + string = trimRepeated(string, replacement); + string = string.length > 1 ? stripOuter(string, replacement) : string; + } + + string = filenameReservedRegex.windowsNames().test(string) ? string + replacement : string; + string = string.slice(0, typeof options.maxLength === 'number' ? options.maxLength : MAX_FILENAME_LENGTH); + + return string; +}; + +module.exports = filenamify; diff --git a/index.js b/index.js index e37c18a..260bbd1 100644 --- a/index.js +++ b/index.js @@ -1,44 +1,8 @@ 'use strict'; -const path = require('path'); -const trimRepeated = require('trim-repeated'); -const filenameReservedRegex = require('filename-reserved-regex'); -const stripOuter = require('strip-outer'); +const filenamify = require('./filenamify'); +const filenamifyPath = require('./filenamify-path'); -// Doesn't make sense to have longer filenames -const MAX_FILENAME_LENGTH = 100; - -const reControlChars = /[\u0000-\u001f\u0080-\u009f]/g; // eslint-disable-line no-control-regex -const reRelativePath = /^\.+/; - -const filenamify = (string, options = {}) => { - if (typeof string !== 'string') { - throw new TypeError('Expected a string'); - } - - const replacement = options.replacement === undefined ? '!' : options.replacement; - - if (filenameReservedRegex().test(replacement) && reControlChars.test(replacement)) { - throw new Error('Replacement string cannot contain reserved filename characters'); - } - - string = string.replace(filenameReservedRegex(), replacement); - string = string.replace(reControlChars, replacement); - string = string.replace(reRelativePath, replacement); - - if (replacement.length > 0) { - string = trimRepeated(string, replacement); - string = string.length > 1 ? stripOuter(string, replacement) : string; - } - - string = filenameReservedRegex.windowsNames().test(string) ? string + replacement : string; - string = string.slice(0, typeof options.maxLength === 'number' ? options.maxLength : MAX_FILENAME_LENGTH); - - return string; -}; - -filenamify.path = (filePath, options) => { - filePath = path.resolve(filePath); - return path.join(path.dirname(filePath), filenamify(path.basename(filePath), options)); -}; +const filenamifyCombined = filenamify; +filenamifyCombined.path = filenamifyPath; module.exports = filenamify; diff --git a/package.json b/package.json index da1e297..6b3d3ae 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,11 @@ "index.js", "index.d.ts" ], + "exports": { + ".": "./index.js", + "./filenamify": "./filenamify.js", + "./filenamify-path": "./filenamify-path.js" + }, "keywords": [ "filename", "safe", From f393bc69002dc65dcdf829f236f8ce4903e20e9d Mon Sep 17 00:00:00 2001 From: Marcel Gerber Date: Sat, 19 Sep 2020 14:32:19 +0200 Subject: [PATCH 2/6] provide type definitions for all exports --- filenamify-path.d.ts | 8 ++++++++ filenamify.d.ts | 39 +++++++++++++++++++++++++++++++++++++++ index.d.ts | 32 +++++--------------------------- 3 files changed, 52 insertions(+), 27 deletions(-) create mode 100644 filenamify-path.d.ts create mode 100644 filenamify.d.ts diff --git a/filenamify-path.d.ts b/filenamify-path.d.ts new file mode 100644 index 0000000..2346602 --- /dev/null +++ b/filenamify-path.d.ts @@ -0,0 +1,8 @@ +import filenamify = require('./filenamify'); + +/** +Convert the filename in a path a valid filename and return the augmented path. +*/ +declare const filenamifyPath: (path: string, options?: filenamify.Options) => string; + +export = filenamifyPath; diff --git a/filenamify.d.ts b/filenamify.d.ts new file mode 100644 index 0000000..4d73ddc --- /dev/null +++ b/filenamify.d.ts @@ -0,0 +1,39 @@ +declare namespace filenamify { + interface Options { + /** + String to use as replacement for reserved filename characters. + + Cannot contain: `<` `>` `:` `"` `/` `\` `|` `?` `*` + + @default '!' + */ + readonly replacement?: string; + + /** + Truncate the filename to the given length. + + Systems generally allow up to 255 characters, but we default to 100 for usability reasons. + + @default 100 + */ + readonly maxLength?: number; + } +} + +/** +Convert a string to a valid filename. + +@example +``` +import filenamify = require('filenamify'); + +filenamify(''); +//=> 'foo!bar' + +filenamify('foo:"bar"', {replacement: '🐴'}); +//=> 'foo🐴bar' +``` +*/ +declare const filenamify: (string: string, options?: filenamify.Options) => string; + +export = filenamify; diff --git a/index.d.ts b/index.d.ts index b0faa2c..0dd9716 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,26 +1,7 @@ -declare namespace filenamify { - interface Options { - /** - String to use as replacement for reserved filename characters. +import filenamify = require('./filenamify'); +import filenamifyPath = require('./filenamify-path'); - Cannot contain: `<` `>` `:` `"` `/` `\` `|` `?` `*` - - @default '!' - */ - readonly replacement?: string; - - /** - Truncate the filename to the given length. - - Systems generally allow up to 255 characters, but we default to 100 for usability reasons. - - @default 100 - */ - readonly maxLength?: number; - } -} - -declare const filenamify: { +declare const filenamifyCombined: { /** Convert a string to a valid filename. @@ -37,10 +18,7 @@ declare const filenamify: { */ (string: string, options?: filenamify.Options): string; - /** - Convert the filename in a path a valid filename and return the augmented path. - */ - path(path: string, options?: filenamify.Options): string; + path: typeof filenamifyPath; }; -export = filenamify; +export = filenamifyCombined; From 6ea01d866ed962ea217f838923fa863fcb747201 Mon Sep 17 00:00:00 2001 From: Marcel Gerber Date: Wed, 23 Sep 2020 23:36:52 +0200 Subject: [PATCH 3/6] remove `filenamify-path` export --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 6b3d3ae..b2b5802 100644 --- a/package.json +++ b/package.json @@ -21,8 +21,7 @@ ], "exports": { ".": "./index.js", - "./filenamify": "./filenamify.js", - "./filenamify-path": "./filenamify-path.js" + "./browser": "./filenamify.js" }, "keywords": [ "filename", From 7a798d1b9ad6ebe5746a7294d72452109f4fb9f8 Mon Sep 17 00:00:00 2001 From: Marcel Gerber Date: Thu, 24 Sep 2020 00:18:08 +0200 Subject: [PATCH 4/6] add note about `filenamify/browser` export to readme --- readme.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/readme.md b/readme.md index e1c96b0..3c1bc91 100644 --- a/readme.md +++ b/readme.md @@ -57,6 +57,18 @@ Truncate the filename to the given length. Systems generally allow up to 255 characters, but we default to 100 for usability reasons. +## Browser-only import + +You can also import `filenamify/browser`, which only imports `filenamify` and not `filenamify.path`, which relies on `path` being available or polyfilled. +Importing `filenamify` this way is therefore useful when it is shipped using `webpack` or similar tools, and if `filenamify.path` is not needed. + +```js +const filenamify = require('filenamify/browser'); + +filenamify(''); +//=> 'foo!bar' +``` + ## Related From e948a8cb1b22e11d8202440ca5543caaf16b027c Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Thu, 24 Sep 2020 00:21:34 +0200 Subject: [PATCH 5/6] Update readme.md --- readme.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 3c1bc91..43ae76a 100644 --- a/readme.md +++ b/readme.md @@ -59,8 +59,7 @@ Systems generally allow up to 255 characters, but we default to 100 for usabilit ## Browser-only import -You can also import `filenamify/browser`, which only imports `filenamify` and not `filenamify.path`, which relies on `path` being available or polyfilled. -Importing `filenamify` this way is therefore useful when it is shipped using `webpack` or similar tools, and if `filenamify.path` is not needed. +You can also import `filenamify/browser`, which only imports `filenamify` and not `filenamify.path`, which relies on `path` being available or polyfilled. Importing `filenamify` this way is therefore useful when it is shipped using `webpack` or similar tools, and if `filenamify.path` is not needed. ```js const filenamify = require('filenamify/browser'); From 028af24b43a286ca32db83aed678a4dd36641d8a Mon Sep 17 00:00:00 2001 From: Marcel Gerber Date: Thu, 24 Sep 2020 00:24:11 +0200 Subject: [PATCH 6/6] include new files in package.json `files` --- package.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b2b5802..1041b52 100644 --- a/package.json +++ b/package.json @@ -16,8 +16,12 @@ "test": "xo && ava && tsd" }, "files": [ - "index.js", - "index.d.ts" + "filenamify-path.d.ts", + "filenamify-path.js", + "filenamify.d.ts", + "filenamify.js", + "index.d.ts", + "index.js" ], "exports": { ".": "./index.js",