Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support resolve url() statements #53

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ module.exports = {
|**[`patterns`](#patterns)**|`string \| string[]`|`/`|Path to the resources you would like to inject|
|**[`injector`](#injector)**|`Injector \| 'prepend' \| 'append'`|`'prepend'`|Controls the resources injection precisely|
|**[`globOptions`](#globoptions)**|`GlobOptions`|`{}`|An options that can be passed to `glob(...)`|
|**[`resolveUrl`](#resolveurl)**|`boolean`|`true`|Enable/Disable `@import` url to be resolved|
|**[`resolveUrl`](#resolveurl)**|`boolean`|`true`|Enable/Disable `@import` url and `url()` to be resolved|

See [the type definition file](https://github.com/yenshih/style-resources-loader/blob/master/src/types.ts) for more details.

Expand Down Expand Up @@ -190,9 +190,9 @@ Options that can be passed to `glob(...)`. See [node-glob options](https://githu

### `resolveUrl`

A boolean which defaults to `true`. It represents whether the relative path in `@import` or `@require` statements should be resolved.
A boolean which defaults to `true`. It represents whether the relative path in `@import` or `@require` and `url()` statements should be resolved.

If you were to use `@import` or `@require` statements in style resource files, you should make sure that the URL is relative to that resource file, rather than the source file.
If you were to use `@import` or `@require` or `url()` statements in style resource files, you should make sure that the URL is relative to that resource file, rather than the source file.

You could disable this feature by setting `resolveUrl` to `false`.

Expand Down
2 changes: 2 additions & 0 deletions src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ export const VALIDATION_BASE_DATA_PATH = 'options';
export const SUPPORTED_FILE_FORMATS: StyleResourcesFileFormat[] = ['css', 'sass', 'scss', 'less', 'styl'];

export const SUPPORTED_FILE_EXTS = SUPPORTED_FILE_FORMATS.map(type => `.${type}`);

export const CWD = process.cwd();
2 changes: 1 addition & 1 deletion src/utils/get-resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const getResources = async (ctx: LoaderContext, options: StyleResourcesLo
const content = await util.promisify(fs.readFile)(file, 'utf8');
const resource: StyleResource = {file, content};

return resolveUrl ? resolveImportUrl(ctx, resource) : resource;
return resolveUrl ? resolveImportUrl(resource) : resource;
}),
);

Expand Down
42 changes: 25 additions & 17 deletions src/utils/resolve-import-url.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
/* eslint-disable prefer-named-capture-group */
import path from 'path';

import type {LoaderContext, StyleResource} from '../types';
import type {StyleResource} from '../types';

/* eslint-disable-next-line prefer-named-capture-group */
const regex = /@(?:import|require)\s+(?:\([a-z,\s]+\)\s*)?['"]?([^'"\s;]+)['"]?;?/gu;
const regexImport = /@(?:import|require|use)\s+(?:\([a-z,\s]+\)\s*)?['"]?([^'"\s;]+)['"]?;?/gu;
const regexUrl = /url\(['"]?([^'"\s;]+)['"]?\)/gu;

export const resolveImportUrl = (ctx: LoaderContext, {file, content}: StyleResource): StyleResource => ({
file,
content: content.replace(regex, (match: string, pathToResource?: string) => {
if (!pathToResource || /^[~/]/u.test(pathToResource)) {
return match;
}
export const resolveImportUrl = ({file, content}: StyleResource): StyleResource => {
const result = content
.replace(regexImport, (match: string, pathToResource?: string) => {
if (!pathToResource || /^(?!\.{1,2}\/)/u.test(pathToResource)) {
return match;
}

const absolutePathToResource = path.resolve(path.dirname(file), pathToResource);
const relativePathFromContextToResource = path
.relative(ctx.context, absolutePathToResource)
.split(path.sep)
.join('/');
const absolutePathToResource = path.resolve(path.dirname(file), pathToResource);

return match.replace(pathToResource, relativePathFromContextToResource);
}),
});
return match.replace(pathToResource, absolutePathToResource);
})
.replace(regexUrl, (match: string, pathToResource?: string) => {
if (!pathToResource || /^(?!\.{1,2}\/)/u.test(pathToResource)) {
return match;
}

const absolutePathToResource = path.resolve(path.dirname(file), pathToResource);

return match.replace(pathToResource, absolutePathToResource);
});

return {file, content: result};
};
1 change: 1 addition & 0 deletions test/css/resources/theming.css
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
@import "~@angular/material/theming";
@import "webpack/package.json";
1 change: 1 addition & 0 deletions test/css/resources/variables.css
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
@import '../variables/color';
@import "../variables/font.css";
@import '../variables/urls.css';
3 changes: 3 additions & 0 deletions test/css/source.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ html {
body {
background: var(--body-background);
}
div {
background: var(--panel-background);
}
#root {
@mixin size 100%;
}
11 changes: 8 additions & 3 deletions test/css/specs/append-injector.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ html {
body {
background: var(--body-background);
}
div {
background: var(--panel-background);
}
#root {
@mixin size 100%;
}
@import "mixins/size";
@import "$CWD/test/css/mixins/size";
@import '~bootstrap/mixins';
@import "~@angular/material/theming";
@import 'variables/color';
@import "variables/font.css";
@import "webpack/package.json";
@import '$CWD/test/css/variables/color';
@import "$CWD/test/css/variables/font.css";
@import '$CWD/test/css/variables/urls.css';
6 changes: 6 additions & 0 deletions test/css/specs/array-of-string-patterns.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@
}
--body-background: #fff;
--html-font-size: 100px;
--panel-background: url('$CWD/test/css/variables/a.png');
--panel-background-alias: url('~@angular/material/theming/a.png');
--panel-background-base64: url('data:image/jpeg;base64,bm90IGFjdHVhbGx5IGEganBlZyBmaWxlCg==');
html {
font-size: var(--html-font-size);
}
body {
background: var(--body-background);
}
div {
background: var(--panel-background);
}
#root {
@mixin size 100%;
}
6 changes: 6 additions & 0 deletions test/css/specs/async-injector.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ html {
body {
background: var(--body-background);
}
div {
background: var(--panel-background);
}
#root {
@mixin size 100%;
}
--body-background: #fff;
--html-font-size: 100px;
--panel-background: url('./a.png');
--panel-background-alias: url('~@angular/material/theming/a.png');
--panel-background-base64: url('data:image/jpeg;base64,bm90IGFjdHVhbGx5IGEganBlZyBmaWxlCg==');
6 changes: 6 additions & 0 deletions test/css/specs/customized-injector.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ html {
body {
background: var(--body-background);
}
div {
background: var(--panel-background);
}
#root {
@mixin size 100%;
}
--body-background: #fff;
--html-font-size: 100px;
--panel-background: url('$CWD/test/css/variables/a.png');
--panel-background-alias: url('~@angular/material/theming/a.png');
--panel-background-base64: url('data:image/jpeg;base64,bm90IGFjdHVhbGx5IGEganBlZyBmaWxlCg==');
6 changes: 6 additions & 0 deletions test/css/specs/file-globbing.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
--body-background: #fff;
--html-font-size: 100px;
--panel-background: url('$CWD/test/css/variables/a.png');
--panel-background-alias: url('~@angular/material/theming/a.png');
--panel-background-base64: url('data:image/jpeg;base64,bm90IGFjdHVhbGx5IGEganBlZyBmaWxlCg==');
@define-mixin size $width, $height: $width {
width: $width;
height: $height;
Expand All @@ -10,6 +13,9 @@ html {
body {
background: var(--body-background);
}
div {
background: var(--panel-background);
}
#root {
@mixin size 100%;
}
11 changes: 8 additions & 3 deletions test/css/specs/imports.css
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
@import "mixins/size";
@import "$CWD/test/css/mixins/size";
@import '~bootstrap/mixins';
@import "~@angular/material/theming";
@import 'variables/color';
@import "variables/font.css";
@import "webpack/package.json";
@import '$CWD/test/css/variables/color';
@import "$CWD/test/css/variables/font.css";
@import '$CWD/test/css/variables/urls.css';
html {
font-size: var(--html-font-size);
}
body {
background: var(--body-background);
}
div {
background: var(--panel-background);
}
#root {
@mixin size 100%;
}
5 changes: 5 additions & 0 deletions test/css/specs/no-resolve-url.css
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
@import "../mixins/size";
@import '~bootstrap/mixins';
@import "~@angular/material/theming";
@import "webpack/package.json";
@import '../variables/color';
@import "../variables/font.css";
@import '../variables/urls.css';
html {
font-size: var(--html-font-size);
}
body {
background: var(--body-background);
}
div {
background: var(--panel-background);
}
#root {
@mixin size 100%;
}
11 changes: 8 additions & 3 deletions test/css/specs/prepend-injector.css
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
@import "mixins/size";
@import "$CWD/test/css/mixins/size";
@import '~bootstrap/mixins';
@import "~@angular/material/theming";
@import 'variables/color';
@import "variables/font.css";
@import "webpack/package.json";
@import '$CWD/test/css/variables/color';
@import "$CWD/test/css/variables/font.css";
@import '$CWD/test/css/variables/urls.css';
html {
font-size: var(--html-font-size);
}
body {
background: var(--body-background);
}
div {
background: var(--panel-background);
}
#root {
@mixin size 100%;
}
3 changes: 3 additions & 0 deletions test/css/specs/string-pattern.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ html {
body {
background: var(--body-background);
}
div {
background: var(--panel-background);
}
#root {
@mixin size 100%;
}
3 changes: 3 additions & 0 deletions test/css/variables/urls.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
--panel-background: url('./a.png');
--panel-background-alias: url('~@angular/material/theming/a.png');
--panel-background-base64: url('data:image/jpeg;base64,bm90IGFjdHVhbGx5IGEganBlZyBmaWxlCg==');
5 changes: 3 additions & 2 deletions test/helpers/exec-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import type {Configuration} from 'webpack';
import merge from 'webpack-merge';

import type {StyleResourcesFileFormat} from '../../src';
import {isFunction} from '../../src/utils';
import {CWD, isFunction} from '../../src/utils';

import {createBaseConfigOf} from './create-base-config';
import {injectVariable} from './inject-variable';
import {readStyleOf} from './read-style';
import {runWebpack} from './run-webpack';

Expand Down Expand Up @@ -39,7 +40,7 @@ export const execTestOf = (format: StyleResourcesFileFormat) => {
}

const actualStyle = ((await import(`../${format}/outputs/${testId}`)) as {default: string}).default;
const expectedStyle = await readStyle(testId);
const expectedStyle = injectVariable(await readStyle(testId), 'CWD', CWD);

expect(actualStyle).toBe(expectedStyle);
};
Expand Down
2 changes: 2 additions & 0 deletions test/helpers/inject-variable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const injectVariable = (code: string, key: string, value: string) =>
code.replace(new RegExp(`\\$${key}`, 'gu'), value);
1 change: 1 addition & 0 deletions test/less/resources/theming.less
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
@import "~@angular/material/theming";
@import "webpack/package.json";
1 change: 1 addition & 0 deletions test/less/resources/variables.less
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
@import '../variables/color';
@import "../variables/font.less";
@import '../variables/urls.less';
3 changes: 3 additions & 0 deletions test/less/source.less
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ html {
body {
background: @body-background;
}
div {
background: @panel-background
}
#root {
.size(100%);
}
11 changes: 8 additions & 3 deletions test/less/specs/append-injector.less
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ html {
body {
background: @body-background;
}
div {
background: @panel-background
}
#root {
.size(100%);
}
@import "mixins/size";
@import "$CWD/test/less/mixins/size";
@import (optional, once) '~bootstrap/mixins';
@import "~@angular/material/theming";
@import 'variables/color';
@import "variables/font.less";
@import "webpack/package.json";
@import '$CWD/test/less/variables/color';
@import "$CWD/test/less/variables/font.less";
@import '$CWD/test/less/variables/urls.less';
6 changes: 6 additions & 0 deletions test/less/specs/array-of-string-patterns.less
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@
}
@body-background: #fff;
@html-font-size: 100px;
@panel-background: url('$CWD/test/less/variables/a.png');
@panel-background-alias: url('~@angular/material/theming/a.png');
@panel-background-base64: url('data:image/jpeg;base64,bm90IGFjdHVhbGx5IGEganBlZyBmaWxlCg==');
html {
font-size: @html-font-size;
}
body {
background: @body-background;
}
div {
background: @panel-background
}
#root {
.size(100%);
}
6 changes: 6 additions & 0 deletions test/less/specs/async-injector.less
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ html {
body {
background: @body-background;
}
div {
background: @panel-background
}
#root {
.size(100%);
}
@body-background: #fff;
@html-font-size: 100px;
@panel-background: url('./a.png');
@panel-background-alias: url('~@angular/material/theming/a.png');
@panel-background-base64: url('data:image/jpeg;base64,bm90IGFjdHVhbGx5IGEganBlZyBmaWxlCg==');
6 changes: 6 additions & 0 deletions test/less/specs/customized-injector.less
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ html {
body {
background: @body-background;
}
div {
background: @panel-background
}
#root {
.size(100%);
}
@body-background: #fff;
@html-font-size: 100px;
@panel-background: url('$CWD/test/less/variables/a.png');
@panel-background-alias: url('~@angular/material/theming/a.png');
@panel-background-base64: url('data:image/jpeg;base64,bm90IGFjdHVhbGx5IGEganBlZyBmaWxlCg==');
6 changes: 6 additions & 0 deletions test/less/specs/file-globbing.less
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
@body-background: #fff;
@html-font-size: 100px;
@panel-background: url('$CWD/test/less/variables/a.png');
@panel-background-alias: url('~@angular/material/theming/a.png');
@panel-background-base64: url('data:image/jpeg;base64,bm90IGFjdHVhbGx5IGEganBlZyBmaWxlCg==');
.size(@width, @height: @width) {
width: @width;
height: @height;
Expand All @@ -10,6 +13,9 @@ html {
body {
background: @body-background;
}
div {
background: @panel-background
}
#root {
.size(100%);
}
Loading