Skip to content
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/sass-loader
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 2759618d2e05318ea6dc307fff0f84d1d867fff0
Choose a base ref
...
head repository: webpack-contrib/sass-loader
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 45bd8655864adbfe7e1c71a277c8e9cbb22b86ab
Choose a head ref

Commits on Apr 24, 2018

  1. fix: Report error to user for problems loading node-sass (#562)

    * Update loader.js
    * Update index.test.js
    acouch authored and jhnns committed Apr 24, 2018
    Copy the full SHA
    2529c07 View commit details

Commits on Apr 25, 2018

  1. Copy the full SHA
    10a8161 View commit details

Commits on May 7, 2018

  1. docs(readme) Use mini-css-extract-plugin in examples. (#568)

    * update(readme) Use mini-css-extract-plugin in examples.
    
    * update(readme) dont use variable for dev
    EugeneHlushko authored and evilebottnawi committed May 7, 2018
    Copy the full SHA
    437450f View commit details

Commits on Jun 1, 2018

  1. Copy the full SHA
    6dfb274 View commit details

Commits on Jun 2, 2018

  1. chore(release): 7.0.2

    jhnns committed Jun 2, 2018
    Copy the full SHA
    2efb8cf View commit details

Commits on Jun 4, 2018

  1. fix: Bare imports not working sometimes (#579)

    Fixes #566
    Supersedes #577
    jhnns authored and evilebottnawi committed Jun 4, 2018
    2
    Copy the full SHA
    c348281 View commit details

Commits on Jun 5, 2018

  1. chore(release): 7.0.3

    jhnns committed Jun 5, 2018
    Copy the full SHA
    d0b35cb View commit details

Commits on Aug 1, 2018

  1. test: Refactor module import tests (#599)

    In preparation for #573
    Imports without file extensions are deprecated in LibSass and
    even not supported in DartSass.
    jhnns authored Aug 1, 2018
    Copy the full SHA
    714f5c6 View commit details
  2. feat: Make this package implementation-agnostic (#573)

    Rather than always loading Node Sass, this now requires users to pass in
    either Dart Sass or Node Sass as an option to the loader.
    
    Closes #435
    nex3 authored and jhnns committed Aug 1, 2018
    Copy the full SHA
    bed9fb5 View commit details
  3. chore(release): 7.1.0

    jhnns committed Aug 1, 2018

    Verified

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

Commits on Aug 7, 2018

  1. Copy the full SHA
    b7aca40 View commit details

Commits on Aug 23, 2018

  1. Copy the full SHA
    f4bdcfe View commit details

Commits on Aug 25, 2018

  1. Copy the full SHA
    a7bf7c0 View commit details

Commits on Oct 30, 2018

  1. Copy the full SHA
    472d09a View commit details

Commits on Dec 12, 2018

  1. Copy the full SHA
    5984a2c View commit details
  2. Copy the full SHA
    69dc5e5 View commit details
  3. Copy the full SHA
    d56c0f8 View commit details
  4. Copy the full SHA
    f799569 View commit details

Commits on Dec 13, 2018

  1. Copy the full SHA
    a80cdb1 View commit details
  2. Copy the full SHA
    bc3b848 View commit details
  3. Copy the full SHA
    2adcca3 View commit details

Commits on Dec 14, 2018

  1. Copy the full SHA
    f524223 View commit details
  2. feat: support auto resolving dart-sass

    Now you don't need setup `implementation: require('sass')`, just add `sass` to your `package.json` and install dependencies and `sass-loader` automatically load `sass`. Beware situation when `node-sass` and `sass` was installed, by default `sass-loader` loads `node-sass`, to avoid this situation use `implementation` option.
    evilebottnawi authored Dec 14, 2018
    Copy the full SHA
    ff90dd6 View commit details
  3. Copy the full SHA
    a8709c9 View commit details
  4. Copy the full SHA
    aa64e1b View commit details
  5. Copy the full SHA
    2d6045b View commit details

Commits on Dec 17, 2018

  1. Copy the full SHA
    6c9654d View commit details

Commits on Mar 14, 2019

  1. docs: add source-map to style-loader (#661)

    Jack Zhao authored and evilebottnawi committed Mar 14, 2019
    Copy the full SHA
    69c6f91 View commit details

Commits on Mar 26, 2019

  1. Copy the full SHA
    9162e45 View commit details

Commits on May 7, 2019

  1. Copy the full SHA
    e279f2a View commit details

Commits on Aug 8, 2019

  1. Copy the full SHA
    9e5a45d View commit details
  2. Copy the full SHA
    2a51502 View commit details
  3. Copy the full SHA
    28f1884 View commit details
  4. Copy the full SHA
    6fc9d4e View commit details
  5. Copy the full SHA
    bcb06d5 View commit details

Commits on Aug 9, 2019

  1. Copy the full SHA
    45ac0b5 View commit details
  2. Copy the full SHA
    6e8e409 View commit details
  3. Copy the full SHA
    865f713 View commit details

Commits on Aug 10, 2019

  1. Copy the full SHA
    f59646f View commit details

Commits on Aug 13, 2019

  1. Copy the full SHA
    39b3bf4 View commit details

Commits on Aug 14, 2019

  1. Copy the full SHA
    1905e7b View commit details
  2. refactor: code (#719)

    evilebottnawi authored Aug 14, 2019
    Copy the full SHA
    c459352 View commit details
  3. Copy the full SHA
    96f436f View commit details

Commits on Aug 15, 2019

  1. Copy the full SHA
    0e94940 View commit details

Commits on Aug 16, 2019

  1. Copy the full SHA
    55f1af8 View commit details
  2. Copy the full SHA
    b8a7ca7 View commit details
  3. refactor: code

    alexander-akait committed Aug 16, 2019
    Copy the full SHA
    3545434 View commit details
  4. Copy the full SHA
    b2af379 View commit details
  5. Copy the full SHA
    97c93dd View commit details
Showing 350 changed files with 189,189 additions and 12,261 deletions.
17 changes: 7 additions & 10 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
# This file is for unifying the coding style for different editors and IDEs.
# More information at http://EditorConfig.org

# No .editorconfig files above the root directory
root = true
# editorconfig.org

[*]
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[package.json]
indent_size = 2
[*.md]
trim_trailing_whitespace = false
9 changes: 4 additions & 5 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# Compiled by webpack
test/output

# Fake node_modules folder for tests
test/node_modules
/coverage
/dist
/node_modules
/test/fixtures
17 changes: 17 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = {
root: true,
extends: ['@webpack-contrib/eslint-config-webpack', 'prettier'],
overrides: [
{
files: [
'test/watch/**/*.js',
'test/hmr/**/*.js',
'test/extractText/**/*.js',
'test/helpers/testLoader.js',
],
rules: {
strict: 'off',
},
},
],
};
9 changes: 0 additions & 9 deletions .eslintrc.json

This file was deleted.

4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package-lock.json -diff
* text=auto
bin/* eol=lf
yarn.lock -diff
6 changes: 6 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# These are the default owners for everything in
# webpack-contrib
@webpack-contrib/org-maintainers

# Add repository specific users / groups
# below here for libs that are not maintained by the org.
160 changes: 160 additions & 0 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# Contributing in @webpack-contrib

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)

## <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).
The issue tracker is for bug reports and feature discussions.

## <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.

We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs, we ask that you to provide a minimal reproduction scenario (github repo or failing test case). Having a live, reproducible scenario gives us a wealth of important information without going back & forth to you with additional questions like:

- version of Webpack used
- version of the loader / plugin you are creating a bug report for
- the use-case that fails

A minimal reproduce scenario allows us to quickly confirm a bug (or point out config problems) as well as confirm that we are fixing the right problem.

We will be insisting on a minimal reproduce scenario in order to save maintainers time and ultimately be able to fix more bugs. We understand that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate the problem before we can fix it.

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?

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.

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

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

- Search Github for an open or closed PR that relates to your submission. You don't want to duplicate effort.
- Commit your changes using a descriptive commit message that follows our [commit message conventions](#commit). Adherence to these conventions is necessary because release notes are automatically generated from these messages.
- 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

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**:

```
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
```

The **header** is mandatory and the **scope** of the header is optional.

Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
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:

```
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.
In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.

### 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

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

### 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

### 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

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

**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.

Example

```
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": {
"sass-loader": "webpack-contrib/sass-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/sass-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
16 changes: 16 additions & 0 deletions .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!--
👉🏽 Need support, advice, or help? Don't open an issue!
Head to StackOverflow or https://gitter.im/webpack/webpack.
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:
- sass-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:
- sass-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:
- sass-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.
35 changes: 35 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!--
HOLY CRAP a Pull Request. We ❤️ those!
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.
Please place an x (no spaces!) in all [ ] that apply
-->

This PR contains a:

- [ ] **bugfix**
- [ ] new **feature**
- [ ] **code refactor**
- [ ] **test update** <!-- if bug or feature is checked, this should be too -->
- [ ] **typo fix**
- [ ] **metadata update**

### Motivation / Use-Case

<!--
Please explain the motivation or use-case for your change.
What existing problem does the PR solve?
If this PR addresses an issue, please link to the issue.
-->

### Breaking Changes

<!--
If this PR introduces a breaking change, please describe the impact and a
migration path for existing applications.
-->

### 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: sass-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 }}
27 changes: 14 additions & 13 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
lib-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.gz

pids
logs
results
*.log
npm-debug.log*
.eslintcache

npm-debug.log
/coverage
/dist
/local
/reports
/node_modules
coverage

.DS_Store
Thumbs.db
.idea
*.iml
.vscode
*.sublime-project
*.sublime-workspace
.nyc_output
test/output
14 changes: 0 additions & 14 deletions .nycrc

This file was deleted.

7 changes: 7 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/coverage
/dist
/node_modules
/test/fixtures
CHANGELOG.md
/test/sass
/test/scss
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 };
48 changes: 0 additions & 48 deletions .travis.yml

This file was deleted.

138 changes: 137 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,143 @@
# 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.

## [9.0.0](https://github.com/webpack-contrib/sass-loader/compare/v8.0.2...v9.0.0) (2020-07-02)


### ⚠ BREAKING CHANGES

* minimum supported Nodejs version is `10.13`
* prefer `sass` (`dart-sass`) by default, it is strongly recommended to migrate on `sass` (`dart-sass`)
* the `prependData` option was removed in favor the `additionalData` option, see [docs](https://github.com/webpack-contrib/sass-loader#additionaldata)
* when the `sourceMap` is `true`, `sassOptions.sourceMap`, `sassOptions.sourceMapContents`, `sassOptions.sourceMapEmbed`, `sassOptions.sourceMapRoot` and `sassOptions.omitSourceMapUrl` will be ignored.

### Features

* pass the loader context to custom importers under the `this.webpackLoaderContext` property ([#853](https://github.com/webpack-contrib/sass-loader/issues/853)) ([d487683](https://github.com/webpack-contrib/sass-loader/commit/d487683221fcd1e5a173e083b4b40644751c8cb1))
* supports for `process.cwd()` resolution logic by default ([#837](https://github.com/webpack-contrib/sass-loader/issues/837)) ([0c8d3b3](https://github.com/webpack-contrib/sass-loader/commit/0c8d3b3fb1cf371779b4a886cfc4e60facf68759))
* supports for `SASS-PATH` env variable resolution logic by default ([#836](https://github.com/webpack-contrib/sass-loader/issues/836)) ([8376179](https://github.com/webpack-contrib/sass-loader/commit/83761798380dcccc5a2badde3b3affe2bac385e8))
* supports for the `sass` property for the `exports` field from `package.json` (conditional exports, for more information read [docs](https://nodejs.org/api/esm.html))

### Bug Fixes

* avoid different content on different os ([#832](https://github.com/webpack-contrib/sass-loader/issues/832)) ([68dd278](https://github.com/webpack-contrib/sass-loader/commit/68dd27883ce0536adc5bc170816242c67fb118ff))
* resolution logic when the `includePaths` option used was improved ([#827](https://github.com/webpack-contrib/sass-loader/issues/827)) ([cbe5ad4](https://github.com/webpack-contrib/sass-loader/commit/cbe5ad407582a617be097d3eadd3ad8619e52507))
* resolution logic for `file://` scheme was improved ([17832fd](https://github.com/webpack-contrib/sass-loader/commit/17832fdb11f91593f4e2995003d67aebefb3be90))
* resolution logic for absolute paths and server relative URLs was improved
* source maps generation was improved

### [8.0.2](https://github.com/webpack-contrib/sass-loader/compare/v8.0.1...v8.0.2) (2020-01-13)


### Bug Fixes

* compatibility with node@8 ([#798](https://github.com/webpack-contrib/sass-loader/issues/798)) ([6f3852f](https://github.com/webpack-contrib/sass-loader/commit/6f3852f7d393dd0bc8f8d264d81ecc941bc72511))

### [8.0.1](https://github.com/webpack-contrib/sass-loader/compare/v8.0.0...v8.0.1) (2020-01-10)


### Bug Fixes

* support webpack@5 ([#794](https://github.com/webpack-contrib/sass-loader/issues/794)) ([6c59e37](https://github.com/webpack-contrib/sass-loader/commit/6c59e37e3f67668d7a3908444ddfc0176bc5601f))

## [8.0.0](https://github.com/webpack-contrib/sass-loader/compare/v7.3.1...v8.0.0) (2019-08-29)


### ⚠ BREAKING CHANGES

* minimum required `webpack` version is `4.36.0`
* minimum required `node.js` version is `8.9.0`
* move all sass (`includePaths`, `importer`, `functions`, `outputStyle`) options to the `sassOptions` option. The `functions` option can't be used as `Function`, you should use `sassOption` as `Function` to achieve this.
* the `data` option was renamed to the `prependData` option
* default value of the `sourceMap` option depends on the `devtool` value (`eval`/`false` values don't enable source map generation)


### Features

* automatically use the `fibers` package if it is possible ([#744](https://github.com/webpack-contrib/sass-loader/issues/744)) ([96184e1](https://github.com/webpack-contrib/sass-loader/commit/96184e1))
* source map generation depends on the `devtool` option ([#743](https://github.com/webpack-contrib/sass-loader/issues/743)) ([fcea88e](https://github.com/webpack-contrib/sass-loader/commit/fcea88e))
* validate loader options ([#737](https://github.com/webpack-contrib/sass-loader/issues/737)) ([7b543fc](https://github.com/webpack-contrib/sass-loader/commit/7b543fc))
* reworked error handling from `node-sass`/`sass`
* improve resolution for `@import` (including support `_index` and `index` files in a directory)

### Bug Fixes

* compatibility with `pnp`


### [7.3.1](https://github.com/webpack-contrib/sass-loader/compare/v7.3.0...v7.3.1) (2019-08-20)


### Bug Fixes

* minimum `node` version in `package.json` ([#733](https://github.com/webpack-contrib/sass-loader/issues/733)) ([1175920](https://github.com/webpack-contrib/sass-loader/commit/1175920))

## [7.3.0](https://github.com/webpack-contrib/sass-loader/compare/v7.2.0...v7.3.0) (2019-08-20)


### Bug Fixes

* handle module import ending `/` as module ([#728](https://github.com/webpack-contrib/sass-loader/issues/728)) ([997a255](https://github.com/webpack-contrib/sass-loader/commit/997a255))
* resolution algorithm ([#720](https://github.com/webpack-contrib/sass-loader/issues/720)) ([0e94940](https://github.com/webpack-contrib/sass-loader/commit/0e94940))
* use "compressed" output when mode is "production" ([#723](https://github.com/webpack-contrib/sass-loader/issues/723)) ([b2af379](https://github.com/webpack-contrib/sass-loader/commit/b2af379))


### Features

* `webpackImporter` option ([#732](https://github.com/webpack-contrib/sass-loader/issues/732)) ([6f4ea37](https://github.com/webpack-contrib/sass-loader/commit/6f4ea37))

<a name="7.2.0"></a>
# [7.2.0](https://github.com/webpack-contrib/sass-loader/compare/v7.1.0...v7.2.0) (2019-08-08)


### Bug Fixes

* better handle stdin in sources ([#681](https://github.com/webpack-contrib/sass-loader/issues/681)) ([e279f2a](https://github.com/webpack-contrib/sass-loader/commit/e279f2a))
* prefer `sass`/`scss`/`css` extensions ([#711](https://github.com/webpack-contrib/sass-loader/issues/711)) ([6fc9d4e](https://github.com/webpack-contrib/sass-loader/commit/6fc9d4e))
* relax node engine ([#708](https://github.com/webpack-contrib/sass-loader/issues/708)) ([2a51502](https://github.com/webpack-contrib/sass-loader/commit/2a51502))


### Features

* allow passing `functions` option as function ([#651](https://github.com/webpack-contrib/sass-loader/issues/651)) ([6c9654d](https://github.com/webpack-contrib/sass-loader/commit/6c9654d))
* support `data` as `Function` ([#648](https://github.com/webpack-contrib/sass-loader/issues/648)) ([aa64e1b](https://github.com/webpack-contrib/sass-loader/commit/aa64e1b))
* support `sass` and `style` fields in `package.json` ([#647](https://github.com/webpack-contrib/sass-loader/issues/647)) ([a8709c9](https://github.com/webpack-contrib/sass-loader/commit/a8709c9))
* support auto resolving `dart-sass` ([ff90dd6](https://github.com/webpack-contrib/sass-loader/commit/ff90dd6))



<a name="7.1.0"></a>
# [7.1.0](https://github.com/webpack-contrib/sass-loader/compare/v7.0.3...v7.1.0) (2018-08-01)


### Features

* Make this package implementation-agnostic (#573) ([bed9fb5](https://github.com/webpack-contrib/sass-loader/commit/bed9fb5)), closes [#435](https://github.com/webpack-contrib/sass-loader/issues/435)



<a name="7.0.3"></a>
## [7.0.3](https://github.com/webpack-contrib/sass-loader/compare/v7.0.2...v7.0.3) (2018-06-05)


### Bug Fixes

* Bare imports not working sometimes (#579) ([c348281](https://github.com/webpack-contrib/sass-loader/commit/c348281)), closes [#566](https://github.com/webpack-contrib/sass-loader/issues/566)



<a name="7.0.2"></a>
## [7.0.2](https://github.com/webpack-contrib/sass-loader/compare/v7.0.1...v7.0.2) (2018-06-02)


### Bug Fixes

* Errors being swallowed when trying to load node-sass (#576) ([6dfb274](https://github.com/webpack-contrib/sass-loader/commit/6dfb274)), closes [#563](https://github.com/webpack-contrib/sass-loader/issues/563)
* Report error to user for problems loading node-sass (#562) ([2529c07](https://github.com/webpack-contrib/sass-loader/commit/2529c07))



<a name="7.0.1"></a>
## [7.0.1](https://github.com/webpack-contrib/sass-loader/compare/v7.0.0...v7.0.1) (2018-04-13)

30 changes: 16 additions & 14 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
Copyright JS Foundation and other contributors

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:
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 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.
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.
703 changes: 547 additions & 156 deletions README.md

Large diffs are not rendered by default.

29 changes: 0 additions & 29 deletions appveyor.yml

This file was deleted.

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',
},
},
],
],
};
};
3 changes: 3 additions & 0 deletions commitlint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
extends: ['@commitlint/config-conventional'],
};
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',
},
};
3 changes: 3 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
testEnvironment: 'node',
};
73 changes: 0 additions & 73 deletions lib/formatSassError.js

This file was deleted.

60 changes: 0 additions & 60 deletions lib/importsToResolve.js

This file was deleted.

104 changes: 0 additions & 104 deletions lib/loader.js

This file was deleted.

78 changes: 0 additions & 78 deletions lib/normalizeOptions.js

This file was deleted.

29 changes: 0 additions & 29 deletions lib/proxyCustomImporters.js

This file was deleted.

72 changes: 0 additions & 72 deletions lib/webpackImporter.js

This file was deleted.

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'],
};
21,583 changes: 12,840 additions & 8,743 deletions package-lock.json

Large diffs are not rendered by default.

140 changes: 88 additions & 52 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,69 +1,105 @@
{
"name": "sass-loader",
"version": "7.0.1",
"version": "9.0.0",
"description": "Sass loader for webpack",
"author": "J. Tangelder",
"license": "MIT",
"main": "lib/loader.js",
"repository": "webpack-contrib/sass-loader",
"author": "J. Tangelder",
"homepage": "https://github.com/webpack-contrib/sass-loader",
"bugs": "https://github.com/webpack-contrib/sass-loader/issues",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"main": "dist/cjs.js",
"engines": {
"node": ">= 10.13.0"
},
"scripts": {
"start": "npm run build -- -w",
"clean": "del-cli dist",
"prebuild": "npm run clean",
"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:manual": "npm run build && webpack-dev-server test/manual/src/index.js --open --config test/manual/webpack.config.js",
"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",
"defaults": "webpack-defaults"
},
"files": [
"lib"
"dist"
],
"scripts": {
"appveyor:test": "npm test",
"create-spec": "node test/tools/runCreateSpec.js",
"lint": "eslint lib test",
"test": "nyc --all mocha -R spec -t 10000",
"test-bootstrap-sass": "webpack-dev-server --config test/bootstrapSass/webpack.config.js --content-base ./test/bootstrapSass",
"test-source-map": "webpack-dev-server --config test/sourceMap/webpack.config.js --content-base ./test/sourceMap --inline",
"test-watch": "webpack --config test/watch/webpack.config.js",
"test-extract-text": "webpack --config test/extractText/webpack.config.js",
"test-hmr": "webpack-dev-server --config test/hmr/webpack.config.js --content-base ./test/hmr --hot --inline",
"travis:lint": "npm run lint",
"travis:test": "npm run test",
"travis:coverage": "npm run test",
"pretest": "npm run create-spec",
"posttest": "npm run lint",
"release": "standard-version"
"peerDependencies": {
"webpack": "^4.36.0 || ^5.0.0",
"node-sass": "^4.0.0",
"sass": "^1.3.0",
"fibers": ">= 3.1.0"
},
"peerDependenciesMeta": {
"node-sass": {
"optional": true
},
"sass": {
"optional": true
},
"fibers": {
"optional": true
}
},
"dependencies": {
"clone-deep": "^2.0.1",
"loader-utils": "^1.0.1",
"lodash.tail": "^4.1.1",
"neo-async": "^2.5.0",
"pify": "^3.0.0"
"clone-deep": "^4.0.1",
"loader-utils": "^2.0.0",
"neo-async": "^2.6.1",
"schema-utils": "^2.7.0",
"semver": "^7.3.2"
},
"devDependencies": {
"bootstrap-sass": "^3.3.5",
"css-loader": "^0.28.4",
"eslint": "^3.16.0",
"eslint-config-peerigon": "^9.0.0",
"eslint-plugin-jsdoc": "^2.4.0",
"file-loader": "^0.11.2",
"mocha": "^3.0.2",
"mock-require": "^3.0.1",
"node-sass": "^4.5.0",
"nyc": "^11.0.2",
"raw-loader": "^0.5.1",
"should": "^11.2.0",
"standard-version": "^4.2.0",
"style-loader": "^0.18.2",
"webpack": "^4.5.0",
"webpack-dev-server": "^2.4.1",
"webpack-merge": "^4.0.0"
},
"engines": {
"node": ">= 6.9.0 || >= 8.9.0"
},
"peerDependencies": {
"webpack": "^3.0.0 || ^4.0.0"
"@babel/cli": "^7.10.3",
"@babel/core": "^7.10.3",
"@babel/preset-env": "^7.10.3",
"@commitlint/cli": "^9.0.1",
"@commitlint/config-conventional": "^9.0.1",
"@webpack-contrib/defaults": "^6.3.0",
"@webpack-contrib/eslint-config-webpack": "^3.0.0",
"babel-jest": "^26.0.1",
"bootstrap": "^4.5.0",
"bootstrap-sass": "^3.4.1",
"cross-env": "^7.0.2",
"css-loader": "^3.6.0",
"del": "^5.1.0",
"del-cli": "^3.0.1",
"eslint": "^7.3.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.21.2",
"fibers": "^5.0.0",
"file-loader": "^6.0.0",
"foundation-sites": "^6.6.3",
"husky": "^4.2.5",
"jest": "^26.0.1",
"lint-staged": "^10.2.11",
"material-components-web": "^7.0.0",
"memfs": "^3.2.0",
"node-sass": "^4.14.1",
"npm-run-all": "^4.1.5",
"prettier": "^2.0.5",
"sass": "^1.26.8",
"standard-version": "^8.0.0",
"style-loader": "^1.2.1",
"webpack": "^4.43.0"
},
"keywords": [
"sass",
"libsass",
"webpack",
"loader"
],
"repository": "https://github.com/webpack-contrib/sass-loader.git",
"bugs": "https://github.com/webpack-contrib/sass-loader/issues",
"homepage": "https://github.com/webpack-contrib/sass-loader"
]
}
30 changes: 30 additions & 0 deletions src/SassError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
class SassError extends Error {
constructor(sassError) {
super();

this.name = 'SassError';
this.originalSassError = sassError;
this.loc = {
line: sassError.line,
column: sassError.column,
};

// Keep original error if `sassError.formatted` is unavailable
this.message = `${this.name}: ${this.originalSassError.message}`;

if (this.originalSassError.formatted) {
this.message = `${this.name}: ${this.originalSassError.formatted.replace(
/^Error: /,
''
)}`;

// Instruct webpack to hide the JS stack from the console.
// Usually you're only interested in the SASS stack in this case.
this.hideStack = true;

Error.captureStackTrace(this, this.constructor);
}
}
}

export default SassError;
3 changes: 3 additions & 0 deletions src/cjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const loader = require('./index');

module.exports = loader.default;
82 changes: 82 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import path from 'path';

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

import schema from './options.json';
import {
getSassImplementation,
getSassOptions,
getWebpackImporter,
getRenderFunctionFromSassImplementation,
} from './utils';
import SassError from './SassError';

/**
* The sass-loader makes node-sass and dart-sass available to webpack modules.
*
* @this {object}
* @param {string} content
*/
function loader(content) {
const options = getOptions(this);

validateOptions(schema, options, {
name: 'Sass Loader',
baseDataPath: 'options',
});

const implementation = getSassImplementation(options.implementation);
const sassOptions = getSassOptions(this, options, content, implementation);

const shouldUseWebpackImporter =
typeof options.webpackImporter === 'boolean'
? options.webpackImporter
: true;

if (shouldUseWebpackImporter) {
const { includePaths } = sassOptions;

sassOptions.importer.push(getWebpackImporter(this, includePaths));
}

const callback = this.async();
const render = getRenderFunctionFromSassImplementation(implementation);

render(sassOptions, (error, result) => {
if (error) {
// `node-sass` returns POSIX paths
this.addDependency(path.normalize(error.file));

callback(new SassError(error));

return;
}

if (result.map) {
// eslint-disable-next-line no-param-reassign
result.map = JSON.parse(result.map);

// result.map.file is an optional property that provides the output filename.
// Since we don't know the final filename in the webpack build chain yet, it makes no sense to have it.
// eslint-disable-next-line no-param-reassign
delete result.map.file;

// node-sass returns POSIX paths, that's why we need to transform them back to native paths.
// This fixes an error on windows where the source-map module cannot resolve the source maps.
// @see https://github.com/webpack-contrib/sass-loader/issues/366#issuecomment-279460722
// eslint-disable-next-line no-param-reassign
result.map.sourceRoot = path.normalize(result.map.sourceRoot);
// eslint-disable-next-line no-param-reassign
result.map.sources = result.map.sources.map(path.normalize);
}

result.stats.includedFiles.forEach((includedFile) => {
this.addDependency(path.normalize(includedFile));
});

callback(null, result.css.toString(), result.map);
});
}

export default loader;
41 changes: 41 additions & 0 deletions src/options.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"type": "object",
"properties": {
"implementation": {
"description": "The implementation of the sass to be used (https://github.com/webpack-contrib/sass-loader#implementation).",
"type": "object"
},
"sassOptions": {
"description": "Options for `node-sass` or `sass` (`Dart Sass`) implementation. (https://github.com/webpack-contrib/sass-loader#implementation).",
"anyOf": [
{
"type": "object",
"additionalProperties": true
},
{
"instanceof": "Function"
}
]
},
"additionalData": {
"description": "Prepends/Appends `Sass`/`SCSS` code before the actual entry file (https://github.com/webpack-contrib/sass-loader#additionaldata).",
"anyOf": [
{
"type": "string"
},
{
"instanceof": "Function"
}
]
},
"sourceMap": {
"description": "Enables/Disables generation of source maps (https://github.com/webpack-contrib/sass-loader#sourcemap).",
"type": "boolean"
},
"webpackImporter": {
"description": "Enables/Disables default `webpack` importer (https://github.com/webpack-contrib/sass-loader#webpackimporter).",
"type": "boolean"
}
},
"additionalProperties": false
}
426 changes: 426 additions & 0 deletions src/utils.js

Large diffs are not rendered by default.

5 changes: 0 additions & 5 deletions test/.eslintrc.json

This file was deleted.

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

exports[`additionalData option should use same EOL on all os (dart-sass) (sass): css 1`] = `
"a {
color: hotpink;
}
body {
color: hotpink;
}"
`;

exports[`additionalData option should use same EOL on all os (dart-sass) (sass): errors 1`] = `Array []`;

exports[`additionalData option should use same EOL on all os (dart-sass) (sass): warnings 1`] = `Array []`;

exports[`additionalData option should use same EOL on all os (dart-sass) (scss): css 1`] = `
"a {
color: red;
}
body {
color: hotpink;
}"
`;

exports[`additionalData option should use same EOL on all os (dart-sass) (scss): errors 1`] = `Array []`;

exports[`additionalData option should use same EOL on all os (dart-sass) (scss): warnings 1`] = `Array []`;

exports[`additionalData option should use same EOL on all os (node-sass) (sass): css 1`] = `
"a {
color: hotpink; }
body {
color: hotpink; }
"
`;

exports[`additionalData option should use same EOL on all os (node-sass) (sass): errors 1`] = `Array []`;

exports[`additionalData option should use same EOL on all os (node-sass) (sass): warnings 1`] = `Array []`;

exports[`additionalData option should use same EOL on all os (node-sass) (scss): css 1`] = `
"a {
color: red; }
body {
color: hotpink; }
"
`;

exports[`additionalData option should use same EOL on all os (node-sass) (scss): errors 1`] = `Array []`;

exports[`additionalData option should use same EOL on all os (node-sass) (scss): warnings 1`] = `Array []`;

exports[`additionalData option should work with the "data" option as a function (dart-sass) (sass): css 1`] = `
"body {
color: hotpink;
}"
`;

exports[`additionalData option should work with the "data" option as a function (dart-sass) (sass): errors 1`] = `Array []`;

exports[`additionalData option should work with the "data" option as a function (dart-sass) (sass): warnings 1`] = `Array []`;

exports[`additionalData option should work with the "data" option as a function (dart-sass) (scss): css 1`] = `
"body {
color: hotpink;
}"
`;

exports[`additionalData option should work with the "data" option as a function (dart-sass) (scss): errors 1`] = `Array []`;

exports[`additionalData option should work with the "data" option as a function (dart-sass) (scss): warnings 1`] = `Array []`;

exports[`additionalData option should work with the "data" option as a function (node-sass) (sass): css 1`] = `
"body {
color: hotpink; }
"
`;

exports[`additionalData option should work with the "data" option as a function (node-sass) (sass): errors 1`] = `Array []`;

exports[`additionalData option should work with the "data" option as a function (node-sass) (sass): warnings 1`] = `Array []`;

exports[`additionalData option should work with the "data" option as a function (node-sass) (scss): css 1`] = `
"body {
color: hotpink; }
"
`;

exports[`additionalData option should work with the "data" option as a function (node-sass) (scss): errors 1`] = `Array []`;

exports[`additionalData option should work with the "data" option as a function (node-sass) (scss): warnings 1`] = `Array []`;

exports[`additionalData option should work with the "data" option as a string (dart-sass) (sass): css 1`] = `
"body {
color: hotpink;
}"
`;

exports[`additionalData option should work with the "data" option as a string (dart-sass) (sass): errors 1`] = `Array []`;

exports[`additionalData option should work with the "data" option as a string (dart-sass) (sass): warnings 1`] = `Array []`;

exports[`additionalData option should work with the "data" option as a string (dart-sass) (scss): css 1`] = `
"body {
color: hotpink;
}"
`;

exports[`additionalData option should work with the "data" option as a string (dart-sass) (scss): errors 1`] = `Array []`;

exports[`additionalData option should work with the "data" option as a string (dart-sass) (scss): warnings 1`] = `Array []`;

exports[`additionalData option should work with the "data" option as a string (node-sass) (sass): css 1`] = `
"body {
color: hotpink; }
"
`;

exports[`additionalData option should work with the "data" option as a string (node-sass) (sass): errors 1`] = `Array []`;

exports[`additionalData option should work with the "data" option as a string (node-sass) (sass): warnings 1`] = `Array []`;

exports[`additionalData option should work with the "data" option as a string (node-sass) (scss): css 1`] = `
"body {
color: hotpink; }
"
`;

exports[`additionalData option should work with the "data" option as a string (node-sass) (scss): errors 1`] = `Array []`;

exports[`additionalData option should work with the "data" option as a string (node-sass) (scss): warnings 1`] = `Array []`;
60 changes: 60 additions & 0 deletions test/__snapshots__/implementation-option.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`implementation option dart-sass: errors 1`] = `Array []`;

exports[`implementation option dart-sass: warnings 1`] = `Array []`;

exports[`implementation option node-sass: errors 1`] = `Array []`;

exports[`implementation option node-sass: warnings 1`] = `Array []`;

exports[`implementation option not specify: errors 1`] = `Array []`;

exports[`implementation option not specify: warnings 1`] = `Array []`;

exports[`implementation option should not swallow an error when trying to load a sass implementation 1`] = `
[Error: Module build failed (from ../src/cjs.js):
Some error]
`;

exports[`implementation option should throw an error on an unknown sass implementation 1`] = `
[Error: Module build failed (from ../src/cjs.js):
Error: Unknown Sass implementation "strange-sass".
at ReplacedStackEntry
at ReplacedStackEntry]
`;

exports[`implementation option should throw an error when the "info" is unparseable #2 1`] = `
[Error: Module build failed (from ../src/cjs.js):
Error: Node Sass version 1 is incompatible with ^4.0.0.
at ReplacedStackEntry
at ReplacedStackEntry]
`;

exports[`implementation option should throw an error when the "info" is unparseable 1`] = `
[Error: Module build failed (from ../src/cjs.js):
Error: Unknown Sass implementation "asdfj".
at ReplacedStackEntry
at ReplacedStackEntry]
`;

exports[`implementation option should throw an error when the "node-sass" package is an incompatible version 1`] = `
[Error: Module build failed (from ../src/cjs.js):
Error: Node Sass version 3.0.0 is incompatible with ^4.0.0.
at ReplacedStackEntry
at ReplacedStackEntry]
`;

exports[`implementation option should throw an error when the "sass" package is an incompatible version 1`] = `
[Error: Module build failed (from ../src/cjs.js):
Error: Dart Sass version 1.2.0 is incompatible with ^1.3.0.
at ReplacedStackEntry
at ReplacedStackEntry]
`;

exports[`implementation option should throw error when the "info" does not exist 1`] = `
[Error: Module build failed (from ../src/cjs.js):
Error: Unknown Sass implementation.
at ReplacedStackEntry
at ReplacedStackEntry]
`;
165,163 changes: 165,163 additions & 0 deletions test/__snapshots__/loader.test.js.snap

Large diffs are not rendered by default.

2,863 changes: 2,863 additions & 0 deletions test/__snapshots__/sassOptions-option.test.js.snap

Large diffs are not rendered by default.

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

exports[`sourceMap option should generate source maps when value has "true" value and the "devtool" option has "false" value (dart-sass) (sass): errors 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value has "true" value and the "devtool" option has "false" value (dart-sass) (sass): warnings 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value has "true" value and the "devtool" option has "false" value (dart-sass) (scss): errors 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value has "true" value and the "devtool" option has "false" value (dart-sass) (scss): warnings 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value has "true" value and the "devtool" option has "false" value (node-sass) (sass): errors 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value has "true" value and the "devtool" option has "false" value (node-sass) (sass): warnings 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value has "true" value and the "devtool" option has "false" value (node-sass) (scss): errors 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value has "true" value and the "devtool" option has "false" value (node-sass) (scss): warnings 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value has "true" value and the "devtool" option has "source-map" value (dart-sass) (sass): errors 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value has "true" value and the "devtool" option has "source-map" value (dart-sass) (sass): warnings 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value has "true" value and the "devtool" option has "source-map" value (dart-sass) (scss): errors 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value has "true" value and the "devtool" option has "source-map" value (dart-sass) (scss): warnings 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value has "true" value and the "devtool" option has "source-map" value (node-sass) (sass): errors 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value has "true" value and the "devtool" option has "source-map" value (node-sass) (sass): warnings 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value has "true" value and the "devtool" option has "source-map" value (node-sass) (scss): errors 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value has "true" value and the "devtool" option has "source-map" value (node-sass) (scss): warnings 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value is not specified and the "devtool" option has "source-map" value (dart-sass) (sass): errors 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value is not specified and the "devtool" option has "source-map" value (dart-sass) (sass): warnings 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value is not specified and the "devtool" option has "source-map" value (dart-sass) (scss): errors 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value is not specified and the "devtool" option has "source-map" value (dart-sass) (scss): warnings 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value is not specified and the "devtool" option has "source-map" value (node-sass) (sass): errors 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value is not specified and the "devtool" option has "source-map" value (node-sass) (sass): warnings 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value is not specified and the "devtool" option has "source-map" value (node-sass) (scss): errors 1`] = `Array []`;

exports[`sourceMap option should generate source maps when value is not specified and the "devtool" option has "source-map" value (node-sass) (scss): warnings 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value has "false" value and the "devtool" option has "false" value (dart-sass) (sass): errors 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value has "false" value and the "devtool" option has "false" value (dart-sass) (sass): warnings 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value has "false" value and the "devtool" option has "false" value (dart-sass) (scss): errors 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value has "false" value and the "devtool" option has "false" value (dart-sass) (scss): warnings 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value has "false" value and the "devtool" option has "false" value (node-sass) (sass): errors 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value has "false" value and the "devtool" option has "false" value (node-sass) (sass): warnings 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value has "false" value and the "devtool" option has "false" value (node-sass) (scss): errors 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value has "false" value and the "devtool" option has "false" value (node-sass) (scss): warnings 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value has "false" value and the "devtool" option has "source-map" value (dart-sass) (sass): errors 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value has "false" value and the "devtool" option has "source-map" value (dart-sass) (sass): warnings 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value has "false" value and the "devtool" option has "source-map" value (dart-sass) (scss): errors 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value has "false" value and the "devtool" option has "source-map" value (dart-sass) (scss): warnings 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value has "false" value and the "devtool" option has "source-map" value (node-sass) (sass): errors 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value has "false" value and the "devtool" option has "source-map" value (node-sass) (sass): warnings 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value has "false" value and the "devtool" option has "source-map" value (node-sass) (scss): errors 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value has "false" value and the "devtool" option has "source-map" value (node-sass) (scss): warnings 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value is not specified and the "devtool" option has "false" value (dart-sass) (sass): errors 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value is not specified and the "devtool" option has "false" value (dart-sass) (sass): warnings 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value is not specified and the "devtool" option has "false" value (dart-sass) (scss): errors 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value is not specified and the "devtool" option has "false" value (dart-sass) (scss): warnings 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value is not specified and the "devtool" option has "false" value (node-sass) (sass): errors 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value is not specified and the "devtool" option has "false" value (node-sass) (sass): warnings 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value is not specified and the "devtool" option has "false" value (node-sass) (scss): errors 1`] = `Array []`;

exports[`sourceMap option should not generate source maps when value is not specified and the "devtool" option has "false" value (node-sass) (scss): warnings 1`] = `Array []`;
107 changes: 107 additions & 0 deletions test/__snapshots__/validate-options.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`validate options should throw an error on the "additionalData" option with "true" value 1`] = `
"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
- options.additionalData should be one of these:
string | function
-> Prepends/Appends \`Sass\`/\`SCSS\` code before the actual entry file (https://github.com/webpack-contrib/sass-loader#additionaldata).
Details:
* options.additionalData should be a string.
* options.additionalData should be an instance of function."
`;

exports[`validate options should throw an error on the "implementation" option with "string" value 1`] = `
"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
- options.implementation should be an object:
object {}
-> The implementation of the sass to be used (https://github.com/webpack-contrib/sass-loader#implementation)."
`;

exports[`validate options should throw an error on the "implementation" option with "true" value 1`] = `
"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
- options.implementation should be an object:
object {}
-> The implementation of the sass to be used (https://github.com/webpack-contrib/sass-loader#implementation)."
`;

exports[`validate options should throw an error on the "sassOptions" option with "string" value 1`] = `
"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
- options.sassOptions should be one of these:
object {} | function
-> Options for \`node-sass\` or \`sass\` (\`Dart Sass\`) implementation. (https://github.com/webpack-contrib/sass-loader#implementation).
Details:
* options.sassOptions should be an object:
object {}
* options.sassOptions should be an instance of function."
`;

exports[`validate options should throw an error on the "sassOptions" option with "true" value 1`] = `
"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
- options.sassOptions should be one of these:
object {} | function
-> Options for \`node-sass\` or \`sass\` (\`Dart Sass\`) implementation. (https://github.com/webpack-contrib/sass-loader#implementation).
Details:
* options.sassOptions should be an object:
object {}
* options.sassOptions should be an instance of function."
`;

exports[`validate options should throw an error on the "sourceMap" option with "string" value 1`] = `
"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
- options.sourceMap should be a boolean.
-> Enables/Disables generation of source maps (https://github.com/webpack-contrib/sass-loader#sourcemap)."
`;

exports[`validate options should throw an error on the "unknown" option with "/test/" value 1`] = `
"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
- options has an unknown property 'unknown'. These properties are valid:
object { implementation?, sassOptions?, additionalData?, sourceMap?, webpackImporter? }"
`;
exports[`validate options should throw an error on the "unknown" option with "[]" value 1`] = `
"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
- options has an unknown property 'unknown'. These properties are valid:
object { implementation?, sassOptions?, additionalData?, sourceMap?, webpackImporter? }"
`;
exports[`validate options should throw an error on the "unknown" option with "{"foo":"bar"}" value 1`] = `
"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
- options has an unknown property 'unknown'. These properties are valid:
object { implementation?, sassOptions?, additionalData?, sourceMap?, webpackImporter? }"
`;
exports[`validate options should throw an error on the "unknown" option with "{}" value 1`] = `
"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
- options has an unknown property 'unknown'. These properties are valid:
object { implementation?, sassOptions?, additionalData?, sourceMap?, webpackImporter? }"
`;
exports[`validate options should throw an error on the "unknown" option with "1" value 1`] = `
"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
- options has an unknown property 'unknown'. These properties are valid:
object { implementation?, sassOptions?, additionalData?, sourceMap?, webpackImporter? }"
`;
exports[`validate options should throw an error on the "unknown" option with "false" value 1`] = `
"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
- options has an unknown property 'unknown'. These properties are valid:
object { implementation?, sassOptions?, additionalData?, sourceMap?, webpackImporter? }"
`;
exports[`validate options should throw an error on the "unknown" option with "test" value 1`] = `
"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
- options has an unknown property 'unknown'. These properties are valid:
object { implementation?, sassOptions?, additionalData?, sourceMap?, webpackImporter? }"
`;
exports[`validate options should throw an error on the "unknown" option with "true" value 1`] = `
"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
- options has an unknown property 'unknown'. These properties are valid:
object { implementation?, sassOptions?, additionalData?, sourceMap?, webpackImporter? }"
`;
exports[`validate options should throw an error on the "webpackImporter" option with "string" value 1`] = `
"Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
- options.webpackImporter should be a boolean.
-> Enables/Disables default \`webpack\` importer (https://github.com/webpack-contrib/sass-loader#webpackimporter)."
`;
565 changes: 565 additions & 0 deletions test/__snapshots__/webpackImporter-options.test.js.snap

Large diffs are not rendered by default.

97 changes: 97 additions & 0 deletions test/additionalData-option.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import nodeSass from 'node-sass';
import dartSass from 'sass';
import Fiber from 'fibers';

import {
compile,
getCodeFromBundle,
getCodeFromSass,
getCompiler,
getErrors,
getImplementationByName,
getTestId,
getWarnings,
} from './helpers';

const implementations = [nodeSass, dartSass];
const syntaxStyles = ['scss', 'sass'];

describe('additionalData option', () => {
beforeEach(() => {
// The `sass` (`Dart Sass`) package modify the `Function` prototype, but the `jest` lose a prototype
Object.setPrototypeOf(Fiber, Function.prototype);
});

implementations.forEach((implementation) => {
const [implementationName] = implementation.info.split('\t');

syntaxStyles.forEach((syntax) => {
it(`should work with the "data" option as a string (${implementationName}) (${syntax})`, async () => {
const testId = getTestId('prepending-data', syntax);
const options = {
implementation: getImplementationByName(implementationName),
additionalData: `$prepended-data: hotpink${
syntax === 'sass' ? '\n' : ';'
}`,
};
const compiler = getCompiler(testId, { loader: { options } });
const stats = await compile(compiler);
const codeFromBundle = getCodeFromBundle(stats, compiler);
const codeFromSass = getCodeFromSass(testId, options);

expect(codeFromBundle.css).toBe(codeFromSass.css);
expect(codeFromBundle.css).toMatchSnapshot('css');
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});

it(`should work with the "data" option as a function (${implementationName}) (${syntax})`, async () => {
const testId = getTestId('prepending-data', syntax);
const options = {
implementation: getImplementationByName(implementationName),
additionalData: (content, loaderContext) => {
expect(loaderContext).toBeDefined();
expect(content).toBeDefined();

return `$prepended-data: hotpink${
syntax === 'sass' ? '\n' : ';\n'
}${content}`;
},
};
const compiler = getCompiler(testId, { loader: { options } });
const stats = await compile(compiler);
const codeFromBundle = getCodeFromBundle(stats, compiler);
const codeFromSass = getCodeFromSass(testId, options);

expect(codeFromBundle.css).toBe(codeFromSass.css);
expect(codeFromBundle.css).toMatchSnapshot('css');
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});

it(`should use same EOL on all os (${implementationName}) (${syntax})`, async () => {
const testId = getTestId('prepending-data', syntax);
const additionalData =
syntax === 'sass'
? `$prepended-data: hotpink
a
color: $prepended-data`
: `$prepended-data: hotpink;
a {
color: red;
}`;
const options = {
implementation: getImplementationByName(implementationName),
additionalData,
};
const compiler = getCompiler(testId, { loader: { options } });
const stats = await compile(compiler);
const codeFromBundle = getCodeFromBundle(stats, compiler);

expect(codeFromBundle.css).toMatchSnapshot('css');
expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');
});
});
});
});
2,009 changes: 0 additions & 2,009 deletions test/bootstrapSass/index.html

This file was deleted.

35 changes: 0 additions & 35 deletions test/bootstrapSass/webpack.config.js

This file was deleted.

8 changes: 8 additions & 0 deletions test/cjs.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import src from '../src';
import cjs from '../src/cjs';

describe('cjs', () => {
it('should exported', () => {
expect(cjs).toEqual(src);
});
});
34 changes: 0 additions & 34 deletions test/extractText/webpack.config.js

This file was deleted.

11 changes: 11 additions & 0 deletions test/helpers/compiler.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);
});
});
};
16 changes: 16 additions & 0 deletions test/helpers/customFunctions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export default (implementation) => {
return {
'headings($from: 0, $to: 6)': (from, to) => {
const f = from.getValue();
const t = to.getValue();
const list = new implementation.types.List(t - f + 1);
let i;

for (i = f; i <= t; i++) {
list.setValue(i - f, new implementation.types.String(`h${i}`));
}

return list;
},
};
};
20 changes: 20 additions & 0 deletions test/helpers/customImporter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
function customImporter(url, prev, done) {
expect(url).toBe('import-with-custom-logic');
expect(prev).toMatch(/(sass|scss)[/\\]custom-importer\.(scss|sass)/);
expect(this.options).toBeDefined();

if (done) {
done(customImporter.returnValue);

return;
}

// eslint-disable-next-line consistent-return
return customImporter.returnValue;
}

