Skip to content

Commit

Permalink
refactor!: added isUrlRequest again, but now it ignores only absolu…
Browse files Browse the repository at this point in the history
…te URLs and `#hash` requests, `data URI` and root relative request are handled as requestable due webpack v5 support them
  • Loading branch information
alexander-akait committed Oct 20, 2021
1 parent 46b032d commit 10503d6
Show file tree
Hide file tree
Showing 4 changed files with 224 additions and 1 deletion.
11 changes: 10 additions & 1 deletion README.md
Expand Up @@ -10,8 +10,17 @@ If the loader options have been passed as loader query string (`loader?some&para

Converts some resource URL to a webpack module request.

> i Before call `urlToRequest` you need call `isUrlRequest` to ensure it is requestable url
```javascript
const request = loaderUtils.urlToRequest(url);
const url = "path/to/module.js";

if (loaderUtils.isUrlRequest(url)) {
// Logic for requestable url
const request = loaderUtils.urlToRequest(url);
} else {
// Logic for not requestable url
}
```

Simple example:
Expand Down
2 changes: 2 additions & 0 deletions lib/index.js
@@ -1,9 +1,11 @@
"use strict";

const isUrlRequest = require("./isUrlRequest");
const urlToRequest = require("./urlToRequest");
const getHashDigest = require("./getHashDigest");
const interpolateName = require("./interpolateName");

exports.urlToRequest = urlToRequest;
exports.getHashDigest = getHashDigest;
exports.interpolateName = interpolateName;
exports.isUrlRequest = isUrlRequest;
31 changes: 31 additions & 0 deletions lib/isUrlRequest.js
@@ -0,0 +1,31 @@
"use strict";

const path = require("path");

function isUrlRequest(url) {
// An URL is not an request if

// 1. Allow `data URI`
if (/^data:/i.test(url)) {
return true;
}

// 2. It's an absolute url and it is not `windows` path like `C:\dir\file`
if (/^[a-z][a-z0-9+.-]*:/i.test(url) && !path.win32.isAbsolute(url)) {
return false;
}

// 3. It's a protocol-relative
if (/^\/\//.test(url)) {
return false;
}

// 4. It's some kind of url for a template
if (/^#/.test(url)) {
return false;
}

return true;
}

module.exports = isUrlRequest;
181 changes: 181 additions & 0 deletions test/isUrlRequest.test.js
@@ -0,0 +1,181 @@
"use strict";

const loaderUtils = require("../");

function ExpectedError(regex) {
this.regex = regex;
}
ExpectedError.prototype.matches = function (err) {
return this.regex.test(err.message);
};

describe("isUrlRequest()", () => {
[
// without root
[["//google.com"], false, "should be negative for scheme-agnostic urls"],
[["http://google.com"], false, "should be negative for http urls"],
[["HTTP://google.com"], false, "should be negative for http urls"],
[["https://google.com"], false, "should be negative for https urls"],
[["HTTPS://google.com"], false, "should be negative for https urls"],

[["chrome-extension://"], false, "should be negative for nonstandard urls"],
[["moz-extension://"], false, "should be negative for nonstandard urls"],
[
["ms-browser-extension://"],
false,
"should be negative for nonstandard urls",
],
[["custom-extension://"], false, "should be negative for nonstandard urls"],

[["path/to/thing"], true, "should be positive for implicit relative urls"],
[["./img.png"], true, "should be positive for implicit relative urls"],
[["../img.png"], true, "should be positive for implicit relative urls"],
[
["./img.png?foo=bar#hash"],
true,
"should be positive for implicit relative urls",
],
[
["./path/to/thing"],
true,
"should be positive for explicit relative urls",
],
[["~path/to/thing"], true, "should be positive for module urls (with ~)"],
[
["some/other/stuff/and/then~path/to/thing"],
true,
"should be positive for module urls with path prefix",
],
[
["./some/other/stuff/and/then~path/to/thing"],
true,
"should be positive for module urls with relative path prefix",
],
[["C:/thing"], true, "should be positive for linux path with driver"],
[["C:\\thing"], true, "should be positive for windows path with driver"],
[
["directory/things"],
true,
"should be positive for relative path (linux)",
],
[
["directory\\things"],
true,
"should be positive for relative path (windows)",
],

// with root (normal path)
[
["path/to/thing", "root/dir"],
true,
"should be positive with root if implicit relative url",
],
[
["./path/to/thing", "root/dir"],
true,
"should be positive with root if explicit relative url",
],

// with root (boolean) on Windows
[
["C:\\path\\to\\thing"],
true,
"should be positive for Windows absolute paths with drive letter",
],
[
["\\\\?\\UNC\\ComputerName\\path\\to\\thing"],
true,
"should be positive for Windows absolute UNC paths",
],

// with root (module)
[
["/path/to/thing", "~"],
true,
"should be positive for module url if root = ~",
],

// with root (module path)
[
["/path/to/thing", "~module"],
true,
"should be positive for module prefixes when root starts with ~",
],
[
["/path/to/thing", "~module/"],
true,
"should be positive for module prefixes (with trailing slash) when root starts with ~",
],

// error cases
[
["/path/to/thing", 1],
new ExpectedError(/unexpected parameters/i),
"should throw an error on invalid root",
],

// empty url
[[""], true, "should be positive if url is empty"],

// about url
[["about:blank"], false, "should be negative for about:blank"],

// hash
[["#gradient"], false, "should be negative for hash url"],

// url
[["//sindresorhus.com"], false, "should ignore noscheme url"],
[
["//at.alicdn.com/t/font_515771_emcns5054x3whfr.eot"],
false,
"should ignore noscheme url with path",
],
[
["https://example.com/././foo"],
false,
"should ignore absolute url with relative",
],

// non standard protocols
[
["file://sindresorhus.com"],
false,
"should ignore non standard protocols (file)",
],
[
["mailto:someone@example.com"],
false,
"should ignore non standard protocols (mailto)",
],
[
["data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D"],
true,
"should work with non standard protocols (data)",
],
[
["DATA:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D"],
true,
"should work with non standard protocols (data)",
],

// root-relative url
[["/"], true, "should work with root-relative url 1"],
[["//"], false, "ignore root-relative url 1"],
].forEach((test) => {
it(test[2], () => {
const expected = test[1];

try {
const request = loaderUtils.isUrlRequest.apply(loaderUtils, test[0]);

expect(request).toBe(expected);
} catch (e) {
if (expected instanceof ExpectedError) {
expect(expected.matches(e)).toBe(true);
} else {
throw new Error("should not have thrown an error: " + e.message);
}
}
});
});
});

0 comments on commit 10503d6

Please sign in to comment.