Skip to content
This repository was archived by the owner on Mar 17, 2021. It is now read-only.
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: webpack-contrib/url-loader
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.1.2
Choose a base ref
...
head repository: webpack-contrib/url-loader
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v4.1.1
Choose a head ref

Commits on Oct 25, 2018

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    b603665 View commit details

Commits on Dec 20, 2018

  1. Copy the full SHA
    16bc97c View commit details
  2. Copy the full SHA
    c2d7b73 View commit details

Commits on Apr 4, 2019

  1. test: test svg scenario. #176 (#177)

    Jeff-Tian authored and evilebottnawi committed Apr 4, 2019
    Copy the full SHA
    a6705cc View commit details

Commits on Jun 5, 2019

  1. fix: fallback loader will be used than limit is equal or greater (#179)

    BREAKING CHANGE: fix: fallback loader will be used than limit is equal or greater
    evilebottnawi authored Jun 5, 2019
    Copy the full SHA
    3c24545 View commit details
  2. fix: limit should always be a number and 0 value handles as number (#…

    …180)
    
    BREAKING CHANGE: `limit` should always be a number and 0 value handles as number
    evilebottnawi authored Jun 5, 2019
    Copy the full SHA
    d82e453 View commit details
  3. Copy the full SHA
    60d2cb3 View commit details
  4. chore(deps): update (#182)

    BREAKING CHANGE: minimum required nodejs version is `8.9.0`
    evilebottnawi authored Jun 5, 2019
    Copy the full SHA
    4386b3e View commit details
  5. Copy the full SHA
    78833ac View commit details

Commits on Jun 25, 2019

  1. Copy the full SHA
    c0341da View commit details
  2. Copy the full SHA
    4842f93 View commit details
  3. chore(release): 2.0.1

    alexander-akait committed Jun 25, 2019
    Copy the full SHA
    37c6acc View commit details

Commits on Jul 18, 2019

  1. Copy the full SHA
    f3d4dd2 View commit details
  2. chore(release): 2.1.0

    alexander-akait committed Jul 18, 2019
    Copy the full SHA
    1b9dbd1 View commit details

Commits on Oct 3, 2019

  1. Copy the full SHA
    2bffcfd View commit details
  2. Copy the full SHA
    a251a23 View commit details

Commits on Oct 4, 2019

  1. Copy the full SHA
    9431124 View commit details
  2. Copy the full SHA
    196110e View commit details
  3. Copy the full SHA
    cbd1950 View commit details

Commits on Nov 21, 2019

  1. Copy the full SHA
    0ee2b99 View commit details
  2. chore(release): 2.3.0

    alexander-akait committed Nov 21, 2019
    Copy the full SHA
    2451157 View commit details

Commits on Nov 26, 2019

  1. refactor: next (#198)

    evilebottnawi authored Nov 26, 2019
    Copy the full SHA
    3f0bbc5 View commit details
  2. chore(release): 3.0.0

    alexander-akait committed Nov 26, 2019
    Copy the full SHA
    4301f87 View commit details

Commits on Jan 6, 2020

  1. Copy the full SHA
    a2f127d View commit details

Commits on Mar 17, 2020

  1. Copy the full SHA
    f13757a View commit details
  2. chore(deps): migrate on mime-types package (#209)

    BREAKING CHANGE: migrate on `mime-types` package, some rare types may have other mimetype
    evilebottnawi authored Mar 17, 2020
    Copy the full SHA
    fc8721f View commit details
  3. chore(release): 4.0.0

    alexander-akait committed Mar 17, 2020
    Copy the full SHA
    8828d64 View commit details

Commits on Apr 8, 2020

  1. Copy the full SHA
    36f1354 View commit details
  2. Copy the full SHA
    488b6ec View commit details
  3. Copy the full SHA
    06d270a View commit details

Commits on Apr 24, 2020

  1. Copy the full SHA
    35eeed1 View commit details
  2. Copy the full SHA
    1811901 View commit details

Commits on Oct 9, 2020

  1. Copy the full SHA
    20c744b View commit details
  2. Copy the full SHA
    acf4eb1 View commit details
Showing with 13,393 additions and 9,768 deletions.
  1. +0 −35 .babelrc
  2. +0 −156 .circleci/config.yml
  3. +1 −2 .editorconfig
  4. +3 −1 .eslintignore
  5. +1 −8 .eslintrc.js
  6. +1 −0 .gitattributes
  7. +78 −42 .github/CONTRIBUTING.md
  8. +1 −0 .github/FUNDING.yml
  9. +13 −4 .github/ISSUE_TEMPLATE.md
  10. +50 −0 .github/ISSUE_TEMPLATE/BUG.md
  11. +28 −0 .github/ISSUE_TEMPLATE/DOCS.md
  12. +25 −0 .github/ISSUE_TEMPLATE/FEATURE.md
  13. +27 −0 .github/ISSUE_TEMPLATE/MODIFICATION.md
  14. +8 −0 .github/ISSUE_TEMPLATE/SUPPORT.md
  15. +1 −1 .github/PULL_REQUEST_TEMPLATE.md
  16. +95 −0 .github/workflows/nodejs.yml
  17. +2 −1 .gitignore
  18. +5 −0 .prettierignore
  19. +0 −5 .prettierrc
  20. +1 −0 .prettierrc.js
  21. +96 −1 CHANGELOG.md
  22. +340 −66 README.md
  23. +19 −0 babel.config.js
  24. +0 −10 codecov.yml
  25. +1 −30 commitlint.config.js
  26. +6 −0 husky.config.js
  27. +4 −0 lint-staged.config.js
  28. +10,096 −9,050 package-lock.json
  29. +53 −66 package.json
  30. +101 −28 src/index.js
  31. +42 −4 src/options.json
  32. +0 −25 test/Errors.test.js
  33. +0 −11 test/__snapshots__/Errors.test.js.snap
  34. +378 −0 test/__snapshots__/encoding-option.test.js.snap
  35. +19 −0 test/__snapshots__/esModule-options.test.js.snap
  36. +116 −4 test/__snapshots__/fallback-option.test.js.snap
  37. +79 −0 test/__snapshots__/generator-option.test.js.snap
  38. +208 −4 test/__snapshots__/limit-option.test.js.snap
  39. +60 −1 test/__snapshots__/loader.test.js.snap
  40. +109 −2 test/__snapshots__/mimetype-option.test.js.snap
  41. +42 −0 test/__snapshots__/validate-options.test.js.snap
  42. +8 −4 test/cjs.test.js
  43. +197 −0 test/encoding-option.test.js
  44. +53 −0 test/esModule-options.test.js
  45. +137 −89 test/fallback-option.test.js
  46. +3 −0 test/fixtures/concated.js
  47. +1 −0 test/fixtures/file.html
  48. +1 −0 test/fixtures/file.unknown
  49. +4 −0 test/fixtures/simple-html.js
  50. +4 −0 test/fixtures/simple-svg.js
  51. +4 −0 test/fixtures/simple-unknown.js
  52. +2 −1 test/fixtures/{fixture.js → simple.js}
  53. +3 −0 test/fixtures/string-raw-loader/index.js
  54. +1 −1 test/fixtures/x-custom-loader/index.js
  55. +125 −0 test/generator-option.test.js
  56. +11 −0 test/helpers/compile.js
  57. +20 −0 test/helpers/execute.js
  58. +47 −0 test/helpers/getCompiler.js
  59. +7 −0 test/helpers/index.js
  60. +19 −0 test/helpers/normalizeErrors.js
  61. +15 −0 test/helpers/readAsset.js
  62. +277 −66 test/limit-option.test.js
  63. +117 −16 test/loader.test.js
  64. +149 −34 test/mimetype-option.test.js
  65. +79 −0 test/validate-options.test.js
35 changes: 0 additions & 35 deletions .babelrc

This file was deleted.

156 changes: 0 additions & 156 deletions .circleci/config.yml

This file was deleted.

3 changes: 1 addition & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -9,5 +9,4 @@ insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
insert_final_newline = false
trim_trailing_whitespace = false
trim_trailing_whitespace = false
4 changes: 3 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
/node_modules
/coverage
/dist
/node_modules
/test/fixtures
9 changes: 1 addition & 8 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
module.exports = {
root: true,
plugins: ['prettier'],
extends: ['@webpack-contrib/eslint-config-webpack'],
rules: {
'prettier/prettier': [
'error',
{ singleQuote: true, trailingComma: 'es5', arrowParens: 'always' },
],
},
extends: ['@webpack-contrib/eslint-config-webpack', 'prettier'],
};
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
package-lock.json -diff
* text=auto
bin/* eol=lf
yarn.lock -diff
120 changes: 78 additions & 42 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
## Contributing in @webpack-contrib
# Contributing in @webpack-contrib

We'd always love contributions to further improve the webpack / webpack-contrib ecosystem!
We'd always love contributions to further improve the webpack / webpack-contrib ecosystem!
Here are the guidelines we'd like you to follow:

* [Questions and Problems](#question)
* [Issues and Bugs](#issue)
* [Feature Requests](#feature)
* [Pull Request Submission Guidelines](#submit-pr)
* [Commit Message Conventions](#commit)
- [Questions and Problems](#question)
- [Issues and Bugs](#issue)
- [Feature Requests](#feature)
- [Pull Request Submission Guidelines](#submit-pr)
- [Commit Message Conventions](#commit)

### <a name="question"></a> Got a Question or Problem?
## <a name="question"></a> Got a Question or Problem?

Please submit support requests and questions to StackOverflow using the tag [[webpack]](http://stackoverflow.com/tags/webpack).
StackOverflow is better suited for this kind of support though you may also inquire in [Webpack Gitter](https://gitter.im/webpack/webpack).
Please submit support requests and questions to StackOverflow using the tag [[webpack]](http://stackoverflow.com/tags/webpack).
StackOverflow is better suited for this kind of support though you may also inquire in [Webpack Gitter](https://gitter.im/webpack/webpack).
The issue tracker is for bug reports and feature discussions.

### <a name="issue"></a> Found an Issue or Bug?
## <a name="issue"></a> Found an Issue or Bug?

Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.

@@ -31,13 +31,13 @@ We will be insisting on a minimal reproduce scenario in order to save maintainer

Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you we are going to close an issue that doesn't have enough info to be reproduced.

### <a name="feature"></a> Feature Requests?
## <a name="feature"></a> Feature Requests?

You can *request* a new feature by creating an issue on Github.
You can _request_ a new feature by creating an issue on Github.

If you would like to *implement* a new feature, please submit an issue with a proposal for your work `first`, to be sure that particular makes sense for the project.
If you would like to _implement_ a new feature, please submit an issue with a proposal for your work `first`, to be sure that particular makes sense for the project.

### <a name="submit-pr"></a> Pull Request Submission Guidelines
## <a name="submit-pr"></a> Pull Request Submission Guidelines

Before you submit your Pull Request (PR) consider the following guidelines:

@@ -46,9 +46,9 @@ Before you submit your Pull Request (PR) consider the following guidelines:
- Fill out our `Pull Request Template`. Your pull request will not be considered if it is ignored.
- Please sign the `Contributor License Agreement (CLA)` when a pull request is opened. We cannot accept your pull request without this. Make sure you sign with the primary email address associated with your local / github account.

### <a name="commit"></a> Webpack Contrib Commit Conventions
## <a name="commit"></a> Webpack Contrib Commit Conventions

Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
format that includes a **type**, a **scope** and a **subject**:

```
@@ -66,48 +66,56 @@ to read on GitHub as well as in various git tools.

The footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.

Examples:
Examples:

```
docs(readme): update install instructions
```

```
fix: refer to the `entrypoint` instead of the first `module`
```

#### Revert
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit.
### Revert

If the commit reverts a previous commit, it should begin with `revert:`, followed by the header of the reverted commit.
In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.

#### Type
### Type

Must be one of the following:

* **build**: Changes that affect the build system or external dependencies (example scopes: babel, npm)
* **chore**: Changes that fall outside of build / docs that do not effect source code (example scopes: package, defaults)
* **ci**: Changes to our CI configuration files and scripts (example scopes: circleci, travis)
* **docs**: Documentation only changes (example scopes: readme, changelog)
* **feat**: A new feature
* **fix**: A bug fix
* **perf**: A code change that improves performance
* **refactor**: A code change that neither fixes a bug nor adds a feature
* **revert**: Used when reverting a committed change
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons)
* **test**: Addition of or updates to Jest tests

#### Scope
- **build**: Changes that affect the build system or external dependencies (example scopes: babel, npm)
- **chore**: Changes that fall outside of build / docs that do not effect source code (example scopes: package, defaults)
- **ci**: Changes to our CI configuration files and scripts (example scopes: circleci, travis)
- **docs**: Documentation only changes (example scopes: readme, changelog)
- **feat**: A new feature
- **fix**: A bug fix
- **perf**: A code change that improves performance
- **refactor**: A code change that neither fixes a bug nor adds a feature
- **revert**: Used when reverting a committed change
- **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons)
- **test**: Addition of or updates to Jest tests

### Scope

The scope is subjective & depends on the `type` see above. A good example would be a change to a particular class / module.

#### Subject
### Subject

The subject contains a succinct description of the change:

* use the imperative, present tense: "change" not "changed" nor "changes"
* don't capitalize the first letter
* no dot (.) at the end
- use the imperative, present tense: "change" not "changed" nor "changes"
- don't capitalize the first letter
- no dot (.) at the end

### Body

#### Body
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
The body should include the motivation for the change and contrast this with previous behavior.

#### Footer
### Footer

The footer should contain any information about **Breaking Changes** and is also the place to
reference GitHub issues that this commit **Closes**.

@@ -116,9 +124,37 @@ reference GitHub issues that this commit **Closes**.
Example

```
BREAKING CHANGE: Updates to `Chunk.mapModules`.
BREAKING CHANGE: Updates to `Chunk.mapModules`.
This release is not backwards compatible with `Webpack 2.x` due to breaking changes in webpack/webpack#4764
Migration: see webpack/webpack#5225
```
```

## Testing Your Pull Request

You may have the need to test your changes in a real-world project or dependent
module. Thankfully, Github provides a means to do this. Add a dependency to the
`package.json` for such a project as follows:

```json
{
"devDependencies": {
"url-loader": "webpack-contrib/url-loader#{id}/head"
}
}
```

Where `{id}` is the # ID of your Pull Request.

## Contributor License Agreement

When submitting your contribution, a CLA (Contributor License Agreement) bot will come by to verify that you signed the [CLA](https://cla.js.foundation/webpack-contrib/url-loader).
If it is your first time, it will link you to the right place to sign it.
However, if you have committed your contributions using an email that is not the same as your email used on GitHub, the CLA bot can't accept your contribution.

Run `git config user.email` to see your Git email, and verify it with [your GitHub email](https://github.com/settings/emails).

## Thanks

For your interest, time, understanding, and for following this simple guide.
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
open_collective: webpack
17 changes: 13 additions & 4 deletions .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
<!--
1. Check the version of package you are using. If it's not the newest version, update and try again (see changelog while updating!).
2. If the issue is still there, write a minimal project showing the problem and expected output.
3. Link to the project and mention Node version and OS in your report.
👉🏽 Need support, advice, or help? Don't open an issue!
Head to StackOverflow or https://gitter.im/webpack/webpack.
**IMPORTANT! You should use [Stack Overflow](https://stackoverflow.com/) for support related questions.**
Hey there!
You arrived at this template because you felt none of the other options
matched the kind of issue you'd like to report. Please use this opportunity to
tell us about your particular type of issue so we can try to accomodate
similar issues in the future.
PLEASE do note, if you're using this to report an issue already covered by the
existing template types, your issue may be closed as invalid. Our issue
templates contain fields that help us help you, and without that important
info, we might as well be ice-skating uphill, carrying a wooly mammoth.
-->
50 changes: 50 additions & 0 deletions .github/ISSUE_TEMPLATE/BUG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
name: 🐛 Bug Report
about: Something went awry and you'd like to tell us about it.
---

<!--
Issues are so 🔥
If you remove or skip this template, you'll make the 🐼 sad and the mighty god
of Github will appear and pile-drive the close button from a great height
while making animal noises.
👉🏽 Need support, advice, or help? Don't open an issue!
Head to StackOverflow or https://gitter.im/webpack/webpack.
-->

- Operating System:
- Node Version:
- NPM Version:
- webpack Version:
- url-loader Version:

### Expected Behavior

<!-- Remove this section if not reporting a bug or modification request. -->

### Actual Behavior

<!-- Remove this section if not reporting a bug or modification request. -->

### Code

```js
// webpack.config.js
// If your code blocks are over 20 lines, please paste a link to a gist
// (https://gist.github.com).
```

```js
// additional code, HEY YO remove this block if you don't need it
```

### How Do We Reproduce?

<!--
Remove this section if not reporting a bug.
If your webpack config is over 50 lines long, please provide a URL to a repo
for your beefy 🍖 app that we can use to reproduce.
-->
28 changes: 28 additions & 0 deletions .github/ISSUE_TEMPLATE/DOCS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
name: 📚 Documentation
about: Are the docs lacking or missing something? Do they need some new 🔥 hotness? Tell us here.
---

<!--
Issues are so 🔥
If you remove or skip this template, you'll make the 🐼 sad and the mighty god
of Github will appear and pile-drive the close button from a great height
while making animal noises.
👉🏽 Need support, advice, or help? Don't open an issue!
Head to StackOverflow or https://gitter.im/webpack/webpack.
-->

Documentation Is:

<!-- Please place an x (no spaces!) in all [ ] that apply -->

- [ ] Missing
- [ ] Needed
- [ ] Confusing
- [ ] Not Sure?

### Please Explain in Detail...

### Your Proposal for Changes
25 changes: 25 additions & 0 deletions .github/ISSUE_TEMPLATE/FEATURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
name: ✨ Feature Request
about: Suggest an idea for this project
---

<!--
Issues are so 🔥
If you remove or skip this template, you'll make the 🐼 sad and the mighty god
of Github will appear and pile-drive the close button from a great height
while making animal noises.
👉🏽 Need support, advice, or help? Don't open an issue!
Head to StackOverflow or https://gitter.im/webpack/webpack.
-->

- Operating System:
- Node Version:
- NPM Version:
- webpack Version:
- url-loader Version:

### Feature Proposal

### Feature Use Case
27 changes: 27 additions & 0 deletions .github/ISSUE_TEMPLATE/MODIFICATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
name: 🔧 Modification Request
about: Would you like something work differently? Have an alternative approach? This is the template for you.
---

<!--
Issues are so 🔥
If you remove or skip this template, you'll make the 🐼 sad and the mighty god
of Github will appear and pile-drive the close button from a great height
while making animal noises.
👉🏽 Need support, advice, or help? Don't open an issue!
Head to StackOverflow or https://gitter.im/webpack/webpack.
-->

- Operating System:
- Node Version:
- NPM Version:
- webpack Version:
- url-loader Version:

### Expected Behavior / Situation

### Actual Behavior / Situation

### Modification Proposal
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/SUPPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
name: 🆘 Support, Help, and Advice
about: 👉🏽 Need support, help, or advice? Don't open an issue! Head to StackOverflow or https://gitter.im/webpack/webpack.
---

Hey there! If you need support, help, or advice then this is not the place to ask.
Please visit [StackOverflow](https://stackoverflow.com/questions/tagged/webpack)
or [the Webpack Gitter](https://gitter.im/webpack/webpack) instead.
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -32,4 +32,4 @@ This PR contains a:
migration path for existing applications.
-->

### Additional Info
### Additional Info
95 changes: 95 additions & 0 deletions .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
name: url-loader

on:
push:
branches:
- master
- next
pull_request:
branches:
- master
- next

jobs:
lint:
name: Lint - ${{ matrix.os }} - Node v${{ matrix.node-version }}

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

strategy:
matrix:
os: [ubuntu-latest]
node-version: [12.x]

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0

- name: Use Node.js ${{ env.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ env.node-version }}

- name: Use latest NPM
run: sudo npm i -g npm

- name: Install dependencies
run: npm ci

- name: Lint
run: npm run lint

- name: Security audit
run: npm run security

- name: Check commit message
uses: wagoid/commitlint-github-action@v1

test:
name: Test - ${{ matrix.os }} - Node v${{ matrix.node-version }}, Webpack ${{ matrix.webpack-version }}

strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [10.x, 12.x, 14.x]
webpack-version: [latest, next]

runs-on: ${{ matrix.os }}

steps:
- name: Setup Git
if: matrix.os == 'windows-latest'
run: git config --global core.autocrlf input

- uses: actions/checkout@v2

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}

- name: Use latest NPM on ubuntu/macos
if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest'
run: sudo npm i -g npm

- name: Use latest NPM on windows
if: matrix.os == 'windows-latest'
run: npm i -g npm

- name: Install dependencies
run: npm ci

- name: Install webpack ${{ matrix.webpack-version }}
run: npm i webpack@${{ matrix.webpack-version }}

- name: Run tests for webpack version ${{ matrix.webpack-version }}
run: npm run test:coverage -- --ci

- name: Submit coverage data to codecov
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -13,4 +13,5 @@ Thumbs.db
.idea
.vscode
*.sublime-project
*.sublime-workspace
*.sublime-workspace
*.iml
5 changes: 5 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/coverage
/dist
/node_modules
/test/fixtures
CHANGELOG.md
5 changes: 0 additions & 5 deletions .prettierrc

This file was deleted.

1 change: 1 addition & 0 deletions .prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = { singleQuote: true };
97 changes: 96 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,102 @@
# Change Log
# Changelog

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

### [4.1.1](https://github.com/webpack-contrib/url-loader/compare/v4.1.0...v4.1.1) (2020-10-09)

### Chore

* update `schema-utils`

## [4.1.0](https://github.com/webpack-contrib/url-loader/compare/v4.0.0...v4.1.0) (2020-04-08)


### Features

* the `mimetype` option can be `Boolean`
* added the `encoding` option
* added the `generator` option

## [4.0.0](https://github.com/webpack-contrib/url-loader/compare/v3.0.0...v4.0.0) (2020-03-17)


### ⚠ BREAKING CHANGES

* **deps:** migrate on `mime-types` package, some rare types may have other mimetype

### Bug Fixes

* description on the `esModule` option ([#204](https://github.com/webpack-contrib/url-loader/issues/204)) ([a2f127d](https://github.com/webpack-contrib/url-loader/commit/a2f127d16b88cda3c38509821a51487a89827c28))


* **deps:** migrate on `mime-types` package ([#209](https://github.com/webpack-contrib/url-loader/issues/209)) ([fc8721f](https://github.com/webpack-contrib/url-loader/commit/fc8721f49626360dd81300085a747b3afa5acd38))

## [3.0.0](https://github.com/webpack-contrib/url-loader/compare/v2.0.0...v3.0.0) (2019-11-26)


### BREAKING CHANGES

* minimum required nodejs version is `10.13.0`
* rename the `esModules` option to `esModule`
* switch to ES modules by default (the option `esModule` is `true` by default)


## [2.3.0](https://github.com/webpack-contrib/url-loader/compare/v2.2.0...v2.3.0) (2019-11-21)


### Features

* new `esModules` option to output ES modules ([0ee2b99](https://github.com/webpack-contrib/url-loader/commit/0ee2b9964f37f4d7c5dd6ea09f8526525e0fab91))

### [2.2.0](https://github.com/webpack-contrib/url-loader/compare/v2.1.0...v2.2.0) (2019-10-04)


### Features

* limit allow using `Infinity` and `Number` ([#192](https://github.com/webpack-contrib/url-loader/issues/192)) ([2bffcfd](https://github.com/webpack-contrib/url-loader/commit/2bffcfd))
* pnp support ([#195](https://github.com/webpack-contrib/url-loader/issues/195)) ([196110e](https://github.com/webpack-contrib/url-loader/commit/196110e))

## [2.1.0](https://github.com/webpack-contrib/url-loader/compare/v2.0.1...v2.1.0) (2019-07-18)


### Features

* improved validation error messages ([#187](https://github.com/webpack-contrib/url-loader/issues/187)) ([f3d4dd2](https://github.com/webpack-contrib/url-loader/commit/f3d4dd2))



### [2.0.1](https://github.com/webpack-contrib/url-loader/compare/v2.0.0...v2.0.1) (2019-06-25)


### Bug Fixes

* allow using limit as string when you use loader with query string ([#185](https://github.com/webpack-contrib/url-loader/issues/185)) ([4842f93](https://github.com/webpack-contrib/url-loader/commit/4842f93))



## [2.0.0](https://github.com/webpack-contrib/url-loader/compare/v1.1.2...v2.0.0) (2019-06-05)


### Bug Fixes

* rm unnecessary `bin` field ([#163](https://github.com/webpack-contrib/url-loader/issues/163)) ([b603665](https://github.com/webpack-contrib/url-loader/commit/b603665))
* `limit` should always be a number and 0 value handles as number ([#180](https://github.com/webpack-contrib/url-loader/issues/180)) ([d82e453](https://github.com/webpack-contrib/url-loader/commit/d82e453))
* fallback loader will be used than limit is equal or greater ([#179](https://github.com/webpack-contrib/url-loader/issues/179)) ([3c24545](https://github.com/webpack-contrib/url-loader/commit/3c24545))


### Features

* limit option can be boolean ([#181](https://github.com/webpack-contrib/url-loader/issues/181)) ([60d2cb3](https://github.com/webpack-contrib/url-loader/commit/60d2cb3))


### BREAKING CHANGES

* minimum required nodejs version is `8.9.0`
* `limit` should always be a number and 0 value handles as number
* fallback loader will be used than limit is equal or greater (before only when greater)



<a name="1.1.2"></a>
## [1.1.2](https://github.com/webpack-contrib/url-loader/compare/v1.1.0...v1.1.2) (2018-10-10)

406 changes: 340 additions & 66 deletions README.md

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const MIN_BABEL_VERSION = 7;

module.exports = (api) => {
api.assertVersion(MIN_BABEL_VERSION);
api.cache(true);

return {
presets: [
[
'@babel/preset-env',
{
targets: {
node: '10.13.0',
},
},
],
],
};
};
10 changes: 0 additions & 10 deletions codecov.yml

This file was deleted.

31 changes: 1 addition & 30 deletions commitlint.config.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,3 @@
/* eslint-disable */
const Configuration = {
module.exports = {
extends: ['@commitlint/config-conventional'],

rules: {
'body-leading-blank': [1, 'always'],
'footer-leading-blank': [1, 'always'],
'header-max-length': [2, 'always', 72],
'scope-case': [2, 'always', 'lower-case'],
'subject-case': [2, 'never', ['sentence-case', 'start-case', 'pascal-case', 'upper-case']],
'subject-empty': [2, 'never'],
'subject-full-stop': [2, 'never', '.'],
'type-case': [2, 'always', 'lower-case'],
'type-empty': [2, 'never'],
'type-enum': [2, 'always', [
'build',
'chore',
'ci',
'docs',
'feat',
'fix',
'perf',
'refactor',
'revert',
'style',
'test',
],
],
},
};

module.exports = Configuration;
6 changes: 6 additions & 0 deletions husky.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
hooks: {
'pre-commit': 'lint-staged',
'commit-msg': 'commitlint -E HUSKY_GIT_PARAMS',
},
};
4 changes: 4 additions & 0 deletions lint-staged.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
'*.js': ['prettier --write', 'eslint --fix'],
'*.{json,md,yml,css,ts}': ['prettier --write'],
};
19,146 changes: 10,096 additions & 9,050 deletions package-lock.json

Large diffs are not rendered by default.

119 changes: 53 additions & 66 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,96 +1,83 @@
{
"name": "url-loader",
"version": "1.1.2",
"version": "4.1.1",
"description": "A loader for webpack which transforms files into base64 URIs",
"license": "MIT",
"repository": "webpack-contrib/url-loader",
"author": "Tobias Koppers @sokra",
"homepage": "https://github.com/webpack-contrib/url-loader",
"bugs": "https://github.com/webpack-contrib/url-loader/issues",
"bin": "",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"main": "dist/cjs.js",
"engines": {
"node": ">= 6.9.0"
"node": ">= 10.13.0"
},
"scripts": {
"start": "npm run build -- -w",
"build": "cross-env NODE_ENV=production babel src -d dist --ignore 'src/**/*.test.js' --copy-files",
"clean": "del-cli dist",
"commitlint": "commitlint",
"commitmsg": "commitlint -e $GIT_PARAMS",
"lint": "eslint --cache src test",
"ci:lint:commits": "commitlint --from=${CIRCLE_BRANCH} --to=${CIRCLE_SHA1}",
"lint-staged": "lint-staged",
"prebuild": "npm run clean",
"prepublish": "npm run build",
"build": "cross-env NODE_ENV=production babel src -d dist --copy-files",
"commitlint": "commitlint --from=master",
"security": "npm audit",
"lint:prettier": "prettier --list-different .",
"lint:js": "eslint --cache .",
"lint": "npm-run-all -l -p \"lint:**\"",
"test:only": "cross-env NODE_ENV=test jest",
"test:watch": "npm run test:only -- --watch",
"test:coverage": "npm run test:only -- --collectCoverageFrom=\"src/**/*.js\" --coverage",
"pretest": "npm run lint",
"test": "npm run test:coverage",
"prepare": "npm run build",
"release": "standard-version",
"release:ci": "conventional-github-releaser -p angular",
"release:validate": "commitlint --from=$(git describe --tags --abbrev=0) --to=$(git rev-parse HEAD)",
"security": "nsp check",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --collectCoverageFrom='src/**/*.js' --coverage",
"ci:lint": "npm run lint && npm run security",
"ci:test": "npm run test -- --runInBand",
"ci:coverage": "npm run test:coverage -- --runInBand",
"defaults": "webpack-defaults"
},
"files": [
"dist"
],
"peerDependencies": {
"webpack": "^3.0.0 || ^4.0.0"
"webpack": "^4.0.0 || ^5.0.0",
"file-loader": "*"
},
"peerDependenciesMeta": {
"file-loader": {
"optional": true
}
},
"dependencies": {
"loader-utils": "^1.1.0",
"mime": "^2.0.3",
"schema-utils": "^1.0.0"
"loader-utils": "^2.0.0",
"mime-types": "^2.1.27",
"schema-utils": "^3.0.0"
},
"devDependencies": {
"@commitlint/cli": "^5.2.5",
"@commitlint/config-angular": "^5.1.1",
"@commitlint/config-conventional": "^7.0.1",
"@webpack-contrib/defaults": "^2.4.0",
"@webpack-contrib/eslint-config-webpack": "^2.0.2",
"@webpack-contrib/test-utils": "^0.1.2",
"babel-cli": "^6.26.0",
"babel-jest": "^22.0.3",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.1",
"conventional-github-releaser": "^2.0.0",
"cross-env": "^5.1.1",
"del": "^3.0.0",
"del-cli": "^1.1.0",
"eslint": "^4.13.1",
"eslint-plugin-import": "^2.8.0",
"eslint-plugin-prettier": "^2.4.0",
"file-loader": "^1.1.6",
"husky": "^0.14.3",
"jest": "^22.0.3",
"jest-serializer-path": "^0.1.15",
"lint-staged": "^6.0.0",
"memory-fs": "^0.4.1",
"nsp": "^3.1.0",
"pre-commit": "^1.2.2",
"prettier": "^1.9.2",
"standard-version": "^4.2.0",
"webpack": "^4.0.0"
"@babel/cli": "^7.11.6",
"@babel/core": "^7.11.6",
"@babel/preset-env": "^7.11.5",
"@commitlint/cli": "^11.0.0",
"@commitlint/config-conventional": "^11.0.0",
"@webpack-contrib/defaults": "^6.3.0",
"@webpack-contrib/eslint-config-webpack": "^3.0.0",
"babel-jest": "^26.5.2",
"cross-env": "^7.0.2",
"del": "^6.0.0",
"del-cli": "^3.0.1",
"eslint": "^7.10.0",
"eslint-config-prettier": "^6.12.0",
"eslint-plugin-import": "^2.22.1",
"file-loader": "^6.1.0",
"husky": "^4.3.0",
"jest": "^26.5.2",
"lint-staged": "^10.4.0",
"memfs": "^3.2.0",
"mini-svg-data-uri": "^1.2.3",
"npm-run-all": "^4.1.5",
"prettier": "^2.1.2",
"standard-version": "^9.0.0",
"webpack": "^4.44.2"
},
"keywords": [
"webpack"
],
"jest": {
"snapshotSerializers": [
"jest-serializer-path"
],
"testEnvironment": "node"
},
"pre-commit": "lint-staged",
"lint-staged": {
"*.js": [
"eslint --fix",
"git add"
]
}
]
}
129 changes: 101 additions & 28 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,113 @@
/* eslint-disable
global-require,
no-param-reassign,
prefer-destructuring,
import/no-dynamic-require,
*/
import path from 'path';

import { getOptions } from 'loader-utils';
import validateOptions from 'schema-utils';
import mime from 'mime';
import { validate } from 'schema-utils';
import mime from 'mime-types';

import normalizeFallback from './utils/normalizeFallback';
import schema from './options.json';

// Loader Mode
export const raw = true;
function shouldTransform(limit, size) {
if (typeof limit === 'boolean') {
return limit;
}

export default function loader(src) {
// Loader Options
const options = getOptions(this) || {};
if (typeof limit === 'string') {
return size <= parseInt(limit, 10);
}

if (typeof limit === 'number') {
return size <= limit;
}

return true;
}

validateOptions(schema, options, 'URL Loader');
function getMimetype(mimetype, resourcePath) {
if (typeof mimetype === 'boolean') {
if (mimetype) {
const resolvedMimeType = mime.contentType(path.extname(resourcePath));

const file = this.resourcePath;
// Set limit for resource inlining (file size)
let limit = options.limit;
if (!resolvedMimeType) {
return '';
}

if (limit) {
limit = parseInt(limit, 10);
return resolvedMimeType.replace(/;\s+charset/i, ';charset');
}

return '';
}

if (typeof mimetype === 'string') {
return mimetype;
}

const resolvedMimeType = mime.contentType(path.extname(resourcePath));

if (!resolvedMimeType) {
return '';
}
// Get MIME type
const mimetype = options.mimetype || mime.getType(file);

return resolvedMimeType.replace(/;\s+charset/i, ';charset');
}

function getEncoding(encoding) {
if (typeof encoding === 'boolean') {
return encoding ? 'base64' : '';
}

if (typeof encoding === 'string') {
return encoding;
}

return 'base64';
}

function getEncodedData(generator, mimetype, encoding, content, resourcePath) {
if (generator) {
return generator(content, mimetype, encoding, resourcePath);
}

return `data:${mimetype}${encoding ? `;${encoding}` : ''},${content.toString(
// eslint-disable-next-line no-undefined
encoding || undefined
)}`;
}

export default function loader(content) {
// Loader Options
const options = getOptions(this) || {};

validate(schema, options, {
name: 'URL Loader',
baseDataPath: 'options',
});

// No limit or within the specified limit
if (!limit || src.length < limit) {
if (typeof src === 'string') {
src = Buffer.from(src);
if (shouldTransform(options.limit, content.length)) {
const { resourcePath } = this;
const mimetype = getMimetype(options.mimetype, resourcePath);
const encoding = getEncoding(options.encoding);

if (typeof content === 'string') {
// eslint-disable-next-line no-param-reassign
content = Buffer.from(content);
}

return `module.exports = ${JSON.stringify(
`data:${mimetype || ''};base64,${src.toString('base64')}`
)}`;
const encodedData = getEncodedData(
options.generator,
mimetype,
encoding,
content,
resourcePath
);

const esModule =
typeof options.esModule !== 'undefined' ? options.esModule : true;

return `${
esModule ? 'export default' : 'module.exports ='
} ${JSON.stringify(encodedData)}`;
}

// Normalize the fallback.
@@ -48,6 +117,7 @@ export default function loader(src) {
} = normalizeFallback(options.fallback, options);

// Require the fallback.
// eslint-disable-next-line global-require, import/no-dynamic-require
const fallback = require(fallbackLoader);

// Call the fallback, passing a copy of the loader context. The copy has the query replaced. This way, the fallback
@@ -56,5 +126,8 @@ export default function loader(src) {
query: fallbackOptions,
});

return fallback.call(fallbackLoaderContext, src);
return fallback.call(fallbackLoaderContext, content);
}

// Loader Mode
export const raw = true;
46 changes: 42 additions & 4 deletions src/options.json
Original file line number Diff line number Diff line change
@@ -2,12 +2,46 @@
"type": "object",
"properties": {
"limit": {
"type": ["string", "number"]
"description": "Enables/Disables transformation target file into base64 URIs (https://github.com/webpack-contrib/url-loader#limit).",
"type": ["boolean", "number", "string"]
},
"encoding": {
"description": "Specify the encoding which the file will be in-lined with.",
"oneOf": [
{
"type": "boolean"
},
{
"enum": [
"utf8",
"utf16le",
"latin1",
"base64",
"hex",
"ascii",
"binary",
"ucs2"
]
}
]
},
"mimetype": {
"type": "string"
"description": "The MIME type for the file to be transformed (https://github.com/webpack-contrib/url-loader#mimetype).",
"oneOf": [
{
"type": "boolean"
},
{
"type": "string"
}
]
},
"generator": {
"description": "Adding custom implementation for encoding files.",
"instanceof": "Function"
},
"fallback": {
"description": "An alternative loader to use when a target file's size exceeds the limit set in the limit option (https://github.com/webpack-contrib/url-loader#fallback).",
"anyOf": [
{
"type": "string"
@@ -16,11 +50,11 @@
"additionalProperties": false,
"properties": {
"loader": {
"description": "Fallback loader name",
"description": "Fallback loader name.",
"type": "string"
},
"options": {
"description": "Fallback loader options",
"description": "Fallback loader options.",
"anyOf": [
{
"type": "object"
@@ -34,6 +68,10 @@
"type": "object"
}
]
},
"esModule": {
"description": "By default, url-loader generates JS modules that use the ES modules syntax.",
"type": "boolean"
}
},
"additionalProperties": true
25 changes: 0 additions & 25 deletions test/Errors.test.js

This file was deleted.

11 changes: 0 additions & 11 deletions test/__snapshots__/Errors.test.js.snap

This file was deleted.

378 changes: 378 additions & 0 deletions test/__snapshots__/encoding-option.test.js.snap

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions test/__snapshots__/esModule-options.test.js.snap

Large diffs are not rendered by default.

120 changes: 116 additions & 4 deletions test/__snapshots__/fallback-option.test.js.snap

Large diffs are not rendered by default.

79 changes: 79 additions & 0 deletions test/__snapshots__/generator-option.test.js.snap

Large diffs are not rendered by default.

212 changes: 208 additions & 4 deletions test/__snapshots__/limit-option.test.js.snap

Large diffs are not rendered by default.

61 changes: 60 additions & 1 deletion test/__snapshots__/loader.test.js.snap

Large diffs are not rendered by default.

111 changes: 109 additions & 2 deletions test/__snapshots__/mimetype-option.test.js.snap

Large diffs are not rendered by default.

42 changes: 42 additions & 0 deletions test/__snapshots__/validate-options.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`validate options should throw an error on the "esModule" option with "true" value 1`] = `
"Invalid options object. URL Loader has been initialized using an options object that does not match the API schema.
- options.esModule should be a boolean.
-> By default, url-loader generates JS modules that use the ES modules syntax."
`;

exports[`validate options should throw an error on the "fallback" option with "true" value 1`] = `
"Invalid options object. URL Loader has been initialized using an options object that does not match the API schema.
- options.fallback should be one of these:
string | object { loader?, options? }
-> An alternative loader to use when a target file's size exceeds the limit set in the limit option (https://github.com/webpack-contrib/url-loader#fallback).
Details:
* options.fallback should be a string.
* options.fallback should be an object:
object { loader?, options? }"
`;
exports[`validate options should throw an error on the "limit" option with "[]" value 1`] = `
"Invalid options object. URL Loader has been initialized using an options object that does not match the API schema.
- options.limit should be:
boolean | number | string
-> Enables/Disables transformation target file into base64 URIs (https://github.com/webpack-contrib/url-loader#limit)."
`;
exports[`validate options should throw an error on the "limit" option with "{}" value 1`] = `
"Invalid options object. URL Loader has been initialized using an options object that does not match the API schema.
- options.limit should be:
boolean | number | string
-> Enables/Disables transformation target file into base64 URIs (https://github.com/webpack-contrib/url-loader#limit)."
`;
exports[`validate options should throw an error on the "mimetype" option with "() => {}" value 1`] = `
"Invalid options object. URL Loader has been initialized using an options object that does not match the API schema.
- options.mimetype should be one of these:
boolean | string
-> The MIME type for the file to be transformed (https://github.com/webpack-contrib/url-loader#mimetype).
Details:
* options.mimetype should be a boolean.
* options.mimetype should be a string."
`;
12 changes: 8 additions & 4 deletions test/cjs.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import loader from '../src';
import CJSLoader from '../src/cjs';
import src from '../src';
import cjs from '../src/cjs';

describe('CJS', () => {
it('should exported loader', () => {
expect(CJSLoader).toEqual(loader);
it('should export loader', () => {
expect(cjs).toEqual(src);
});

it('should export "raw" flag', () => {
expect(cjs.raw).toEqual(true);
});
});
197 changes: 197 additions & 0 deletions test/encoding-option.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import {
compile,
execute,
getCompiler,
normalizeErrors,
readAsset,
} from './helpers';

describe('"encoding" option', () => {
it('should work with unspecified value with the default base64 encoding', async () => {
const compiler = getCompiler('simple-svg.js');
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Boolean" true (default base64)', async () => {
const compiler = getCompiler('simple-svg.js', {
encoding: true,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Boolean" false (no encoding)', async () => {
const compiler = getCompiler('simple-svg.js', {
encoding: false,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "String" right encoding value (utf8)', async () => {
const compiler = getCompiler('simple-svg.js', {
encoding: 'utf8',
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "String" right encoding value (hex)', async () => {
const compiler = getCompiler('simple-svg.js', {
encoding: 'hex',
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "String" right encoding value (utf16le)', async () => {
const compiler = getCompiler('simple-svg.js', {
encoding: 'utf16le',
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "String" right encoding value (latin1)', async () => {
const compiler = getCompiler('simple-svg.js', {
encoding: 'latin1',
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "String" right encoding value (base64)', async () => {
const compiler = getCompiler('simple-svg.js', {
encoding: 'base64',
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "String" right encoding value (ascii)', async () => {
const compiler = getCompiler('simple-svg.js', {
encoding: 'ascii',
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "String" right encoding value (binary)', async () => {
const compiler = getCompiler('simple-svg.js', {
encoding: 'binary',
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "String" right encoding value (ucs2)', async () => {
const compiler = getCompiler('simple-svg.js', {
encoding: 'ucs2',
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should throw an error with "String" wrong encoding value equal to xyz', async () => {
const compiler = getCompiler('simple-svg.js', {
encoding: 'xyz',
});
const stats = await compile(compiler);

try {
execute(readAsset('main.bundle.js', compiler, stats));
expect(true).toBe(false);
} catch (err) {
expect(err.message.indexOf('ValidationError')).not.toBe(-1);
}
});
});
53 changes: 53 additions & 0 deletions test/esModule-options.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {
compile,
execute,
getCompiler,
normalizeErrors,
readAsset,
} from './helpers';

// TODO
describe('"esModule" option', () => {
it('should work without value', async () => {
const compiler = getCompiler('simple.js');
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Boolean" value equal "true"', async () => {
const compiler = getCompiler('simple.js', {
esModule: true,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Boolean" value equal "false"', async () => {
const compiler = getCompiler('simple.js', {
esModule: false,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});
});
226 changes: 137 additions & 89 deletions test/fallback-option.test.js
Original file line number Diff line number Diff line change
@@ -1,108 +1,156 @@
/* eslint-disable
prefer-destructuring,
*/
import path from 'path';

import webpack from '@webpack-contrib/test-utils';
import {
compile,
execute,
getCompiler,
normalizeErrors,
readAsset,
} from './helpers';

describe('fallback option', () => {
test('{undefined}', async () => {
const config = {
rules: [
{
test: /\.png$/,
use: {
loader: path.join(__dirname, '../src'),
options: {},
},
},
],
};

const stats = await webpack('fixture.js', config);
const { source } = stats.toJson().modules[0];
describe('"fallback" option', () => {
it('should work with unspecified value', async () => {
const compiler = getCompiler('simple.js');
const stats = await compile(compiler);

expect(source).toMatchSnapshot();
expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

test('{String}', async () => {
const config = {
rules: [
{
test: /\.png$/,
use: {
loader: path.join(__dirname, '../src'),
options: {
limit: Number.MIN_SAFE_INTEGER,
name: '[name].[hash].[ext]',
unknown: 'value',
fallback: path.join(__dirname, 'fixtures/x-custom-loader'),
},
},
},
],
};
it('should work with "String" value', async () => {
const compiler = getCompiler('simple.js', {
limit: Number.MIN_SAFE_INTEGER,
name: '[name].[hash].[ext]',
unknown: 'value',
fallback: path.join(__dirname, 'fixtures/x-custom-loader'),
});
const stats = await compile(compiler);

const stats = await webpack('fixture.js', config);
const { source } = stats.toJson().modules[0];
expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "String" value and require.resolve', async () => {
const compiler = getCompiler('simple.js', {
limit: Number.MIN_SAFE_INTEGER,
name: '[name].[hash].[ext]',
unknown: 'value',
fallback: require.resolve('./fixtures/x-custom-loader'),
});
const stats = await compile(compiler);

expect(source).toMatchSnapshot();
expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

test('{String} (with query)', async () => {
const config = {
rules: [
{
test: /\.png$/,
use: {
loader: path.join(__dirname, '../src'),
options: {
limit: Number.MIN_SAFE_INTEGER,
name: '[name].[hash].[ext]',
unknown: 'value',
fallback: `${path.join(
__dirname,
'fixtures/x-custom-loader'
)}?name=fallback-[hash].[ext]&unknown=fallback-value`,
},
},
},
],
};
it('should work with "String" value and with query', async () => {
const compiler = getCompiler('simple.js', {
limit: Number.MIN_SAFE_INTEGER,
name: '[name].[hash].[ext]',
unknown: 'value',
fallback: `${path.join(
__dirname,
'fixtures/x-custom-loader'
)}?name=fallback-[hash].[ext]&unknown=fallback-value`,
});
const stats = await compile(compiler);

const stats = await webpack('fixture.js', config);
const { source } = stats.toJson().modules[0];
expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "String" value, with query and require.resolve', async () => {
const compiler = getCompiler('simple.js', {
limit: Number.MIN_SAFE_INTEGER,
name: '[name].[hash].[ext]',
unknown: 'value',
fallback: `${require.resolve(
'./fixtures/x-custom-loader'
)}?name=fallback-[hash].[ext]&unknown=fallback-value`,
});
const stats = await compile(compiler);

expect(source).toMatchSnapshot();
expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

test('{Object}', async () => {
const config = {
rules: [
{
test: /\.png$/,
use: {
loader: path.join(__dirname, '../src'),
options: {
limit: Number.MIN_SAFE_INTEGER,
name: '[name].[hash].[ext]',
unknown: 'value',
fallback: {
loader: path.join(__dirname, 'fixtures/x-custom-loader'),
options: {
name: 'fallback-[hash].[ext]',
unknown: 'fallback-other-value',
},
},
},
},
it('should work with "Object" value', async () => {
const compiler = getCompiler('simple.js', {
limit: Number.MIN_SAFE_INTEGER,
name: '[name].[hash].[ext]',
unknown: 'value',
fallback: {
loader: path.join(__dirname, 'fixtures/x-custom-loader'),
options: {
name: 'fallback-[hash].[ext]',
unknown: 'fallback-other-value',
},
],
};
},
});
const stats = await compile(compiler);

const stats = await webpack('fixture.js', config);
const { source } = stats.toJson().modules[0];
expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Object" value and require.resolve', async () => {
const compiler = getCompiler('simple.js', {
limit: Number.MIN_SAFE_INTEGER,
name: '[name].[hash].[ext]',
unknown: 'value',
fallback: {
loader: require.resolve('./fixtures/x-custom-loader'),
options: {
name: 'fallback-[hash].[ext]',
unknown: 'fallback-other-value',
},
},
});
const stats = await compile(compiler);

expect(source).toMatchSnapshot();
expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});
});
3 changes: 3 additions & 0 deletions test/fixtures/concated.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import png from './file.png';

export default '<img alt="test" src="' + png + '" />';
1 change: 1 addition & 0 deletions test/fixtures/file.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<h1>Hello, World! Привет мир!</h1>
1 change: 1 addition & 0 deletions test/fixtures/file.unknown
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test
4 changes: 4 additions & 0 deletions test/fixtures/simple-html.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* eslint-disable */
import html from './file.html';

export default html;
4 changes: 4 additions & 0 deletions test/fixtures/simple-svg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* eslint-disable */
import svg from './file.svg';

export default svg;
4 changes: 4 additions & 0 deletions test/fixtures/simple-unknown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* eslint-disable */
import unknown from './file.unknown';

export default unknown;
3 changes: 2 additions & 1 deletion test/fixtures/fixture.js → test/fixtures/simple.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/* eslint-disable */
import png from './file.png';

export default png;
3 changes: 3 additions & 0 deletions test/fixtures/string-raw-loader/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = () => {
return 'string';
};
2 changes: 1 addition & 1 deletion test/fixtures/x-custom-loader/index.js
Original file line number Diff line number Diff line change
@@ -3,5 +3,5 @@ const utils = require('loader-utils');
module.exports = function loader() {
const options = utils.getOptions(this);

return `module.exports=${JSON.stringify(options)}`;
return `module.exports = ${JSON.stringify(options)}`;
};
125 changes: 125 additions & 0 deletions test/generator-option.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import {
compile,
execute,
getCompiler,
normalizeErrors,
readAsset,
} from './helpers';

const svgToMiniDataURI = require('mini-svg-data-uri');

describe('"generator" option', () => {
it('should work with unspecified value with the default base64 encoding', async () => {
const compiler = getCompiler('simple-svg.js');
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Function" mini-svg-data-uri generator', async () => {
const compiler = getCompiler('simple-svg.js', {
generator: (content) => svgToMiniDataURI(content.toString()),
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Function" generating encoded file manually', async () => {
const compiler = getCompiler('file.html', {
generator: (content, mimetype, encoding) => {
return `data:${mimetype}${
encoding ? `;${encoding}` : ''
},${content.toString(encoding)}`;
},
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Function" generating encoded file manually without "mimetype"', async () => {
const compiler = getCompiler('file.html', {
mimetype: false,
generator: (content, mimetype, encoding) => {
return `data:${mimetype}${
encoding ? `;${encoding}` : ''
},${content.toString(encoding || 'utf-8')}`;
},
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Function" generating encoded file manually without "encoding"', async () => {
const compiler = getCompiler('file.html', {
encoding: false,
generator: (content, mimetype, encoding) => {
return `data:${mimetype}${
encoding ? `;${encoding}` : ''
},${content.toString(encoding || 'utf-8')}`;
},
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Function" generating encoded file manually without "mimetype" and "encoding"', async () => {
const compiler = getCompiler('file.html', {
mimetype: false,
encoding: false,
generator: (content, mimetype, encoding) => {
return `data:${mimetype}${
encoding ? `;${encoding}` : ''
},${content.toString(encoding || 'utf-8')}`;
},
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});
});
11 changes: 11 additions & 0 deletions test/helpers/compile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default (compiler) => {
return new Promise((resolve, reject) => {
compiler.run((error, stats) => {
if (error) {
return reject(error);
}

return resolve(stats);
});
});
};
20 changes: 20 additions & 0 deletions test/helpers/execute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Module from 'module';
import path from 'path';

const parentModule = module;

export default (code) => {
const resource = 'test.js';
const module = new Module(resource, parentModule);
// eslint-disable-next-line no-underscore-dangle
module.paths = Module._nodeModulePaths(
path.resolve(__dirname, '../fixtures')
);
module.filename = resource;

// eslint-disable-next-line no-underscore-dangle
module._compile(code, resource);

// eslint-disable-next-line no-underscore-dangle
return module.exports.__esModule ? module.exports.default : module.exports;
};
47 changes: 47 additions & 0 deletions test/helpers/getCompiler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import path from 'path';

import webpack from 'webpack';
import { createFsFromVolume, Volume } from 'memfs';

export default (fixture, loaderOptions = {}, config = {}) => {
const fullConfig = {
mode: 'development',
devtool: config.devtool || false,
context: path.resolve(__dirname, '../fixtures'),
entry: path.resolve(__dirname, '../fixtures', fixture),
output: {
publicPath: '',
path: path.resolve(__dirname, '../outputs'),
filename: '[name].bundle.js',
chunkFilename: '[name].chunk.js',
libraryTarget: 'commonjs2',
},
module: {
rules: [
{
test: /\.(gif|jpg|png|svg|html|unknown)$/i,
rules: [
{
loader: path.resolve(__dirname, '../../src'),
options: loaderOptions || {},
},
],
},
],
},
plugins: [],
...config,
};

const compiler = webpack(fullConfig);

if (!config.outputFileSystem) {
const outputFileSystem = createFsFromVolume(new Volume());
// Todo remove when we drop webpack@4 support
outputFileSystem.join = path.join.bind(path);

compiler.outputFileSystem = outputFileSystem;
}

return compiler;
};
7 changes: 7 additions & 0 deletions test/helpers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import compile from './compile';
import execute from './execute';
import getCompiler from './getCompiler';
import normalizeErrors from './normalizeErrors';
import readAsset from './readAsset';

export { compile, execute, getCompiler, normalizeErrors, readAsset };
19 changes: 19 additions & 0 deletions test/helpers/normalizeErrors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
function removeCWD(str) {
const isWin = process.platform === 'win32';
let cwd = process.cwd();

if (isWin) {
// eslint-disable-next-line no-param-reassign
str = str.replace(/\\/g, '/');
// eslint-disable-next-line no-param-reassign
cwd = cwd.replace(/\\/g, '/');
}

return str.replace(new RegExp(cwd, 'g'), '');
}

export default (errors) => {
return errors.map((error) =>
removeCWD(error.toString().split('\n').slice(0, 2).join('\n'))
);
};
15 changes: 15 additions & 0 deletions test/helpers/readAsset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import path from 'path';

export default (asset, compiler, stats) => {
const usedFs = compiler.outputFileSystem;
const outputPath = stats.compilation.outputOptions.path;
let data = '';

try {
data = usedFs.readFileSync(path.join(outputPath, asset)).toString();
} catch (error) {
data = error.toString();
}

return data;
};
343 changes: 277 additions & 66 deletions test/limit-option.test.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,279 @@
/* eslint-disable
prefer-destructuring,
*/
import webpack from '@webpack-contrib/test-utils';

describe('limit option', () => {
test('{undefined}', async () => {
const config = {
loader: {
test: /\.png$/,
options: {},
},
};

const stats = await webpack('fixture.js', config);
const { source } = stats.toJson().modules[0];

expect(source).toMatchSnapshot();
});

test('{Number} (big)', async () => {
const config = {
loader: {
test: /\.png$/,
options: {
limit: Number.MAX_SAFE_INTEGER,
},
},
};

const stats = await webpack('fixture.js', config);
const { source } = stats.toJson().modules[0];

expect(source).toMatchSnapshot();
});

test('{Number} (less)', async () => {
const config = {
loader: {
test: /\.png$/,
options: {
limit: Number.MIN_SAFE_INTEGER,
},
},
};

const stats = await webpack('fixture.js', config);
const { source } = stats.toJson().modules[0];

expect(source).toMatchSnapshot();
});

test('{String} (big)', async () => {
const config = {
loader: {
test: /\.png$/,
options: {
limit: '8192',
},
},
};

const stats = await webpack('fixture.js', config);
const { source } = stats.toJson().modules[0];

expect(source).toMatchSnapshot();
import {
compile,
execute,
getCompiler,
normalizeErrors,
readAsset,
} from './helpers';

describe('"limit" option', () => {
it('should work with unspecified value', async () => {
const compiler = getCompiler('simple.js');
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Number" value equal to 0', async () => {
const compiler = getCompiler('simple.js', {
limit: 0,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Number" value equal to 0.1', async () => {
const compiler = getCompiler('simple.js', {
limit: 0.1,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Number" value equal to 6776', async () => {
const compiler = getCompiler('simple.js', {
limit: 6776,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Number" value equal to 6777', async () => {
const compiler = getCompiler('simple.js', {
limit: 6777,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Number" value equal to 6778', async () => {
const compiler = getCompiler('simple.js', {
limit: 6778,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Number" value equal to Number.MAX_SAFE_INTEGER', async () => {
const compiler = getCompiler('simple.js', {
limit: Number.MAX_SAFE_INTEGER,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Number" value equal to Number.MIN_SAFE_INTEGER', async () => {
const compiler = getCompiler('simple.js', {
limit: Number.MIN_SAFE_INTEGER,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Number" value equal to Number.MAX_VALUE', async () => {
const compiler = getCompiler('simple.js', {
limit: Number.MAX_VALUE,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Number" value equal to Infinity', async () => {
const compiler = getCompiler('simple.js', {
limit: Infinity,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Boolean" value equal to true', async () => {
const compiler = getCompiler('simple.js', {
limit: true,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Boolean" value equal to false', async () => {
const compiler = getCompiler('simple.js', {
limit: false,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "String" value equal to 0', async () => {
const compiler = getCompiler('simple.js', {
limit: '0',
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "String" value equal to 0.1', async () => {
const compiler = getCompiler('simple.js', {
limit: '0.1',
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "String" value equal to 6776', async () => {
const compiler = getCompiler('simple.js', {
limit: '6776',
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "String" value equal to 6777', async () => {
const compiler = getCompiler('simple.js', {
limit: '6777',
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "String" value equal to 6778', async () => {
const compiler = getCompiler('simple.js', {
limit: '6778',
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});
});
133 changes: 117 additions & 16 deletions test/loader.test.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,121 @@
/* eslint-disable
prefer-destructuring,
*/
import webpack from '@webpack-contrib/test-utils';

describe('Loader', () => {
test('Defaults', async () => {
const config = {
loader: {
test: /\.png$/,
options: {},
},
};
import path from 'path';

import {
compile,
execute,
getCompiler,
normalizeErrors,
readAsset,
} from './helpers';

describe('loader', () => {
it('should work with unspecified value', async () => {
const compiler = getCompiler('simple.js');
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with SVG', async () => {
const compiler = getCompiler('simple-svg.js');
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

const stats = await webpack('fixture.js', config);
const { source } = stats.toJson().modules[0];
it('should work with loader that exported string', async () => {
const compiler = getCompiler(
'simple.js',
{},
{
module: {
rules: [
{
test: /\.(gif|jpg|png|svg)$/i,
rules: [
{
loader: path.resolve(__dirname, '../src'),
},
{
loader: path.resolve(__dirname, 'fixtures/string-raw-loader'),
},
],
},
],
},
}
);
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with ModuleConcatenationPlugin', async () => {
const compiler = getCompiler(
'concated.js',
{},
{
mode: 'production',
optimization: {
minimize: false,
},
}
);
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with ModuleConcatenationPlugin with fallback', async () => {
const compiler = getCompiler(
'concated.js',
{
limit: 10,
},
{
mode: 'production',
optimization: {
minimize: false,
},
}
);
const stats = await compile(compiler);

expect(source).toMatchSnapshot();
expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});
});
183 changes: 149 additions & 34 deletions test/mimetype-option.test.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,151 @@
/* eslint-disable
prefer-destructuring,
*/
import webpack from '@webpack-contrib/test-utils';

describe('mimetype option', () => {
test('{undefined}', async () => {
const config = {
loader: {
test: /\.png$/,
options: {},
},
};

const stats = await webpack('fixture.js', config);
const { source } = stats.toJson().modules[0];

expect(source).toMatchSnapshot();
});

test('{String}', async () => {
const config = {
loader: {
test: /\.png$/,
options: {
mimetype: 'image/x-custom',
},
},
};

const stats = await webpack('fixture.js', config);
const { source } = stats.toJson().modules[0];

expect(source).toMatchSnapshot();
import {
compile,
execute,
getCompiler,
normalizeErrors,
readAsset,
} from './helpers';

describe('"mimetype" option', () => {
it('should work with unspecified value', async () => {
const compiler = getCompiler('simple.js');
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Boolean" true', async () => {
const compiler = getCompiler('simple-html.js', {
mimetype: true,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "Boolean" false', async () => {
const compiler = getCompiler('simple-html.js', {
mimetype: false,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "String" value', async () => {
const compiler = getCompiler('simple.js', {
mimetype: 'image/x-custom',
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work with "String" value equal to unknown/unknown', async () => {
const compiler = getCompiler('simple.js', {
mimetype: 'unknown/unknown',
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work for unknown mimetype', async () => {
const compiler = getCompiler('simple-unknown.js');
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work for unknown mimetype when value is true', async () => {
const compiler = getCompiler('simple-unknown.js', {
mimetype: true,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work for unknown mimetype when value is false and encoding is false', async () => {
const compiler = getCompiler('simple-unknown.js', {
mimetype: false,
encoding: false,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});

it('should work for unknown mimetype when value is true and encoding is true', async () => {
const compiler = getCompiler('simple-unknown.js', {
mimetype: true,
encoding: true,
});
const stats = await compile(compiler);

expect(
execute(readAsset('main.bundle.js', compiler, stats))
).toMatchSnapshot('result');
expect(Object.keys(stats.compilation.assets)).toMatchSnapshot('assets');
expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
'warnings'
);
expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot('errors');
});
});
79 changes: 79 additions & 0 deletions test/validate-options.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { getCompiler, compile } from './helpers';

describe('validate options', () => {
const tests = {
limit: {
success: [8192, true, '8192'],
failure: [{}, []],
},
mimetype: {
success: ['image/png', 'unknown/unknown', true, false],
failure: [() => {}],
},
fallback: {
success: [
// 'custom-loader',
{ loader: 'custom-loader' },
{
loader: 'custom-loader',
options: { unknown: 'unknown' },
},
],
failure: [true],
},
esModule: {
success: [true, false],
failure: ['true'],
},
unknown: {
success: [1, true, false, 'test', /test/, [], {}, { foo: 'bar' }],
failure: [],
},
};

function stringifyValue(value) {
if (
Array.isArray(value) ||
(value && typeof value === 'object' && value.constructor === Object)
) {
return JSON.stringify(value);
}

return value;
}

async function createTestCase(key, value, type) {
it(`should ${
type === 'success' ? 'successfully validate' : 'throw an error on'
} the "${key}" option with "${stringifyValue(value)}" value`, async () => {
const compiler = getCompiler('simple.js', { [key]: value });

let stats;

try {
stats = await compile(compiler);
} finally {
if (type === 'success') {
expect(stats.hasErrors()).toBe(false);
} else if (type === 'failure') {
const {
compilation: { errors },
} = stats;

expect(errors).toHaveLength(1);
expect(() => {
throw new Error(errors[0].error.message);
}).toThrowErrorMatchingSnapshot();
}
}
});
}

for (const [key, values] of Object.entries(tests)) {
for (const type of Object.keys(values)) {
for (const value of values[type]) {
createTestCase(key, value, type);
}
}
}
});