Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
const cssnano = require('cssnano');
const { ModuleFilenameHelpers } = require('webpack');
const { SourceMapSource, RawSource } = require('webpack-sources');
import cssnano from 'cssnano';
import { ModuleFilenameHelpers } from 'webpack';
import { SourceMapSource, RawSource } from 'webpack-sources';
import validateOptions from 'schema-utils';

import schema from './options.json';

class CssnanoPlugin {
constructor(options) {
constructor(options = {}) {
validateOptions(schema, options, {
name: 'Cssnano webpack plugin',
baseDataPath: 'options',
});

this.options = Object.assign(
{
test: /\.css(\?.*)?$/i,
Expand Down
78 changes: 76 additions & 2 deletions src/options.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,82 @@
{
"definitions": {
"Rule": {
"description": "Filtering rule as regex or string.",
"anyOf": [
{
"instanceof": "RegExp",
"tsType": "RegExp"
},
{
"type": "string",
"minLength": 1
}
]
},
"Rules": {
"description": "Filtering rules.",
"anyOf": [
{
"type": "array",
"items": {
"description": "A rule condition.",
"oneOf": [
{
"$ref": "#/definitions/Rule"
}
]
}
},
{
"$ref": "#/definitions/Rule"
}
]
}
},
"title": "CssnanoWebpackPluginOptions",
"type": "object",
"properties": {
"name": {
"type": "boolean"
"test": {
"description": "Include all modules that pass test assertion.",
"oneOf": [
{
"$ref": "#/definitions/Rules"
}
]
},
"include": {
"description": "Include all modules matching any of these conditions.",
"oneOf": [
{
"$ref": "#/definitions/Rules"
}
]
},
"exclude": {
"description": "Exclude all modules matching any of these conditions.",
"oneOf": [
{
"$ref": "#/definitions/Rules"
}
]
},
"sourceMap": {
"description": "Enables/Disables generation of source maps.",
"anyOf": [
{
"description": "Options for source map.",
"additionalProperties": true,
"type": "object"
},
{
"type": "boolean"
}
]
},
"cssnanoOptions": {
"description": "Options for `cssnanoOptions`.",
"additionalProperties": true,
"type": "object"
}
},
"additionalProperties": false
Expand Down
116 changes: 116 additions & 0 deletions test/__snapshots__/validate-options.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`validation 1`] = `
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
- options.test should be one of these:
[RegExp | non-empty string, ...] | RegExp | non-empty string
-> Filtering rules.
Details:
* options.test should be an array:
[RegExp | non-empty string, ...]
* options.test should be one of these:
RegExp | non-empty string
-> Filtering rule as regex or string.
Details:
* options.test should be an instance of RegExp.
* options.test should be a non-empty string."
`;

exports[`validation 2`] = `
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
- options.test should be one of these:
[RegExp | non-empty string, ...] | RegExp | non-empty string
-> Filtering rules.
Details:
* options.test[0] should be one of these:
RegExp | non-empty string
-> Filtering rule as regex or string.
Details:
* options.test[0] should be an instance of RegExp.
* options.test[0] should be a non-empty string."
`;

exports[`validation 3`] = `
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
- options.include should be one of these:
[RegExp | non-empty string, ...] | RegExp | non-empty string
-> Filtering rules.
Details:
* options.include should be an array:
[RegExp | non-empty string, ...]
* options.include should be one of these:
RegExp | non-empty string
-> Filtering rule as regex or string.
Details:
* options.include should be an instance of RegExp.
* options.include should be a non-empty string."
`;

exports[`validation 4`] = `
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
- options.include should be one of these:
[RegExp | non-empty string, ...] | RegExp | non-empty string
-> Filtering rules.
Details:
* options.include[0] should be one of these:
RegExp | non-empty string
-> Filtering rule as regex or string.
Details:
* options.include[0] should be an instance of RegExp.
* options.include[0] should be a non-empty string."
`;

exports[`validation 5`] = `
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
- options.exclude should be one of these:
[RegExp | non-empty string, ...] | RegExp | non-empty string
-> Filtering rules.
Details:
* options.exclude should be an array:
[RegExp | non-empty string, ...]
* options.exclude should be one of these:
RegExp | non-empty string
-> Filtering rule as regex or string.
Details:
* options.exclude should be an instance of RegExp.
* options.exclude should be a non-empty string."
`;

exports[`validation 6`] = `
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
- options.exclude should be one of these:
[RegExp | non-empty string, ...] | RegExp | non-empty string
-> Filtering rules.
Details:
* options.exclude[0] should be one of these:
RegExp | non-empty string
-> Filtering rule as regex or string.
Details:
* options.exclude[0] should be an instance of RegExp.
* options.exclude[0] should be a non-empty string."
`;

exports[`validation 7`] = `
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
- options.sourceMap should be one of these:
object { … } | boolean
-> Enables/Disables generation of source maps.
Details:
* options.sourceMap should be an object:
object { … }
-> Options for source map.
* options.sourceMap should be a boolean."
`;

exports[`validation 8`] = `
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
- options.cssnanoOptions should be an object:
object { … }
-> Options for \`cssnanoOptions\`."
`;

exports[`validation 9`] = `
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
- options has an unknown property 'unknown'. These properties are valid:
object { test?, include?, exclude?, sourceMap?, cssnanoOptions? }"
`;
135 changes: 135 additions & 0 deletions test/validate-options.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import CssnanoWebpackPlugin from '../src';

it('validation', () => {
/* eslint-disable no-new */
expect(() => {
new CssnanoWebpackPlugin({ test: /foo/ });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ test: 'foo' });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ test: [/foo/] });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ test: [/foo/, /bar/] });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ test: ['foo', 'bar'] });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ test: [/foo/, 'bar'] });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ test: true });
}).toThrowErrorMatchingSnapshot();

expect(() => {
new CssnanoWebpackPlugin({ test: [true] });
}).toThrowErrorMatchingSnapshot();

expect(() => {
new CssnanoWebpackPlugin({ include: /foo/ });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ include: 'foo' });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ include: [/foo/] });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ include: [/foo/, /bar/] });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ include: ['foo', 'bar'] });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ include: [/foo/, 'bar'] });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ include: true });
}).toThrowErrorMatchingSnapshot();

expect(() => {
new CssnanoWebpackPlugin({ include: [true] });
}).toThrowErrorMatchingSnapshot();

expect(() => {
new CssnanoWebpackPlugin({ exclude: /foo/ });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ exclude: 'foo' });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ exclude: [/foo/] });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ exclude: [/foo/, /bar/] });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ exclude: ['foo', 'bar'] });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ exclude: [/foo/, 'bar'] });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ exclude: true });
}).toThrowErrorMatchingSnapshot();

expect(() => {
new CssnanoWebpackPlugin({ exclude: [true] });
}).toThrowErrorMatchingSnapshot();

expect(() => {
new CssnanoWebpackPlugin({ sourceMap: true });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ sourceMap: false });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ sourceMap: { inline: true } });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ sourceMap: 'true' });
}).toThrowErrorMatchingSnapshot();

expect(() => {
new CssnanoWebpackPlugin({ cssnanoOptions: {} });
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ cssnanoOptions: null });
}).toThrowErrorMatchingSnapshot();

expect(() => {
new CssnanoWebpackPlugin({
cssnanoOptions: { colormin: true },
});
}).not.toThrow();

expect(() => {
new CssnanoWebpackPlugin({ unknown: true });
}).toThrowErrorMatchingSnapshot();
/* eslint-enable no-new */
});