Skip to content

Commit c2163af

Browse files
refactor: add schema (#7)
1 parent ea7b960 commit c2163af

File tree

4 files changed

+339
-6
lines changed

4 files changed

+339
-6
lines changed

src/index.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1-
const cssnano = require('cssnano');
2-
const { ModuleFilenameHelpers } = require('webpack');
3-
const { SourceMapSource, RawSource } = require('webpack-sources');
1+
import cssnano from 'cssnano';
2+
import { ModuleFilenameHelpers } from 'webpack';
3+
import { SourceMapSource, RawSource } from 'webpack-sources';
4+
import validateOptions from 'schema-utils';
5+
6+
import schema from './options.json';
47

58
class CssnanoPlugin {
6-
constructor(options) {
9+
constructor(options = {}) {
10+
validateOptions(schema, options, {
11+
name: 'Cssnano webpack plugin',
12+
baseDataPath: 'options',
13+
});
14+
715
this.options = Object.assign(
816
{
917
test: /\.css(\?.*)?$/i,

src/options.json

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,82 @@
11
{
2+
"definitions": {
3+
"Rule": {
4+
"description": "Filtering rule as regex or string.",
5+
"anyOf": [
6+
{
7+
"instanceof": "RegExp",
8+
"tsType": "RegExp"
9+
},
10+
{
11+
"type": "string",
12+
"minLength": 1
13+
}
14+
]
15+
},
16+
"Rules": {
17+
"description": "Filtering rules.",
18+
"anyOf": [
19+
{
20+
"type": "array",
21+
"items": {
22+
"description": "A rule condition.",
23+
"oneOf": [
24+
{
25+
"$ref": "#/definitions/Rule"
26+
}
27+
]
28+
}
29+
},
30+
{
31+
"$ref": "#/definitions/Rule"
32+
}
33+
]
34+
}
35+
},
36+
"title": "CssnanoWebpackPluginOptions",
237
"type": "object",
338
"properties": {
4-
"name": {
5-
"type": "boolean"
39+
"test": {
40+
"description": "Include all modules that pass test assertion.",
41+
"oneOf": [
42+
{
43+
"$ref": "#/definitions/Rules"
44+
}
45+
]
46+
},
47+
"include": {
48+
"description": "Include all modules matching any of these conditions.",
49+
"oneOf": [
50+
{
51+
"$ref": "#/definitions/Rules"
52+
}
53+
]
54+
},
55+
"exclude": {
56+
"description": "Exclude all modules matching any of these conditions.",
57+
"oneOf": [
58+
{
59+
"$ref": "#/definitions/Rules"
60+
}
61+
]
62+
},
63+
"sourceMap": {
64+
"description": "Enables/Disables generation of source maps.",
65+
"anyOf": [
66+
{
67+
"description": "Options for source map.",
68+
"additionalProperties": true,
69+
"type": "object"
70+
},
71+
{
72+
"type": "boolean"
73+
}
74+
]
75+
},
76+
"cssnanoOptions": {
77+
"description": "Options for `cssnanoOptions`.",
78+
"additionalProperties": true,
79+
"type": "object"
680
}
781
},
882
"additionalProperties": false
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`validation 1`] = `
4+
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
5+
- options.test should be one of these:
6+
[RegExp | non-empty string, ...] | RegExp | non-empty string
7+
-> Filtering rules.
8+
Details:
9+
* options.test should be an array:
10+
[RegExp | non-empty string, ...]
11+
* options.test should be one of these:
12+
RegExp | non-empty string
13+
-> Filtering rule as regex or string.
14+
Details:
15+
* options.test should be an instance of RegExp.
16+
* options.test should be a non-empty string."
17+
`;
18+
19+
exports[`validation 2`] = `
20+
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
21+
- options.test should be one of these:
22+
[RegExp | non-empty string, ...] | RegExp | non-empty string
23+
-> Filtering rules.
24+
Details:
25+
* options.test[0] should be one of these:
26+
RegExp | non-empty string
27+
-> Filtering rule as regex or string.
28+
Details:
29+
* options.test[0] should be an instance of RegExp.
30+
* options.test[0] should be a non-empty string."
31+
`;
32+
33+
exports[`validation 3`] = `
34+
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
35+
- options.include should be one of these:
36+
[RegExp | non-empty string, ...] | RegExp | non-empty string
37+
-> Filtering rules.
38+
Details:
39+
* options.include should be an array:
40+
[RegExp | non-empty string, ...]
41+
* options.include should be one of these:
42+
RegExp | non-empty string
43+
-> Filtering rule as regex or string.
44+
Details:
45+
* options.include should be an instance of RegExp.
46+
* options.include should be a non-empty string."
47+
`;
48+
49+
exports[`validation 4`] = `
50+
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
51+
- options.include should be one of these:
52+
[RegExp | non-empty string, ...] | RegExp | non-empty string
53+
-> Filtering rules.
54+
Details:
55+
* options.include[0] should be one of these:
56+
RegExp | non-empty string
57+
-> Filtering rule as regex or string.
58+
Details:
59+
* options.include[0] should be an instance of RegExp.
60+
* options.include[0] should be a non-empty string."
61+
`;
62+
63+
exports[`validation 5`] = `
64+
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
65+
- options.exclude should be one of these:
66+
[RegExp | non-empty string, ...] | RegExp | non-empty string
67+
-> Filtering rules.
68+
Details:
69+
* options.exclude should be an array:
70+
[RegExp | non-empty string, ...]
71+
* options.exclude should be one of these:
72+
RegExp | non-empty string
73+
-> Filtering rule as regex or string.
74+
Details:
75+
* options.exclude should be an instance of RegExp.
76+
* options.exclude should be a non-empty string."
77+
`;
78+
79+
exports[`validation 6`] = `
80+
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
81+
- options.exclude should be one of these:
82+
[RegExp | non-empty string, ...] | RegExp | non-empty string
83+
-> Filtering rules.
84+
Details:
85+
* options.exclude[0] should be one of these:
86+
RegExp | non-empty string
87+
-> Filtering rule as regex or string.
88+
Details:
89+
* options.exclude[0] should be an instance of RegExp.
90+
* options.exclude[0] should be a non-empty string."
91+
`;
92+
93+
exports[`validation 7`] = `
94+
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
95+
- options.sourceMap should be one of these:
96+
object {} | boolean
97+
-> Enables/Disables generation of source maps.
98+
Details:
99+
* options.sourceMap should be an object:
100+
object {}
101+
-> Options for source map.
102+
* options.sourceMap should be a boolean."
103+
`;
104+
105+
exports[`validation 8`] = `
106+
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
107+
- options.cssnanoOptions should be an object:
108+
object {}
109+
-> Options for \`cssnanoOptions\`."
110+
`;
111+
112+
exports[`validation 9`] = `
113+
"Invalid options object. Cssnano webpack plugin has been initialized using an options object that does not match the API schema.
114+
- options has an unknown property 'unknown'. These properties are valid:
115+
object { test?, include?, exclude?, sourceMap?, cssnanoOptions? }"
116+
`;

test/validate-options.test.js

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import CssnanoWebpackPlugin from '../src';
2+
3+
it('validation', () => {
4+
/* eslint-disable no-new */
5+
expect(() => {
6+
new CssnanoWebpackPlugin({ test: /foo/ });
7+
}).not.toThrow();
8+
9+
expect(() => {
10+
new CssnanoWebpackPlugin({ test: 'foo' });
11+
}).not.toThrow();
12+
13+
expect(() => {
14+
new CssnanoWebpackPlugin({ test: [/foo/] });
15+
}).not.toThrow();
16+
17+
expect(() => {
18+
new CssnanoWebpackPlugin({ test: [/foo/, /bar/] });
19+
}).not.toThrow();
20+
21+
expect(() => {
22+
new CssnanoWebpackPlugin({ test: ['foo', 'bar'] });
23+
}).not.toThrow();
24+
25+
expect(() => {
26+
new CssnanoWebpackPlugin({ test: [/foo/, 'bar'] });
27+
}).not.toThrow();
28+
29+
expect(() => {
30+
new CssnanoWebpackPlugin({ test: true });
31+
}).toThrowErrorMatchingSnapshot();
32+
33+
expect(() => {
34+
new CssnanoWebpackPlugin({ test: [true] });
35+
}).toThrowErrorMatchingSnapshot();
36+
37+
expect(() => {
38+
new CssnanoWebpackPlugin({ include: /foo/ });
39+
}).not.toThrow();
40+
41+
expect(() => {
42+
new CssnanoWebpackPlugin({ include: 'foo' });
43+
}).not.toThrow();
44+
45+
expect(() => {
46+
new CssnanoWebpackPlugin({ include: [/foo/] });
47+
}).not.toThrow();
48+
49+
expect(() => {
50+
new CssnanoWebpackPlugin({ include: [/foo/, /bar/] });
51+
}).not.toThrow();
52+
53+
expect(() => {
54+
new CssnanoWebpackPlugin({ include: ['foo', 'bar'] });
55+
}).not.toThrow();
56+
57+
expect(() => {
58+
new CssnanoWebpackPlugin({ include: [/foo/, 'bar'] });
59+
}).not.toThrow();
60+
61+
expect(() => {
62+
new CssnanoWebpackPlugin({ include: true });
63+
}).toThrowErrorMatchingSnapshot();
64+
65+
expect(() => {
66+
new CssnanoWebpackPlugin({ include: [true] });
67+
}).toThrowErrorMatchingSnapshot();
68+
69+
expect(() => {
70+
new CssnanoWebpackPlugin({ exclude: /foo/ });
71+
}).not.toThrow();
72+
73+
expect(() => {
74+
new CssnanoWebpackPlugin({ exclude: 'foo' });
75+
}).not.toThrow();
76+
77+
expect(() => {
78+
new CssnanoWebpackPlugin({ exclude: [/foo/] });
79+
}).not.toThrow();
80+
81+
expect(() => {
82+
new CssnanoWebpackPlugin({ exclude: [/foo/, /bar/] });
83+
}).not.toThrow();
84+
85+
expect(() => {
86+
new CssnanoWebpackPlugin({ exclude: ['foo', 'bar'] });
87+
}).not.toThrow();
88+
89+
expect(() => {
90+
new CssnanoWebpackPlugin({ exclude: [/foo/, 'bar'] });
91+
}).not.toThrow();
92+
93+
expect(() => {
94+
new CssnanoWebpackPlugin({ exclude: true });
95+
}).toThrowErrorMatchingSnapshot();
96+
97+
expect(() => {
98+
new CssnanoWebpackPlugin({ exclude: [true] });
99+
}).toThrowErrorMatchingSnapshot();
100+
101+
expect(() => {
102+
new CssnanoWebpackPlugin({ sourceMap: true });
103+
}).not.toThrow();
104+
105+
expect(() => {
106+
new CssnanoWebpackPlugin({ sourceMap: false });
107+
}).not.toThrow();
108+
109+
expect(() => {
110+
new CssnanoWebpackPlugin({ sourceMap: { inline: true } });
111+
}).not.toThrow();
112+
113+
expect(() => {
114+
new CssnanoWebpackPlugin({ sourceMap: 'true' });
115+
}).toThrowErrorMatchingSnapshot();
116+
117+
expect(() => {
118+
new CssnanoWebpackPlugin({ cssnanoOptions: {} });
119+
}).not.toThrow();
120+
121+
expect(() => {
122+
new CssnanoWebpackPlugin({ cssnanoOptions: null });
123+
}).toThrowErrorMatchingSnapshot();
124+
125+
expect(() => {
126+
new CssnanoWebpackPlugin({
127+
cssnanoOptions: { colormin: true },
128+
});
129+
}).not.toThrow();
130+
131+
expect(() => {
132+
new CssnanoWebpackPlugin({ unknown: true });
133+
}).toThrowErrorMatchingSnapshot();
134+
/* eslint-enable no-new */
135+
});

0 commit comments

Comments
 (0)