Skip to content

Commit

Permalink
refactor: options for commonjs
Browse files Browse the repository at this point in the history
  • Loading branch information
cap-Bernardito committed Jun 16, 2020
1 parent bef708f commit 7265bc8
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 54 deletions.
35 changes: 23 additions & 12 deletions README.md
Expand Up @@ -75,7 +75,7 @@ require(`imports-loader?imports[]=default%20jquery%20$&imports[]=angular!./examp
```

```js
require(`imports-loader?type=commonjsimports[]=default%20jquery%20$&imports[]=angular!./example.js`);
require(`imports-loader?type=commonjsimports[]=single%20jquery%20$&imports[]=angular!./example.js`);
// Adds the following code to the beginning of example.js:
//
// var $ = require("jquery");
Expand Down Expand Up @@ -114,14 +114,13 @@ module.exports = {
options: {
type: 'commonjs',
imports: [
'default ./lib_1 $',
'default ./lib_2 lib_2_default',
'named ./lib_2 lib2_method_1',
'named ./lib_2 lib2_method_2 lib_2_method_2_short',
'default ./lib_3 lib_3_defaul',
'namespace ./lib_3 lib_3_all',
'side-effect ./lib_4',
'default jquery $',
'single ./lib_1 $',
'single ./lib_2 lib_2_default',
'multiple ./lib_2 lib2_method_1',
'multiple ./lib_2 lib2_method_2 lib_2_method_2_short',
'single ./lib_3 lib_3_defaul',
'pure ./lib_4',
'single jquery $',
{
moduleName: 'angular',
name: 'angular',
Expand Down Expand Up @@ -223,13 +222,19 @@ String values let you specify import syntax, moduleName, name, and alias.

String syntax - `[[syntax] [moduleName] [name] [alias]]`, where:

- `[syntax]` - can be `default`, `named`, `namespace` or `side-effect`
- `[syntax]`:

- if type `module`- can be `default`, `named`, `namespace` or `side-effect`
- if type `commonjs`- can be `single`, `multiple` or `pure`

- `[moduleName]` - name of an imported module (**required**)
- `[name]` - name of an imported value (**required**)
- `[alias]` - alias of an imported value (**may be omitted**)

Examples:

If type `module`:

- `[Foo]` - generates `import Foo from "Foo";`.
- `[default Foo]` - generates `import Foo from "Foo";`.
- `[default ./my-lib Foo]` - generates `import Foo from "./my-lib";`.
Expand All @@ -240,6 +245,14 @@ Examples:
- `[[default Foo] [namespace Foo FooA]]` - generates `import Foo, * as FooA from "Foo";`.
- `[side-effect Foo]` - generates `import "Foo";`.

If type `commonjs`:

- `[Foo]` - generates `const Foo = require("Foo");`.
- `[single Foo]` - generates `const Foo = require("Foo");`.
- `[single ./my-lib Foo]` - generates `const Foo = require("./my-lib");`.
- `[multiple Foo FooA Bar]` - generates `const { FooA:Bar } = require("Foo");`.
- `[pure Foo]` - generates `require("Foo");`.

> ⚠ Aliases can't be used together with `default` or `side-effect` syntax.
###### Examples
Expand Down Expand Up @@ -296,7 +309,6 @@ module.exports = {
{
loader: 'imports-loader',
options: {
type: 'commonjs',
imports: {
syntax: 'named',
moduleName: './lib_2',
Expand Down Expand Up @@ -334,7 +346,6 @@ module.exports = {
{
loader: 'imports-loader',
options: {
type: 'commonjs',
imports: [
{
moduleName: 'angular',
Expand Down
10 changes: 9 additions & 1 deletion src/options.json
Expand Up @@ -5,7 +5,15 @@
"additionalProperties": false,
"properties": {
"syntax": {
"enum": ["default", "named", "namespace", "side-effect"]
"enum": [
"default",
"named",
"namespace",
"side-effect",
"single",
"multiple",
"pure"
]
},
"moduleName": {
"type": "string",
Expand Down
104 changes: 75 additions & 29 deletions src/utils.js
@@ -1,6 +1,7 @@
import { stringifyRequest } from 'loader-utils';

function resolveImports(type, item) {
const defaultSyntax = type === 'module' ? 'default' : 'single';
let result;

if (typeof item === 'string') {
Expand All @@ -13,7 +14,7 @@ function resolveImports(type, item) {
if (splittedItem.length === 1) {
result = {
type,
syntax: 'default',
syntax: defaultSyntax,
moduleName: splittedItem[0],
name: splittedItem[0],
// eslint-disable-next-line no-undefined
Expand All @@ -29,9 +30,9 @@ function resolveImports(type, item) {
};
}
} else {
result = { syntax: 'default', ...item };
result = { syntax: defaultSyntax, ...item };

if (result.syntax === 'default' && !result.name) {
if (result.syntax === defaultSyntax && !result.name) {
result.name = result.moduleName;
}
}
Expand All @@ -43,7 +44,7 @@ function resolveImports(type, item) {
}

if (
['default', 'side-effect'].includes(result.syntax) &&
['default', 'single', 'side-effect', 'pure'].includes(result.syntax) &&
typeof result.alias !== 'undefined'
) {
throw new Error(
Expand All @@ -52,22 +53,34 @@ function resolveImports(type, item) {
}

if (
['side-effect'].includes(result.syntax) &&
['side-effect', 'pure'].includes(result.syntax) &&
typeof result.name !== 'undefined'
) {
throw new Error(
`The "${result.syntax}" syntax can't have "${result.name}" name in "${item}" value`
);
}

