Repository: webpack-contrib/compression-webpack-plugin (js)

Issue:
Use original filename without .gz extension
* Operating System:
OSX Mojave 10.14

* Node Version:
v8.11.4

* NPM Version:
6.8.0

* webpack Version:
4.17.1

* webpack-defaults Version:
Unknown

### Expected Behavior

To be able to use `[file]` for the `filename` prop and it return the original filename without the `.gz` extension

### Actual Behavior

There is no output

### Code

```js
  {
          filename: "[file]",
          algorithm: "gzip",
          test: new RegExp("\\.(" + productionGzipExtensions.join("|") + ")$"),
          threshold: 0,
          minRatio: 1,
          deleteOriginalAssets: true
    }
```

As background we're using S3 to host static assets and you have to upload the asset without the `.gz` extension.

I was trying to use the `filename` function to hack together what I needed, something like this...
```js
filename(info) {
    // info.file is the original asset filename
    // info.path is the path of the original asset
    // info.query is the query

    // The extension (info.path) is coming through as part of the filename so we need to remove it to get correct filenames for S3
    const filename = info.file.replace(info.path, "");
    return `${filename}.${info.path}`;
},
```

But then the output folders come out as `.js` and `.css`. For some reason they have a proceeding `.`

Using the `filename` function and logging the `info` param I get the following...
```js
  { 
    file: 'js/app.25450252.js',
    path: 'js/app.25450252.js',
    query: '' 
}
```
Seems like `path` and `file` are returning the same thing. 

### How Do We Reproduce?

You can test it by setting `filename: "[file]"`.

Sorry if I'm missing something blatantly obvious!!

Pull request description:
feat: add options for `dir`, `name` and `ext` in filename option (fix #117)
<!--
  HOLY CRAP a Pull Request. We ❤️ those!

  If you remove or skip this template, you'll make the 🐼 sad and the mighty god
  of Github will appear and pile-drive the close button from a great height
  while making animal noises.

  Please place an x (no spaces!) in all [ ] that apply
-->

This PR contains a:

- [ ] **bugfix**
- [x] new **feature**
- [ ] **code refactor**
- [ ] **test update** <!-- if bug or feature is checked, this should be too -->
- [ ] **typo fix**
- [ ] **metadata update**

### Motivation / Use-Case

Fixes #117 



Patch:
diff --git a/README.md b/README.md
index a554010..988bd52 100644
--- a/README.md
+++ b/README.md
@@ -127,6 +127,9 @@ The target asset filename.
 
 `[file]` is replaced with the original asset filename.
 `[path]` is replaced with the path of the original asset.
+`[dir]` is replaced with the directory of the original asset.
+`[name]` is replaced with the filename of the original asset.
+`[ext]` is replaced with the extension of the original asset.
 `[query]` is replaced with the query.
 
 ```js
@@ -134,6 +137,10 @@ The target asset filename.
 new CompressionPlugin({
   filename: '[path].gz[query]',
 });
+
+new CompressionPlugin({
+  filename: '[dir][name].gz[ext][query]',
+});
 ```
 
 #### `Function`
diff --git a/src/index.js b/src/index.js
index e059da6..d2272c6 100644
--- a/src/index.js
+++ b/src/index.js
@@ -6,6 +6,7 @@ Author Tobias Koppers @sokra
 import os from 'os';
 import crypto from 'crypto';
 import url from 'url';
+import path from 'path';
 
 import async from 'neo-async';
 import RawSource from 'webpack-sources/lib/RawSource';
@@ -143,9 +144,14 @@ class CompressionPlugin {
                 }
 
                 const parse = url.parse(file);
+                const { pathname } = parse;
+                const { dir, name, ext } = path.parse(pathname);
                 const info = {
                   file,
-                  path: parse.pathname,
+                  path: pathname,
+                  dir: dir ? `${dir}/` : '',
+                  name,
+                  ext,
                   query: parse.query ? `?${parse.query}` : '',
                 };
 
@@ -153,7 +159,7 @@ class CompressionPlugin {
                   typeof filename === 'function'
                     ? filename(info)
                     : filename.replace(
-                        /\[(file|path|query)\]/g,
+                        /\[(file|path|query|dir|name|ext)\]/g,
                         (p0, p1) => info[p1]
                       );
 


Test patch:
diff --git a/test/__snapshots__/filename-option.test.js.snap b/test/__snapshots__/filename-option.test.js.snap
index 3834f9e..4229b0d 100644
--- a/test/__snapshots__/filename-option.test.js.snap
+++ b/test/__snapshots__/filename-option.test.js.snap
@@ -1,5 +1,46 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
+exports[`when applied with \`function\` option matches snapshot for \`[dir][name].super-compressed.gz[ext][query]\` value ({String}): assets 1`] = `
+Array [
+  Array [
+    "0.async.js?ver=81982f432266ef1edd1a",
+    130,
+  ],
+  Array [
+    "0.async.super-compressed.gz.js?ver=81982f432266ef1edd1a",
+    117,
+  ],
+  Array [
+    "5b1f36bc41ab31f5b801d48ba1d65781.png",
+    78117,
+  ],
+  Array [
+    "5b1f36bc41ab31f5b801d48ba1d65781.super-compressed.gz.png",
+    73160,
+  ],
+  Array [
+    "96621d3c37d96ad3bf792fcc848d912f.super-compressed.gz.svg",
+    393,
+  ],
+  Array [
+    "96621d3c37d96ad3bf792fcc848d912f.svg",
+    672,
+  ],
+  Array [
+    "js.js?var=81982f432266ef1edd1a",
+    10221,
+  ],
+  Array [
+    "js.super-compressed.gz.js?var=81982f432266ef1edd1a",
+    2802,
+  ],
+]
+`;
+
+exports[`when applied with \`function\` option matches snapshot for \`[dir][name].super-compressed.gz[ext][query]\` value ({String}): errors 1`] = `Array []`;
+
+exports[`when applied with \`function\` option matches snapshot for \`[dir][name].super-compressed.gz[ext][query]\` value ({String}): warnings 1`] = `Array []`;
+
 exports[`when applied with \`function\` option matches snapshot for \`[path].super-compressed.gz[query]\` value ({String}): assets 1`] = `
 Array [
   Array [
diff --git a/test/filename-option.test.js b/test/filename-option.test.js
index fff80f1..8ca3af9 100644
--- a/test/filename-option.test.js
+++ b/test/filename-option.test.js
@@ -39,6 +39,22 @@ describe('when applied with `function` option', () => {
     });
   });
 
+  it('matches snapshot for `[dir][name].super-compressed.gz[ext][query]` value ({String})', () => {
+    new Plugin({
+      minRatio: 1,
+      filename: '[dir][name].super-compressed.gz[ext][query]',
+    }).apply(compiler);
+
+    return compile(compiler).then((stats) => {
+      const errors = stats.compilation.errors.map(cleanErrorStack);
+      const warnings = stats.compilation.warnings.map(cleanErrorStack);
+
+      expect(errors).toMatchSnapshot('errors');
+      expect(warnings).toMatchSnapshot('warnings');
+      expect(getAssetsInfo(stats.compilation.assets)).toMatchSnapshot('assets');
+    });
+  });
+
   it('matches snapshot for custom function ({Function})', () => {
     new Plugin({
       minRatio: 1,