Skip to content

Commit 3946937

Browse files
fix: ignore watch for remove URLs
1 parent 1eeec73 commit 3946937

File tree

6 files changed

+127
-3
lines changed

6 files changed

+127
-3
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ yarn-debug.log*
2424
/test/fixtures/css
2525
/test/fixtures/generated-1.less
2626
/test/fixtures/generated-2.less
27+
/test/fixtures/generated-3.less
2728
/test/output
2829
.DS_Store
2930
Thumbs.db

src/index.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ import { getOptions } from 'loader-utils';
44
import validateOptions from 'schema-utils';
55

66
import schema from './options.json';
7-
import { getLessOptions, getLessImplementation } from './utils';
7+
import {
8+
getLessOptions,
9+
getLessImplementation,
10+
isUnsupportedUrl,
11+
} from './utils';
812
import LessError from './LessError';
913

1014
function lessLoader(source) {
@@ -38,6 +42,10 @@ function lessLoader(source) {
3842
.render(data, lessOptions)
3943
.then(({ css, map, imports }) => {
4044
imports.forEach((item) => {
45+
if (isUnsupportedUrl(item)) {
46+
return;
47+
}
48+
4149
// `less` return forward slashes on windows when `webpack` resolver return an absolute windows path in `WebpackFileManager`
4250
// Ref: https://github.com/webpack-contrib/less-loader/issues/357
4351
this.addDependency(path.normalize(item));

src/utils.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import path from 'path';
2+
13
import less from 'less';
24
import clone from 'clone';
35

@@ -126,7 +128,7 @@ function createWebpackLessPlugin(loaderContext) {
126128
return super.loadFile(result, ...args);
127129
}
128130

129-
loaderContext.addDependency(result.filename);
131+
loaderContext.addDependency(path.normalize(result.filename));
130132

131133
return result;
132134
}
@@ -188,4 +190,15 @@ function getLessImplementation(implementation) {
188190
return less;
189191
}
190192

191-
export { getLessImplementation, getLessOptions };
193+
function isUnsupportedUrl(url) {
194+
// Is Windows paths `c:\`
195+
if (/^[a-zA-Z]:\\/.test(url)) {
196+
return false;
197+
}
198+
199+
// Scheme: https://tools.ietf.org/html/rfc3986#section-3.1
200+
// Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3
201+
return /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url);
202+
}
203+
204+
export { getLessImplementation, getLessOptions, isUnsupportedUrl };

test/__snapshots__/loader.test.js.snap

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,23 @@ exports[`loader should add all resolved imports as dependencies: errors 1`] = `A
2525

2626
exports[`loader should add all resolved imports as dependencies: warnings 1`] = `Array []`;
2727

28+
exports[`loader should add path to dependencies: css 1`] = `
29+
".box {
30+
color: #fe33ac;
31+
border-color: #fdcdea;
32+
background: url(box.png);
33+
}
34+
.box div {
35+
-webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
36+
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
37+
}
38+
"
39+
`;
40+
41+
exports[`loader should add path to dependencies: errors 1`] = `Array []`;
42+
43+
exports[`loader should add path to dependencies: warnings 1`] = `Array []`;
44+
2845
exports[`loader should allow to import non-less files: css 1`] = `
2946
".some-file {
3047
background: hotpink;
@@ -135,6 +152,38 @@ exports[`loader should install plugins: errors 1`] = `Array []`;
135152
136153
exports[`loader should install plugins: warnings 1`] = `Array []`;
137154
155+
exports[`loader should not add to dependencies imports with URLs: css 1`] = `
156+
"@font-face {
157+
font-family: 'Roboto';
158+
font-style: normal;
159+
font-weight: 300;
160+
src: local('Roboto Light'), local('Roboto-Light'), url(http://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmSU5fBBc9.ttf) format('truetype');
161+
}
162+
@font-face {
163+
font-family: 'Roboto';
164+
font-style: normal;
165+
font-weight: 300;
166+
src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmSU5fBBc9.ttf) format('truetype');
167+
}
168+
@font-face {
169+
font-family: 'Roboto';
170+
font-style: normal;
171+
font-weight: 400;
172+
src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu4mxP.ttf) format('truetype');
173+
}
174+
@font-face {
175+
font-family: 'Roboto';
176+
font-style: normal;
177+
font-weight: 500;
178+
src: local('Roboto Medium'), local('Roboto-Medium'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fBBc9.ttf) format('truetype');
179+
}
180+
"
181+
`;
182+
183+
exports[`loader should not add to dependencies imports with URLs: errors 1`] = `Array []`;
184+
185+
exports[`loader should not add to dependencies imports with URLs: warnings 1`] = `Array []`;
186+
138187
exports[`loader should not alter the original options object: errors 1`] = `Array []`;
139188
140189
exports[`loader should not alter the original options object: warnings 1`] = `Array []`;

test/fixtures/import-url-deps.less

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@import url("http://fonts.googleapis.com/css?family=Roboto:300");
2+
@import url("https://fonts.googleapis.com/css?family=Roboto:300,400,500");

test/loader.test.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,4 +616,55 @@ describe('loader', () => {
616616
expect(getWarnings(stats)).toMatchSnapshot('warnings');
617617
expect(getErrors(stats)).toMatchSnapshot('errors');
618618
});
619+
620+
it('should not add to dependencies imports with URLs', async () => {
621+
const testId = './import-url-deps.less';
622+
const compiler = getCompiler(testId);
623+
const stats = await compile(compiler);
624+
const codeFromBundle = getCodeFromBundle(stats, compiler);
625+
const codeFromLess = await getCodeFromLess(testId);
626+
const { fileDependencies } = stats.compilation;
627+
628+
validateDependencies(fileDependencies);
629+
630+
Array.from(fileDependencies).forEach((item) => {
631+
['http', 'https'].forEach((protocol) => {
632+
expect(item.includes(protocol)).toBe(false);
633+
});
634+
});
635+
636+
expect(codeFromBundle.css).toBe(codeFromLess.css);
637+
expect(codeFromBundle.css).toMatchSnapshot('css');
638+
expect(getWarnings(stats)).toMatchSnapshot('warnings');
639+
expect(getErrors(stats)).toMatchSnapshot('errors');
640+
});
641+
642+
it('should add path to dependencies', async () => {
643+
// Create the file with absolute path
644+
const file = path.resolve(__dirname, 'fixtures', 'generated-3.less');
645+
const absolutePath = path.resolve(__dirname, 'fixtures', 'basic.less');
646+
647+
fs.writeFileSync(file, `@import "${absolutePath}";`);
648+
649+
const testId = './generated-3.less';
650+
const compiler = getCompiler(testId);
651+
const stats = await compile(compiler);
652+
const codeFromBundle = getCodeFromBundle(stats, compiler);
653+
const { fileDependencies } = stats.compilation;
654+
655+
validateDependencies(fileDependencies);
656+
657+
let isAddedToDependensies = false;
658+
659+
Array.from(fileDependencies).forEach((item) => {
660+
if (item === absolutePath) {
661+
isAddedToDependensies = true;
662+
}
663+
});
664+
665+
expect(isAddedToDependensies).toBe(true);
666+
expect(codeFromBundle.css).toMatchSnapshot('css');
667+
expect(getWarnings(stats)).toMatchSnapshot('warnings');
668+
expect(getErrors(stats)).toMatchSnapshot('errors');
669+
});
619670
});

0 commit comments

Comments
 (0)