Merge pull request #17229 from webpack/css-empty-import
fix: CSS `@import` parsing edge cases
This commit is contained in:
commit
27e95ff3b5
|
@ -123,10 +123,9 @@ class LocConverter {
|
|||
|
||||
const CSS_MODE_TOP_LEVEL = 0;
|
||||
const CSS_MODE_IN_BLOCK = 1;
|
||||
const CSS_MODE_AT_IMPORT_EXPECT_URL = 2;
|
||||
const CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA = 3;
|
||||
const CSS_MODE_AT_IMPORT_INVALID = 4;
|
||||
const CSS_MODE_AT_NAMESPACE_INVALID = 5;
|
||||
const CSS_MODE_IN_AT_IMPORT = 2;
|
||||
const CSS_MODE_AT_IMPORT_INVALID = 3;
|
||||
const CSS_MODE_AT_NAMESPACE_INVALID = 4;
|
||||
|
||||
class CssParser extends Parser {
|
||||
constructor({ allowModeSwitch = true, defaultMode = "global" } = {}) {
|
||||
|
@ -185,7 +184,7 @@ class CssParser extends Parser {
|
|||
let lastIdentifier = undefined;
|
||||
/** @type [string, number, number][] */
|
||||
let balanced = [];
|
||||
/** @type {undefined | { start: number, end: number, url?: string, media?: string, supports?: string, layer?: string }} */
|
||||
/** @type {undefined | { start: number, url?: string, urlStart?: number, urlEnd?: number, layer?: string, layerStart?: number, layerEnd?: number, supports?: string, supportsStart?: number, supportsEnd?: number, inSupports?:boolean, media?: string }} */
|
||||
let importData = undefined;
|
||||
/** @type {boolean} */
|
||||
let inAnimationProperty = false;
|
||||
|
@ -407,15 +406,32 @@ class CssParser extends Parser {
|
|||
},
|
||||
url: (input, start, end, contentStart, contentEnd) => {
|
||||
let value = normalizeUrl(input.slice(contentStart, contentEnd), false);
|
||||
|
||||
switch (scope) {
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_URL: {
|
||||
case CSS_MODE_IN_AT_IMPORT: {
|
||||
// Do not parse URLs in `supports(...)`
|
||||
if (importData.inSupports) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (importData.url) {
|
||||
this._emitWarning(
|
||||
state,
|
||||
`Duplicate of 'url(...)' in '${input.slice(
|
||||
importData.start,
|
||||
end
|
||||
)}'`,
|
||||
locConverter,
|
||||
start,
|
||||
end
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
importData.url = value;
|
||||
importData.end = end;
|
||||
scope = CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA;
|
||||
break;
|
||||
}
|
||||
// Do not parse URLs in `supports(...)`
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA: {
|
||||
importData.urlStart = start;
|
||||
importData.urlEnd = end;
|
||||
break;
|
||||
}
|
||||
// Do not parse URLs in import between rules
|
||||
|
@ -442,23 +458,44 @@ class CssParser extends Parser {
|
|||
},
|
||||
string: (input, start, end) => {
|
||||
switch (scope) {
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_URL: {
|
||||
importData.url = normalizeUrl(
|
||||
input.slice(start + 1, end - 1),
|
||||
true
|
||||
);
|
||||
importData.end = end;
|
||||
case CSS_MODE_IN_AT_IMPORT: {
|
||||
const insideURLFunction =
|
||||
balanced[balanced.length - 1] &&
|
||||
balanced[balanced.length - 1][0] === "url";
|
||||
|
||||
if (!insideURLFunction) {
|
||||
scope = CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA;
|
||||
// Do not parse URLs in `supports(...)` and other strings if we already have a URL
|
||||
if (
|
||||
importData.inSupports ||
|
||||
(!insideURLFunction && importData.url)
|
||||
) {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Do not parse URLs in `supports(...)`
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA: {
|
||||
|
||||
if (insideURLFunction && importData.url) {
|
||||
this._emitWarning(
|
||||
state,
|
||||
`Duplicate of 'url(...)' in '${input.slice(
|
||||
importData.start,
|
||||
end
|
||||
)}'`,
|
||||
locConverter,
|
||||
start,
|
||||
end
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
importData.url = normalizeUrl(
|
||||
input.slice(start + 1, end - 1),
|
||||
true
|
||||
);
|
||||
|
||||
if (!insideURLFunction) {
|
||||
importData.urlStart = start;
|
||||
importData.urlEnd = end;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case CSS_MODE_IN_BLOCK: {
|
||||
|
@ -499,7 +536,7 @@ class CssParser extends Parser {
|
|||
scope = CSS_MODE_AT_NAMESPACE_INVALID;
|
||||
this._emitWarning(
|
||||
state,
|
||||
"@namespace is not supported in bundled CSS",
|
||||
"'@namespace' is not supported in bundled CSS",
|
||||
locConverter,
|
||||
start,
|
||||
end
|
||||
|
@ -510,7 +547,7 @@ class CssParser extends Parser {
|
|||
scope = CSS_MODE_AT_IMPORT_INVALID;
|
||||
this._emitWarning(
|
||||
state,
|
||||
"Any @import rules must precede all other rules",
|
||||
"Any '@import' rules must precede all other rules",
|
||||
locConverter,
|
||||
start,
|
||||
end
|
||||
|
@ -518,8 +555,8 @@ class CssParser extends Parser {
|
|||
return end;
|
||||
}
|
||||
|
||||
scope = CSS_MODE_AT_IMPORT_EXPECT_URL;
|
||||
importData = { start, end };
|
||||
scope = CSS_MODE_IN_AT_IMPORT;
|
||||
importData = { start };
|
||||
} else if (
|
||||
this.allowModeSwitch &&
|
||||
OPTIONALLY_VENDOR_PREFIXED_KEYFRAMES_AT_RULE.test(name)
|
||||
|
@ -600,54 +637,99 @@ class CssParser extends Parser {
|
|||
},
|
||||
semicolon: (input, start, end) => {
|
||||
switch (scope) {
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_URL: {
|
||||
this._emitWarning(
|
||||
state,
|
||||
`Expected URL for @import at ${start}`,
|
||||
locConverter,
|
||||
start,
|
||||
end
|
||||
);
|
||||
return end;
|
||||
}
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA: {
|
||||
if (!importData.url === undefined) {
|
||||
case CSS_MODE_IN_AT_IMPORT: {
|
||||
const { start } = importData;
|
||||
|
||||
if (importData.url === undefined) {
|
||||
this._emitWarning(
|
||||
state,
|
||||
`Expected URL for @import at ${importData.start}`,
|
||||
`Expected URL in '${input.slice(start, end)}'`,
|
||||
locConverter,
|
||||
importData.start,
|
||||
importData.end
|
||||
start,
|
||||
end
|
||||
);
|
||||
importData = undefined;
|
||||
scope = CSS_MODE_TOP_LEVEL;
|
||||
return end;
|
||||
}
|
||||
if (
|
||||
importData.urlStart > importData.layerStart ||
|
||||
importData.urlStart > importData.supportsStart
|
||||
) {
|
||||
this._emitWarning(
|
||||
state,
|
||||
`An URL in '${input.slice(
|
||||
start,
|
||||
end
|
||||
)}' should be before 'layer(...)' or 'supports(...)'`,
|
||||
locConverter,
|
||||
start,
|
||||
end
|
||||
);
|
||||
importData = undefined;
|
||||
scope = CSS_MODE_TOP_LEVEL;
|
||||
return end;
|
||||
}
|
||||
if (importData.layerStart > importData.supportsStart) {
|
||||
this._emitWarning(
|
||||
state,
|
||||
`The 'layer(...)' in '${input.slice(
|
||||
start,
|
||||
end
|
||||
)}' should be before 'supports(...)'`,
|
||||
locConverter,
|
||||
start,
|
||||
end
|
||||
);
|
||||
importData = undefined;
|
||||
scope = CSS_MODE_TOP_LEVEL;
|
||||
return end;
|
||||
}
|
||||
|
||||
const semicolonPos = end;
|
||||
end = walkCssTokens.eatWhiteLine(input, end + 1);
|
||||
const { line: sl, column: sc } = locConverter.get(importData.start);
|
||||
const { line: sl, column: sc } = locConverter.get(start);
|
||||
const { line: el, column: ec } = locConverter.get(end);
|
||||
const pos = walkCssTokens.eatWhitespaceAndComments(
|
||||
input,
|
||||
importData.end
|
||||
);
|
||||
const lastEnd =
|
||||
importData.supportsEnd ||
|
||||
importData.layerEnd ||
|
||||
importData.urlEnd ||
|
||||
start;
|
||||
const pos = walkCssTokens.eatWhitespaceAndComments(input, lastEnd);
|
||||
// Prevent to consider comments as a part of media query
|
||||
if (pos !== semicolonPos - 1) {
|
||||
importData.media = input
|
||||
.slice(importData.end, semicolonPos - 1)
|
||||
.trim();
|
||||
importData.media = input.slice(lastEnd, semicolonPos - 1).trim();
|
||||
}
|
||||
const dep = new CssImportDependency(
|
||||
importData.url.trim(),
|
||||
[importData.start, end],
|
||||
importData.layer,
|
||||
importData.supports,
|
||||
importData.media && importData.media.length > 0
|
||||
? importData.media
|
||||
: undefined
|
||||
);
|
||||
dep.setLoc(sl, sc, el, ec);
|
||||
module.addDependency(dep);
|
||||
|
||||
const url = importData.url.trim();
|
||||
|
||||
if (url.length === 0) {
|
||||
const dep = new ConstDependency("", [start, end]);
|
||||
module.addPresentationalDependency(dep);
|
||||
dep.setLoc(sl, sc, el, ec);
|
||||
} else {
|
||||
const dep = new CssImportDependency(
|
||||
url,
|
||||
[start, end],
|
||||
importData.layer,
|
||||
importData.supports,
|
||||
importData.media && importData.media.length > 0
|
||||
? importData.media
|
||||
: undefined
|
||||
);
|
||||
dep.setLoc(sl, sc, el, ec);
|
||||
module.addDependency(dep);
|
||||
}
|
||||
|
||||
importData = undefined;
|
||||
scope = CSS_MODE_TOP_LEVEL;
|
||||
|
||||
break;
|
||||
}
|
||||
case CSS_MODE_AT_IMPORT_INVALID:
|
||||
case CSS_MODE_AT_NAMESPACE_INVALID: {
|
||||
scope = CSS_MODE_TOP_LEVEL;
|
||||
|
||||
break;
|
||||
}
|
||||
case CSS_MODE_IN_BLOCK: {
|
||||
|
@ -720,10 +802,11 @@ class CssParser extends Parser {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA: {
|
||||
case CSS_MODE_IN_AT_IMPORT: {
|
||||
if (input.slice(start, end).toLowerCase() === "layer") {
|
||||
importData.layer = "";
|
||||
importData.end = end;
|
||||
importData.layerStart = start;
|
||||
importData.layerEnd = end;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -758,6 +841,13 @@ class CssParser extends Parser {
|
|||
|
||||
balanced.push([name, start, end]);
|
||||
|
||||
if (
|
||||
scope === CSS_MODE_IN_AT_IMPORT &&
|
||||
name.toLowerCase() === "supports"
|
||||
) {
|
||||
importData.inSupports = true;
|
||||
}
|
||||
|
||||
if (isLocalMode()) {
|
||||
name = name.toLowerCase();
|
||||
|
||||
|
@ -812,20 +902,23 @@ class CssParser extends Parser {
|
|||
}
|
||||
|
||||
switch (scope) {
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_URL: {
|
||||
if (last && last[0] === "url") {
|
||||
importData.end = end;
|
||||
scope = CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CSS_MODE_AT_IMPORT_EXPECT_LAYER_OR_SUPPORTS_OR_MEDIA: {
|
||||
if (last && last[0].toLowerCase() === "layer") {
|
||||
case CSS_MODE_IN_AT_IMPORT: {
|
||||
if (last && last[0] === "url" && !importData.inSupports) {
|
||||
importData.urlStart = last[1];
|
||||
importData.urlEnd = end;
|
||||
} else if (
|
||||
last &&
|
||||
last[0].toLowerCase() === "layer" &&
|
||||
!importData.inSupports
|
||||
) {
|
||||
importData.layer = input.slice(last[2], end - 1).trim();
|
||||
importData.end = end;
|
||||
importData.layerStart = last[1];
|
||||
importData.layerEnd = end;
|
||||
} else if (last && last[0].toLowerCase() === "supports") {
|
||||
importData.supports = input.slice(last[2], end - 1).trim();
|
||||
importData.end = end;
|
||||
importData.supportsStart = last[1];
|
||||
importData.supportsEnd = end;
|
||||
importData.inSupports = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
|||
module.exports = [
|
||||
/Any @import rules must precede all other rules/,
|
||||
/Any @import rules must precede all other rules/,
|
||||
/Any @import rules must precede all other rules/,
|
||||
/Any @import rules must precede all other rules/
|
||||
/Any '@import' rules must precede all other rules/,
|
||||
/Any '@import' rules must precede all other rules/,
|
||||
/Any '@import' rules must precede all other rules/,
|
||||
/Any '@import' rules must precede all other rules/
|
||||
];
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = function loader(content) {
|
||||
return content + `.using-loader { color: red; }`;
|
||||
};
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
@import url(
|
||||
style2.css?foo=9
|
||||
);
|
||||
/*@import url();
|
||||
@import url();
|
||||
@import url('');
|
||||
@import url("");
|
||||
@import '';
|
||||
|
@ -50,7 +50,9 @@ style2.css?foo=9
|
|||
";
|
||||
@import url();
|
||||
@import url('');
|
||||
@import url("");*/
|
||||
@import url("");
|
||||
@import url("") /* test */;
|
||||
@import url("") screen and (orientation:landscape);
|
||||
@import url(style2.css) screen and (orientation:landscape);
|
||||
@import url(style2.css) SCREEN AND (ORIENTATION: LANDSCAPE);
|
||||
@import url(style2.css)screen and (orientation:landscape);
|
||||
|
@ -58,20 +60,15 @@ style2.css?foo=9
|
|||
@import url(style2.css) screen and (orientation:landscape);
|
||||
@import url(style2.css) (min-width: 100px);
|
||||
@import url(https://test.cases/path/../../../../configCases/css/css-import/external.css);
|
||||
/*@import url(https://test.cases/path/../../../../configCases/css/css-import/external.css) screen and (orientation:landscape);
|
||||
@import url(https://test.cases/path/../../../../configCases/css/css-import/external.css) screen and (orientation:landscape);*/
|
||||
/*@import "//example.com/style.css";*/
|
||||
/*@import url(~package/test.css);*/
|
||||
/*@import ;*/
|
||||
/*@import foo-bar;*/
|
||||
/*@import-normalize;*/
|
||||
/*@import url('http://') :root {}*/
|
||||
/*@import url('query.css?foo=1&bar=1');*/
|
||||
/*@import url('other-query.css?foo=1&bar=1#hash');*/
|
||||
/*@import url('other-query.css?foo=1&bar=1#hash') screen and (orientation:landscape);*/
|
||||
/*@import url('https://fonts.googleapis.com/css?family=Roboto');*/
|
||||
/*@import url('https://fonts.googleapis.com/css?family=Noto+Sans+TC');*/
|
||||
/*@import url('https://fonts.googleapis.com/css?family=Noto+Sans+TC|Roboto');*/
|
||||
@import url(https://test.cases/path/../../../../configCases/css/css-import/external.css) screen and (orientation:landscape);
|
||||
@import "//example.com/style.css";
|
||||
@import url('test.css?foo=1&bar=1');
|
||||
@import url('style2.css?foo=1&bar=1#hash');
|
||||
@import url('style2.css?foo=1&bar=1#hash') screen and (orientation:landscape);
|
||||
@import url('https://fonts.googleapis.com/css?family=Roboto');
|
||||
@import url('https://fonts.googleapis.com/css?family=Noto+Sans+TC');
|
||||
@import url('https://fonts.googleapis.com/css?family=Noto+Sans+TC|Roboto');
|
||||
@import url('https://fonts.googleapis.com/css?family=Noto+Sans+TC|Roboto') layer(super.foo) supports(display: flex) screen and (min-width: 400px);
|
||||
|
||||
@import './sty\
|
||||
le3.css?bar=1';
|
||||
|
@ -107,12 +104,11 @@ le3.css?=bar4');
|
|||
@import "./t\65st%20test.css?fpp=10";
|
||||
@import './t\65st%20test.css?foo=11';
|
||||
@import url( style6.css?foo=bazz );
|
||||
/*@import nourl(test.css);
|
||||
@import '\
|
||||
\
|
||||
\
|
||||
';
|
||||
@import url('!!../../helpers/string-loader.js?esModule=false!~package/tilde.css');*/
|
||||
@import url('./string-loader.js?esModule=false!./test.css');
|
||||
@import url(style4.css?foo=bar);
|
||||
@import url(style4.css?foo=bar#hash);
|
||||
@import url(style4.css?#hash);
|
||||
|
@ -123,9 +119,9 @@ le3.css?=bar4');
|
|||
@import url(' ./style4.css?foo=4 ');
|
||||
@import url( ./style4.css?foo=5 );
|
||||
|
||||
/*@import url(' https://fonts.googleapis.com/css?family=Roboto ');*/
|
||||
/*@import url('!!../../helpers/string-loader.js?esModule=false!');*/
|
||||
/*@import url(' !!../../helpers/string-loader.js?esModule=false!~package/tilde.css ');*/
|
||||
@import url(' https://fonts.googleapis.com/css?family=Roboto ');
|
||||
@import url('./string-loader.js?esModule=false');
|
||||
@import url(' ./string-loader.js?esModule=false!./test.css ') screen and (orientation: landscape);
|
||||
@import url(data:text/css;charset=utf-8,a%20%7B%0D%0A%20%20color%3A%20red%3B%0D%0A%7D);
|
||||
@import url(data:text/css;charset=utf-8,a%20%7B%0D%0A%20%20color%3A%20blue%3B%0D%0A%7D) screen and (orientation:landscape);
|
||||
|
||||
|
@ -145,7 +141,6 @@ le3.css?=bar4');
|
|||
@import url("./layer.css?foo=5") layer();
|
||||
@import url("./layer.css?foo=6") layer( foo.bar.baz );
|
||||
@import url("./layer.css?foo=7") layer( );
|
||||
/*@import "http://example.com/style.css" supports(display: flex) screen and (min-width: 400px);*/
|
||||
@import url("./style6.css")layer(default)supports(display: flex)screen and (min-width:400px);
|
||||
@import "./style6.css?foo=1"layer(default)supports(display: flex)screen and (min-width:400px);
|
||||
@import "./style6.css?foo=2"supports(display: flex)screen and (min-width:400px);
|
||||
|
@ -204,6 +199,46 @@ url(style6.css?foo=14)
|
|||
@import "./anonymous-nested.css" supports(display: flex) screen and (orientation: portrait);
|
||||
@import "./all-nested.css" layer(super.foo) supports(display: flex) screen and (min-width: 400px);
|
||||
|
||||
/* Inside support */
|
||||
|
||||
@import url("/style2.css?warning=6") supports(unknown: layer(super.foo)) screen and (min-width: 400px);
|
||||
@import url("/style2.css?warning=7") supports(url: url("./unknown.css")) screen and (min-width: 400px);
|
||||
@import url("/style2.css?warning=8") supports(url: url(./unknown.css)) screen and (min-width: 400px);
|
||||
|
||||
/** Possible syntax in future */
|
||||
|
||||
@import url("/style2.css?foo=unknown") layer(super.foo) supports(display: flex) unknown("foo") screen and (min-width: 400px);
|
||||
@import url("/style2.css?foo=unknown1") layer(super.foo) supports(display: url("./unknown.css")) unknown(foo) screen and (min-width: 400px);
|
||||
@import url("/style2.css?foo=unknown2") layer(super.foo) supports(display: url(./unknown.css)) "foo" screen and (min-width: 400px);
|
||||
@import "./style2.css?unknown3" "string";
|
||||
|
||||
/** Unknown */
|
||||
|
||||
@import-normalize;
|
||||
|
||||
/** Warnings */
|
||||
|
||||
@import nourl(test.css);
|
||||
@import ;
|
||||
@import foo-bar;
|
||||
@import layer(super.foo) "./style2.css?warning=1" supports(display: flex) screen and (min-width: 400px);
|
||||
@import layer(super.foo) supports(display: flex) "./style2.css?warning=2" screen and (min-width: 400px);
|
||||
@import layer(super.foo) supports(display: flex) screen and (min-width: 400px) "./style2.css?warning=3";
|
||||
@import layer(super.foo) url("./style2.css?warning=4") supports(display: flex) screen and (min-width: 400px);
|
||||
@import layer(super.foo) supports(display: flex) url("./style2.css?warning=5") screen and (min-width: 400px);
|
||||
@import layer(super.foo) supports(display: flex) screen and (min-width: 400px) url("./style2.css?warning=6");
|
||||
@import url("/style2.css?warning=6") supports(display: flex) layer(super.foo) screen and (min-width: 400px);
|
||||
@namespace url(http://www.w3.org/1999/xhtml);
|
||||
@import url("./style2.css?after-namespace");
|
||||
@import supports(background: url("./img.png"));
|
||||
@import supports(background: url("./img.png")) screen and (min-width: 400px);
|
||||
@import layer(test) supports(background: url("./img.png")) screen and (min-width: 400px);
|
||||
@import screen and (min-width: 400px);
|
||||
|
||||
@import url(./style2.css?multiple=1) url(./style2.css?multiple=2);
|
||||
@import url("./style2.css?multiple=3") url("./style2.css?multiple=4");
|
||||
@import "./style2.css?strange=3" url("./style2.css?multiple=4");
|
||||
|
||||
body {
|
||||
background: red;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
module.exports = [
|
||||
/Expected URL in '@import nourl\(test.css\);'/,
|
||||
/Expected URL in '@import ;'/,
|
||||
/Expected URL in '@import foo-bar;'/,
|
||||
/An URL in '@import layer\(super\.foo\) "\.\/style2\.css\?warning=1" supports\(display: flex\) screen and \(min-width: 400px\);' should be before 'layer\(\.\.\.\)' or 'supports\(\.\.\.\)'/,
|
||||
/An URL in '@import layer\(super\.foo\) supports\(display: flex\) "\.\/style2.css\?warning=2" screen and \(min-width: 400px\);' should be before 'layer\(\.\.\.\)' or 'supports\(\.\.\.\)'/,
|
||||
/An URL in '@import layer\(super\.foo\) supports\(display: flex\) screen and \(min-width: 400px\) "\.\/style2.css\?warning=3";' should be before 'layer\(\.\.\.\)' or 'supports\(\.\.\.\)'/,
|
||||
/An URL in '@import layer\(super\.foo\) url\("\.\/style2.css\?warning=4"\) supports\(display: flex\) screen and \(min-width: 400px\);' should be before 'layer\(\.\.\.\)' or 'supports\(\.\.\.\)'/,
|
||||
/An URL in '@import layer\(super\.foo\) supports\(display: flex\) url\("\.\/style2.css\?warning=5"\) screen and \(min-width: 400px\);' should be before 'layer\(\.\.\.\)' or 'supports\(\.\.\.\)'/,
|
||||
/An URL in '@import layer\(super\.foo\) supports\(display: flex\) screen and \(min-width: 400px\) url\("\.\/style2.css\?warning=6"\);' should be before 'layer\(\.\.\.\)' or 'supports\(\.\.\.\)'/,
|
||||
/The 'layer\(\.\.\.\)' in '@import url\("\/style2.css\?warning=6"\) supports\(display: flex\) layer\(super.foo\) screen and \(min-width: 400px\);' should be before 'supports\(\.\.\.\)'/,
|
||||
/'@namespace' is not supported in bundled CSS/,
|
||||
/Expected URL in '@import supports\(background: url\("\.\/img.png"\)\);'/,
|
||||
/Expected URL in '@import supports\(background: url\("\.\/img.png"\)\) screen and \(min-width: 400px\);'/,
|
||||
/Expected URL in '@import layer\(test\) supports\(background: url\("\.\/img.png"\)\) screen and \(min-width: 400px\);'/,
|
||||
/Expected URL in '@import screen and \(min-width: 400px\);'/,
|
||||
/Duplicate of 'url\(\.\.\.\)' in '@import url\(\.\/style2.css\?multiple=1\) url\(\.\/style2.css\?multiple=2\)'/,
|
||||
/Duplicate of 'url\(\.\.\.\)' in '@import url\("\.\/style2.css\?multiple=3"\) url\("\.\/style2.css\?multiple=4"'/,
|
||||
/Duplicate of 'url\(\.\.\.\)' in '@import "\.\/style2.css\?strange=3" url\("\.\/style2.css\?multiple=4"'/
|
||||
];
|
|
@ -1 +1 @@
|
|||
module.exports = [/@namespace is not supported in bundled CSS/];
|
||||
module.exports = [/'@namespace' is not supported in bundled CSS/];
|
||||
|
|
|
@ -155,6 +155,10 @@ class FakeSheet {
|
|||
);
|
||||
|
||||
css = css.replace(/@import url\("([^"]+)"\);/g, (match, url) => {
|
||||
if (!/^https:\/\/test\.cases\/path\//.test(url)) {
|
||||
return `@import url("${url}");`;
|
||||
}
|
||||
|
||||
if (url.startsWith("#")) {
|
||||
return url;
|
||||
}
|
||||
|
@ -195,6 +199,10 @@ class FakeSheet {
|
|||
"utf-8"
|
||||
);
|
||||
css = css.replace(/@import url\("([^"]+)"\);/g, (match, url) => {
|
||||
if (!/^https:\/\/test\.cases\/path\//.test(url)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
if (url.startsWith("#")) {
|
||||
return url;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue