Fast and easy parser for declarations of import and export from the ECMAScript standard, with TypeScript syntax support.
parse-imports-exports
works for syntactically correct, well-formatted code (for example, by prettier).
Single-line and multi-line ECMAScript comments in import
/export
statements are supported.
Imagine a module with the following content:
/**
* Imports.
*/
// {Qux: [{start: 17, end: 58, names: {baz: {by: 'foo'}}, types: {Bar: {}}}]}
import {foo as baz, type Bar} from 'Qux';
// {Qux: [{start: 80, end: 112, namespace: 'foo', default: 'Foo'}]}
import Foo, * as foo from 'Qux';
// {Qux: [{start: 114, end: 127}]}
const foo = await import('Qux');
// {Qux: [{start: 128, end, 134}]}
const foo = require('Qux');
// {Qux: [{start: 137, end: 141}]}
type Foo = typeof import('Qux');
// {Qux: [{start: 142, end: 175, names: {Baz: {by: 'Foo'}, Bar: {}}}]}
import type {Foo as Baz, Bar} from 'Qux';
// {Qux: [{start: 201, end: 233, namespace: 'Foo'}]}
import type * as Foo from 'Qux';
/**
* Reexports.
*/
// {Qux: [{start: 254, end: 295, names: {baz: {by: 'foo'}}, types: {Bar: {}}}]}
export {foo as baz, type Bar} from 'Qux';
// {Qux: [{start: 319, end: 346, namespace: 'foo'}]}
export * as foo from 'Qux';
// {Qux: [{start: 365, end: 385}]}
export * from 'Qux';
// {Qux: [{start: 409, end: 450, names: {Baz: {by: 'Foo'}, Bar: {}}}]}
export type {Foo as Baz, Bar} from 'Qux';
// {Qux: [{start: 478, end: 510, namespace: 'Foo'}]}
export type * as Foo from 'Qux';
// {Qux: [{start: 533, end: 558}]}
export type * from 'Qux';
/**
* Exports.
*/
// {start: 578, end: 596}
export default 42;
// [{start: 614, end: 644, names: {baz: {by: 'foo'}}, types: {Bar: {}}}]
export {foo as baz, type Bar};
// {foo: {start: 668, end: 689, kind: 'const'}}
export const foo = 2;
// [{start: 711, end: 741, names: {Baz: {by: 'Foo'}, Bar: {}}}]
export type {Foo as Baz, Bar};
// {T: {start: 758, end: 781}}
export type T = number;
// {I: [{start: 803, end: 836}]}
export interface I {
foo: number;
}
// {N: [{start: 858, end: 891}]}
export namespace N {
foo: number;
}
// {start: 901, end: 915}
module.exports = 42;
// {foo: {start: 917, end: 931, startsWithModule: true}}
module.exports.foo = 2;
Let its content be stored as a string in the variable source
.
Then it can be parsed like this:
import {parseImportsExports} from 'parse-imports-exports';
const importsExports = parseImportsExports(source);
// Now `importsExports` has the following shape (the `start` and `end` indices, which indicate
// the beginning and end of the corresponding statement in the source, may differ):
const importsExportsShape = {
/**
* Imports.
*/
// import {foo as baz, type Bar} from 'Qux';
namedImports: {Qux: [{start: 17, end: 58, names: {baz: {by: 'foo'}}, types: {Bar: {}}}]},
// import Foo, * as foo from 'Qux';
namespaceImports: {Qux: [{start: 80, end: 112, namespace: 'foo', default: 'Foo'}]},
// const foo = await import('Qux');
dynamicImports: {Qux: [{start: 114, end: 127}]},
// const foo = require('Qux');
requires: {Qux: [{start: 128, end: 134}]},
// type Foo = typeof import('Qux');
typeDynamicImports: {Qux: [{start: 137, end: 141}]},
// import type {Foo as Baz, Bar} from 'Qux';
typeNamedImports: {Qux: [{start: 142, end: 175, names: {Baz: {by: 'Foo'}, Bar: {}}}]},
// import type * as Foo from 'Qux';
typeNamespaceImports: {Qux: [{start: 201, end: 233, namespace: 'Foo'}]},
/**
* Reexports.
*/
// export {foo as baz, type Bar} from 'Qux';
namedReexports: {Qux: [{start: 254, end: 295, names: {baz: {by: 'foo'}}, types: {Bar: {}}}]},
// export * as foo from 'Qux';
namespaceReexports: {Qux: [{start: 319, end: 346, namespace: 'foo'}]},
// export * from 'Qux';
starReexports: {Qux: [{start: 365, end: 385}]},
// export type {Foo as Baz, Bar} from 'Qux';
typeNamedReexports: {Qux: [{start: 409, end: 450, names: {Baz: {by: 'Foo'}, Bar: {}}}]},
// export type * as Foo from 'Qux';
typeNamespaceReexports: {Qux: [{start: 478, end: 510, namespace: 'Foo'}]},
// export type * from 'Qux';
typeStarReexports: {Qux: [{start: 533, end: 558}]},
/**
* Exports.
*/
// export default 42;
defaultExport: {start: 578, end: 596},
// export {foo as baz, type Bar};
namedExports: [{start: 614, end: 644, names: {baz: {by: 'foo'}}, types: {Bar: {}}}],
// export const foo = 2;
declarationExports: {foo: {start: 668, end: 689, kind: 'const'}},
// export type {Foo as Baz, Bar};
typeNamedExports: [{start: 711, end: 741, names: {Baz: {by: 'Foo'}, Bar: {}}}],
// export type T = number;
typeExports: {T: {start: 758, end: 781}},
// export interface I {foo: number};
interfaceExports: {I: [{start: 803, end: 836}]},
// export namespace N {foo: number};
namespaceExports: {N: [{start: 858, end: 891}]},
// module.exports = 42;
commonJsNamespaceExport: {start, end},
// module.exports.foo = 2;
commonJsExports: {foo: {start, end, startsWithModule: true}},
};
Requires node version 10 or higher:
npm install parse-imports-exports
parse-imports-exports
works in any environment that supports ES2018
(because package uses RegExp Named Capture Groups).
parse-imports-exports
exports one runtime value — the parseImportsExports
function:
import {parseImportsExports} from 'parse-imports-exports';
import type {ImportsExports, Options} from 'parse-imports-exports';
const importsExports: ImportsExports = parseImportsExports('some source code (as string)');
// or with optional options:
const importsExports = parseImportsExports('some source code (as string)', options);
// all option fields are optional boolean with default `false` value
const options: Options = {
/**
* If `true`, then we ignore `module.exports = ...`/`(module.)exports.foo = ...` expressions
* during parsing (maybe a little faster).
* By default (if `false` or skipped option), `module.exports = ...`/`(module.)exports.foo = ...`
* expressions are parsed.
*/
ignoreCommonJsExports: false;
/**
* If `true`, then we ignore `import(...)` expressions during parsing (maybe a little faster).
* By default (if `false` or skipped option), `import(...)` expressions are parsed.
*/
ignoreDynamicImports: false;
/**
* If `true`, then we ignore regular expression literals (`/.../`)
* during parsing (maybe a little faster).
* By default (if `false` or skipped option), regular expression literals are parsed.
*/
ignoreRegexpLiterals: false;
/**
* If `true`, then we ignore `require(...)` expressions during parsing (maybe a little faster).
* By default (if `false` or skipped option), `require(...)` expressions are parsed.
*/
ignoreRequires: false;
/**
* If `true`, then we ignore string literals during parsing (maybe a little faster).
* By default (if `false` or skipped option), string literals are parsed, that is,
* the text inside them cannot be interpreted as another expression.
*/
ignoreStringLiterals: false;
};
parse-imports-exports
also exports types included in the API:
export type {
/**
* Parsed JSON presentation of imports, exports and reexports of ECMAScript/TypeScript module.
*/
ImportsExports,
/**
* Kind of exported declaration.
*/
Kind,
/**
* Options of `parseImportsExports` function.
*/
Options,
};