Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,24 @@ Current options:
* `es6.mixedImports`: allows for all dependencies to be fetched from a file that contains both CJS and ES6 imports.
* Note: This will work for any file format that contains an ES6 import.
* `css.url`: tells the CSS detective to include `url()` references to images, fonts, etc.
* `walker`: options passed directly to the underlying [node-source-walk](https://github.com/dependents/node-source-walk) instance.

Example:

```js
precinct(content, {
walker: {
allowImportExportEverywhere: true
}
});

// Or supply a fully custom parser:
precinct(content, {
walker: {
parser: myCustomParser // any object with a .parse(src, opts) method
}
});
```

Finding non-JavaScript (ex: Sass and Stylus) dependencies:

Expand All @@ -79,6 +97,7 @@ Supported options:

* `includeCore`: (default: `true`) set to `false` to exclude core Node.js dependencies from the list of dependencies.
* `fileSystem`: (default: `undefined`) set to an alternative `fs` implementation that will be used to read the file path.
* `walker`: (default: `undefined`) options forwarded to the underlying [node-source-walk](https://github.com/dependents/node-source-walk) instance - same as the top-level `walker` option.
* You may also pass detective-specific configuration like you would to `precinct(content, options)`.

### CLI
Expand Down
5 changes: 5 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ export = precinct;
* @param {String|Object} content - File's content or AST
* @param {Object} [options]
* @param {String} [options.type] - The type of content being passed in. Useful if you want to use a non-js detective
* @param {Object} [options.walker] - Options to pass to the underlying source walker (node-source-walk)
* @return {String[]}
*/
declare function precinct(content: string | any, options?: {
type?: string;
walker?: Record<string, any>;
}): string[];

declare namespace precinct {
/**
* Returns the dependencies for the given file path
Expand All @@ -19,10 +22,12 @@ declare namespace precinct {
* @param {Object} [options]
* @param {Boolean} [options.includeCore=true] - Whether or not to include core modules in the dependency list
* @param {Object} [options.fileSystem=undefined] - An alternative fs implementation to use for reading the file path.
* @param {Object} [options.walker] - Options to pass to the underlying source walker (node-source-walk)
* @return {String[]}
*/
function paperwork(filename: string, options?: {
includeCore?: boolean;
fileSystem?: any;
walker?: Record<string, any>;
}): string[];
}
3 changes: 2 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const debug = debuglog('precinct');
* @param {String|Object} content - File's content or AST
* @param {Object} [options]
* @param {String} [options.type] - The type of content being passed in. Useful if you want to use a non-js detective
* @param {Object} [options.walker] - Options to pass to the underlying source walker (node-source-walk)
* @return {String[]}
*/
function precinct(content, options = {}) {
Expand All @@ -35,7 +36,7 @@ function precinct(content, options = {}) {
// We assume we're dealing with a JS file
if (!options.type && typeof content !== 'object') {
debug('we assume this is JS');
const walker = new Walker();
const walker = new Walker(options.walker);

try {
// Parse once and distribute the AST to all detectives
Expand Down
3 changes: 3 additions & 0 deletions test/fixtures/es6ImportInsideBlock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
if (true) {
import lib from 'lib';
}
61 changes: 61 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,67 @@ describe('node-precinct', () => {
const expected = ['mystyles', 'styles2.styl', 'styles3.styl', 'styles4'];
assert.deepEqual(result, expected);
});

describe('walker options', () => {
it('finds imports inside blocks when allowImportExportEverywhere is enabled', async() => {
// By default babel disallows import/export outside the top level, so
// a file with an import inside an if-block yields no dependencies.
const fixture = await read('es6ImportInsideBlock.js');
const withoutOption = precinct(fixture);
assert.equal(withoutOption.length, 0);

// With allowImportExportEverywhere the same file is parsed correctly.
const withOption = precinct(fixture, {
walker: {
allowImportExportEverywhere: true
}
});
assert.equal(withOption.includes('lib'), true);
assert.equal(withOption.length, 1);
});

it('accepts a custom parser via walker options', async() => {
const fixture = await read('commonjs.js');

// Parse the AST up-front - the custom parser below returns it directly
// without invoking Babel, demonstrating that any object with a parse()
// method can be supplied, not just @babel/parser.
const prebuiltAst = require('@babel/parser').parse(fixture, {
sourceType: 'module',
allowHashBang: true
});

let parseCallCount = 0;
const customParser = {
parse() {
parseCallCount++;
return prebuiltAst;
}
};

const result = precinct(fixture, {
walker: {
parser: customParser
}
});
assert.equal(parseCallCount, 1);
assert.equal(result.includes('./a'), true);
});

it('passes walker options through paperwork', () => {
const fixture = path.join(__dirname, 'fixtures/es6ImportInsideBlock.js');
const withoutOption = precinct.paperwork(fixture);
assert.equal(withoutOption.length, 0);

const withOption = precinct.paperwork(fixture, {
walker: {
allowImportExportEverywhere: true
}
});
assert.equal(withOption.includes('lib'), true);
assert.equal(withOption.length, 1);
});
});
});

describe('paperwork', () => {
Expand Down
Loading