if (['namespace'].includes(result.syntax) && type === 'commonjs') {
if (
['default', 'namespace', 'named', 'side-effect'].includes(result.syntax) &&
type === 'commonjs'
) {
throw new Error(
`The "commonjs" type not support "namespace" syntax import in "${item}" value`
`The "commonjs" type not support "${result.syntax}" syntax import in "${item}" value`
);
}

if (
['namespace', 'named'].includes(result.syntax) &&
['single', 'multiple', 'pure'].includes(result.syntax) &&
type === 'module'
) {
throw new Error(
`The "module" type not support "${result.syntax}" syntax import in "${item}" value`
);
}

if (
['namespace', 'named', 'multiple'].includes(result.syntax) &&
typeof result.name === 'undefined'
) {
throw new Error(
Expand Down Expand Up @@ -97,18 +110,23 @@ function getImports(type, imports) {
sortedResults[item.moduleName].push(item);
}

const defaultSyntax = type === 'module' ? 'default' : 'single';

for (const item of Object.entries(sortedResults)) {
const defaultImports = item[1].filter(
(entry) => entry.syntax === 'default'
(entry) => entry.syntax === defaultSyntax
);

const namespaceImports = item[1].filter(
(entry) => entry.syntax === 'namespace'
);
const sideEffectImports = item[1].filter(
(entry) => entry.syntax === 'side-effect'
);

[defaultImports, namespaceImports, sideEffectImports].forEach(
const pure = item[1].filter((entry) => entry.syntax === 'pure');

[defaultImports, namespaceImports, sideEffectImports, pure].forEach(
(importsSyntax) => {
if (importsSyntax.length > 1) {
const [{ syntax }] = importsSyntax;
Expand All @@ -127,37 +145,48 @@ function getImports(type, imports) {
function renderImports(loaderContext, type, imports) {
const [{ moduleName }] = imports;
const defaultImports = imports.filter((item) => item.syntax === 'default');
const singleImports = imports.filter((item) => item.syntax === 'single');
const namedImports = imports.filter((item) => item.syntax === 'named');
const multipleImports = imports.filter((item) => item.syntax === 'multiple');
const namespaceImports = imports.filter(
(item) => item.syntax === 'namespace'
);
const sideEffectImports = imports.filter(
(item) => item.syntax === 'side-effect'
);
const pure = imports.filter((item) => item.syntax === 'pure');
const isModule = type === 'module';

// 1. Import-side-effect
// 1. Module import-side-effect
if (sideEffectImports.length > 0) {
return isModule
? `import ${stringifyRequest(loaderContext, moduleName)};`
: `require(${stringifyRequest(loaderContext, moduleName)});`;
return `import ${stringifyRequest(loaderContext, moduleName)};`;
}

// 2. CommonJs pure
if (pure.length > 0) {
return `require(${stringifyRequest(loaderContext, moduleName)});`;
}

let code = isModule ? 'import' : '';

// 2. Default import
// 3. Module default import
if (defaultImports.length > 0) {
const [{ name }] = defaultImports;

code += isModule
? ` ${name}`
: `var ${name} = require(${stringifyRequest(
loaderContext,
moduleName
)});`;
code += ` ${name}`;
}

// 3. Namespace import
// 4. CommonJs single import
if (singleImports.length > 0) {
const [{ name }] = singleImports;

code += `var ${name} = require(${stringifyRequest(
loaderContext,
moduleName
)});`;
}

// 5. Module namespace import
if (namespaceImports.length > 0) {
if (defaultImports.length > 0) {
code += `,`;
Expand All @@ -168,25 +197,42 @@ function renderImports(loaderContext, type, imports) {
code += ` * as ${name}`;
}

// 4. Named import
// 6. Module named import
if (namedImports.length > 0) {
if (defaultImports.length > 0) {
code += isModule ? ', { ' : '\nvar { ';
code += ', { ';
} else {
code += isModule ? ' { ' : 'var { ';
code += ' { ';
}

namedImports.forEach((namedImport, i) => {
const comma = i > 0 ? ', ' : '';
const { name, alias } = namedImport;
const sep = isModule ? ' as ' : ': ';
const sep = ' as ';

code += alias ? `${comma}${name}${sep}${alias}` : `${comma}${name}`;
});

code += ' }';
}

// 7. CommonJs multiple import
if (multipleImports.length > 0) {
if (singleImports.length > 0) {
code += '\nvar { ';
} else {
code += 'var { ';
}

multipleImports.forEach((multipleImport, i) => {
const comma = i > 0 ? ', ' : '';
const { name, alias } = multipleImport;
const sep = ': ';

code += alias ? `${comma}${name}${sep}${alias}` : `${comma}${name}`;
});

code += isModule
? ' }'
: ` } = require(${stringifyRequest(loaderContext, moduleName)});`;
code += ` } = require(${stringifyRequest(loaderContext, moduleName)});`;
}

if (!isModule) {
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/inline2.js
@@ -1 +1 @@
require('../../src/cjs.js?type=commonjs&imports[]=default%20lib_2%20lib_2_all&imports[]=named%20lib_2%20lib_2_method%20lib_2_method_alias!./some-library.js');
require('../../src/cjs.js?type=commonjs&imports[]=single%20lib_2%20lib_2_all&imports[]=multiple%20lib_2%20lib_2_method%20lib_2_method_alias!./some-library.js');
22 changes: 11 additions & 11 deletions test/loader.test.js
Expand Up @@ -239,7 +239,7 @@ describe('loader', () => {
imports: {
moduleName: './lib_1',
name: '$',
syntax: 'default',
syntax: 'single',
},
});
const stats = await compile(compiler);
Expand All @@ -256,12 +256,12 @@ describe('loader', () => {
type: 'commonjs',
imports: [
{
syntax: 'named',
syntax: 'multiple',
moduleName: './lib_2',
name: 'lib2_method_1',
},
{
syntax: 'named',
syntax: 'multiple',
moduleName: './lib_2',
name: 'lib2_method_2',
alias: 'lib_2_method_2_short',
Expand Down Expand Up @@ -290,12 +290,12 @@ describe('loader', () => {
name: 'lib_2_all',
},
{
syntax: 'named',
syntax: 'multiple',
moduleName: './lib_2',
name: 'lib2_method_1',
},
{
syntax: 'named',
syntax: 'multiple',
moduleName: './lib_2',
name: 'lib2_method_2',
alias: 'lib_2_method_2_short',
Expand All @@ -315,7 +315,7 @@ describe('loader', () => {
const compiler = getCompiler('some-library.js', {
type: 'commonjs',
imports: {
syntax: 'side-effect',
syntax: 'pure',
moduleName: './lib_1',
},
});
Expand All @@ -332,11 +332,11 @@ describe('loader', () => {
const compiler = getCompiler('some-library.js', {
type: 'commonjs',
imports: [
'default ./lib_1 $',
'default ./lib_2 lib_2_all',
'named ./lib_2 lib2_method_1',
'named ./lib_2 lib2_method_2 lib_2_method_2_short',
'side-effect ./lib_3',
'single ./lib_1 $',
'single ./lib_2 lib_2_all',
'multiple ./lib_2 lib2_method_1',
'multiple ./lib_2 lib2_method_2 lib_2_method_2_short',
'pure ./lib_3',
],
});
const stats = await compile(compiler);
Expand Down

0 comments on commit 7265bc8

Please sign in to comment.