diff --git a/packages/pluginutils/README.md b/packages/pluginutils/README.md index 7475be7af..f02dda33a 100755 --- a/packages/pluginutils/README.md +++ b/packages/pluginutils/README.md @@ -50,9 +50,9 @@ export default function myPlugin(options = {}) { return { resolveId(code, id) { // only adds an extension if there isn't one already - id = addExtension(id); // `foo` -> `foo.js`, `foo.js -> foo.js` - id = addExtension(id, '.myext'); // `foo` -> `foo.myext`, `foo.js -> `foo.js` - } + id = addExtension(id); // `foo` -> `foo.js`, `foo.js` -> `foo.js` + id = addExtension(id, '.myext'); // `foo` -> `foo.myext`, `foo.js` -> `foo.js` + }, }; } ``` @@ -88,9 +88,9 @@ export default function myPlugin(options = {}) { }, leave(node) { if (node.scope) scope = scope.parent; - } + }, }); - } + }, }; } ``` @@ -126,7 +126,7 @@ import { createFilter } from '@rollup/pluginutils'; export default function myPlugin(options = {}) { // assume that the myPlugin accepts options of `options.include` and `options.exclude` var filter = createFilter(options.include, options.exclude, { - resolve: '/my/base/dir' + resolve: '/my/base/dir', }); return { @@ -134,7 +134,7 @@ export default function myPlugin(options = {}) { if (!filter(id)) return; // proceed with the transformation... - } + }, }; } ``` @@ -160,14 +160,14 @@ import { dataToEsm } from '@rollup/pluginutils'; const esModuleSource = dataToEsm( { custom: 'data', - to: ['treeshake'] + to: ['treeshake'], }, { compact: false, indent: '\t', preferConst: false, objectShorthand: false, - namedExports: true + namedExports: true, } ); /* @@ -207,11 +207,11 @@ export default function myPlugin(options = {}) { if (node.type === 'VariableDeclarator') { const declaredNames = extractAssignedNames(node.id); // do something with the declared names - // e.g. for `const {x, y: z} = ... => declaredNames = ['x', 'z'] + // e.g. for `const {x, y: z} = ...` => declaredNames = ['x', 'z'] } - } + }, }); - } + }, }; } ``` @@ -232,6 +232,22 @@ makeLegalIdentifier('foo-bar'); // 'foo_bar' makeLegalIdentifier('typeof'); // '_typeof' ``` +### normalizePath + +Converts path separators to forward slash. + +Parameters: `(filename: String)`
+Returns: `String` + +#### Usage + +```js +import { normalizePath } from '@rollup/pluginutils'; + +normalizePath('foo\\bar'); // 'foo/bar' +normalizePath('foo/bar'); // 'foo/bar' +``` + ## Meta [CONTRIBUTING](/.github/CONTRIBUTING.md) diff --git a/packages/pluginutils/src/createFilter.ts b/packages/pluginutils/src/createFilter.ts index 09ca831d2..67d65fce6 100755 --- a/packages/pluginutils/src/createFilter.ts +++ b/packages/pluginutils/src/createFilter.ts @@ -1,10 +1,11 @@ -import { resolve, sep, posix, isAbsolute } from 'path'; +import { resolve, posix, isAbsolute } from 'path'; import pm from 'picomatch'; import { CreateFilter } from '../types'; import ensureArray from './utils/ensureArray'; +import normalizePath from './normalizePath'; function getMatcherString(id: string, resolutionBase: string | false | null | undefined) { if (resolutionBase === false || isAbsolute(id) || id.startsWith('*')) { @@ -12,9 +13,7 @@ function getMatcherString(id: string, resolutionBase: string | false | null | un } // resolve('') is valid and will default to process.cwd() - const basePath = resolve(resolutionBase || '') - .split(sep) - .join('/') + const basePath = normalizePath(resolve(resolutionBase || '')) // escape all possible (posix + win) path characters that might interfere with regex .replace(/[-^$*+?.()|[\]{}]/g, '\\$&'); // Note that we use posix.join because: @@ -48,7 +47,7 @@ const createFilter: CreateFilter = function createFilter(include?, exclude?, opt if (typeof id !== 'string') return false; if (/\0/.test(id)) return false; - const pathId = id.split(sep).join('/'); + const pathId = normalizePath(id); for (let i = 0; i < excludeMatchers.length; ++i) { const matcher = excludeMatchers[i]; diff --git a/packages/pluginutils/src/index.ts b/packages/pluginutils/src/index.ts index ac39803fe..61df2bcf9 100644 --- a/packages/pluginutils/src/index.ts +++ b/packages/pluginutils/src/index.ts @@ -4,6 +4,7 @@ import createFilter from './createFilter'; import dataToEsm from './dataToEsm'; import extractAssignedNames from './extractAssignedNames'; import makeLegalIdentifier from './makeLegalIdentifier'; +import normalizePath from './normalizePath'; export { addExtension, @@ -11,7 +12,8 @@ export { createFilter, dataToEsm, extractAssignedNames, - makeLegalIdentifier + makeLegalIdentifier, + normalizePath }; // TODO: remove this in next major @@ -21,5 +23,6 @@ export default { createFilter, dataToEsm, extractAssignedNames, - makeLegalIdentifier + makeLegalIdentifier, + normalizePath }; diff --git a/packages/pluginutils/src/normalizePath.ts b/packages/pluginutils/src/normalizePath.ts new file mode 100644 index 000000000..0b0b7f6a7 --- /dev/null +++ b/packages/pluginutils/src/normalizePath.ts @@ -0,0 +1,9 @@ +import { win32, posix } from 'path'; + +import { NormalizePath } from '../types'; + +const normalizePath: NormalizePath = function(filename: string) { + return filename.split(win32.sep).join(posix.sep); +}; + +export { normalizePath as default }; diff --git a/packages/pluginutils/test/createFilter.ts b/packages/pluginutils/test/createFilter.ts index 7a68ca999..ac878e9b3 100755 --- a/packages/pluginutils/test/createFilter.ts +++ b/packages/pluginutils/test/createFilter.ts @@ -1,8 +1,10 @@ -import { resolve } from 'path'; +import { resolve as rawResolve } from 'path'; import test from 'ava'; -import { createFilter } from '../'; +import { createFilter, normalizePath } from '../'; + +const resolve = (...parts: string[]) => normalizePath(rawResolve(...parts)); test.beforeEach(() => process.chdir(__dirname)); diff --git a/packages/pluginutils/test/normalizePath.ts b/packages/pluginutils/test/normalizePath.ts new file mode 100644 index 000000000..06c9914c5 --- /dev/null +++ b/packages/pluginutils/test/normalizePath.ts @@ -0,0 +1,17 @@ +import test from 'ava'; + +import { normalizePath } from '../'; + +test('replaces \\ with /', (t) => { + t.is(normalizePath('foo\\bar'), 'foo/bar'); + t.is(normalizePath('foo\\bar\\baz'), 'foo/bar/baz'); +}); + +test('ignores forward slash', (t) => { + t.is(normalizePath('foo/bar'), 'foo/bar'); + t.is(normalizePath('foo/bar\\baz'), 'foo/bar/baz'); +}); + +test('handles empty string', (t) => { + t.is(normalizePath(''), ''); +}); diff --git a/packages/pluginutils/types/index.d.ts b/packages/pluginutils/types/index.d.ts index 33d40e509..39f7ab87a 100755 --- a/packages/pluginutils/types/index.d.ts +++ b/packages/pluginutils/types/index.d.ts @@ -68,11 +68,17 @@ export function extractAssignedNames(param: BaseNode): string[]; */ export function makeLegalIdentifier(str: string): string; +/** + * Converts path separators to forward slash. + */ +export function normalizePath(filename: string): string; + export type AddExtension = typeof addExtension; export type AttachScopes = typeof attachScopes; export type CreateFilter = typeof createFilter; export type ExtractAssignedNames = typeof extractAssignedNames; export type MakeLegalIdentifier = typeof makeLegalIdentifier; +export type NormalizePath = typeof normalizePath; export type DataToEsm = typeof dataToEsm; declare const defaultExport: { @@ -82,5 +88,6 @@ declare const defaultExport: { dataToEsm: DataToEsm; extractAssignedNames: ExtractAssignedNames; makeLegalIdentifier: MakeLegalIdentifier; + normalizePath: NormalizePath; }; export default defaultExport;