diff --git a/README.md b/README.md index 1743d4cf..e4fe257e 100644 --- a/README.md +++ b/README.md @@ -262,7 +262,7 @@ new TerserPlugin({ ### `extractComments` -Type: `Boolean|String|RegExp|Function<(node, comment) -> Boolean|Object>` +Type: `Boolean|String|RegExp|Function<(node, comment) -> Boolean|Object>|Object` Default: `false` Whether comments shall be extracted to a separate file, (see [details](https://github.com/webpack/webpack/commit/71933e979e51c533b432658d5e37917f9e71595a)). @@ -362,7 +362,7 @@ new TerserPlugin({ ##### `filename` -Type: `Regex|Function<(string) -> String>` +Type: `String|Function<(string) -> String>` Default: `${file}.LICENSE` The file where the extracted comments will be stored. diff --git a/src/options.json b/src/options.json index b3bf06a0..39db2417 100644 --- a/src/options.json +++ b/src/options.json @@ -1,17 +1,91 @@ { - "type": "object", + "additionalProperties": false, + "definitions": { + "file-conditions": { + "anyOf": [ + { + "instanceof": "RegExp" + }, + { + "type": "string" + } + ] + } + }, "properties": { - "test": {}, - "include": {}, - "exclude": {}, + "test": { + "anyOf": [ + { + "$ref": "#/definitions/file-conditions" + }, + { + "items": { + "anyOf": [ + { + "$ref": "#/definitions/file-conditions" + } + ] + }, + "type": "array" + } + ] + }, + "include": { + "anyOf": [ + { + "$ref": "#/definitions/file-conditions" + }, + { + "items": { + "anyOf": [ + { + "$ref": "#/definitions/file-conditions" + } + ] + }, + "type": "array" + } + ] + }, + "exclude": { + "anyOf": [ + { + "$ref": "#/definitions/file-conditions" + }, + { + "items": { + "anyOf": [ + { + "$ref": "#/definitions/file-conditions" + } + ] + }, + "type": "array" + } + ] + }, "cache": { - "oneOf": [{ "type": "boolean" }, { "type": "string" }] + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + } + ] }, "cacheKeys": { "instanceof": "Function" }, "parallel": { - "oneOf": [{ "type": "boolean" }, { "type": "integer" }] + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "integer" + } + ] }, "sourceMap": { "type": "boolean" @@ -23,10 +97,70 @@ "additionalProperties": true, "type": "object" }, - "extractComments": {}, + "extractComments": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "instanceof": "RegExp" + }, + { + "instanceof": "Function" + }, + { + "additionalProperties": false, + "properties": { + "condition": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "instanceof": "RegExp" + }, + { + "instanceof": "Function" + } + ] + }, + "filename": { + "anyOf": [ + { + "type": "string" + }, + { + "instanceof": "Function" + } + ] + }, + "banner": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "instanceof": "Function" + } + ] + } + }, + "type": "object" + } + ] + }, "warningsFilter": { "instanceof": "Function" } }, - "additionalProperties": false + "type": "object" } diff --git a/test/__snapshots__/validation.test.js.snap b/test/__snapshots__/validation.test.js.snap index ce65aad8..74be1a0a 100644 --- a/test/__snapshots__/validation.test.js.snap +++ b/test/__snapshots__/validation.test.js.snap @@ -3,54 +3,200 @@ exports[`validation 1`] = ` "Terser Plugin Invalid Options -options should NOT have additional properties +options.test should pass \\"instanceof\\" keyword validation +options.test should be string +options.test should match some schema in anyOf +options.test should be array +options.test should match some schema in anyOf " `; exports[`validation 2`] = ` "Terser Plugin Invalid Options +options.test should pass \\"instanceof\\" keyword validation +options.test should be string +options.test should match some schema in anyOf +options.test.0 should pass \\"instanceof\\" keyword validation +options.test.0 should be string +options.test.0 should match some schema in anyOf +options.test.0 should match some schema in anyOf +options.test should match some schema in anyOf +" +`; + +exports[`validation 3`] = ` +"Terser Plugin Invalid Options + +options.include should pass \\"instanceof\\" keyword validation +options.include should be string +options.include should match some schema in anyOf +options.include should be array +options.include should match some schema in anyOf +" +`; + +exports[`validation 4`] = ` +"Terser Plugin Invalid Options + +options.include should pass \\"instanceof\\" keyword validation +options.include should be string +options.include should match some schema in anyOf +options.include.0 should pass \\"instanceof\\" keyword validation +options.include.0 should be string +options.include.0 should match some schema in anyOf +options.include.0 should match some schema in anyOf +options.include should match some schema in anyOf +" +`; + +exports[`validation 5`] = ` +"Terser Plugin Invalid Options + +options.exclude should pass \\"instanceof\\" keyword validation +options.exclude should be string +options.exclude should match some schema in anyOf +options.exclude should be array +options.exclude should match some schema in anyOf +" +`; + +exports[`validation 6`] = ` +"Terser Plugin Invalid Options + +options.exclude should pass \\"instanceof\\" keyword validation +options.exclude should be string +options.exclude should match some schema in anyOf +options.exclude.0 should pass \\"instanceof\\" keyword validation +options.exclude.0 should be string +options.exclude.0 should match some schema in anyOf +options.exclude.0 should match some schema in anyOf +options.exclude should match some schema in anyOf +" +`; + +exports[`validation 7`] = ` +"Terser Plugin Invalid Options + options.cache should be boolean options.cache should be string -options.cache should match exactly one schema in oneOf +options.cache should match some schema in anyOf " `; -exports[`validation 3`] = ` +exports[`validation 8`] = ` +"Terser Plugin Invalid Options + +options.cacheKeys should pass \\"instanceof\\" keyword validation +" +`; + +exports[`validation 9`] = ` "Terser Plugin Invalid Options options.parallel should be boolean options.parallel should be integer -options.parallel should match exactly one schema in oneOf +options.parallel should match some schema in anyOf " `; -exports[`validation 4`] = ` +exports[`validation 10`] = ` "Terser Plugin Invalid Options options.parallel should be boolean options.parallel should be integer -options.parallel should match exactly one schema in oneOf +options.parallel should match some schema in anyOf " `; -exports[`validation 5`] = ` +exports[`validation 11`] = ` "Terser Plugin Invalid Options options.sourceMap should be boolean " `; -exports[`validation 6`] = ` +exports[`validation 12`] = ` +"Terser Plugin Invalid Options + +options.minify should pass \\"instanceof\\" keyword validation +" +`; + +exports[`validation 13`] = ` "Terser Plugin Invalid Options options.terserOptions should be object " `; -exports[`validation 7`] = ` +exports[`validation 14`] = ` +"Terser Plugin Invalid Options + +options.extractComments should be boolean +options.extractComments should be string +options.extractComments should pass \\"instanceof\\" keyword validation +options.extractComments should pass \\"instanceof\\" keyword validation +options.extractComments.condition should be boolean +options.extractComments.condition should be string +options.extractComments.condition should pass \\"instanceof\\" keyword validation +options.extractComments.condition should pass \\"instanceof\\" keyword validation +options.extractComments.condition should match some schema in anyOf +options.extractComments should match some schema in anyOf +" +`; + +exports[`validation 15`] = ` +"Terser Plugin Invalid Options + +options.extractComments should be boolean +options.extractComments should be string +options.extractComments should pass \\"instanceof\\" keyword validation +options.extractComments should pass \\"instanceof\\" keyword validation +options.extractComments.filename should be string +options.extractComments.filename should pass \\"instanceof\\" keyword validation +options.extractComments.filename should match some schema in anyOf +options.extractComments should match some schema in anyOf +" +`; + +exports[`validation 16`] = ` +"Terser Plugin Invalid Options + +options.extractComments should be boolean +options.extractComments should be string +options.extractComments should pass \\"instanceof\\" keyword validation +options.extractComments should pass \\"instanceof\\" keyword validation +options.extractComments.banner should be boolean +options.extractComments.banner should be string +options.extractComments.banner should pass \\"instanceof\\" keyword validation +options.extractComments.banner should match some schema in anyOf +options.extractComments should match some schema in anyOf +" +`; + +exports[`validation 17`] = ` +"Terser Plugin Invalid Options + +options.extractComments should be boolean +options.extractComments should be string +options.extractComments should pass \\"instanceof\\" keyword validation +options.extractComments should pass \\"instanceof\\" keyword validation +options.extractComments should NOT have additional properties +options.extractComments should match some schema in anyOf +" +`; + +exports[`validation 18`] = ` "Terser Plugin Invalid Options options.warningsFilter should pass \\"instanceof\\" keyword validation " `; + +exports[`validation 19`] = ` +"Terser Plugin Invalid Options + +options should NOT have additional properties +" +`; diff --git a/test/validation.test.js b/test/validation.test.js index d7994543..41790f68 100644 --- a/test/validation.test.js +++ b/test/validation.test.js @@ -6,28 +6,96 @@ it('validation', () => { new TerserPlugin({ test: /foo/ }); }).not.toThrow(); + expect(() => { + new TerserPlugin({ test: 'foo' }); + }).not.toThrow(); + expect(() => { new TerserPlugin({ test: [/foo/] }); }).not.toThrow(); + expect(() => { + new TerserPlugin({ test: [/foo/, /bar/] }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ test: ['foo', 'bar'] }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ test: [/foo/, 'bar'] }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ test: true }); + }).toThrowErrorMatchingSnapshot(); + + expect(() => { + new TerserPlugin({ test: [true] }); + }).toThrowErrorMatchingSnapshot(); + expect(() => { new TerserPlugin({ include: /foo/ }); }).not.toThrow(); + expect(() => { + new TerserPlugin({ include: 'foo' }); + }).not.toThrow(); + expect(() => { new TerserPlugin({ include: [/foo/] }); }).not.toThrow(); + expect(() => { + new TerserPlugin({ include: [/foo/, /bar/] }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ include: ['foo', 'bar'] }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ include: [/foo/, 'bar'] }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ include: true }); + }).toThrowErrorMatchingSnapshot(); + + expect(() => { + new TerserPlugin({ include: [true] }); + }).toThrowErrorMatchingSnapshot(); + expect(() => { new TerserPlugin({ exclude: /foo/ }); }).not.toThrow(); + expect(() => { + new TerserPlugin({ exclude: 'foo' }); + }).not.toThrow(); + expect(() => { new TerserPlugin({ exclude: [/foo/] }); }).not.toThrow(); expect(() => { - new TerserPlugin({ doesntExist: true }); + new TerserPlugin({ exclude: [/foo/, /bar/] }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ exclude: ['foo', 'bar'] }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ exclude: [/foo/, 'bar'] }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ exclude: true }); + }).toThrowErrorMatchingSnapshot(); + + expect(() => { + new TerserPlugin({ exclude: [true] }); }).toThrowErrorMatchingSnapshot(); expect(() => { @@ -50,6 +118,10 @@ it('validation', () => { new TerserPlugin({ cacheKeys() {} }); }).not.toThrow(); + expect(() => { + new TerserPlugin({ cacheKeys: 'test' }); + }).toThrowErrorMatchingSnapshot(); + expect(() => { new TerserPlugin({ parallel: true }); }).not.toThrow(); @@ -87,13 +159,17 @@ it('validation', () => { }).not.toThrow(); expect(() => { - new TerserPlugin({ terserOptions: null }); + new TerserPlugin({ minify: true }); }).toThrowErrorMatchingSnapshot(); expect(() => { new TerserPlugin({ terserOptions: {} }); }).not.toThrow(); + expect(() => { + new TerserPlugin({ terserOptions: null }); + }).toThrowErrorMatchingSnapshot(); + expect(() => { new TerserPlugin({ terserOptions: { @@ -127,6 +203,10 @@ it('validation', () => { new TerserPlugin({ extractComments: false }); }).not.toThrow(); + expect(() => { + new TerserPlugin({ extractComments: 'comment' }); + }).not.toThrow(); + expect(() => { new TerserPlugin({ extractComments: /comment/ }); }).not.toThrow(); @@ -135,6 +215,106 @@ it('validation', () => { new TerserPlugin({ extractComments() {} }); }).not.toThrow(); + expect(() => { + new TerserPlugin({ + extractComments: { + condition: true, + }, + }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ + extractComments: { + condition: 'comment', + }, + }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ + extractComments: { + condition: /comment/, + }, + }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ + extractComments: { + condition() {}, + }, + }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ + extractComments: { + condition: {}, + }, + }); + }).toThrowErrorMatchingSnapshot(); + + expect(() => { + new TerserPlugin({ + extractComments: { + filename: 'test.js', + }, + }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ + extractComments: { + filename() {}, + }, + }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ + extractComments: { + filename: true, + }, + }); + }).toThrowErrorMatchingSnapshot(); + + expect(() => { + new TerserPlugin({ + extractComments: { + banner: true, + }, + }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ + extractComments: { + banner: 'banner', + }, + }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ + extractComments: { + banner() {}, + }, + }); + }).not.toThrow(); + + expect(() => { + new TerserPlugin({ + extractComments: { + banner: /test/, + }, + }); + }).toThrowErrorMatchingSnapshot(); + + expect(() => { + new TerserPlugin({ extractComments: { unknown: true } }); + }).toThrowErrorMatchingSnapshot(); + expect(() => { new TerserPlugin({ warningsFilter() {} }); }).not.toThrow(); @@ -142,5 +322,9 @@ it('validation', () => { expect(() => { new TerserPlugin({ warningsFilter: true }); }).toThrowErrorMatchingSnapshot(); + + expect(() => { + new TerserPlugin({ unknown: true }); + }).toThrowErrorMatchingSnapshot(); /* eslint-enable no-new */ });