customImporter.returnValue = {
contents: '.custom-imported {}',
};

export default customImporter;
31 changes: 31 additions & 0 deletions test/helpers/getCodeFromBundle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import vm from 'vm';

import readAsset from './readAsset';

function getCodeFromBundle(stats, compiler, asset) {
let code = null;

if (
stats &&
stats.compilation &&
stats.compilation.assets &&
stats.compilation.assets[asset || 'main.bundle.js']
) {
code = readAsset(asset || 'main.bundle.js', compiler, stats);
}

if (!code) {
throw new Error("Can't find compiled code");
}

const result = vm.runInNewContext(
`${code};\nmodule.exports = sassLoaderExport;`,
{
module: {},
}
);

return result.default;
}

export default getCodeFromBundle;
759 changes: 759 additions & 0 deletions test/helpers/getCodeFromSass.js

Large diffs are not rendered by default.

77 changes: 77 additions & 0 deletions test/helpers/getCompiler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import path from 'path';

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

const module = (config) => {
return {
rules: config.rules
? config.rules
: [
{
test: (config.loader && config.loader.test) || /\.s[ac]ss$/i,
resolve: config.loader.resolve,
use: [
{
loader: require.resolve('./testLoader'),
},
{
loader: path.join(__dirname, '../../src/cjs.js'),
options: (config.loader && config.loader.options) || {},
},
],
},
],
};
};

const plugins = (config) => [].concat(config.plugins || []);

const output = (config) => {
return {
path: path.resolve(
__dirname,
`../outputs/${config.output ? config.output : ''}`
),
filename: '[name].bundle.js',
library: 'sassLoaderExport',
};
};

export default function getCompiler(fixture, config = {}, options = {}) {
// webpack Config
// eslint-disable-next-line no-param-reassign
config = {
mode: config.mode || 'development',
devtool: config.devtool || false,
// context: path.resolve(__dirname, '..', 'fixtures'),
context: path.resolve(__dirname, '..'),
entry: config.entry || `./${fixture}`,
output: output(config),
module: module(config),
plugins: plugins(config),
optimization: {
runtimeChunk: false,
minimizer: [],
},
// eslint-disable-next-line no-undefined
resolve: config.resolve || undefined,
};
// Compiler Options
// eslint-disable-next-line no-param-reassign
options = Object.assign({ output: false }, options);

if (options.output) {
del.sync(config.output.path);
}

const compiler = webpack(config);

if (!options.output) {
compiler.outputFileSystem = createFsFromVolume(new Volume());
compiler.outputFileSystem.join = path.join.bind(path);
}

return compiler;
}
5 changes: 5 additions & 0 deletions test/helpers/getErrors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import normalizeErrors from './normalizeErrors';

export default (stats) => {
return normalizeErrors(stats.compilation.errors.sort());
};
13 changes: 13 additions & 0 deletions test/helpers/getImplementationByName.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
function getImplementationByName(implementationName) {
if (implementationName === 'node-sass') {
// eslint-disable-next-line global-require
return require('node-sass');
} else if (implementationName === 'dart-sass') {
// eslint-disable-next-line global-require
return require('sass');
}

throw new Error(`Can't find ${implementationName}`);
}

export default getImplementationByName;
5 changes: 5 additions & 0 deletions test/helpers/getTestId.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
function getTestId(testId, syntax) {
return `${syntax}/${testId}.${syntax}`;
}

export default getTestId;
5 changes: 5 additions & 0 deletions test/helpers/getWarnings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import normalizeErrors from './normalizeErrors';

export default (stats) => {
return normalizeErrors(stats.compilation.warnings.sort());
};
27 changes: 27 additions & 0 deletions test/helpers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import compile from './compiler';
import customFunctions from './customFunctions';
import customImporter from './customImporter';
import getCodeFromBundle from './getCodeFromBundle';
import getCodeFromSass from './getCodeFromSass';
import getCompiler from './getCompiler';
import getErrors from './getErrors';
import getImplementationByName from './getImplementationByName';
import getTestId from './getTestId';
import getWarnings from './getWarnings';
import normalizeImplementationError from './normalizeImplementationError';
import readAsset from './readAsset';

export {
compile,
customFunctions,
customImporter,
getCodeFromBundle,
getCodeFromSass,
getCompiler,
getErrors,
getImplementationByName,
getTestId,
getWarnings,
normalizeImplementationError,
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'))
);
};
17 changes: 17 additions & 0 deletions test/helpers/normalizeImplementationError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import path from 'path';

function normalizeImplementationError(error) {
// eslint-disable-next-line no-param-reassign
error.message = error.message.replace(/\sat.*/g, ' at ReplacedStackEntry');
// eslint-disable-next-line no-param-reassign
error.message = error.message.replace(/\\/g, '/');
// eslint-disable-next-line no-param-reassign
error.message = error.message.replace(
new RegExp(path.resolve(__dirname, '..').replace(/\\/g, '/'), 'g'),
'/absolute/path/to'
);

return error;
}

export default normalizeImplementationError;
23 changes: 23 additions & 0 deletions test/helpers/readAsset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import path from 'path';

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

let data = '';
let targetFile = asset;

const queryStringIdx = targetFile.indexOf('?');

if (queryStringIdx >= 0) {
targetFile = targetFile.substr(0, queryStringIdx);
}

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

return data;
};
13 changes: 13 additions & 0 deletions test/helpers/testLoader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';

function testLoader(content, sourceMap) {
const result = { css: content };

if (sourceMap) {
result.sourceMap = sourceMap;
}

return `export default ${JSON.stringify(result)}`;
}

module.exports = testLoader;
3 changes: 0 additions & 3 deletions test/hmr/README.md

This file was deleted.

9 changes: 0 additions & 9 deletions test/hmr/entry.js

This file was deleted.

11 changes: 0 additions & 11 deletions test/hmr/index.html

This file was deleted.

7 changes: 0 additions & 7 deletions test/hmr/simple.scss

This file was deleted.

24 changes: 0 additions & 24 deletions test/hmr/webpack.config.js

This file was deleted.

219 changes: 219 additions & 0 deletions test/implementation-option.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
import nodeSass from 'node-sass';
import dartSass from 'sass';
import Fiber from 'fibers';

import {
compile,
getCodeFromBundle,
getCompiler,
getErrors,
getImplementationByName,
getTestId,
getWarnings,
normalizeImplementationError,
} from './helpers';

const implementations = [nodeSass, dartSass];

jest.setTimeout(30000);

describe('implementation option', () => {
beforeEach(() => {
// The `sass` (`Dart Sass`) package modify the `Function` prototype, but the `jest` lose a prototype
Object.setPrototypeOf(Fiber, Function.prototype);
jest.clearAllMocks();
});

implementations.forEach((implementation) => {
const [implementationName] = implementation.info.split('\t');

it(`${implementationName}`, async () => {
const nodeSassSpy = jest.spyOn(nodeSass, 'render');
const dartSassSpy = jest.spyOn(dartSass, 'render');

const testId = getTestId('language', 'scss');
const options = {
implementation: getImplementationByName(implementationName),
};
const compiler = getCompiler(testId, { loader: { options } });
const stats = await compile(compiler);
const { css, sourceMap } = getCodeFromBundle(stats, compiler);

expect(css).toBeDefined();
expect(sourceMap).toBeUndefined();

expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');

if (implementationName === 'node-sass') {
expect(nodeSassSpy).toHaveBeenCalledTimes(1);
expect(dartSassSpy).toHaveBeenCalledTimes(0);
} else if (implementationName === 'dart-sass') {
expect(nodeSassSpy).toHaveBeenCalledTimes(0);
expect(dartSassSpy).toHaveBeenCalledTimes(1);
}
});
});

it('not specify', async () => {
const nodeSassSpy = jest.spyOn(nodeSass, 'render');
const dartSassSpy = jest.spyOn(dartSass, 'render');

const testId = getTestId('language', 'scss');
const options = {};
const compiler = getCompiler(testId, { loader: { options } });
const stats = await compile(compiler);
const { css, sourceMap } = getCodeFromBundle(stats, compiler);

expect(css).toBeDefined();
expect(sourceMap).toBeUndefined();

expect(getWarnings(stats)).toMatchSnapshot('warnings');
expect(getErrors(stats)).toMatchSnapshot('errors');

expect(nodeSassSpy).toHaveBeenCalledTimes(0);
expect(dartSassSpy).toHaveBeenCalledTimes(1);
});

it('should throw an error when the "node-sass" package is an incompatible version', async () => {
const testId = getTestId('language', 'scss');
const options = {
implementation: Object.assign({}, nodeSass, {
info: 'node-sass\t3.0.0',
}),
};

const compiler = getCompiler(testId, { loader: { options } });

try {
const stats = await compile(compiler);

getCodeFromBundle(stats, compiler);
} catch (error) {
expect(normalizeImplementationError(error)).toMatchSnapshot();
}
});

it('should throw an error when the "sass" package is an incompatible version', async () => {
const testId = getTestId('language', 'scss');
const options = {
implementation: Object.assign({}, dartSass, {
info: 'dart-sass\t1.2.0',
}),
};

const compiler = getCompiler(testId, { loader: { options } });

try {
const stats = await compile(compiler);

getCodeFromBundle(stats, compiler);
} catch (error) {
expect(normalizeImplementationError(error)).toMatchSnapshot();
}
});

it('should throw an error on an unknown sass implementation', async () => {
const testId = getTestId('language', 'scss');
const options = {
implementation: Object.assign({}, dartSass, {
info: 'strange-sass\t1.0.0',
}),
};

const compiler = getCompiler(testId, { loader: { options } });

try {
const stats = await compile(compiler);

getCodeFromBundle(stats, compiler);
} catch (error) {
expect(normalizeImplementationError(error)).toMatchSnapshot();
}
});

it('should throw an error when the "info" is unparseable', async () => {
const testId = getTestId('language', 'scss');
const options = {
implementation: Object.assign({}, dartSass, { info: 'asdfj' }),
};

const compiler = getCompiler(testId, { loader: { options } });

try {
const stats = await compile(compiler);

getCodeFromBundle(stats, compiler);
} catch (error) {
expect(normalizeImplementationError(error)).toMatchSnapshot();
}
});

it('should throw an error when the "info" is unparseable #2', async () => {
const testId = getTestId('language', 'scss');
const options = {
implementation: Object.assign({}, nodeSass, { info: 'node-sass\t1' }),
};

const compiler = getCompiler(testId, { loader: { options } });

try {
const stats = await compile(compiler);

getCodeFromBundle(stats, compiler);
} catch (error) {
expect(normalizeImplementationError(error)).toMatchSnapshot();
}
});

it('should throw error when the "info" does not exist', async () => {
const testId = getTestId('language', 'scss');
const options = {
// eslint-disable-next-line no-undefined
implementation: Object.assign({}, dartSass, { info: undefined }),
};

const compiler = getCompiler(testId, { loader: { options } });

try {
const stats = await compile(compiler);

getCodeFromBundle(stats, compiler);
} catch (error) {
expect(normalizeImplementationError(error)).toMatchSnapshot();
}
});

it('should not swallow an error when trying to load a sass implementation', async () => {
jest.doMock('node-sass', () => {
const error = new Error('Some error');

error.code = 'MODULE_NOT_FOUND';
error.stack = null;

throw error;
});

jest.doMock('sass', () => {
const error = new Error('Some error');

error.code = 'MODULE_NOT_FOUND';
error.stack = null;

throw error;
});

const testId = getTestId('language', 'scss');
const options = {};

const compiler = getCompiler(testId, { loader: { options } });

try {
const stats = await compile(compiler);

getCodeFromBundle(stats, compiler);
} catch (error) {
expect(error).toMatchSnapshot();
}
});
});
333 changes: 0 additions & 333 deletions test/index.test.js

This file was deleted.

Loading