diff --git a/README.md b/README.md index 07cdf99..84bf788 100644 --- a/README.md +++ b/README.md @@ -36,10 +36,23 @@ someLibrary(options); #### Options as query strings -If the loader options have been passed as loader query string (`loader?some¶ms`), the string is parsed like this: +If the loader options have been passed as loader query string (`loader?some¶ms`), the string is parsed by using [`parseQuery`](#parsequery). + +### `parseQuery` + +Parses a passed string (e.g. `loaderContext.resourceQuery`) as a query string, and returns an object. + +``` javascript +const params = loaderUtils.parseQuery(this.resourceQuery); // resource: `file?param1=foo` +if (params.param1 === "foo") { + // do something +} +``` + +The string is parsed like this: ``` text - -> null + -> Error ? -> {} ?flag -> { flag: true } ?+flag -> { flag: true } @@ -103,8 +116,8 @@ loaderUtils.stringifyRequest(this, "\\\\network-drive\\test.js"); Converts some resource URL to a webpack module request. ```javascript -var url = "path/to/module.js"; -var request = loaderUtils.urlToRequest(url); // "./path/to/module.js" +const url = "path/to/module.js"; +const request = loaderUtils.urlToRequest(url); // "./path/to/module.js" ``` #### Module URLs @@ -112,8 +125,8 @@ var request = loaderUtils.urlToRequest(url); // "./path/to/module.js" Any URL containing a `~` will be interpreted as a module request. Anything after the `~` will be considered the request path. ```javascript -var url = "~path/to/module.js"; -var request = loaderUtils.urlToRequest(url); // "path/to/module.js" +const url = "~path/to/module.js"; +const request = loaderUtils.urlToRequest(url); // "path/to/module.js" ``` #### Root-relative URLs @@ -121,17 +134,17 @@ var request = loaderUtils.urlToRequest(url); // "path/to/module.js" URLs that are root-relative (start with `/`) can be resolved relative to some arbitrary path by using the `root` parameter: ```javascript -var url = "/path/to/module.js"; -var root = "./root"; -var request = loaderUtils.urlToRequest(url, root); // "./root/path/to/module.js" +const url = "/path/to/module.js"; +const root = "./root"; +const request = loaderUtils.urlToRequest(url, root); // "./root/path/to/module.js" ``` To convert a root-relative URL into a module URL, specify a `root` value that starts with `~`: ```javascript -var url = "/path/to/module.js"; -var root = "~"; -var request = loaderUtils.urlToRequest(url, root); // "path/to/module.js" +const url = "/path/to/module.js"; +const root = "~"; +const request = loaderUtils.urlToRequest(url, root); // "path/to/module.js" ``` ### `interpolateName` @@ -140,7 +153,7 @@ Interpolates a filename template using multiple placeholders and/or a regular ex The template and regular expression are set as query params called `name` and `regExp` on the current loader's context. ```javascript -var interpolatedName = loaderUtils.interpolateName(loaderContext, name, options); +const interpolatedName = loaderUtils.interpolateName(loaderContext, name, options); ``` The following tokens are replaced in the `name` parameter: @@ -203,7 +216,7 @@ loaderUtils.interpolateName(loaderContext, "script-[1].[ext]", { regExp: "page-( ### `getHashDigest` ``` javascript -var digestString = loaderUtils.getHashDigest(buffer, hashType, digestType, maxLength); +const digestString = loaderUtils.getHashDigest(buffer, hashType, digestType, maxLength); ``` * `buffer` the content that should be hashed diff --git a/lib/index.js b/lib/index.js index 0ca780b..a595092 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,6 +1,7 @@ "use strict"; const getOptions = require("./getOptions"); +const parseQuery = require("./parseQuery"); const stringifyRequest = require("./stringifyRequest"); const getRemainingRequest = require("./getRemainingRequest"); const getCurrentRequest = require("./getCurrentRequest"); @@ -11,6 +12,7 @@ const getHashDigest = require("./getHashDigest"); const interpolateName = require("./interpolateName"); exports.getOptions = getOptions; +exports.parseQuery = parseQuery; exports.stringifyRequest = stringifyRequest; exports.getRemainingRequest = getRemainingRequest; exports.getCurrentRequest = getCurrentRequest; diff --git a/test/getOptions.test.js b/test/getOptions.test.js index 8d244e3..803a293 100644 --- a/test/getOptions.test.js +++ b/test/getOptions.test.js @@ -4,72 +4,14 @@ const assert = require("assert"); const loaderUtils = require("../lib"); describe("getOptions()", () => { - describe("when loaderContext.query is a query string starting with ?", () => { - [{ - it: "should return an empty object by default", - query: "?", - expected: {} - }, - { - it: "should parse query params", - query: "?name=cheesecake&slices=8&delicious&warm=false", - expected: { - delicious: true, - name: "cheesecake", - slices: "8", // numbers are still strings with query params - warm: false - } - }, - { - it: "should parse query params with arrays", - query: "?ingredients[]=flour&ingredients[]=sugar", - expected: { - ingredients: ["flour", "sugar"] - } - }, - { - it: "should parse query params in JSON format", - query: "?" + JSON.stringify({ - delicious: true, - name: "cheesecake", - slices: 8, - warm: false - }), - expected: { - delicious: true, - name: "cheesecake", - slices: 8, - warm: false - } - }, - { - it: "should use decodeURIComponent", - query: "?%3d", - expected: { "=": true } - }, - { - it: "should recognize params starting with + as boolean params with the value true", - query: "?+%3d", - expected: { "=": true } - }, - { - it: "should recognize params starting with - as boolean params with the value false", - query: "?-%3d", - expected: { "=": false } - }, - { - it: "should not confuse regular equal signs and encoded equal signs", - query: "?%3d=%3D", - expected: { "=": "=" } - }].forEach(test => { - it(test.it, () => { - assert.deepEqual( - loaderUtils.getOptions({ - query: test.query - }), - test.expected - ); - }); + describe("when loaderContext.query is a string with length > 0", () => { + it("should call parseQuery() and return its result", () => { + assert.deepEqual( + loaderUtils.getOptions({ + query: "?something=getOptions_cannot_parse" + }), + { something: "getOptions_cannot_parse" } + ); }); }); describe("when loaderContext.query is an empty string", () => { @@ -82,14 +24,6 @@ describe("getOptions()", () => { ); }); }); - describe("when loaderContext.query is any other string not starting with ?", () => { - it("should throw an error", () => { - assert.throws( - () => loaderUtils.getOptions({ query: "a" }), - "A valid query string passed to parseQuery should begin with '?'" - ); - }); - }); describe("when loaderContext.query is an object", () => { it("should just return it", () => { const query = {}; diff --git a/test/parseQuery.test.js b/test/parseQuery.test.js new file mode 100644 index 0000000..03b9a58 --- /dev/null +++ b/test/parseQuery.test.js @@ -0,0 +1,83 @@ +"use strict"; + +const assert = require("assert"); +const loaderUtils = require("../"); + +describe("parseQuery()", () => { + describe("when passed string is a query string starting with ?", () => { + [{ + it: "should return an empty object by default", + query: "?", + expected: {} + }, + { + it: "should parse query params", + query: "?name=cheesecake&slices=8&delicious&warm=false", + expected: { + delicious: true, + name: "cheesecake", + slices: "8", // numbers are still strings with query params + warm: false + } + }, + { + it: "should parse query params with arrays", + query: "?ingredients[]=flour&ingredients[]=sugar", + expected: { + ingredients: ["flour", "sugar"] + } + }, + { + it: "should parse query params in JSON format", + query: "?" + JSON.stringify({ + delicious: true, + name: "cheesecake", + slices: 8, + warm: false + }), + expected: { + delicious: true, + name: "cheesecake", + slices: 8, + warm: false + } + }, + { + it: "should use decodeURIComponent", + query: "?%3d", + expected: { "=": true } + }, + { + it: "should recognize params starting with + as boolean params with the value true", + query: "?+%3d", + expected: { "=": true } + }, + { + it: "should recognize params starting with - as boolean params with the value false", + query: "?-%3d", + expected: { "=": false } + }, + { + it: "should not confuse regular equal signs and encoded equal signs", + query: "?%3d=%3D", + expected: { "=": "=" } + }].forEach(test => { + it(test.it, () => { + assert.deepEqual( + loaderUtils.parseQuery(test.query), + test.expected + ); + }); + }); + }); + + describe("when passed string is any other string not starting with ?", () => { + it("should throw an error", () => { + assert.throws( + () => loaderUtils.parseQuery("a"), + "A valid query string passed to parseQuery should begin with '?'" + ); + }); + }); + +});