Skip to content

Commit 6f4472a

Browse files
authored
Merge pull request #65 from webpack/add/get-options
Add/get options
2 parents 8933f86 + ff86dd6 commit 6f4472a

8 files changed

+156
-133
lines changed

README.md

Lines changed: 26 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,57 +2,46 @@
22

33
## Methods
44

5-
### `getLoaderConfig`
5+
### getOptions
66

7-
Recommended way to retrieve the loader config:
7+
Recommended way to retrieve the options of a loader invocation:
88

99
```javascript
1010
// inside your loader
11-
config = loaderUtils.getLoaderConfig(this, "myLoader");
11+
const options = loaderUtils.getOptions(this);
1212
```
1313

14-
Tries to read the loader config from the `webpack.config.js` under the given property name (`"myLoader"` in this case) and merges the result with the loader query. For example, if your `webpack.config.js` had this property...
14+
**Please note:** The returned `options` object is *read-only*. It may be re-used across multiple invocations.
15+
If you pass it on to another library, make sure to make a *deep copy* of it:
1516

1617
```javascript
17-
cheesecakeLoader: {
18-
type: "delicious",
19-
slices: 4
20-
}
18+
const options = Object.assign({}, loaderUtils.getOptions(this));
19+
// don't forget nested objects or arrays
20+
options.obj = Object.assign({}, options.obj);
21+
options.arr = options.arr.slice();
22+
someLibrary(options);
2123
```
2224

