Skip to content

Commit

Permalink
feat: support web url and query strings inside @import
Browse files Browse the repository at this point in the history
Closes #140
  • Loading branch information
Anidetrix committed Dec 28, 2020
1 parent c61f0ce commit bbff4e5
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 15 deletions.
3 changes: 3 additions & 0 deletions __tests__/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ exports[`basic resolvers: css 1`] = `
.foo3 {
background-image: url(\\"/pubpath/bg.png?query#hash\\");
}
@import url(\\"https://fonts.googleapis.com/css?family=Gudea:400,700\\");
.bar {
background-image: url(\\"/pubpath/bg1.png\\");
background-image: url(\\"/pubpath/bg2.testing.regex.png\\"); }
Expand Down Expand Up @@ -234,6 +235,7 @@ exports[`basic resolvers-hash: css 1`] = `
.foo3 {
background-image: url(\\"/pubpath/bg-bd25d3fd.png?query#hash\\");
}
@import url(\\"https://fonts.googleapis.com/css?family=Gudea:400,700\\");
.bar {
background-image: url(\\"/pubpath/bg-cc57d19a.png\\");
background-image: url(\\"/pubpath/bg.testing.regex-e13f1639.png\\"); }
Expand Down Expand Up @@ -282,6 +284,7 @@ exports[`basic resolvers-url-inline: css 1`] = `
.foo3 {
background-image: url(\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGYAAABmBAMAAADL8flRAAAAG1BMVEXMzMyWlpacnJy+vr6jo6PFxcW3t7eqqqqxsbHbm8QuAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAArUlEQVRYhe3QIQ+CUBTF8cPTB8RHsKMTqQQ/gMqmVRkj4+ZmZQRnNBD42F7Afp3N7fxIN/zH2wGIiIiI6J8ZBKk95NMRo23KdaYksz36oKtv47F14et59HdKY69I7AoX9PMMlTPnIrZOe5sHJ18Hc5fDeXKH2n+mpmzgLz6NPWmJNIlNNkA4NvK2ov6ikQ1kqWKYYdggVxNpgtREER6ygTyzbZaRugERERER/eYNUMwTiwsgIHkAAAAASUVORK5CYII=\\");
}
@import url(\\"https://fonts.googleapis.com/css?family=Gudea:400,700\\");
.bar {
background-image: url(\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAG1BMVEXMzMyWlpacnJy+vr6jo6PFxcW3t7eqqqqxsbHbm8QuAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAiklEQVRYhe3QMQ6EIBAF0C+GSInF9mYTs+1ewRsQbmBlayysKefYO2asXbbYxvxHQj6ECQMAEREREf2NQ/fCtp5Zky6vtRMkSJEzhyISynWJnzH6Z8oQlzS7lEc/fLmmQUSvc16OrCPqRl1JePxQYo1ZSWVj9nxrrOb5esw+eXdvzTWfTERERHRXH4tWFZGswQ2yAAAAAElFTkSuQmCC\\");
background-image: url(\\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGUAAABlBAMAAACmUjD8AAAAG1BMVEXMzMyWlpacnJy+vr6jo6PFxcW3t7eqqqqxsbHbm8QuAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAi0lEQVRYhe3QoQ7CMBRG4b/bGipr8DMNFsEL7A2WifkpLEGgl2D62NwRmG2RJOcT7a04SXMlAAAA/LNGh5Mdn1n3m/pS0g7K4Tl857DmSyw1flHyaZFyN9rcjNNcbOQUFZ00XbfZvd+1TTj+0iTf7439rarJYd3/ZjuoamzX1jy683bZrssNAAAApBeYlQ7gQL3QgQAAAABJRU5ErkJggg==\\"); }
Expand Down
4 changes: 3 additions & 1 deletion __tests__/fixtures/resolvers/style.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
@import "@/foo.css";
@import url("@/foo.css#hash");
@import "features2/bar";

@import url("https://fonts.googleapis.com/css?family=Gudea:400,700");

@font-face {
font-family: "Demo";
font-style: normal;
Expand Down
16 changes: 12 additions & 4 deletions src/loaders/postcss/import/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import path from "path";
import postcss, { PluginCreator, Result, AtRule } from "postcss";
import valueParser from "postcss-value-parser";

import { normalizePath } from "../../../utils/path";

import { isAbsolutePath, normalizePath } from "../../../utils/path";
import resolveDefault, { ImportResolve } from "./resolve";

const name = "styles-import";
Expand Down Expand Up @@ -92,12 +90,22 @@ const plugin: PluginCreator<ImportOptions> = (options = {}) => {
url = normalizePath(to) + url.slice(from.length);
}

// Empty url
// Empty URL
if (url.length === 0) {
rule.warn(res, `Empty URL in \`${rule.toString()}\``);
return;
}

// Skip Web URLs
if (!isAbsolutePath(url)) {
try {
new URL(url);
return;
} catch {
// Is not a Web URL, continuing
}
}

importList.push({ rule, url });
});

Expand Down
6 changes: 4 additions & 2 deletions src/loaders/postcss/import/resolve.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import fs from "fs-extra";

import { parseUrl } from "query-string";
import resolveAsync from "../../../utils/resolve-async";

/** File resolved by `@import` resolver */
Expand All @@ -17,8 +17,10 @@ export type ImportResolve = (
extensions: string[],
) => Promise<ImportFile>;

const resolve: ImportResolve = async (url, basedir, extensions) => {
const resolve: ImportResolve = async (inputUrl, basedir, extensions) => {
const options = { caller: "@import resolver", basedirs: [basedir], extensions };
const parseOptions = { parseFragmentIdentifier: true, sort: false as const, decode: false };
const { url } = parseUrl(inputUrl, parseOptions);
const from = await resolveAsync([url, `./${url}`], options);
return { from, source: await fs.readFile(from) };
};
Expand Down
7 changes: 2 additions & 5 deletions src/loaders/postcss/url/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,8 @@ const plugin: PluginCreator<UrlOptions> = (options = {}) => {
usedNames.set(to, from);

node.type = "string";
node.value =
publicPath +
(/[/\\]$/.test(publicPath) ? "" : "/") +
path.basename(to) +
(urlQuery ?? "");
node.value = publicPath + (/[/\\]$/.test(publicPath) ? "" : "/") + path.basename(to);
if (urlQuery) node.value += urlQuery;

to = normalizePath(assetDir, to);
res.messages.push({ plugin: name, type: "asset", to, source });
Expand Down
5 changes: 2 additions & 3 deletions src/loaders/postcss/url/resolve.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import fs from "fs-extra";
import { ParseOptions, parseUrl, stringifyUrl } from "query-string";

import { parseUrl, stringifyUrl } from "query-string";
import resolveAsync from "../../../utils/resolve-async";

/** File resolved by URL resolver */
Expand All @@ -18,7 +17,7 @@ export type UrlResolve = (inputUrl: string, basedir: string) => Promise<UrlFile>

const resolve: UrlResolve = async (inputUrl, basedir) => {
const options = { caller: "URL resolver", basedirs: [basedir] };
const parseOptions: ParseOptions = { parseFragmentIdentifier: true, sort: false, decode: false };
const parseOptions = { parseFragmentIdentifier: true, sort: false as const, decode: false };
const { url, query, fragmentIdentifier } = parseUrl(inputUrl, parseOptions);
const from = await resolveAsync([url, `./${url}`], options);
const urlQuery = stringifyUrl({ url: "", query, fragmentIdentifier }, parseOptions);
Expand Down

0 comments on commit bbff4e5

Please sign in to comment.