Skip to content

Commit

Permalink
fix: add extension mapping and fix (#27)
Browse files Browse the repository at this point in the history
* Add extension mapping and fix

* Add doc for option.extentionMapping
  • Loading branch information
licg9999 committed Dec 24, 2022
1 parent 683f1f2 commit 29a4258
Show file tree
Hide file tree
Showing 7 changed files with 256 additions and 37 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ Given input files `src/server/index.js` `src/server/constants/greeting.js` and o

Though, given input files `src/index.js` `src/server/constants/greeting.js` and output dir `dist`, with this option `'./src/server'`, output files will still be `dist/index.js` `dist/server/constants/greeting.js` because the common dir of input files is shorter than this option.

### `extentionMapping`

Type: `{Record<string, string>}`

Default: `{}`

Option `extentionMapping` indicates how file extensions are mapped from input to output. By default, one output file will have exactly the same file extension as the input file. But you may change it by this option. Given this option `{ '.ts': '.js' }`, any input file with ext `.ts` will have the output file with ext `.js`.

## Contributing

Please take a moment to read our contributing guidelines if you haven't yet done so.
Expand Down
17 changes: 10 additions & 7 deletions e2e/handles-js-outside-node_modules.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
execNode,
execWebpack,
execWebpackAsync,
expectCommonDirToIncludeAllFiles,
expectCommonDirToIncludeSameFiles,
expectCommonDirToIncludeSameFilesAnd,
killExecAsyncProcess,
Expand Down Expand Up @@ -186,7 +185,7 @@ exports.greeting = 'Hi, there!';
expect(execWebpack().status).toBe(0);
expectCommonDirToIncludeSameFilesAnd({
'dist/index.js': (t) => {
expect(t).toInclude('require("../third_party/constants');
expect(t).toInclude('require("../third_party/constants"');
expect(t).not.toInclude('Hi, there!');
},
});
Expand All @@ -195,7 +194,7 @@ exports.greeting = 'Hi, there!';
expect(stdout).toInclude('Hi, there!');
});

it('works with resolve aliases', () => {
it('works with resolve.alias', () => {
setupWebpackProject({
'webpack.config.js': `
const Plugin = require('${rootPath}');
Expand Down Expand Up @@ -294,7 +293,11 @@ export function throwErrUnconditional() {
}),
});
expect(execWebpack().status).toBe(0);
expectCommonDirToIncludeAllFiles(['dist/index.js', 'dist/throw.js']);
expectCommonDirToIncludeSameFiles([
'dist/index.js',
'dist/throw.js',
...(devtool === 'source-map' ? ['dist/index.js.map', 'dist/throw.js.map'] : []),
]);
const { stdout, stderr, status } = execNode(
'-r',
'source-map-support/register',
Expand Down Expand Up @@ -890,7 +893,7 @@ module.exports = {
${webpackConfigReusable}
entry: './server/index.js',
plugins: [
new Plugin({ exclude: /third_party/ })
new Plugin({ exclude: /third_party/ }),
],
};
`,
Expand Down Expand Up @@ -934,7 +937,7 @@ module.exports = {
${webpackConfigReusable}
entry: './src/some/where/index.js',
plugins: [
new Plugin({ longestCommonDir: './src' })
new Plugin({ longestCommonDir: './src' }),
],
};
`,
Expand All @@ -956,7 +959,7 @@ module.exports = {
${webpackConfigReusable}
entry: './src/index.js',
plugins: [
new Plugin({ longestCommonDir: './src/some/where' })
new Plugin({ longestCommonDir: './src/some/where' }),
],
};
`,
Expand Down
205 changes: 201 additions & 4 deletions e2e/handles-non-js.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { noop } from 'lodash';

import {
evaluateMustHavePackageJsonText,
execNode,
execWebpack,
expectCommonDirToIncludeAllFiles,
expectCommonDirToIncludeAllFilesAnd,
expectCommonDirToIncludeSameFiles,
expectCommonDirToIncludeSameFilesAnd,
rootPath,
setupWebpackProject,
Expand All @@ -18,13 +20,42 @@ output: {
`;

describe('handles json', () => {
it('with default JSON parser, outputs .json file as JSON', () => {
it('with default JSON parser, outputs .json file as JSON file', () => {
setupWebpackProject({
'webpack.config.js': `
const Plugin = require('${rootPath}');
module.exports = {
${webpackConfigReusable}
entry: './src/index.js',
plugins: [new Plugin()],
};
`,
'src/index.js': `
import { greeting } from './constants.json';
console.log(greeting);
`,
'src/constants.json': `
{ "greeting": "Hi, there!" }
`,
});
expect(execWebpack().status).toBe(0);
expectCommonDirToIncludeSameFilesAnd({
'dist/index.js': (t) => expect(t).not.toInclude('Hi, there!'),
'dist/constants.json': (t) => expect(JSON.parse(t)).toEqual({ greeting: 'Hi, there!' }),
});
const { stdout, status } = execNode('dist/index.js');
expect(status).toBe(0);
expect(stdout).toInclude('Hi, there!');
});

it(`with default JSON parser, doesn't generate source-map file for outputted JSON file`, () => {
setupWebpackProject({
'webpack.config.js': `
const Plugin = require('${rootPath}');
module.exports = {
${webpackConfigReusable}
entry: './src/index.js',
devtool: 'source-map',
plugins: [new Plugin()],
};
`,
Expand All @@ -39,6 +70,7 @@ console.log(greeting);
expect(execWebpack().status).toBe(0);
expectCommonDirToIncludeSameFilesAnd({
'dist/index.js': (t) => expect(t).not.toInclude('Hi, there!'),
'dist/index.js.map': noop,
'dist/constants.json': (t) => expect(JSON.parse(t)).toEqual({ greeting: 'Hi, there!' }),
});
const { stdout, status } = execNode('dist/index.js');
Expand Down Expand Up @@ -327,6 +359,76 @@ console.log(textsContent);
expect(stdout).toInclude('Hi, there!');
}
);

it(`with asset/*, doesn't generate source-map file for outputted JS file`, () => {
setupWebpackProject({
'webpack.config.js': `
const Plugin = require('${rootPath}');
module.exports = {
${webpackConfigReusable.replace(
/output:\s*\{([^}]*)\}/s,
`output: {
$1
publicPath: '/public/',
}`
)}
entry: './src/index.js',
devtool: 'source-map',
module: {
rules: [
{
test: /\\.1\\.txt$/,
type: 'asset/resource',
generator: {
emit: false,
},
},
{
test: /\\.2\\.txt$/,
type: 'asset/inline',
},
{
test: /\\.3\\.txt$/,
type: 'asset/source',
},
],
},
plugins: [new Plugin()],
};
`,
'src/index.js': `
import { Buffer } from 'node:buffer';
import t1 from './texts.1.txt';
import t2 from './texts.2.txt';
import t3 from './texts.3.txt';
console.log(t1, Buffer.from(t2.substring(t2.indexOf(',') + 1), 'base64').toString('utf8'), t3);
`,
'src/texts.1.txt': 'Hi, t1!',
'src/texts.2.txt': 'Hi, t2!',
'src/texts.3.txt': 'Hi, t3!',
});
expect(execWebpack().status).toBe(0);
expectCommonDirToIncludeSameFilesAnd({
'dist/index.js': (t) => {
expect(t).not.toInclude('Hi');
expect(t).toIncludeMultiple([
'require("./texts.1.txt")',
'require("./texts.2.txt")',
'require("./texts.3.txt")',
]);
},
'dist/index.js.map': noop,
'dist/texts.1.txt': (t) => expect(t).toIncludeMultiple(['/public/', '.txt']),
'dist/texts.2.txt': (t) => {
expect(t).not.toInclude('Hi, t2!');
expect(t).toInclude('data:text/plain;base64');
},
'dist/texts.3.txt': (t) => expect(t).toInclude('Hi, t3!'),
});
const { stdout, status } = execNode('dist/index.js');
expect(status).toBe(0);
expect(stdout).toIncludeMultiple(['/public/', '.txt', 'Hi, t2!', 'Hi, t3!']);
});
});

describe('handles vue SFC', () => {
Expand Down Expand Up @@ -428,6 +530,49 @@ h1 {
);
});

describe('with option.extentionMapping', () => {
it('maps but correctly resolves the mapped in the output', () => {
setupWebpackProject({
'webpack.config.js': `
const Plugin = require('${rootPath}');
module.exports = {
${webpackConfigReusable}
entry: './src/index.es',
module: {
rules: [
{
test: /\\.(es|ts)$/,
type: 'javascript/auto',
}
]
},
plugins: [
new Plugin({ extentionMapping: { '.ts': '.js' } })
],
};
`,
'src/index.es': `
import { greeting } from './constants.ts';
console.log(greeting);
`,
'src/constants.ts': `
export const greeting = 'Hi, there!';
`,
});
expect(execWebpack().status).toBe(0);
expectCommonDirToIncludeSameFilesAnd({
'dist/index.es': (t) => {
expect(t).not.toInclude('Hi, there!');
expect(t).toInclude('require("./constants.js")');
},
'dist/constants.js': (t) => expect(t).toInclude('Hi, there!'),
});
const { stdout, status } = execNode('dist/index.es');
expect(status).toBe(0);
expect(stdout).toInclude('Hi, there!');
});
});

describe('edge cases on outputting JS file with ext other than .js', () => {
for (const devtool of ['source-map', 'inline-source-map']) {
it(`works with ${devtool}`, () => {
Expand All @@ -451,7 +596,7 @@ module.exports = {
`,
'src/index.coffee': `
import { throwErrUnconditional } from './throw.coffee'
throwErrUnconditional();
throwErrUnconditional()
`,
'src/throw.coffee': `
export throwErrUnconditional = () ->
Expand All @@ -467,7 +612,11 @@ export throwErrUnconditional = () ->
}),
});
expect(execWebpack().status).toBe(0);
expectCommonDirToIncludeAllFiles(['dist/index.coffee', 'dist/throw.coffee']);
expectCommonDirToIncludeSameFiles([
'dist/index.coffee',
'dist/throw.coffee',
...(devtool === 'source-map' ? ['dist/index.coffee.map', 'dist/throw.coffee.map'] : []),
]);
const { stdout, stderr, status } = execNode(
'-r',
'source-map-support/register',
Expand Down Expand Up @@ -520,4 +669,52 @@ console.log('Hi, there!');
expect(status).toBe(0);
expect(stdout).toInclude('Hi, there!');
});

it('works with resolve.extensions', () => {
setupWebpackProject({
'webpack.config.js': `
const Plugin = require('${rootPath}');
module.exports = {
${webpackConfigReusable}
entry: './src/index.coffee',
module: {
rules: [
{
test: /\\.coffee$/,
use: 'coffee-loader',
}
]
},
resolve: {
extensions: ['.coffee']
},
plugins: [new Plugin()],
};
`,
'src/index.coffee': `
import { greeting } from './constants'
console.log(greeting)
`,
'src/constants.coffee': `
export greeting = 'Hi, there!'
`,
'package.json': evaluateMustHavePackageJsonText({
['devDependencies']: {
['coffee-loader']: '^4.0.0',
['coffeescript']: '^2.7.0',
},
}),
});
expect(execWebpack().status).toBe(0);
expectCommonDirToIncludeSameFilesAnd({
'dist/index.coffee': (t) => {
expect(t).not.toInclude('Hi, there!');
expect(t).toInclude('require("./constants.coffee")');
},
'dist/constants.coffee': (t) => expect(t).toInclude('Hi, there!'),
});
const { stdout, status } = execNode('dist/index.coffee');
expect(status).toBe(0);
expect(stdout).toInclude('Hi, there!');
});
});
15 changes: 12 additions & 3 deletions e2e/validates-inputs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ describe('validates options', () => {
exclude?: boolean;
hoistNodeModules?: boolean;
longestCommonDir?: boolean | string;
extentionMapping?: boolean;
}) {
setupWebpackProject({
'webpack.config.js': `
Expand All @@ -43,13 +44,14 @@ module.exports = {
entry: './src/index.js',
plugins: [
new Plugin({
${boolToText(validOpts.exclude, `exclude: /bower_components/,`, `exclude: false,`)}
${boolToText(validOpts.hoistNodeModules, `hoistNodeModules: false,`, `hoistNodeModules: 0,`)}
${boolToText(validOpts.exclude, 'exclude: /bower_components/,', 'exclude: false,')}
${boolToText(validOpts.hoistNodeModules, 'hoistNodeModules: false,', 'hoistNodeModules: 0,')}
${mapStrToText(
validOpts.longestCommonDir,
(s) => `longestCommonDir: '${s}',`,
(b) => boolToText(b, `longestCommonDir: __dirname,`, `longestCommonDir: 0,`)
(b) => boolToText(b, 'longestCommonDir: __dirname,', 'longestCommonDir: 0,')
)}
${boolToText(validOpts.extentionMapping, 'extentionMapping: {},', 'extentionMapping: 0,')}
}),
],
};
Expand Down Expand Up @@ -85,6 +87,13 @@ module.exports = {
expect(status).toBeGreaterThan(0);
expect(stderr).toIncludeMultiple(['Error', 'longestCommonDir', './src/some/where']);
});

it(`throws error if extentionMapping not valid in format`, () => {
setup({ extentionMapping: false });
const { status, stderr } = execWebpack();
expect(status).toBeGreaterThan(0);
expect(stderr).toIncludeMultiple(['Invalid', 'extentionMapping']);
});
});

describe('validates entries', () => {
Expand Down
Loading

0 comments on commit 29a4258

Please sign in to comment.