23-
...and your loader was called with `?slices=8`, `getLoaderConfig(this, "cheesecakeLoader")` would return
25+
[assign-deep](https://www.npmjs.com/package/assign-deep) is a good library to make a deep copy of the options.
2426

25-
```javascript
26-
{
27-
type: "delicious",
28-
slices: 8
29-
}
30-
```
31-
32-
It is recommended that you use the camelCased loader name as your default config property name.
27+
#### Options as query strings
3328

34-
### `parseQuery`
35-
36-
``` javascript
37-
var query = loaderUtils.parseQuery(this.query);
38-
assert(typeof query == "object");
39-
if(query.flag)
40-
// ...
41-
```
29+
If the loader options have been passed as loader query string (`loader?some&params`), the string is parsed like this:
4230

4331
``` text
44-
null -> {}
45-
? -> {}
46-
?flag -> { flag: true }
47-
?+flag -> { flag: true }
48-
?-flag -> { flag: false }
49-
?xyz=test -> { xyz: "test" }
50-
?xyz[]=a -> { xyz: ["a"] }
51-
?flag1&flag2 -> { flag1: true, flag2: true }
52-
?+flag1,-flag2 -> { flag1: true, flag2: false }
53-
?xyz[]=a,xyz[]=b -> { xyz: ["a", "b"] }
54-
?a%2C%26b=c%2C%26d -> { "a,&b": "c,&d" }
55-
?{json:5,data:{a:1}} -> { json: 5, data: { a: 1 } }
32+
null -> {}
33+
? -> {}
34+
?flag -> { flag: true }
35+
?+flag -> { flag: true }
36+
?-flag -> { flag: false }
37+
?xyz=test -> { xyz: "test" }
38+
?xyz=1 -> { xyz: "1" }
39+
?xyz[]=a -> { xyz: ["a"] }
40+
?flag1&flag2 -> { flag1: true, flag2: true }
41+
?+flag1,-flag2 -> { flag1: true, flag2: false }
42+
?xyz[]=a,xyz[]=b -> { xyz: ["a", "b"] }
43+
?a%2C%26b=c%2C%26d -> { "a,&b": "c,&d" }
44+
?{data:{a:1},isJSON5:true} -> { data: { a: 1 }, isJSON5: true }
5645
```
5746

5847
### `stringifyRequest`

lib/getLoaderConfig.js

Lines changed: 0 additions & 17 deletions
This file was deleted.

lib/getOptions.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"use strict";
2+
3+
const parseQuery = require("./parseQuery");
4+
5+
function getOptions(loaderContext) {
6+
const query = loaderContext.query;
7+
if(typeof query === "string") {
8+
return parseQuery(loaderContext.query);
9+
}
10+
return query;
11+
}
12+
13+
module.exports = getOptions;

lib/index.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"use strict";
22

3-
const parseQuery = require("./parseQuery");
4-
const getLoaderConfig = require("./getLoaderConfig");
3+
const getOptions = require("./getOptions");
54
const stringifyRequest = require("./stringifyRequest");
65
const getRemainingRequest = require("./getRemainingRequest");
76
const getCurrentRequest = require("./getCurrentRequest");
@@ -11,8 +10,7 @@ const parseString = require("./parseString");
1110
const getHashDigest = require("./getHashDigest");
1211
const interpolateName = require("./interpolateName");
1312

14-
exports.parseQuery = parseQuery;
15-
exports.getLoaderConfig = getLoaderConfig;
13+
exports.getOptions = getOptions;
1614
exports.stringifyRequest = stringifyRequest;
1715
exports.getRemainingRequest = getRemainingRequest;
1816
exports.getCurrentRequest = getCurrentRequest;

lib/parseQuery.js

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,22 @@
11
"use strict";
22

33
const JSON5 = require("json5");
4-
const util = require("util");
5-
const os = require("os");
64

7-
const parseQueryDeprecationWarning = util.deprecate(() => {},
8-
"loaderUtils.parseQuery() received a non-string value which can be problematic, " +
9-
"see https://github.com/webpack/loader-utils/issues/56" + os.EOL +
10-
"parseQuery() will be replaced with getOptions() in the next major version of loader-utils."
11-
);
125
const specialValues = {
136
"null": null,
147
"true": true,
158
"false": false
169
};
1710

1811
function parseQuery(query) {
19-
if(!query) return {};
20-
if(typeof query !== "string") {
21-
parseQueryDeprecationWarning();
22-
return query;
12+
if(query.substr(0, 1) !== "?") {
13+
throw new Error("A valid query string passed to parseQuery should begin with '?'");
2314
}
24-
if(query.substr(0, 1) !== "?")
25-
throw new Error("a valid query string passed to parseQuery should begin with '?'");
2615
query = query.substr(1);
2716
if(query.substr(0, 1) === "{" && query.substr(-1) === "}") {
2817
return JSON5.parse(query);
2918
}
30-
const queryArgs = query.split(/[,\&]/g);
19+
const queryArgs = query.split(/[,&]/g);
3120
const result = {};
3221
queryArgs.forEach(arg => {
3322
const idx = arg.indexOf("=");

test/getLoaderConfig.test.js

Lines changed: 0 additions & 23 deletions
This file was deleted.

test/getOptions.test.js

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
"use strict";
2+
3+
const assert = require("assert");
4+
const loaderUtils = require("../lib");
5+
6+
describe("getOptions()", () => {
7+
describe("when loaderContext.query is a string", () => {
8+
[{
9+
it: "should parse query params",
10+
query: "?name=cheesecake&slices=8&delicious&warm=false",
11+
expected: {
12+
delicious: true,
13+
name: "cheesecake",
14+
slices: "8", // numbers are still strings with query params
15+
warm: false
16+
}
17+
},
18+
{
19+
it: "should parse query params with arrays",
20+
query: "?ingredients[]=flour&ingredients[]=sugar",
21+
expected: {
22+
ingredients: ["flour", "sugar"]
23+
}
24+
},
25+
{
26+
it: "should parse query params in JSON format",
27+
query: "?" + JSON.stringify({
28+
delicious: true,
29+
name: "cheesecake",
30+
slices: 8,
31+
warm: false
32+
}),
33+
expected: {
34+
delicious: true,
35+
name: "cheesecake",
36+
slices: 8,
37+
warm: false
38+
}
39+
},
40+
{
41+
it: "should use decodeURIComponent",
42+
query: "?%3d",
43+
expected: { "=": true }
44+
},
45+
{
46+
it: "should recognize params starting with + as boolean params with the value true",
47+
query: "?+%3d",
48+
expected: { "=": true }
49+
},
50+
{
51+
it: "should recognize params starting with - as boolean params with the value false",
52+
query: "?-%3d",
53+
expected: { "=": false }
54+
},
55+
{
56+
it: "should not confuse regular equal signs and encoded equal signs",
57+
query: "?%3d=%3D",
58+
expected: { "=": "=" }
59+
}].forEach(test => {
60+
it(test.it, () => {
61+
assert.deepEqual(
62+
loaderUtils.getOptions({
63+
query: test.query
64+
}),
65+
test.expected
66+
);
67+
});
68+
});
69+
describe("and the query string does not start with ?", () => {
70+
it("should throw an error", () => {
71+
assert.throws(
72+
() => loaderUtils.getOptions({ query: "a" }),
73+
"A valid query string passed to parseQuery should begin with '?'"
74+
);
75+
});
76+
});
77+
});
78+
describe("when loaderContext.query is an object", () => {
79+
it("should just return the object", () => {
80+
const query = {};
81+
assert.strictEqual(
82+
loaderUtils.getOptions({
83+
query
84+
}),
85+
query
86+
);
87+
});
88+
});
89+
describe("when loaderContext.query is anything else", () => {
90+
it("should just return it", () => {
91+
const query = [];
92+
assert.strictEqual(
93+
loaderUtils.getOptions({
94+
query
95+
}),
96+
query
97+
);
98+
assert.strictEqual(
99+
loaderUtils.getOptions({
100+
query: undefined
101+
}),
102+
undefined
103+
);
104+
assert.strictEqual(
105+
loaderUtils.getOptions({
106+
query: null
107+
}),
108+
null
109+
);
110+
});
111+
});
112+
});

test/parseQuery.test.js

Lines changed: 0 additions & 38 deletions
This file was deleted.

0 commit comments

Comments
 (0)