This commit is contained in:
Tutur33
2023-11-24 23:58:26 +01:00
parent 25395c0ee1
commit 938ad9d309
4191 changed files with 41 additions and 518781 deletions
-69
View File
@@ -1,69 +0,0 @@
# resolve-url-loader
## Version 5
**Features**
* Update `postcss` and completely remove `rework` parser.
**Breaking Changes**
* Require `node@>=12`.
* Support `webpack@>=4` (no longer tested for earlier versions).
* The `engine` option has been removed.
**Migrating**
Remove the `engine` option if you are using it.
## Version 4
**Features**
* Better resolution of the original source location - You can more successfully use `url()` in variables and mixins.
* Dependencies now accept a wider range and explicit dependency on `rework` and `rework-visit` has been removed.
**Breaking Changes**
* The `engine` option is deprecated which means the old `rework` engine is deprecated.
* The `keepQuery` behaviour is now the default, the `keepQuery` option has been removed.
* The `removeCR` option defaults to `true` when executing on Windows OS.
* The `absolute` option has been removed.
* The `join` option has changed.
**Migrating**
Remove the `engine` option if you are using it - the default "postcss" engine is much more reliable. The "rework" engine will still work for now but will be removed in the next major version.
Remove the `keepQuery` option if you are using it.
Remove the `absolute` option, webpack should work fine without it. If you have a specific need to rebase `url()` then you should use a separate loader.
If you use a custom `join` function then you will need to refactor it to the new API. Refer to the advanced usage documentation.
If you wish to still use `engine: "rework"` then note that `rework` and `rework-visit` packages are now `peerDependencies` that must be explicitly installed by you.
## Version 3
**Features**
* Use `postcss` parser by default. This is long overdue as the old `rework` parser doesn't cope with modern css.
* Lots of automated tests running actual webpack builds. If you have an interesting use-case let me know.
**Breaking Changes**
* Multiple options changed or deprecated.
* Removed file search "magic" in favour of `join` option.
* Errors always fail and are no longer swallowed.
* Processing absolute asset paths requires `root` option to be set.
**Migrating**
Initially set option `engine: 'rework'` for parity with your existing build. Once working you can remove this option **or** set `engine: 'postcss'` explicitly.
Retain `keepQuery` option if you are already using it.
The `root` option now has a different meaning. Previously it limited file search. Now it is the base path for absolute or root-relative URIs, consistent with `css-loader`. If you are already using it you can probably remove it.
If you build on Windows platform **and** your content contains absolute asset paths, then `css-loader` could fail. The `root` option here may fix the URIs before they get to `css-loader`. Try to leave it unspecified, otherwise (windows only) set to empty string `root: ''`.
-21
View File
@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2016 Ben Holloway
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-136
View File
@@ -1,136 +0,0 @@
# Resolve URL Loader
[![NPM](https://nodei.co/npm/resolve-url-loader.png)](https://www.npmjs.com/package/resolve-url-loader)
This **webpack loader** allows you to have a distributed set SCSS files and assets co-located with those SCSS files.
## Do you organise your SCSS and assets by feature?
Where are your assets?
* ✅ I want my assets all over the place, next to my SCSS files.
* ❌ My assets are in a single directory.
How complicated is your SASS?
* ✅ I have a deep SASS composition with partials importing other partials.
* ✅ My asset paths are constructed by functions or `@mixin`s.
* ❌ I have a single SCSS file. The asset paths are just explicit in that.
What asset paths are you using?
* ✅ Fully relative `url(./foo.png)` or `url(foo.png)`
* ❌ Root relative `url(/foo.png)`
* ❌ Relative to some package or webpack root `url(~stuff/foo.png`)
* ❌ Relative to some variable which is your single asset directory `url($variable/foo.png)`
What webpack errors are you getting?
* ✅ Webpack can't find the relative asset `foo.png` 😞
* ❌ Webpack says it doesn't have a loader for `fully/resolved/path/foo.png` 😕
If you can tick at least 1 item in **all of these questions** then use this loader. It will allow webpack to find assets with **fully relative paths**.
If for any question you can't tick _any_ items then webpack should be able to already find your assets. You don't need this loader. 🤷
Once webpack resolves your assets (even if it complains about loading them) then this loading is working correctly. 👍
## What's the problem with SASS?
When you use **fully relative paths** in `url()` statements then Webpack expects to find those assets next to the root SCSS file, regardless of where you specify the `url()`.
To illustrate here are 3 simple examples of SASS and Webpack _without_ `resolve-url-loader`.
[![the basic problem](https://raw.githubusercontent.com/bholloway/resolve-url-loader/v5/packages/resolve-url-loader/docs/basic-problem.svg)](docs/basic-problem.svg)
The first 2 cases are trivial and work fine. The asset is specified in the root SCSS file and Webpack finds it.
But any practical SASS composition will have nested SCSS files, as in the 3rd case. Here Webpack cannot find the asset.
```
Module not found: Can't resolve './cool.png' in '/absolute/path/.../my-project/src/styles.scss'
```
The path we present to Webpack really needs to be `./subdir/cool.png` but we don't want to write that in our SCSS. 😒
Luckily we can use `resolve-url-loader` to do the **url re-writing** and make it work. 😊🎉
With functions and mixins and multiple nesting it gets more complicated. Read more detail in [how the loader works](docs/how-it-works.md). 🤓
## Getting started
> **Upgrading?** the [changelog](CHANGELOG.md) shows how to migrate your webpack config.
### Install
via npm
```bash
npm install resolve-url-loader --save-dev
```
via yarn
```bash
yarn add resolve-url-loader --dev
```
### Configure Webpack
The typical use case is `resolve-url-loader` between `sass-loader` and `css-loader`.
**⚠️ IMPORTANT**
* **source-maps required** for loaders preceding `resolve-url-loader` (regardless of `devtool`).
* Always use **full loader package name** (don't omit `-loader`) otherwise you can get errors that are hard to debug.
``` javascript
rules: [
{
test: /\.scss$/,
use: [
...
{
loader: 'css-loader',
options: {...}
}, {
loader: 'resolve-url-loader',
options: {...}
}, {
loader: 'sass-loader',
options: {
sourceMap: true, // <-- !!IMPORTANT!!
}
}
]
},
...
]
```
## Options
The loader should work without options but use these as required.
| option | type | default | | description |
|-------------|----------|-----------------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `sourceMap` | boolean | `false` | | Generate an outgoing source-map. |
| `removeCR` | boolean | `true` Windows OS<br/>`false` otherwise | | Convert orphan CR to whitespace.<br/>See known issues below. |
| `debug` | boolean | `false` | | Display debug information. |
| `silent` | boolean | `false` | | Do **not** display warnings or deprecation messages. |
| `root` | string | _unset_ | | Similar to the (now defunct) option in `css-loader`.<br/>This string, possibly empty, is prepended to absolute URIs.<br/>Absolute URIs are only processed if this option is set. |
| `join` | function | _inbuilt_ | advanced | Custom join function.<br/>Use custom javascript to fix asset paths on a per-case basis.<br/>Refer to the [advanced features](docs/advanced-features.md) docs. |
## Limitations
### Compatibility
Tested `macOS` and `Windows`.
All `webpack@4`-`webpack@5` with contemporaneous loaders/plugins using `node@12`.
Refer to `test` directory for full webpack configurations as used in automated tests.
### Known issues
Read the [troubleshooting](docs/troubleshooting.md) docs before raising an issue.
-292
View File
@@ -1,292 +0,0 @@
/*
* MIT License http://opensource.org/licenses/MIT
* Author: Ben Holloway @bholloway
*/
'use strict';
const os = require('os');
const path = require('path');
const fs = require('fs');
const util = require('util');
const loaderUtils = require('loader-utils');
const SourceMapConsumer = require('source-map').SourceMapConsumer;
const adjustSourceMap = require('adjust-sourcemap-loader/lib/process');
const valueProcessor = require('./lib/value-processor');
const joinFn = require('./lib/join-function');
const logToTestHarness = require('./lib/log-to-test-harness');
const DEPRECATED_OPTIONS = {
engine: [
'DEP_RESOLVE_URL_LOADER_OPTION_ENGINE',
'"engine" option has been removed, postcss is the only parser used'
],
keepQuery: [
'DEP_RESOLVE_URL_LOADER_OPTION_KEEP_QUERY',
'"keepQuery" option has been removed, the query and/or hash are now always retained'
],
absolute: [
'DEP_RESOLVE_URL_LOADER_OPTION_ABSOLUTE',
'"absolute" option has been removed, consider the "join" option if absolute paths must be processed'
],
attempts: [
'DEP_RESOLVE_URL_LOADER_OPTION_ATTEMPTS',
'"attempts" option has been removed, consider the "join" option if search is needed'
],
includeRoot: [
'DEP_RESOLVE_URL_LOADER_OPTION_INCLUDE_ROOT',
'"includeRoot" option has been removed, consider the "join" option if search is needed'
],
fail: [
'DEP_RESOLVE_URL_LOADER_OPTION_FAIL',
'"fail" option has been removed'
]
};
/**
* A webpack loader that resolves absolute url() paths relative to their original source file.
* Requires source-maps to do any meaningful work.
* @param {string} content Css content
* @param {object} sourceMap The source-map
* @returns {string|String}
*/
function resolveUrlLoader(content, sourceMap) {
/* jshint validthis:true */
// details of the file being processed
const loader = this;
// a relative loader.context is a problem
if (/^\./.test(loader.context)) {
return handleAsError(
'webpack misconfiguration',
'loader.context is relative, expected absolute'
);
}
// infer webpack version from new loader features
const isWebpackGte5 = 'getOptions' in loader && typeof loader.getOptions === 'function';
// use loader.getOptions where available otherwise use loaderUtils
const rawOptions = isWebpackGte5 ? loader.getOptions() : loaderUtils.getOptions(loader);
const options = Object.assign(
{
sourceMap: loader.sourceMap,
silent : false,
removeCR : os.EOL.includes('\r'),
root : false,
debug : false,
join : joinFn.defaultJoin
},
rawOptions,
);
// maybe log options for the test harness
if (process.env.RESOLVE_URL_LOADER_TEST_HARNESS) {
logToTestHarness(
process[process.env.RESOLVE_URL_LOADER_TEST_HARNESS],
options
);
}
// deprecated options
const deprecatedItems = Object.entries(DEPRECATED_OPTIONS).filter(([key]) => key in rawOptions);
if (deprecatedItems.length) {
deprecatedItems.forEach(([, value]) => handleAsDeprecated(...value));
}
// validate join option
if (typeof options.join !== 'function') {
return handleAsError(
'loader misconfiguration',
'"join" option must be a Function'
);
} else if (options.join.length !== 2) {
return handleAsError(
'loader misconfiguration',
'"join" Function must take exactly 2 arguments (options, loader)'
);
}
// validate the result of calling the join option
const joinProper = options.join(options, loader);
if (typeof joinProper !== 'function') {
return handleAsError(
'loader misconfiguration',
'"join" option must itself return a Function when it is called'
);
} else if (joinProper.length !== 1) {
return handleAsError(
'loader misconfiguration',
'"join" Function must create a function that takes exactly 1 arguments (item)'
);
}
// validate root option
if (typeof options.root === 'string') {
const isValid = (options.root === '') ||
(path.isAbsolute(options.root) && fs.existsSync(options.root) && fs.statSync(options.root).isDirectory());
if (!isValid) {
return handleAsError(
'loader misconfiguration',
'"root" option must be an empty string or an absolute path to an existing directory'
);
}
} else if (options.root !== false) {
handleAsWarning(
'loader misconfiguration',
'"root" option must be string where used or false where unused'
);
}
// loader result is cacheable
loader.cacheable();
// incoming source-map
let absSourceMap = null;
let sourceMapConsumer = null;
if (sourceMap) {
// support non-standard string encoded source-map (per less-loader)
if (typeof sourceMap === 'string') {
try {
sourceMap = JSON.parse(sourceMap);
}
catch (exception) {
return handleAsError(
'source-map error',
'cannot parse source-map string (from less-loader?)'
);
}
}
// leverage adjust-sourcemap-loader's codecs to avoid having to make any assumptions about the sourcemap
// historically this is a regular source of breakage
try {
absSourceMap = adjustSourceMap(loader, {format: 'absolute'}, sourceMap);
}
catch (exception) {
return handleAsError(
'source-map error',
exception.message
);
}
// prepare the adjusted sass source-map for later look-ups
sourceMapConsumer = new SourceMapConsumer(absSourceMap);
} else {
handleAsWarning(
'webpack misconfiguration',
'webpack or the upstream loader did not supply a source-map'
);
}
// allow engine to throw at initialisation
let engine = null;
try {
engine = require('./lib/engine/postcss');
} catch (error) {
return handleAsError(
'error initialising',
error
);
}
// process async
const callback = loader.async();
Promise
.resolve(engine(loader.resourcePath, content, {
outputSourceMap : !!options.sourceMap,
absSourceMap : absSourceMap,
sourceMapConsumer : sourceMapConsumer,
removeCR : options.removeCR,
transformDeclaration: valueProcessor({
join : joinProper,
root : options.root,
directory: path.dirname(loader.resourcePath)
})
}))
.catch(onFailure)
.then(onSuccess);
function onFailure(error) {
callback(encodeError('error processing CSS', error));
}
function onSuccess(result) {
if (result) {
// complete with source-map
// webpack4 and earlier: source-map sources are relative to the file being processed
// webpack5: source-map sources are relative to the project root but without a leading slash
if (options.sourceMap) {
const finalMap = adjustSourceMap(loader, {
format: isWebpackGte5 ? 'projectRelative' : 'sourceRelative'
}, result.map);
callback(null, result.content, finalMap);
}
// complete without source-map
else {
callback(null, result.content);
}
}
}
/**
* Trigger a node deprecation message for the given exception and return the original content.
* @param {string} code Deprecation code
* @param {string} message Deprecation message
* @returns {string} The original CSS content
*/
function handleAsDeprecated(code, message) {
if (!options.silent) {
util.deprecate(() => undefined, message, code)();
}
return content;
}
/**
* Push a warning for the given exception and return the original content.
* @param {string} label Summary of the error
* @param {string|Error} [exception] Optional extended error details
* @returns {string} The original CSS content
*/
function handleAsWarning(label, exception) {
if (!options.silent) {
loader.emitWarning(encodeError(label, exception));
}
return content;
}
/**
* Push a warning for the given exception and return the original content.
* @param {string} label Summary of the error
* @param {string|Error} [exception] Optional extended error details
* @returns {string} The original CSS content
*/
function handleAsError(label, exception) {
loader.emitError(encodeError(label, exception));
return content;
}
function encodeError(label, exception) {
return new Error(
[
'resolve-url-loader',
': ',
[label]
.concat(
(typeof exception === 'string') && exception ||
Array.isArray(exception) && exception ||
(exception instanceof Error) && [exception.message, exception.stack.split('\n')[1].trim()] ||
[]
)
.filter(Boolean)
.join('\n ')
].join('')
);
}
}
module.exports = Object.assign(resolveUrlLoader, joinFn);
-44
View File
@@ -1,44 +0,0 @@
{
"name": "resolve-url-loader",
"version": "5.0.0",
"description": "Webpack loader that resolves relative paths in url() statements based on the original source file",
"main": "index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/bholloway/resolve-url-loader.git",
"directory": "packages/resolve-url-loader"
},
"keywords": [
"webpack",
"loader",
"css",
"normalize",
"rewrite",
"resolve",
"url",
"sass",
"relative",
"file"
],
"author": "bholloway",
"license": "MIT",
"bugs": {
"url": "https://github.com/bholloway/resolve-url-loader/issues"
},
"homepage": "https://github.com/bholloway/resolve-url-loader/tree/v5/packages/resolve-url-loader",
"engines": {
"node": ">=12"
},
"files": [
"index.js",
"lib/**/+([a-z-]).js",
"docs/**/*.*"
],
"dependencies": {
"adjust-sourcemap-loader": "^4.0.0",
"convert-source-map": "^1.7.0",
"loader-utils": "^2.0.0",
"postcss": "^8.2.14",
"source-map": "0.6.1"
}
}