├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .gitattributes
├── .github
├── CODEOWNERS
├── CONTRIBUTING.md
├── FUNDING.yml
├── ISSUE_TEMPLATE.md
├── ISSUE_TEMPLATE
│ ├── BUG.md
│ ├── DOCS.md
│ ├── FEATURE.md
│ ├── MODIFICATION.md
│ └── SUPPORT.md
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ └── nodejs.yml
├── .gitignore
├── .prettierignore
├── .prettierrc.js
├── CHANGELOG.md
├── LICENSE
├── README.md
├── babel.config.js
├── commitlint.config.js
├── husky.config.js
├── jest.config.js
├── lint-staged.config.js
├── package-lock.json
├── package.json
├── src
├── ESLintError.js
├── Linter.js
├── cache.js
├── cacheLoader.js
├── cjs.js
├── createEngine.js
├── getOptions.js
├── index.js
└── options.json
└── test
├── Linter.test.js
├── autofix-stop.test.js
├── autofix.test.js
├── cache.test.js
├── cjs.test.js
├── error.test.js
├── eslint-path.test.js
├── eslintignore.test.js
├── fail-on-error.test.js
├── fail-on-warning.test.js
├── fixtures
├── cache.js
├── error-multi-one.js
├── error-multi-two.js
├── error-multi.js
├── error.js
├── fixable.js
├── good-semi.js
├── good.js
├── ignore.js
├── nonfixable.js
├── require.js
└── warn.js
├── force-emit-error.test.js
├── force-emit-warning.test.js
├── formatter-custom.test.js
├── formatter-eslint.test.js
├── formatter-multiple-entries.test.js
├── formatter-official.test.js
├── formatter-write.test.js
├── mock
└── eslint
│ ├── index.js
│ ├── lib
│ ├── cli-engine
│ │ └── formatters
│ │ │ └── stylish.js
│ └── formatters
│ │ └── stylish.js
│ └── package.json
├── multiple-engines.test.js
├── no-eslint-configuration.test.js
├── ok.test.js
├── parameters.test.js
├── quiet.test.js
├── utils
├── conf.js
└── pack.js
└── warning.test.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | /coverage
2 | /dist
3 | /node_modules
4 | /test/fixtures
5 | /test/output
6 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ['@webpack-contrib/eslint-config-webpack', 'prettier'],
4 | rules: {
5 | 'global-require': 'off',
6 | 'import/no-dynamic-require': 'off',
7 | },
8 | };
9 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | bin/* eol=lf
3 | package-lock.json -diff
4 | yarn.lock -diff
5 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # These are the default owners for everything in
2 | # webpack-contrib
3 | @webpack-contrib/org-maintainers
4 |
5 | # Add repository specific users / groups
6 | # below here for libs that are not maintained by the org.
7 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing in @webpack-contrib
2 |
3 | We'd always love contributions to further improve the webpack / webpack-contrib ecosystem!
4 | Here are the guidelines we'd like you to follow:
5 |
6 | - [Questions and Problems](#question)
7 | - [Issues and Bugs](#issue)
8 | - [Feature Requests](#feature)
9 | - [Pull Request Submission Guidelines](#submit-pr)
10 | - [Commit Message Conventions](#commit)
11 |
12 | ## Got a Question or Problem?
13 |
14 | Please submit support requests and questions to StackOverflow using the tag [[webpack]](http://stackoverflow.com/tags/webpack).
15 | StackOverflow is better suited for this kind of support though you may also inquire in [Webpack Gitter](https://gitter.im/webpack/webpack).
16 | The issue tracker is for bug reports and feature discussions.
17 |
18 | ## Found an Issue or Bug?
19 |
20 | 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.
21 |
22 | 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:
23 |
24 | - version of Webpack used
25 | - version of the loader / plugin you are creating a bug report for
26 | - the use-case that fails
27 |
28 | 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.
29 |
30 | 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.
31 |
32 | 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.
33 |
34 | ## Feature Requests?
35 |
36 | You can _request_ a new feature by creating an issue on Github.
37 |
38 | 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.
39 |
40 | ## Pull Request Submission Guidelines
41 |
42 | Before you submit your Pull Request (PR) consider the following guidelines:
43 |
44 | - Search Github for an open or closed PR that relates to your submission. You don't want to duplicate effort.
45 | - 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.
46 | - Fill out our `Pull Request Template`. Your pull request will not be considered if it is ignored.
47 | - 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.
48 |
49 | ## Webpack Contrib Commit Conventions
50 |
51 | Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
52 | format that includes a **type**, a **scope** and a **subject**:
53 |
54 | ```
55 | ():
56 |
57 |
58 |
59 |
60 | ```
61 |
62 | The **header** is mandatory and the **scope** of the header is optional.
63 |
64 | Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
65 | to read on GitHub as well as in various git tools.
66 |
67 | The footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
68 |
69 | Examples:
70 |
71 | ```
72 | docs(readme): update install instructions
73 | ```
74 |
75 | ```
76 | fix: refer to the `entrypoint` instead of the first `module`
77 | ```
78 |
79 | ### Revert
80 |
81 | If the commit reverts a previous commit, it should begin with `revert:`, followed by the header of the reverted commit.
82 | In the body it should say: `This reverts commit .`, where the hash is the SHA of the commit being reverted.
83 |
84 | ### Type
85 |
86 | Must be one of the following:
87 |
88 | - **build**: Changes that affect the build system or external dependencies (example scopes: babel, npm)
89 | - **chore**: Changes that fall outside of build / docs that do not effect source code (example scopes: package, defaults)
90 | - **ci**: Changes to our CI configuration files and scripts (example scopes: circleci, travis)
91 | - **docs**: Documentation only changes (example scopes: readme, changelog)
92 | - **feat**: A new feature
93 | - **fix**: A bug fix
94 | - **perf**: A code change that improves performance
95 | - **refactor**: A code change that neither fixes a bug nor adds a feature
96 | - **revert**: Used when reverting a committed change
97 | - **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons)
98 | - **test**: Addition of or updates to Jest tests
99 |
100 | ### Scope
101 |
102 | The scope is subjective & depends on the `type` see above. A good example would be a change to a particular class / module.
103 |
104 | ### Subject
105 |
106 | The subject contains a succinct description of the change:
107 |
108 | - use the imperative, present tense: "change" not "changed" nor "changes"
109 | - don't capitalize the first letter
110 | - no dot (.) at the end
111 |
112 | ### Body
113 |
114 | Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
115 | The body should include the motivation for the change and contrast this with previous behavior.
116 |
117 | ### Footer
118 |
119 | The footer should contain any information about **Breaking Changes** and is also the place to
120 | reference GitHub issues that this commit **Closes**.
121 |
122 | **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.
123 |
124 | Example
125 |
126 | ```
127 | BREAKING CHANGE: Updates to `Chunk.mapModules`.
128 |
129 | This release is not backwards compatible with `Webpack 2.x` due to breaking changes in webpack/webpack#4764
130 | Migration: see webpack/webpack#5225
131 |
132 | ```
133 |
134 | ## Testing Your Pull Request
135 |
136 | You may have the need to test your changes in a real-world project or dependent
137 | module. Thankfully, Github provides a means to do this. Add a dependency to the
138 | `package.json` for such a project as follows:
139 |
140 | ```json
141 | {
142 | "devDependencies": {
143 | "eslint-loader": "webpack-contrib/eslint-loader#{id}/head"
144 | }
145 | }
146 | ```
147 |
148 | Where `{id}` is the # ID of your Pull Request.
149 |
150 | ## Contributor License Agreement
151 |
152 | 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/eslint-loader).
153 | If it is your first time, it will link you to the right place to sign it.
154 | 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.
155 |
156 | Run `git config user.email` to see your Git email, and verify it with [your GitHub email](https://github.com/settings/emails).
157 |
158 | ## Thanks
159 |
160 | For your interest, time, understanding, and for following this simple guide.
161 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | open_collective: webpack
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/BUG.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🐛 Bug Report
3 | about: Something went awry and you'd like to tell us about it.
4 | ---
5 |
6 |
16 |
17 | - Operating System:
18 | - Node Version:
19 | - NPM Version:
20 | - webpack Version:
21 | - eslint-loader Version:
22 |
23 | ### Expected Behavior
24 |
25 |
26 |
27 | ### Actual Behavior
28 |
29 |
30 |
31 | ### Code
32 |
33 | ```js
34 | // webpack.config.js
35 | // If your code blocks are over 20 lines, please paste a link to a gist
36 | // (https://gist.github.com).
37 | ```
38 |
39 | ```js
40 | // additional code, HEY YO remove this block if you don't need it
41 | ```
42 |
43 | ### How Do We Reproduce?
44 |
45 |
51 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/DOCS.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 📚 Documentation
3 | about: Are the docs lacking or missing something? Do they need some new 🔥 hotness? Tell us here.
4 | ---
5 |
6 |
16 |
17 | Documentation Is:
18 |
19 |
20 |
21 | - [ ] Missing
22 | - [ ] Needed
23 | - [ ] Confusing
24 | - [ ] Not Sure?
25 |
26 | ### Please Explain in Detail...
27 |
28 | ### Your Proposal for Changes
29 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/FEATURE.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: ✨ Feature Request
3 | about: Suggest an idea for this project
4 | ---
5 |
6 |
16 |
17 | - Operating System:
18 | - Node Version:
19 | - NPM Version:
20 | - webpack Version:
21 | - eslint-loader Version:
22 |
23 | ### Feature Proposal
24 |
25 | ### Feature Use Case
26 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/MODIFICATION.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🔧 Modification Request
3 | about: Would you like something work differently? Have an alternative approach? This is the template for you.
4 | ---
5 |
6 |
16 |
17 | - Operating System:
18 | - Node Version:
19 | - NPM Version:
20 | - webpack Version:
21 | - eslint-loader Version:
22 |
23 | ### Expected Behavior / Situation
24 |
25 | ### Actual Behavior / Situation
26 |
27 | ### Modification Proposal
28 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/SUPPORT.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🆘 Support, Help, and Advice
3 | about: 👉🏽 Need support, help, or advice? Don't open an issue! Head to StackOverflow or https://gitter.im/webpack/webpack.
4 | ---
5 |
6 | Hey there! If you need support, help, or advice then this is not the place to ask.
7 | Please visit [StackOverflow](https://stackoverflow.com/questions/tagged/webpack)
8 | or [the Webpack Gitter](https://gitter.im/webpack/webpack) instead.
9 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
10 |
11 | This PR contains a:
12 |
13 | - [ ] **bugfix**
14 | - [ ] new **feature**
15 | - [ ] **code refactor**
16 | - [ ] **test update**
17 | - [ ] **typo fix**
18 | - [ ] **metadata update**
19 |
20 | ### Motivation / Use-Case
21 |
22 |
27 |
28 | ### Breaking Changes
29 |
30 |
34 |
35 | ### Additional Info
36 |
--------------------------------------------------------------------------------
/.github/workflows/nodejs.yml:
--------------------------------------------------------------------------------
1 | name: eslint-loader
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - next
8 | pull_request:
9 | branches:
10 | - master
11 | - next
12 |
13 | jobs:
14 | lint:
15 | name: Lint - ${{ matrix.os }} - Node v${{ matrix.node-version }}
16 |
17 | env:
18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
19 |
20 | strategy:
21 | matrix:
22 | os: [ubuntu-latest]
23 | node-version: [12.x]
24 |
25 | runs-on: ${{ matrix.os }}
26 |
27 | steps:
28 | - uses: actions/checkout@v2
29 | with:
30 | fetch-depth: 0
31 |
32 | - name: Use Node.js ${{ env.node-version }}
33 | uses: actions/setup-node@v1
34 | with:
35 | node-version: ${{ env.node-version }}
36 |
37 | - name: Use latest NPM
38 | run: sudo npm i -g npm
39 |
40 | - name: Install dependencies
41 | run: npm ci
42 |
43 | - name: Lint
44 | run: npm run lint
45 |
46 | #- name: Security audit
47 | # run: npm run security
48 |
49 | - name: Check commit message
50 | uses: wagoid/commitlint-github-action@v1
51 |
52 | test:
53 | name: Test - ${{ matrix.os }} - Node v${{ matrix.node-version }}, Webpack ${{ matrix.webpack-version }}
54 |
55 | strategy:
56 | matrix:
57 | os: [ubuntu-latest, windows-latest, macos-latest]
58 | node-version: [10.x, 12.x, 14.x]
59 | webpack-version: [latest, next]
60 |
61 | runs-on: ${{ matrix.os }}
62 |
63 | steps:
64 | - name: Setup Git
65 | if: matrix.os == 'windows-latest'
66 | run: git config --global core.autocrlf input
67 |
68 | - uses: actions/checkout@v2
69 |
70 | - name: Use Node.js ${{ matrix.node-version }}
71 | uses: actions/setup-node@v1
72 | with:
73 | node-version: ${{ matrix.node-version }}
74 |
75 | - name: Use latest NPM on ubuntu/macos
76 | if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest'
77 | run: sudo npm i -g npm
78 |
79 | - name: Use latest NPM on windows
80 | if: matrix.os == 'windows-latest'
81 | run: npm i -g npm
82 |
83 | - name: Install dependencies
84 | run: npm ci
85 |
86 | - name: Install webpack ${{ matrix.webpack-version }}
87 | run: npm i webpack@${{ matrix.webpack-version }}
88 |
89 | - name: Run tests for webpack version ${{ matrix.webpack-version }}
90 | run: npm run test:coverage -- --ci
91 |
92 | - name: Submit coverage data to codecov
93 | uses: codecov/codecov-action@v1
94 | with:
95 | token: ${{ secrets.CODECOV_TOKEN }}
96 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | logs
2 | *.log
3 | npm-debug.log*
4 | yarn-debug.log*
5 | .eslintcache
6 |
7 | /coverage
8 | /dist
9 | /local
10 | /reports
11 | /node_modules
12 | /test/output
13 |
14 | .DS_Store
15 | Thumbs.db
16 | .idea
17 | .vscode
18 | *.sublime-project
19 | *.sublime-workspace
20 | *.iml
21 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | /coverage
2 | /dist
3 | /node_modules
4 | /test/fixtures
5 | /test/output
6 | CHANGELOG.md
7 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = { singleQuote: true };
2 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | 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 |
5 | ### [4.0.2](https://github.com/webpack-contrib/eslint-loader/compare/v3.0.4...v4.0.2) (2020-04-24)
6 |
7 |
8 | ### Bug Fixes
9 |
10 | * use fs-extra ^8.1.0 ([7febae0](https://github.com/webpack-contrib/eslint-loader/commit/7febae056ac6271c4cf76b8e387f8fae5800a879))
11 |
12 | ### [4.0.1](https://github.com/webpack-contrib/eslint-loader/compare/v3.0.4...v4.0.1) (2020-04-24)
13 |
14 | ### Refactor
15 |
16 | * new cache implementation ([#320](https://github.com/webpack-contrib/eslint-loader/pull/320)) ([6bb1fa6](https://github.com/webpack-contrib/eslint-loader/commit/acae2be88678228e6589b40122a93f88437b8e47))
17 |
18 | ## [4.0.0](https://github.com/webpack-contrib/eslint-loader/compare/v3.0.4...v4.0.0) (2020-04-03)
19 |
20 | ### Breaking Changes
21 |
22 | * drop support for Node < 10.13.0
23 | * minimum supported eslint version is 6
24 |
25 | ### [3.0.4](https://github.com/webpack-contrib/eslint-loader/compare/v3.0.3...v3.0.4) (2020-04-02)
26 |
27 |
28 | ### Bug Fixes
29 |
30 | * [#316](https://github.com/webpack-contrib/eslint-loader/issues/316) updating loader-fs-cache min version ([#317](https://github.com/webpack-contrib/eslint-loader/issues/317)) ([796e3d1](https://github.com/webpack-contrib/eslint-loader/commit/796e3d130a030ce48e14ee3421809ca40d25cde1))
31 |
32 | ### [3.0.3](https://github.com/webpack-contrib/eslint-loader/compare/v3.0.2...v3.0.3) (2019-12-06)
33 |
34 |
35 | ### Bug Fixes
36 |
37 | * check result object ([#311](https://github.com/webpack-contrib/eslint-loader/issues/311)) ([6bb1fa6](https://github.com/webpack-contrib/eslint-loader/commit/6bb1fa68d043f00de63cda4d9babd3a2c9a50d58))
38 | * support webpack 5 ([#312](https://github.com/webpack-contrib/eslint-loader/issues/312)) ([c0a9d0c](https://github.com/webpack-contrib/eslint-loader/commit/c0a9d0c118155c56c41dc344460f333a9e969eaf))
39 |
40 | ### [3.0.2](https://github.com/webpack-contrib/eslint-loader/compare/v3.0.1...v3.0.2) (2019-09-27)
41 |
42 |
43 | ### Bug Fixes
44 |
45 | * check if contain results ([#300](https://github.com/webpack-contrib/eslint-loader/issues/300)) ([7d1d1fe](https://github.com/webpack-contrib/eslint-loader/commit/7d1d1fe))
46 | * ensure output file path ([#299](https://github.com/webpack-contrib/eslint-loader/issues/299)) ([16e9ccf](https://github.com/webpack-contrib/eslint-loader/commit/16e9ccf))
47 |
48 | ### [3.0.1](https://github.com/webpack-contrib/eslint-loader/compare/v3.0.0...v3.0.1) (2019-09-25)
49 |
50 |
51 | ### Bug Fixes
52 |
53 | * module build failed error at Linter.parseResults ([#294](https://github.com/webpack-contrib/eslint-loader/issues/294)) ([360e69c](https://github.com/webpack-contrib/eslint-loader/commit/360e69c))
54 |
55 | ### [3.0.0](https://github.com/webpack-contrib/eslint-loader/compare/v2.2.1...v3.0.0) (2019-08-24)
56 |
57 |
58 | ### Bugfix
59 |
60 | * fix corrupted filenames if cwd == "/"
61 | * cannot use string formatter in outputReport
62 | * no Output Report in File when build fails under webpack 4
63 | * add posibility to use absolute file path in outputReport.filePath
64 | * it should be possible to use absolute file path in outputReport.filePath
65 | * try load official formatter ([#285](https://github.com/webpack-contrib/eslint-loader/issues/285)) ([997cce5](https://github.com/webpack-contrib/eslint-loader/commit/997cce5))
66 | * emit warning/error if no config was found/given ([#286](https://github.com/webpack-contrib/eslint-loader/issues/286)) ([4204560](https://github.com/webpack-contrib/eslint-loader/commit/4204560))
67 |
68 |
69 | ### Features
70 |
71 | * validate schema options
72 |
73 |
74 | ### Breaking Changes
75 |
76 | * drop support for Node < 8.9.0
77 | * minimum supported webpack version is 4
78 | * minimum supported eslint version is 5
79 |
80 |
81 |
82 | # 2.2.1 - 2019-07-04
83 |
84 | - Fixed: path to eslint version for cache
85 | ([#282](https://github.com/webpack-contrib/eslint-loader/issues/282) - @ricardogobbosouza)
86 |
87 | # 2.2.0 - 2019-07-03
88 |
89 | - [Add ESLint 6 support](https://github.com/webpack-contrib/eslint-loader/commit/b6c3938aae61c0390ac8d941af50cf36df14cfc3) by @HDuck
90 |
91 | # 2.1.2 - 2019-01-31
92 |
93 | - [Fix autofix for eslint < 5](https://github.com/webpack-contrib/eslint-loader/commit/d76372676b8badf57df3d6a22be5739d19e25637) by @eschablowski
94 |
95 | # 2.1.1 - 2018-09-19
96 |
97 | - [Stop autofixing infinite loop](https://github.com/webpack-contrib/eslint-loader/commit/704024864f737a487ec0b9f9c9b00b11881f2558) by @eschablowski
98 | - [Allow `formatter` to receive string (path) to file exporting formatter function](https://github.com/webpack-contrib/eslint-loader/commit/7108379e2864f6ffb75cde1d147ee1fe86890ba8) by @Timer
99 |
100 | # 2.1.0 - 2018-07-19
101 |
102 | - [Add ESLint 5 support](https://github.com/webpack-contrib/eslint-loader/commit/1dc9442d9e2344b953ac88c5c416dcb79f3c690d) by @Alex-Sokolov
103 | - [Fix not returning execution flow control to webpack when cache option is enabled and one of the files has a linting error](https://github.com/webpack-contrib/eslint-loader/commit/97761d724e6fa26d8dbde4a544ddb7cb3795f568) by @nicolaslt
104 | - dev deps updates, prettier, eslint config [...](https://github.com/webpack-contrib/eslint-loader/compare/2.0.0...2.1.0)
105 |
106 | # 2.0.0 - 2018-02-26
107 |
108 | - 🚨 Drop webpack@1.x support (by @wonism in [#212](https://github.com/webpack-contrib/eslint-loader/pull/212))
109 | - 🚨 Drop Node 4 supported (by @wonism in [#212](https://github.com/webpack-contrib/eslint-loader/pull/212))
110 | - ✨ Add webpack@4.x support (by @wonism in [#212](https://github.com/webpack-contrib/eslint-loader/pull/212))
111 | - 🐛 Respect `eslintPath` for formatter (by @lmnsg in [#195](https://github.com/webpack-contrib/eslint-loader/pull/195))
112 |
113 | # 1.9.0 - 2017-07-06
114 |
115 | - Added: `eslintPath` option so you can provide your own eslint path.
116 | ([#183](https://github.com/webpack-contrib/eslint-loader/pull/183) - @trungdq88)
117 |
118 | # 1.8.0 - 2017-06-15
119 |
120 | - Added: support for eslint@^4.0.0
121 | ([#178](https://github.com/webpack-contrib/eslint-loader/issues/178) - @Aladdin-ADD)
122 |
123 | # 1.7.1 - 2017-03-31
124 |
125 | - Fixed: Remove duplicate output with webpack 2
126 | ([#169](https://github.com/webpack-contrib/eslint-loader/pull/169) - @jaridmargolin)
127 |
128 | # 1.7.0 - 2017-03-23
129 |
130 | - Fixed: outputReport option writes report for last file checked only
131 | ([#160](https://github.com/webpack-contrib/eslint-loader/pull/160) - @deryni)
132 | - Added: use babel loader fs cache as the default caching engine
133 | ([#159](https://github.com/webpack-contrib/eslint-loader/pull/159) - @viankakrisna)
134 |
135 | # 1.6.3 - 2017-02-22
136 |
137 | - Fixed: ignore cache when eslint rules have changed
138 | ([#151](https://github.com/webpack-contrib/eslint-loader/pull/151) - @wrakky)
139 |
140 | # 1.6.2 - 2017-02-22
141 |
142 | - Fixed: fallback to OS temp directory if findCacheDir fails
143 | ([#154](https://github.com/webpack-contrib/eslint-loader/pull/154) - @viankakrisna)
144 | - Fixed: `loader-utils` deprecation warning by upgrading to v1.0.0
145 | ([#155](https://github.com/webpack-contrib/eslint-loader/pull/155) - @fknussel)
146 |
147 | # 1.6.1 - 2016-11-02
148 |
149 | - Fixed: multiples config per instance are now supported
150 | ([#105](https://github.com/webpack-contrib/eslint-loader/issues/105) -
151 | @jaythomas and @jameslnewell)
152 |
153 | # 1.6.0 - 2016-10-17
154 |
155 | - Added: Option to generate report file
156 | ([#118](https://github.com/webpack-contrib/eslint-loader/pull/118) - @vidhill)
157 |
158 | # 1.5.0 - 2016-07-28
159 |
160 | - Added: `cache` options
161 | ([#93](https://github.com/webpack-contrib/eslint-loader/pull/93) - @genintho)
162 |
163 | # 1.4.1 - 2016-06-07
164 |
165 | - Fixed: .eslintignore is not ignored anymore (eslint 3.x regression)
166 | ([#99](https://github.com/webpack-contrib/eslint-loader/pull/99) - @waiterZen)
167 |
168 | # 1.4.0 - 2016-06-02
169 |
170 | - Added: support for eslint@^3.0.0
171 | ([#96](https://github.com/webpack-contrib/eslint-loader/issues/96))
172 |
173 | # 1.3.0 - 2016-02-17
174 |
175 | - Added: support for eslint@^2.0.0
176 | ([#81](https://github.com/webpack-contrib/eslint-loader/pull/81))
177 |
178 | # 1.2.1 - 2016-01-26
179 |
180 | - Updated: object-assign dependency
181 | ([#77](https://github.com/webpack-contrib/eslint-loader/pull/77))
182 |
183 | # 1.2.0 - 2016-01-02
184 |
185 | - Added: this loader now pass down the input source map to the next chained
186 | loader if it exists
187 | ([#70](https://github.com/webpack-contrib/eslint-loader/pull/70)).
188 |
189 | # 1.1.1 - 2015-10-08
190 |
191 | - Fixed: `failOnError` and `failOnWarning` now print messages.
192 |
193 | # 1.1.0 - 2015-10-08
194 |
195 | - Added: `fix` option to enable ESLint auto fix feature.
196 |
197 | # 1.0.0 - 2015-08-08
198 |
199 | - Added: support for eslint 1.x
200 | - Removed: support for eslint 1.x-rc\*
201 | - Removed: support for eslint 0.x
202 |
203 | # 0.14.2 - 2015-07-18
204 |
205 | - Fixed: support for eslint 1.x-rc
206 |
207 | # 0.14.1 - 2015-06-15
208 |
209 | - Fixed: support for eslint 0.24.x
210 |
211 | # 0.14.0 - 2015-06-15
212 |
213 | - Added: support for eslint 0.23.x
214 |
215 | # 0.13.0 - 2015-06-14
216 |
217 | - Changed: a file that should be ignored doesn't trigger a warning
218 | ([#44](https://github.com/webpack-contrib/eslint-loader/issues/44))
219 |
220 | # 0.12.0 - 2015-06-04
221 |
222 | - Changed: upgrade to eslint 0.22.x
223 | - Fixed: respect .eslintrc/eslintignore files in directory tree
224 | ([#21](https://github.com/webpack-contrib/eslint-loader/issues/21))
225 |
226 | # 0.11.2 - 2015-05-11
227 |
228 | - Fixed: eslint range from 0.17 to 0.21
229 |
230 | # 0.11.1 - 2015-04-27
231 |
232 | - Fixed: eslint range from 0.17 to 0.20
233 |
234 | # 0.11.0 - 2015-04-27
235 |
236 | - Changed: upgrade to eslint 0.20.x
237 |
238 | # 0.10.0 - 2015-04-13
239 |
240 | - Changed: upgrade to eslint 0.19.x
241 |
242 | # 0.9.0 - 2015-03-29
243 |
244 | - Changed: upgrade to eslint 0.18.x
245 |
246 | # 0.8.0 - 2015-03-27
247 |
248 | - Changed: `reporter` is now `formatter` option to fit eslint name
249 | - Changed: plugin is now async as it don't need to be sync
250 | - Added: options are supported as query strings
251 |
252 | # 0.7.0 - 2015-03-15
253 |
254 | - Changed: upgrade to eslint 0.17.x
255 | - Added: `failOnError` option
256 | - Added: `failOnWarning` option
257 |
258 | # 0.6.0 - 2015-03-11
259 |
260 | - Changed: `reporter` now automatically drop lines that contains the filename in
261 | the reporter output.
262 | That mean you can use official or community reporters without worrying to see
263 | lot of lines with `` as filename :)
264 |
265 | # 0.5.0 - 2015-03-11
266 |
267 | - Changed: upgrade to eslint 0.16.x
268 | - Changed: `emitErrors` is now `emitError`
269 | - Changed: loader now use `webpack.emitError` or `webpack.emitWarning`
270 | automatically (according to eslint configuration).
271 | You can still override by using `emitError` or `emitWarning` options to override
272 | this behavior
273 | - Added: `emitWarning` can force eslint to report warning instead of the default
274 | behavior (see above)
275 | - Added: `quiet` option to hide warnings
276 |
277 | # 0.4.0 - 2015-02-23
278 |
279 | - Changed: upgrade to eslint 0.15.x
280 | - Changed: more readable default reporter
281 | - Added: `reporter` options allow to define a custom reporter function
282 |
283 | # 0.3.0 - 2015-02-10
284 |
285 | - Changed: upgrade to eslint 0.14.x
286 |
287 | # 0.2.1 - 2015-01-27
288 |
289 | - Changed: upgrade to eslint 0.13.x
290 |
291 | # 0.2.0 - 2015-01-23
292 |
293 | - Changed: upgrade to eslint 0.12.x
294 | - Added: enable loading of eslint config from webpack config, `.eslintrc`, or
295 | `package.json`
296 |
297 | # 0.1.0 - 2014-12-05
298 |
299 | ✨ Initial release
300 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright JS Foundation and other contributors
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | 'Software'), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | [![npm][npm]][npm-url]
7 | [![node][node]][node-url]
8 | [![deps][deps]][deps-url]
9 | [![tests][tests]][tests-url]
10 | [![coverage][cover]][cover-url]
11 | [![chat][chat]][chat-url]
12 | [![size][size]][size-url]
13 |
14 | # eslint-loader
15 |
16 | > A ESlint loader for webpack
17 |
18 | ## :warning: DEPRECATED
19 |
20 | `eslint-loader` has been deprecated. Please use [`eslint-webpack-plugin`](https://github.com/webpack-contrib/eslint-webpack-plugin).
21 |
22 | ## Install
23 |
24 | ```bash
25 | npm install eslint-loader --save-dev
26 | ```
27 |
28 | **Note**: You also need to install `eslint` from npm, if you haven't already:
29 |
30 | ```bash
31 | npm install eslint --save-dev
32 | ```
33 |
34 | ## Usage
35 |
36 | In your webpack configuration:
37 |
38 | ```js
39 | module.exports = {
40 | // ...
41 | module: {
42 | rules: [
43 | {
44 | test: /\.js$/,
45 | exclude: /node_modules/,
46 | loader: 'eslint-loader',
47 | options: {
48 | // eslint options (if necessary)
49 | },
50 | },
51 | ],
52 | },
53 | // ...
54 | };
55 | ```
56 |
57 | When using with transpiling loaders (like `babel-loader`), make sure they are in correct order (bottom to top). Otherwise files will be checked after being processed by `babel-loader`:
58 |
59 | ```js
60 | module.exports = {
61 | // ...
62 | module: {
63 | rules: [
64 | {
65 | test: /\.js$/,
66 | exclude: /node_modules/,
67 | use: ['babel-loader', 'eslint-loader'],
68 | },
69 | ],
70 | },
71 | // ...
72 | };
73 | ```
74 |
75 | To be safe, you can use `enforce: 'pre'` section to check source files, not modified by other loaders (like `babel-loader`):
76 |
77 | ```js
78 | module.exports = {
79 | // ...
80 | module: {
81 | rules: [
82 | {
83 | enforce: 'pre',
84 | test: /\.js$/,
85 | exclude: /node_modules/,
86 | loader: 'eslint-loader',
87 | },
88 | {
89 | test: /\.js$/,
90 | exclude: /node_modules/,
91 | loader: 'babel-loader',
92 | },
93 | ],
94 | },
95 | // ...
96 | };
97 | ```
98 |
99 | ## Options
100 |
101 | You can pass [eslint options](http://eslint.org/docs/developer-guide/nodejs-api#cliengine) using standard webpack [loader options](https://webpack.js.org/configuration/module/#useentry).
102 |
103 | **Note**: That the config option you provide will be passed to the `CLIEngine`. This is a different set of options than what you'd specify in `package.json` or `.eslintrc`. See the [eslint docs](http://eslint.org/docs/developer-guide/nodejs-api#cliengine) for more detail.
104 |
105 | ### `cache`
106 |
107 | - Type: `Boolean|String`
108 | - Default: `false`
109 |
110 | This option will enable caching of the linting results into a file. This is particularly useful in reducing linting time when doing a full build.
111 |
112 | This can either be a `boolean` value or the cache directory path(ex: `'./.eslint-loader-cache'`).
113 |
114 | If `cache: true` is used, the cache is written to the `./node_modules/.cache/eslint-loader` directory. This is the recommended usage.
115 |
116 | ```js
117 | module.exports = {
118 | entry: '...',
119 | module: {
120 | rules: [
121 | {
122 | test: /\.js$/,
123 | exclude: /node_modules/,
124 | loader: 'eslint-loader',
125 | options: {
126 | cache: true,
127 | },
128 | },
129 | ],
130 | },
131 | };
132 | ```
133 |
134 | ### `eslintPath`
135 |
136 | - Type: `String`
137 | - Default: `eslint`
138 |
139 | Path to `eslint` instance that will be used for linting. If the `eslintPath` is a folder like a official eslint, or specify a `formatter` option. Now you dont have to install `eslint`.
140 |
141 | ```js
142 | module.exports = {
143 | entry: '...',
144 | module: {
145 | rules: [
146 | {
147 | test: /\.js$/,
148 | exclude: /node_modules/,
149 | loader: 'eslint-loader',
150 | options: {
151 | eslintPath: path.join(__dirname, 'reusable-eslint'),
152 | },
153 | },
154 | ],
155 | },
156 | };
157 | ```
158 |
159 | ### `fix`
160 |
161 | - Type: `Boolean`
162 | - Default: `false`
163 |
164 | This option will enable [ESLint autofix feature](http://eslint.org/docs/user-guide/command-line-interface#fix).
165 |
166 | **Be careful: this option will change source files.**
167 |
168 | ```js
169 | module.exports = {
170 | entry: '...',
171 | module: {
172 | rules: [
173 | {
174 | test: /\.js$/,
175 | exclude: /node_modules/,
176 | loader: 'eslint-loader',
177 | options: {
178 | fix: true,
179 | },
180 | },
181 | ],
182 | },
183 | };
184 | ```
185 |
186 | ### `formatter`
187 |
188 | - Type: `String|Function`
189 | - Default: `stylish`
190 |
191 | This option accepts a function that will have one argument: an array of eslint messages (object). The function must return the output as a string. You can use official [eslint formatters](https://eslint.org/docs/user-guide/formatters/).
192 |
193 | ```js
194 | module.exports = {
195 | entry: '...',
196 | module: {
197 | rules: [
198 | {
199 | test: /\.js$/,
200 | exclude: /node_modules/,
201 | loader: 'eslint-loader',
202 | options: {
203 | // several examples !
204 |
205 | // default value
206 | formatter: 'stylish',
207 |
208 | // community formatter
209 | formatter: require('eslint-friendly-formatter'),
210 |
211 | // custom formatter
212 | formatter: function (results) {
213 | // `results` format is available here
214 | // http://eslint.org/docs/developer-guide/nodejs-api.html#executeonfiles()
215 |
216 | // you should return a string
217 | // DO NOT USE console.*() directly !
218 | return 'OUTPUT';
219 | },
220 | },
221 | },
222 | ],
223 | },
224 | };
225 | ```
226 |
227 | ### Errors and Warning
228 |
229 | **By default the loader will auto adjust error reporting depending on eslint errors/warnings counts.** You can still force this behavior by using `emitError` **or** `emitWarning` options:
230 |
231 | #### `emitError`
232 |
233 | - Type: `Boolean`
234 | - Default: `false`
235 |
236 | Will always return errors, if this option is set to `true`.
237 |
238 | ```js
239 | module.exports = {
240 | entry: '...',
241 | module: {
242 | rules: [
243 | {
244 | test: /\.js$/,
245 | exclude: /node_modules/,
246 | loader: 'eslint-loader',
247 | options: {
248 | emitError: true,
249 | },
250 | },
251 | ],
252 | },
253 | };
254 | ```
255 |
256 | #### `emitWarning`
257 |
258 | - Type: `Boolean`
259 | - Default: `false`
260 |
261 | Will always return warnings, if option is set to `true`. **If you're using hot module replacement, you may wish to enable this in development, or else updates will be skipped when there's an eslint error.**
262 |
263 | ```js
264 | module.exports = {
265 | entry: '...',
266 | module: {
267 | rules: [
268 | {
269 | test: /\.js$/,
270 | exclude: /node_modules/,
271 | loader: 'eslint-loader',
272 | options: {
273 | emitWarning: true,
274 | },
275 | },
276 | ],
277 | },
278 | };
279 | ```
280 |
281 | #### `failOnError`
282 |
283 | - Type: `Boolean`
284 | - Default: `false`
285 |
286 | Will cause the module build to fail if there are any errors, if option is set to `true`.
287 |
288 | ```js
289 | module.exports = {
290 | entry: '...',
291 | module: {
292 | rules: [
293 | {
294 | test: /\.js$/,
295 | exclude: /node_modules/,
296 | loader: 'eslint-loader',
297 | options: {
298 | failOnError: true,
299 | },
300 | },
301 | ],
302 | },
303 | };
304 | ```
305 |
306 | #### `failOnWarning`
307 |
308 | - Type: `Boolean`
309 | - Default: `false`
310 |
311 | Will cause the module build to fail if there are any warnings, if option is set to `true`.
312 |
313 | ```js
314 | module.exports = {
315 | entry: '...',
316 | module: {
317 | rules: [
318 | {
319 | test: /\.js$/,
320 | exclude: /node_modules/,
321 | loader: 'eslint-loader',
322 | options: {
323 | failOnWarning: true,
324 | },
325 | },
326 | ],
327 | },
328 | };
329 | ```
330 |
331 | #### `quiet`
332 |
333 | - Type: `Boolean`
334 | - Default: `false`
335 |
336 | Will process and report errors only and ignore warnings, if this option is set to `true`.
337 |
338 | ```js
339 | module.exports = {
340 | entry: '...',
341 | module: {
342 | rules: [
343 | {
344 | test: /\.js$/,
345 | exclude: /node_modules/,
346 | loader: 'eslint-loader',
347 | options: {
348 | quiet: true,
349 | },
350 | },
351 | ],
352 | },
353 | };
354 | ```
355 |
356 | #### `outputReport`
357 |
358 | - Type: `Boolean|Object`
359 | - Default: `false`
360 |
361 | Write the output of the errors to a file, for example a checkstyle xml file for use for reporting on Jenkins CI.
362 |
363 | The `filePath` is an absolute path or relative to the webpack config: `output.path`. You can pass in a different `formatter` for the output file, if none is passed in the default/configured formatter will be used.
364 |
365 | ```js
366 | module.exports = {
367 | entry: '...',
368 | module: {
369 | rules: [
370 | {
371 | test: /\.js$/,
372 | exclude: /node_modules/,
373 | loader: 'eslint-loader',
374 | options: {
375 | outputReport: {
376 | filePath: 'checkstyle.xml',
377 | formatter: 'checkstyle',
378 | },
379 | },
380 | },
381 | ],
382 | },
383 | };
384 | ```
385 |
386 | ## Gotchas
387 |
388 | ### NoEmitOnErrorsPlugin
389 |
390 | `NoEmitOnErrorsPlugin` is now automatically enabled in webpack 4, when mode is either unset, or set to production. So even ESLint warnings will fail the build. No matter what error settings are used for `eslint-loader`, except if `emitWarning` enabled.
391 |
392 | ### Defining `configFile` or using `eslint -c path/.eslintrc`
393 |
394 | Bear in mind that when you define `configFile`, `eslint` doesn't automatically look for `.eslintrc` files in the directory of the file to be linted. More information is available in official eslint documentation in section [_Using Configuration Files_](http://eslint.org/docs/user-guide/configuring#using-configuration-files). See [#129](https://github.com/webpack-contrib/eslint-loader/issues/129).
395 |
396 | ## Changelog
397 |
398 | [Changelog](CHANGELOG.md)
399 |
400 | ## License
401 |
402 | [MIT](./LICENSE)
403 |
404 | [npm]: https://img.shields.io/npm/v/eslint-loader.svg
405 | [npm-url]: https://npmjs.com/package/eslint-loader
406 | [node]: https://img.shields.io/node/v/eslint-loader.svg
407 | [node-url]: https://nodejs.org
408 | [deps]: https://david-dm.org/webpack-contrib/eslint-loader.svg
409 | [deps-url]: https://david-dm.org/webpack-contrib/eslint-loader
410 | [tests]: https://github.com/webpack-contrib/eslint-loader/workflows/eslint-loader/badge.svg
411 | [tests-url]: https://github.com/webpack-contrib/eslint-loader/actions
412 | [cover]: https://codecov.io/gh/webpack-contrib/eslint-loader/branch/master/graph/badge.svg
413 | [cover-url]: https://codecov.io/gh/webpack-contrib/eslint-loader
414 | [chat]: https://badges.gitter.im/webpack/webpack.svg
415 | [chat-url]: https://gitter.im/webpack/webpack
416 | [size]: https://packagephobia.now.sh/badge?p=eslint-loader
417 | [size-url]: https://packagephobia.now.sh/result?p=eslint-loader
418 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | const MIN_BABEL_VERSION = 7;
2 |
3 | module.exports = (api) => {
4 | api.assertVersion(MIN_BABEL_VERSION);
5 | api.cache(true);
6 |
7 | return {
8 | presets: [
9 | [
10 | '@babel/preset-env',
11 | {
12 | targets: {
13 | node: '10.13.0',
14 | },
15 | },
16 | ],
17 | ],
18 | };
19 | };
20 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['@commitlint/config-conventional'],
3 | };
4 |
--------------------------------------------------------------------------------
/husky.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | hooks: {
3 | 'pre-commit': 'lint-staged',
4 | 'commit-msg': 'commitlint -E HUSKY_GIT_PARAMS',
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | testEnvironment: 'node',
3 | testTimeout: 30000,
4 | };
5 |
--------------------------------------------------------------------------------
/lint-staged.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | '*.js': ['prettier --write', 'eslint --fix'],
3 | '*.{json,md,yml,css}': ['prettier --write'],
4 | };
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "eslint-loader",
3 | "version": "4.0.2",
4 | "description": "A ESlint loader for webpack",
5 | "license": "MIT",
6 | "repository": "webpack-contrib/eslint-loader",
7 | "author": "Maxime Thirouin",
8 | "contributors": [
9 | "Ricardo Gobbo de Souza "
10 | ],
11 | "homepage": "https://github.com/webpack-contrib/eslint-loader",
12 | "bugs": "https://github.com/webpack-contrib/eslint-loader/issues",
13 | "funding": {
14 | "type": "opencollective",
15 | "url": "https://opencollective.com/webpack"
16 | },
17 | "main": "dist/cjs.js",
18 | "engines": {
19 | "node": ">= 10.13.0"
20 | },
21 | "scripts": {
22 | "start": "npm run build -- -w",
23 | "clean": "del-cli dist",
24 | "prebuild": "npm run clean",
25 | "build": "cross-env NODE_ENV=production babel src -d dist --copy-files",
26 | "commitlint": "commitlint --from=master",
27 | "security": "npm audit",
28 | "lint:prettier": "prettier --list-different .",
29 | "lint:js": "eslint --cache .",
30 | "lint": "npm-run-all -l -p \"lint:**\"",
31 | "test:only": "cross-env NODE_ENV=test jest",
32 | "test:watch": "npm run test:only -- --watch",
33 | "test:coverage": "npm run test:only -- --collectCoverageFrom=\"src/**/*.js\" --coverage",
34 | "pretest": "npm run lint",
35 | "test": "npm run test:coverage",
36 | "prepare": "npm run build",
37 | "release": "standard-version",
38 | "defaults": "webpack-defaults"
39 | },
40 | "files": [
41 | "dist"
42 | ],
43 | "peerDependencies": {
44 | "eslint": "^6.0.0 || ^7.0.0",
45 | "webpack": "^4.0.0 || ^5.0.0"
46 | },
47 | "dependencies": {
48 | "find-cache-dir": "^3.3.1",
49 | "fs-extra": "^8.1.0",
50 | "loader-utils": "^2.0.0",
51 | "object-hash": "^2.0.3",
52 | "schema-utils": "^2.6.6"
53 | },
54 | "devDependencies": {
55 | "@babel/cli": "^7.8.4",
56 | "@babel/core": "^7.9.6",
57 | "@babel/preset-env": "^7.9.6",
58 | "@commitlint/cli": "^8.3.5",
59 | "@commitlint/config-conventional": "^8.3.4",
60 | "@webpack-contrib/defaults": "^6.3.0",
61 | "@webpack-contrib/eslint-config-webpack": "^3.0.0",
62 | "babel-eslint": "^10.1.0",
63 | "babel-jest": "^25.5.1",
64 | "chokidar": "^3.4.0",
65 | "cross-env": "^7.0.2",
66 | "del": "^5.1.0",
67 | "del-cli": "^3.0.0",
68 | "eslint": "^6.8.0",
69 | "eslint-config-prettier": "^6.11.0",
70 | "eslint-friendly-formatter": "^4.0.1",
71 | "eslint-plugin-import": "^2.20.2",
72 | "husky": "^4.2.5",
73 | "jest": "^25.5.4",
74 | "lint-staged": "^10.2.2",
75 | "npm-run-all": "^4.1.5",
76 | "prettier": "^2.0.5",
77 | "standard-version": "^7.1.0",
78 | "webpack": "^4.43.0"
79 | },
80 | "keywords": [
81 | "eslint",
82 | "lint",
83 | "linter",
84 | "loader",
85 | "webpack"
86 | ]
87 | }
88 |
--------------------------------------------------------------------------------
/src/ESLintError.js:
--------------------------------------------------------------------------------
1 | export default class ESLintError extends Error {
2 | constructor(messages) {
3 | super(messages);
4 | this.name = 'ESLintError';
5 | this.stack = false;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/Linter.js:
--------------------------------------------------------------------------------
1 | import process from 'process';
2 | import { isAbsolute, join } from 'path';
3 |
4 | import { writeFileSync, ensureFileSync } from 'fs-extra';
5 | import { interpolateName } from 'loader-utils';
6 |
7 | import ESLintError from './ESLintError';
8 | import createEngine from './createEngine';
9 |
10 | export default class Linter {
11 | constructor(loaderContext, options) {
12 | this.loaderContext = loaderContext;
13 | this.options = options;
14 | this.resourcePath = this.parseResourcePath();
15 |
16 | const { CLIEngine, engine } = createEngine(options);
17 | this.CLIEngine = CLIEngine;
18 | this.engine = engine;
19 | }
20 |
21 | parseResourcePath() {
22 | const cwd = process.cwd();
23 | let { resourcePath } = this.loaderContext;
24 |
25 | // remove cwd from resource path in case webpack has been started from project
26 | // root, to allow having relative paths in .eslintignore
27 | // istanbul ignore next
28 | if (resourcePath.indexOf(cwd) === 0) {
29 | resourcePath = resourcePath.substr(cwd.length + (cwd === '/' ? 0 : 1));
30 | }
31 |
32 | return resourcePath;
33 | }
34 |
35 | lint(content) {
36 | try {
37 | return this.engine.executeOnText(content, this.resourcePath, true);
38 | } catch (_) {
39 | this.getEmitter(false)(_);
40 |
41 | return { src: content };
42 | }
43 | }
44 |
45 | printOutput(data) {
46 | const { options } = this;
47 |
48 | // skip ignored file warning
49 | if (this.constructor.skipIgnoredFileWarning(data)) {
50 | return;
51 | }
52 |
53 | // quiet filter done now
54 | // eslint allow rules to be specified in the input between comments
55 | // so we can found warnings defined in the input itself
56 | const res = this.filter(data);
57 |
58 | // if enabled, use eslint auto-fixing where possible
59 | if (options.fix) {
60 | this.autoFix(res);
61 | }
62 |
63 | // skip if no errors or warnings
64 | if (res.errorCount < 1 && res.warningCount < 1) {
65 | return;
66 | }
67 |
68 | const results = this.parseResults(res);
69 |
70 | // Do not analyze if there are no results or eslint config
71 | if (!results) {
72 | return;
73 | }
74 |
75 | const messages = options.formatter(results);
76 |
77 | this.reportOutput(results, messages);
78 | this.failOnErrorOrWarning(res, messages);
79 |
80 | const emitter = this.getEmitter(res);
81 | emitter(new ESLintError(messages));
82 | }
83 |
84 | static skipIgnoredFileWarning(res) {
85 | return (
86 | res &&
87 | res.warningCount === 1 &&
88 | res.results &&
89 | res.results[0] &&
90 | res.results[0].messages[0] &&
91 | res.results[0].messages[0].message &&
92 | res.results[0].messages[0].message.indexOf('ignore') > 1
93 | );
94 | }
95 |
96 | filter(data) {
97 | const res = data;
98 |
99 | // quiet filter done now
100 | // eslint allow rules to be specified in the input between comments
101 | // so we can found warnings defined in the input itself
102 | if (
103 | this.options.quiet &&
104 | res &&
105 | res.warningCount &&
106 | res.results &&
107 | res.results[0]
108 | ) {
109 | res.warningCount = 0;
110 | res.results[0].warningCount = 0;
111 | res.results[0].messages = res.results[0].messages.filter(
112 | (message) => message.severity !== 1
113 | );
114 | }
115 |
116 | return res;
117 | }
118 |
119 | autoFix(res) {
120 | if (
121 | res &&
122 | res.results &&
123 | res.results[0] &&
124 | (res.results[0].output !== res.src ||
125 | res.results[0].fixableErrorCount > 0 ||
126 | res.results[0].fixableWarningCount > 0)
127 | ) {
128 | this.CLIEngine.outputFixes(res);
129 | }
130 | }
131 |
132 | parseResults({ results }) {
133 | // add filename for each results so formatter can have relevant filename
134 | if (results) {
135 | results.forEach((r) => {
136 | // eslint-disable-next-line no-param-reassign
137 | r.filePath = this.loaderContext.resourcePath;
138 | });
139 | }
140 |
141 | return results;
142 | }
143 |
144 | reportOutput(results, messages) {
145 | const { outputReport } = this.options;
146 |
147 | if (!outputReport || !outputReport.filePath) {
148 | return;
149 | }
150 |
151 | let content = messages;
152 |
153 | // if a different formatter is passed in as an option use that
154 | if (outputReport.formatter) {
155 | content = outputReport.formatter(results);
156 | }
157 |
158 | let filePath = interpolateName(this.loaderContext, outputReport.filePath, {
159 | content,
160 | });
161 |
162 | if (!isAbsolute(filePath)) {
163 | filePath = join(
164 | // eslint-disable-next-line no-underscore-dangle
165 | this.loaderContext._compiler.options.output.path,
166 | filePath
167 | );
168 | }
169 |
170 | ensureFileSync(filePath);
171 | writeFileSync(filePath, content);
172 | }
173 |
174 | failOnErrorOrWarning({ errorCount, warningCount }, messages) {
175 | const { failOnError, failOnWarning } = this.options;
176 |
177 | if (failOnError && errorCount) {
178 | throw new ESLintError(
179 | `Module failed because of a eslint error.\n${messages}`
180 | );
181 | }
182 |
183 | if (failOnWarning && warningCount) {
184 | throw new ESLintError(
185 | `Module failed because of a eslint warning.\n${messages}`
186 | );
187 | }
188 | }
189 |
190 | getEmitter({ errorCount }) {
191 | const { options, loaderContext } = this;
192 |
193 | // default behavior: emit error only if we have errors
194 | let emitter = errorCount
195 | ? loaderContext.emitError
196 | : loaderContext.emitWarning;
197 |
198 | // force emitError or emitWarning if user want this
199 | if (options.emitError) {
200 | emitter = loaderContext.emitError;
201 | } else if (options.emitWarning) {
202 | emitter = loaderContext.emitWarning;
203 | }
204 |
205 | return emitter;
206 | }
207 | }
208 |
--------------------------------------------------------------------------------
/src/cache.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Original Filesystem Cache implementation by babel-loader
3 | * Licensed under the MIT License
4 | *
5 | * @see https://github.com/babel/babel-loader/commits/master/src/fs-cache.js
6 | * @see https://github.com/babel/babel-loader/commits/master/src/cache.js
7 | */
8 |
9 | /**
10 | * Filesystem Cache
11 | *
12 | * Given a file and a transform function, cache the result into files
13 | * or retrieve the previously cached files if the given file is already known.
14 | *
15 | * @see https://github.com/babel/babel-loader/issues/34
16 | * @see https://github.com/babel/babel-loader/pull/41
17 | */
18 | import fs from 'fs';
19 | import os from 'os';
20 | import { join } from 'path';
21 | import { promisify } from 'util';
22 | import zlib from 'zlib';
23 | import { createHash } from 'crypto';
24 |
25 | import findCacheDir from 'find-cache-dir';
26 |
27 | // Lazily instantiated when needed
28 | let defaultCacheDirectory = null;
29 |
30 | const readFile = promisify(fs.readFile);
31 | const writeFile = promisify(fs.writeFile);
32 | const gunzip = promisify(zlib.gunzip);
33 | const gzip = promisify(zlib.gzip);
34 |
35 | /**
36 | * Read the contents from the compressed file.
37 | *
38 | * @async
39 | * @params {String} filename
40 | * @params {Boolean} compress
41 | */
42 | const read = async (filename, compress) => {
43 | const data = await readFile(filename + (compress ? '.gz' : ''));
44 | const content = compress ? await gunzip(data) : data;
45 |
46 | return JSON.parse(content.toString());
47 | };
48 |
49 | /**
50 | * Write contents into a compressed file.
51 | *
52 | * @async
53 | * @params {String} filename
54 | * @params {Boolean} compress
55 | * @params {String} result
56 | */
57 | const write = async (filename, compress, result) => {
58 | const content = JSON.stringify(result);
59 |
60 | const data = compress ? await gzip(content) : content;
61 | return writeFile(filename + (compress ? '.gz' : ''), data);
62 | };
63 |
64 | /**
65 | * Build the filename for the cached file
66 | *
67 | * @params {String} source File source code
68 | * @params {String} identifier
69 | * @params {Object} options Options used
70 | *
71 | * @return {String}
72 | */
73 | const filename = (source, identifier, options) => {
74 | const hash = createHash('md4');
75 |
76 | const contents = JSON.stringify({ source, options, identifier });
77 |
78 | hash.update(contents);
79 |
80 | return `${hash.digest('hex')}.json`;
81 | };
82 |
83 | /**
84 | * Handle the cache
85 | *
86 | * @params {String} directory
87 | * @params {Object} params
88 | */
89 | const handleCache = async (directory, params) => {
90 | const {
91 | source,
92 | options = {},
93 | transform,
94 | cacheIdentifier,
95 | cacheDirectory,
96 | cacheCompression,
97 | } = params;
98 |
99 | const file = join(directory, filename(source, cacheIdentifier, options));
100 |
101 | try {
102 | // No errors mean that the file was previously cached
103 | // we just need to return it
104 | return await read(file, cacheCompression);
105 | // eslint-disable-next-line no-empty
106 | } catch (err) {}
107 |
108 | const fallback =
109 | typeof cacheDirectory !== 'string' && directory !== os.tmpdir();
110 |
111 | // Make sure the directory exists.
112 | try {
113 | fs.mkdirSync(directory, { recursive: true });
114 | } catch (err) {
115 | if (fallback) {
116 | return handleCache(os.tmpdir(), params);
117 | }
118 |
119 | throw err;
120 | }
121 |
122 | // Otherwise just transform the file
123 | // return it to the user asap and write it in cache
124 | const result = await transform(source, options);
125 |
126 | try {
127 | await write(file, cacheCompression, result);
128 | } catch (err) {
129 | if (fallback) {
130 | // Fallback to tmpdir if node_modules folder not writable
131 | return handleCache(os.tmpdir(), params);
132 | }
133 |
134 | throw err;
135 | }
136 |
137 | return result;
138 | };
139 |
140 | /**
141 | * Retrieve file from cache, or create a new one for future reads
142 | *
143 | * @async
144 | * @param {Object} params
145 | * @param {String} params.cacheDirectory Directory to store cached files
146 | * @param {String} params.cacheIdentifier Unique identifier to bust cache
147 | * @param {Boolean} params.cacheCompression
148 | * @param {String} params.source Original contents of the file to be cached
149 | * @param {Object} params.options Options to be given to the transform fn
150 | * @param {Function} params.transform Function that will transform the
151 | * original file and whose result will be
152 | * cached
153 | *
154 | * @example
155 | *
156 | * cache({
157 | * cacheDirectory: '.tmp/cache',
158 | * cacheIdentifier: 'babel-loader-cachefile',
159 | * cacheCompression: true,
160 | * source: *source code from file*,
161 | * options: {
162 | * experimental: true,
163 | * runtime: true
164 | * },
165 | * transform: function(source, options) {
166 | * var content = *do what you need with the source*
167 | * return content;
168 | * }
169 | * });
170 | */
171 |
172 | module.exports = async (params) => {
173 | let directory;
174 |
175 | if (typeof params.cacheDirectory === 'string') {
176 | directory = params.cacheDirectory;
177 | } else {
178 | if (defaultCacheDirectory === null) {
179 | defaultCacheDirectory =
180 | findCacheDir({ name: 'eslint-loader' }) || os.tmpdir();
181 | }
182 |
183 | directory = defaultCacheDirectory;
184 | }
185 |
186 | return handleCache(directory, params);
187 | };
188 |
--------------------------------------------------------------------------------
/src/cacheLoader.js:
--------------------------------------------------------------------------------
1 | import { version } from '../package.json';
2 |
3 | import cache from './cache';
4 |
5 | export default function cacheLoader(linter, content, map) {
6 | const { loaderContext, options, CLIEngine } = linter;
7 | const callback = loaderContext.async();
8 | const cacheIdentifier = JSON.stringify({
9 | 'eslint-loader': version,
10 | eslint: CLIEngine.version,
11 | });
12 |
13 | cache({
14 | cacheDirectory: options.cache,
15 | cacheIdentifier,
16 | cacheCompression: true,
17 | options,
18 | source: content,
19 | transform() {
20 | return linter.lint(content);
21 | },
22 | })
23 | .then((res) => {
24 | try {
25 | linter.printOutput({ ...res, src: content });
26 | } catch (error) {
27 | return callback(error, content, map);
28 | }
29 | return callback(null, content, map);
30 | })
31 | .catch((err) => {
32 | // istanbul ignore next
33 | return callback(err);
34 | });
35 | }
36 |
--------------------------------------------------------------------------------
/src/cjs.js:
--------------------------------------------------------------------------------
1 | const loader = require('./index');
2 |
3 | module.exports = loader.default;
4 |
--------------------------------------------------------------------------------
/src/createEngine.js:
--------------------------------------------------------------------------------
1 | import objectHash from 'object-hash';
2 |
3 | const engines = {};
4 |
5 | export default function createEngine(options) {
6 | const { CLIEngine } = require(options.eslintPath);
7 | const hash = objectHash(options);
8 |
9 | if (!engines[hash]) {
10 | engines[hash] = new CLIEngine(options);
11 | }
12 |
13 | return {
14 | CLIEngine,
15 | engine: engines[hash],
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/src/getOptions.js:
--------------------------------------------------------------------------------
1 | import loaderUtils from 'loader-utils';
2 | import validateOptions from 'schema-utils';
3 |
4 | import schema from './options.json';
5 |
6 | export default function getOptions(loaderContext) {
7 | const options = {
8 | eslintPath: 'eslint',
9 | ...loaderUtils.getOptions(loaderContext),
10 | };
11 |
12 | validateOptions(schema, options, {
13 | name: 'ESLint Loader',
14 | baseDataPath: 'options',
15 | });
16 |
17 | const { CLIEngine } = require(options.eslintPath);
18 |
19 | options.formatter = getFormatter(CLIEngine, options.formatter);
20 |
21 | if (options.outputReport && options.outputReport.formatter) {
22 | options.outputReport.formatter = getFormatter(
23 | CLIEngine,
24 | options.outputReport.formatter
25 | );
26 | }
27 |
28 | return options;
29 | }
30 |
31 | function getFormatter(CLIEngine, formatter) {
32 | if (typeof formatter === 'function') {
33 | return formatter;
34 | }
35 |
36 | // Try to get oficial formatter
37 | if (typeof formatter === 'string') {
38 | try {
39 | return CLIEngine.getFormatter(formatter);
40 | } catch (e) {
41 | // ignored
42 | }
43 | }
44 |
45 | return CLIEngine.getFormatter('stylish');
46 | }
47 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import getOptions from './getOptions';
2 | import Linter from './Linter';
3 | import cacheLoader from './cacheLoader';
4 |
5 | export default function loader(content, map) {
6 | const options = getOptions(this);
7 | const linter = new Linter(this, options);
8 |
9 | this.cacheable();
10 |
11 | // return early if cached
12 | if (options.cache) {
13 | cacheLoader(linter, content, map);
14 | return;
15 | }
16 |
17 | linter.printOutput(linter.lint(content));
18 | this.callback(null, content, map);
19 | }
20 |
--------------------------------------------------------------------------------
/src/options.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "object",
3 | "additionalProperties": true,
4 | "properties": {
5 | "cache": {
6 | "description": "This option will enable caching of the linting results into a file. This is particularly useful in reducing linting time when doing a full build.",
7 | "anyOf": [{ "type": "boolean" }, { "type": "string" }]
8 | },
9 | "eslintPath": {
10 | "description": "Path to `eslint` instance that will be used for linting. If the `eslintPath` is a folder like a official eslint, or specify a `formatter` option. now you dont have to install `eslint` .",
11 | "type": "string"
12 | },
13 | "formatter": {
14 | "description": "Loader accepts a function that will have one argument: an array of eslint messages (object). The function must return the output as a string.",
15 | "anyOf": [{ "type": "string" }, { "instanceof": "Function" }]
16 | },
17 | "fix": {
18 | "description": "This option will enable ESLint autofix feature",
19 | "type": "boolean"
20 | },
21 | "emitError": {
22 | "description": "Loader will always return errors if this option is set to `true`.",
23 | "type": "boolean"
24 | },
25 | "emitWarning": {
26 | "description": "Loader will always return warnings if option is set to `true`. If you're using hot module replacement, you may wish to enable this in development, or else updates will be skipped when there's an eslint error.",
27 | "type": "boolean"
28 | },
29 | "failOnError": {
30 | "description": "Loader will cause the module build to fail if there are any eslint errors.",
31 | "type": "boolean"
32 | },
33 | "failOnWarning": {
34 | "description": "Loader will cause the module build to fail if there are any eslint warnings.",
35 | "type": "boolean"
36 | },
37 | "quiet": {
38 | "description": "Loader will process and report errors only and ignore warnings if this option is set to true",
39 | "type": "boolean"
40 | },
41 | "outputReport": {
42 | "description": "Write the output of the errors to a file, for example a checkstyle xml file for use for reporting on Jenkins CI",
43 | "anyOf": [
44 | {
45 | "type": "boolean"
46 | },
47 | {
48 | "type": "object",
49 | "additionalProperties": false,
50 | "properties": {
51 | "filePath": {
52 | "description": "The `filePath` is relative to the webpack config: output.path",
53 | "anyOf": [{ "type": "string" }]
54 | },
55 | "formatter": {
56 | "description": "You can pass in a different formatter for the output file, if none is passed in the default/configured formatter will be used",
57 | "anyOf": [{ "type": "string" }, { "instanceof": "Function" }]
58 | }
59 | }
60 | }
61 | ]
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/test/Linter.test.js:
--------------------------------------------------------------------------------
1 | import Linter from '../src/Linter';
2 |
3 | describe('Linter', () => {
4 | let linter;
5 |
6 | beforeAll(() => {
7 | const loaderContext = {
8 | resourcePath: 'test',
9 | };
10 |
11 | const options = {
12 | eslintPath: 'eslint',
13 | ignore: false,
14 | formatter: jest.fn(),
15 | };
16 |
17 | linter = new Linter(loaderContext, options);
18 | });
19 |
20 | it('should parse undefined results without error', () => {
21 | expect(linter.parseResults({})).toBeUndefined();
22 | });
23 |
24 | it('should parse results correctly', () => {
25 | const res = {
26 | results: [{ filePath: '' }],
27 | };
28 |
29 | expect(linter.parseResults(res)).toEqual([{ filePath: 'test' }]);
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/test/autofix-stop.test.js:
--------------------------------------------------------------------------------
1 | import { join } from 'path';
2 |
3 | import { copySync, removeSync } from 'fs-extra';
4 | import chokidar from 'chokidar';
5 |
6 | import pack from './utils/pack';
7 |
8 | describe('autofix stop', () => {
9 | const entry = join(__dirname, 'fixtures/nonfixable-clone.js');
10 |
11 | let changed = false;
12 | let watcher;
13 |
14 | beforeAll(() => {
15 | copySync(join(__dirname, 'fixtures/nonfixable.js'), entry);
16 |
17 | watcher = chokidar.watch(entry);
18 | watcher.on('change', () => {
19 | changed = true;
20 | });
21 | });
22 |
23 | afterAll(() => {
24 | watcher.close();
25 | removeSync(entry);
26 | });
27 |
28 | it('should not change file if there are no fixable errors/warnings', (done) => {
29 | const compiler = pack('nonfixable-clone', { fix: true });
30 |
31 | compiler.run(() => {
32 | expect(changed).toBe(false);
33 | done();
34 | });
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/test/autofix.test.js:
--------------------------------------------------------------------------------
1 | import { join } from 'path';
2 |
3 | import { copySync, removeSync } from 'fs-extra';
4 |
5 | import pack from './utils/pack';
6 |
7 | describe('autofix stop', () => {
8 | const entry = join(__dirname, 'fixtures/fixable-clone.js');
9 |
10 | beforeAll(() => {
11 | copySync(join(__dirname, 'fixtures/fixable.js'), entry);
12 | });
13 |
14 | afterAll(() => {
15 | removeSync(entry);
16 | });
17 |
18 | it('should not throw error if file ok after auto-fixing', (done) => {
19 | const compiler = pack('fixable-clone', { fix: true });
20 |
21 | compiler.run((err, stats) => {
22 | expect(stats.hasWarnings()).toBe(false);
23 | expect(stats.hasErrors()).toBe(false);
24 | done();
25 | });
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/test/cache.test.js:
--------------------------------------------------------------------------------
1 | import { join } from 'path';
2 | import fs from 'fs';
3 |
4 | import { readdirSync, removeSync } from 'fs-extra';
5 | import webpack from 'webpack';
6 |
7 | const defaultCacheDir = join(__dirname, '../node_modules/.cache/eslint-loader');
8 | const cacheDir = join(__dirname, 'output/cache/cachefiles');
9 | const outputDir = join(__dirname, 'output/cache');
10 | const eslintLoader = join(__dirname, '../src/index');
11 | const globalConfig = {
12 | entry: join(__dirname, 'fixtures/cache.js'),
13 | module: {
14 | rules: [
15 | {
16 | test: /\.js$/,
17 | exclude: /node_modules/,
18 | use: eslintLoader,
19 | },
20 | ],
21 | },
22 | };
23 |
24 | function createTestDirectory(dir) {
25 | const directory = join(dir, 'cache');
26 |
27 | removeSync(directory);
28 | fs.mkdirSync(directory, { recursive: true });
29 |
30 | return directory;
31 | }
32 |
33 | describe('cache', () => {
34 | let directory;
35 | let cache;
36 |
37 | beforeEach(() => {
38 | directory = createTestDirectory(outputDir);
39 | cache = createTestDirectory(cacheDir);
40 | removeSync(defaultCacheDir);
41 | });
42 |
43 | afterEach(() => {
44 | removeSync(cache);
45 | removeSync(directory);
46 | });
47 |
48 | it('should output files to cache directory', (done) => {
49 | const compiler = webpack({
50 | ...globalConfig,
51 | output: {
52 | path: directory,
53 | },
54 | module: {
55 | rules: [
56 | {
57 | test: /\.js$/,
58 | exclude: /node_modules/,
59 | use: `${eslintLoader}?cache=${cache}`,
60 | },
61 | ],
62 | },
63 | });
64 | compiler.run(() => {
65 | const files = readdirSync(cache);
66 | expect(files.length).toBeGreaterThan(0);
67 | done();
68 | });
69 | });
70 |
71 | it('should output files to standard cache dir if set to true in query', (done) => {
72 | const compiler = webpack({
73 | ...globalConfig,
74 | output: {
75 | path: directory,
76 | },
77 | module: {
78 | rules: [
79 | {
80 | test: /\.jsx?/,
81 | exclude: /node_modules/,
82 | use: `${eslintLoader}?cache=true`,
83 | },
84 | ],
85 | },
86 | });
87 | compiler.run(() => {
88 | const files = readdirSync(defaultCacheDir).filter((file) =>
89 | /\b[0-9a-f]{5,40}\.json\.gz\b/.test(file)
90 | );
91 | expect(files.length).toBeGreaterThan(0);
92 | done();
93 | });
94 | });
95 |
96 | it('should read from cache directory if cached file exists', (done) => {
97 | const compiler = webpack({
98 | ...globalConfig,
99 | output: {
100 | path: directory,
101 | },
102 | module: {
103 | rules: [
104 | {
105 | test: /\.jsx?/,
106 | exclude: /node_modules/,
107 | use: `${eslintLoader}?cache=${cache}`,
108 | },
109 | ],
110 | },
111 | });
112 | compiler.run(() => {
113 | const files = readdirSync(cache);
114 | expect(files.length).toBe(3);
115 | done();
116 | });
117 | });
118 |
119 | it('should generate a new file if the identifier changes', (done) => {
120 | const configs = [
121 | {
122 | ...globalConfig,
123 | output: {
124 | path: directory,
125 | },
126 | module: {
127 | rules: [
128 | {
129 | test: /\.jsx?/,
130 | exclude: /node_modules/,
131 | use: `${eslintLoader}?cache=${cache}&cacheIdentifier=a`,
132 | },
133 | ],
134 | },
135 | },
136 | {
137 | ...globalConfig,
138 | output: {
139 | path: directory,
140 | },
141 | module: {
142 | rules: [
143 | {
144 | test: /\.jsx?/,
145 | exclude: /node_modules/,
146 | use: `${eslintLoader}?cache=${cache}&cacheIdentifier=b`,
147 | },
148 | ],
149 | },
150 | },
151 | ];
152 |
153 | let counter = configs.length;
154 |
155 | configs.forEach((config) => {
156 | const compiler = webpack(config);
157 | compiler.run(() => {
158 | counter -= 1;
159 |
160 | if (!counter) {
161 | const files = readdirSync(cache);
162 | expect(files.length).toBe(6);
163 | done();
164 | }
165 | });
166 | });
167 | });
168 | });
169 |
--------------------------------------------------------------------------------
/test/cjs.test.js:
--------------------------------------------------------------------------------
1 | import EslintLoader from '../src';
2 | import CJSEslintLoader from '../src/cjs';
3 |
4 | describe('cjs', () => {
5 | it('should exported plugin', () => {
6 | expect(CJSEslintLoader).toEqual(EslintLoader);
7 | });
8 | });
9 |
--------------------------------------------------------------------------------
/test/error.test.js:
--------------------------------------------------------------------------------
1 | import pack from './utils/pack';
2 |
3 | describe('error', () => {
4 | it('should return error if file is bad', (done) => {
5 | const compiler = pack('error');
6 |
7 | compiler.run((err, stats) => {
8 | expect(stats.hasErrors()).toBe(true);
9 | done();
10 | });
11 | });
12 | });
13 |
--------------------------------------------------------------------------------
/test/eslint-path.test.js:
--------------------------------------------------------------------------------
1 | import { join } from 'path';
2 |
3 | import pack from './utils/pack';
4 |
5 | describe('eslint path', () => {
6 | it('should use another instance of eslint via eslintPath config', (done) => {
7 | const eslintPath = join(__dirname, 'mock/eslint');
8 | const compiler = pack('good', { eslintPath });
9 |
10 | compiler.run((err, stats) => {
11 | expect(stats.hasErrors()).toBe(true);
12 | expect(stats.compilation.errors[0].message).toContain('Fake error');
13 | done();
14 | });
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/test/eslintignore.test.js:
--------------------------------------------------------------------------------
1 | import pack from './utils/pack';
2 |
3 | describe('eslintignore', () => {
4 | it('should ignores files present in .eslintignore', (done) => {
5 | const compiler = pack('ignore', { ignore: true });
6 |
7 | compiler.run((err, stats) => {
8 | expect(stats.hasWarnings()).toBe(false);
9 | done();
10 | });
11 | });
12 | });
13 |
--------------------------------------------------------------------------------
/test/fail-on-error.test.js:
--------------------------------------------------------------------------------
1 | import pack from './utils/pack';
2 |
3 | describe('fail on error', () => {
4 | it('should emits errors', (done) => {
5 | const compiler = pack('error', { failOnError: true });
6 |
7 | compiler.run((err, stats) => {
8 | expect(stats.hasErrors()).toBe(true);
9 | done();
10 | });
11 | });
12 |
13 | it('should correctly indentifies a success', (done) => {
14 | const compiler = pack('good', { failOnError: true });
15 |
16 | compiler.run((err, stats) => {
17 | expect(stats.hasErrors()).toBe(false);
18 | done();
19 | });
20 | });
21 |
22 | it('should emits errors when cache enabled', (done) => {
23 | const compiler = pack('error', { failOnError: true, cache: true });
24 |
25 | compiler.run((err, stats) => {
26 | expect(stats.hasErrors()).toBe(true);
27 | done();
28 | });
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/test/fail-on-warning.test.js:
--------------------------------------------------------------------------------
1 | import pack from './utils/pack';
2 |
3 | describe('fail on warning', () => {
4 | it('should emits errors', (done) => {
5 | const compiler = pack('warn', { failOnWarning: true });
6 |
7 | compiler.run((err, stats) => {
8 | expect(stats.hasErrors()).toBe(true);
9 | done();
10 | });
11 | });
12 |
13 | it('should correctly indentifies a success', (done) => {
14 | const compiler = pack('good', { failOnWarning: true });
15 |
16 | compiler.run((err, stats) => {
17 | expect(stats.hasErrors()).toBe(false);
18 | done();
19 | });
20 | });
21 |
22 | it('should emits errors when cache enabled', (done) => {
23 | const compiler = pack('error', { failOnWarning: true, cache: true });
24 |
25 | compiler.run((err, stats) => {
26 | expect(stats.hasErrors()).toBe(true);
27 | done();
28 | });
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/test/fixtures/cache.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | require("./require")
4 |
5 | function cacheIt() {
6 | return "cache"
7 | }
8 |
9 | cacheIt()
10 |
--------------------------------------------------------------------------------
/test/fixtures/error-multi-one.js:
--------------------------------------------------------------------------------
1 | var inone = stuff
2 |
--------------------------------------------------------------------------------
/test/fixtures/error-multi-two.js:
--------------------------------------------------------------------------------
1 | var intwo = stuff
2 |
--------------------------------------------------------------------------------
/test/fixtures/error-multi.js:
--------------------------------------------------------------------------------
1 | var foo = stuff
2 |
--------------------------------------------------------------------------------
/test/fixtures/error.js:
--------------------------------------------------------------------------------
1 | var foo = stuff
2 |
--------------------------------------------------------------------------------
/test/fixtures/fixable.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | function foo() {
4 | return true
5 | }
6 |
7 | foo()
8 |
--------------------------------------------------------------------------------
/test/fixtures/good-semi.js:
--------------------------------------------------------------------------------
1 | function test() {
2 | return 'value'
3 | }
4 |
5 | test()
6 |
--------------------------------------------------------------------------------
/test/fixtures/good.js:
--------------------------------------------------------------------------------
1 | function test() {
2 | return "value"
3 | }
4 |
5 | test()
6 |
--------------------------------------------------------------------------------
/test/fixtures/ignore.js:
--------------------------------------------------------------------------------
1 | // this file should be totally ignore since it's present in .eslintignore
2 | var -dasdas;
3 |
--------------------------------------------------------------------------------
/test/fixtures/nonfixable.js:
--------------------------------------------------------------------------------
1 | function foo() {
2 | return stuff;
3 | }
4 |
5 | foo();
6 |
--------------------------------------------------------------------------------
/test/fixtures/require.js:
--------------------------------------------------------------------------------
1 | "use strict"
2 |
3 | require("./good")
--------------------------------------------------------------------------------
/test/fixtures/warn.js:
--------------------------------------------------------------------------------
1 | /* eslint no-unused-vars: warn */
2 | const foo = this
3 |
--------------------------------------------------------------------------------
/test/force-emit-error.test.js:
--------------------------------------------------------------------------------
1 | import pack from './utils/pack';
2 |
3 | describe('force emit error', () => {
4 | it('should force to emit error', (done) => {
5 | const compiler = pack('warn', { emitError: true });
6 |
7 | compiler.run((err, stats) => {
8 | expect(stats.hasWarnings()).toBe(false);
9 | expect(stats.hasErrors()).toBe(true);
10 | done();
11 | });
12 | });
13 | });
14 |
--------------------------------------------------------------------------------
/test/force-emit-warning.test.js:
--------------------------------------------------------------------------------
1 | import pack from './utils/pack';
2 |
3 | describe('force emit warning', () => {
4 | it('should force to emit warning', (done) => {
5 | const compiler = pack('error', { emitWarning: true });
6 |
7 | compiler.run((err, stats) => {
8 | expect(stats.hasWarnings()).toBe(true);
9 | expect(stats.hasErrors()).toBe(false);
10 | done();
11 | });
12 | });
13 | });
14 |
--------------------------------------------------------------------------------
/test/formatter-custom.test.js:
--------------------------------------------------------------------------------
1 | import pack from './utils/pack';
2 |
3 | describe('formatter eslint', () => {
4 | it('should use custom formatter as function', (done) => {
5 | const formatter = require('eslint-friendly-formatter');
6 | const compiler = pack('error', { formatter });
7 |
8 | compiler.run((err, stats) => {
9 | expect(stats.compilation.errors[0].message).toBeTruthy();
10 | done();
11 | });
12 | });
13 |
14 | it('should use custom formatter as string', (done) => {
15 | const formatter = 'eslint-friendly-formatter';
16 | const compiler = pack('error', { formatter });
17 |
18 | compiler.run((err, stats) => {
19 | expect(stats.compilation.errors[0].message).toBeTruthy();
20 | done();
21 | });
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/test/formatter-eslint.test.js:
--------------------------------------------------------------------------------
1 | import pack from './utils/pack';
2 |
3 | describe('formatter eslint', () => {
4 | it('should use eslint formatter', (done) => {
5 | const compiler = pack('error');
6 |
7 | compiler.run((err, stats) => {
8 | expect(stats.compilation.errors[0].message).toBeTruthy();
9 | done();
10 | });
11 | });
12 | });
13 |
--------------------------------------------------------------------------------
/test/formatter-multiple-entries.test.js:
--------------------------------------------------------------------------------
1 | import { basename, join } from 'path';
2 |
3 | import { readFileSync } from 'fs-extra';
4 | import { CLIEngine } from 'eslint';
5 | import webpack from 'webpack';
6 |
7 | import conf from './utils/conf';
8 |
9 | describe('formatter multiple entries', () => {
10 | it('should be configured to write multiple eslint result files', (done) => {
11 | const formatter = CLIEngine.getFormatter('checkstyle');
12 | const outputFilename = 'outputReport-[name].txt';
13 | const config = conf(
14 | [
15 | join(__dirname, 'fixtures/error-multi-two.js'),
16 | join(__dirname, 'fixtures/error-multi-one.js'),
17 | join(__dirname, 'fixtures/error-multi.js'),
18 | ],
19 | {
20 | formatter,
21 | outputReport: {
22 | filePath: outputFilename,
23 | formatter,
24 | },
25 | }
26 | );
27 |
28 | const compiler = webpack(config);
29 |
30 | compiler.run((err, stats) => {
31 | stats.compilation.errors.forEach((e) => {
32 | const name = basename(e.module.resource, '.js');
33 | const filename = join(config.output.path, `outputReport-${name}.txt`);
34 | const contents = readFileSync(filename, 'utf8');
35 | expect(e.error.message).toBe(contents);
36 | });
37 |
38 | done();
39 | });
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/test/formatter-official.test.js:
--------------------------------------------------------------------------------
1 | import pack from './utils/pack';
2 |
3 | describe('formatter official', () => {
4 | it('should use official formatter', (done) => {
5 | const compiler = pack('error', { formatter: 'table' });
6 |
7 | compiler.run((err, stats) => {
8 | expect(stats.compilation.errors[0].message).toBeTruthy();
9 | done();
10 | });
11 | });
12 | });
13 |
--------------------------------------------------------------------------------
/test/formatter-write.test.js:
--------------------------------------------------------------------------------
1 | import { join } from 'path';
2 |
3 | import { readFileSync } from 'fs-extra';
4 | import { CLIEngine } from 'eslint';
5 | import webpack from 'webpack';
6 |
7 | import conf from './utils/conf';
8 |
9 | describe('formatter write', () => {
10 | it('should configured to write eslint results to a file (relative path)', (done) => {
11 | const outputFilename = 'outputReport-relative.txt';
12 | const loaderOptions = {
13 | formatter: CLIEngine.getFormatter('checkstyle'),
14 | outputReport: {
15 | filePath: outputFilename,
16 | },
17 | };
18 |
19 | const config = conf('error', loaderOptions);
20 | const compiler = webpack(config);
21 |
22 | compiler.run((err, stats) => {
23 | const filePath = join(config.output.path, outputFilename);
24 | const contents = readFileSync(filePath, 'utf8');
25 |
26 | expect(stats.compilation.errors[0].error.message).toBe(contents);
27 | done();
28 | });
29 | });
30 |
31 | it('should configured to write eslint results to a file (absolute path)', (done) => {
32 | const outputFilename = 'outputReport-absolute.txt';
33 | const outputFilepath = join(__dirname, 'output', outputFilename);
34 | const loaderOptions = {
35 | formatter: CLIEngine.getFormatter('checkstyle'),
36 | outputReport: {
37 | filePath: outputFilepath,
38 | },
39 | };
40 |
41 | const config = conf('error', loaderOptions);
42 | const compiler = webpack(config);
43 |
44 | compiler.run((err, stats) => {
45 | const contents = readFileSync(outputFilepath, 'utf8');
46 |
47 | expect(stats.compilation.errors[0].error.message).toBe(contents);
48 | done();
49 | });
50 | });
51 | });
52 |
--------------------------------------------------------------------------------
/test/mock/eslint/index.js:
--------------------------------------------------------------------------------
1 | function CLIEngine() {}
2 |
3 | CLIEngine.prototype.executeOnText = function executeOnText() {
4 | return {
5 | results: [
6 | {
7 | filePath: '',
8 | messages: [
9 | {
10 | ruleId: 'no-undef',
11 | severity: 2,
12 | message: 'Fake error',
13 | line: 1,
14 | column: 11,
15 | nodeType: 'Identifier',
16 | source: 'var foo = stuff',
17 | },
18 | ],
19 | errorCount: 2,
20 | warningCount: 0,
21 | fixableErrorCount: 0,
22 | fixableWarningCount: 0,
23 | source: '',
24 | },
25 | ],
26 | errorCount: 2,
27 | warningCount: 0,
28 | fixableErrorCount: 0,
29 | fixableWarningCount: 0,
30 | };
31 | };
32 |
33 | CLIEngine.prototype.getFormatter = function getFormatter(format) {
34 | const resolvedFormatName = format || 'stylish';
35 |
36 | if (typeof resolvedFormatName !== 'string') {
37 | return null;
38 | }
39 |
40 | const eslintVersion = require('./package.json').version;
41 | const formatterPath =
42 | eslintVersion >= '6.0.0'
43 | ? './lib/cli-engine/formatters/stylish'
44 | : './lib/formatters/stylish';
45 |
46 | try {
47 | return require(formatterPath);
48 | } catch (ex) {
49 | ex.message = `There was a problem loading formatter: ${formatterPath}\nError: ${ex.message}`;
50 | throw ex;
51 | }
52 | };
53 |
54 | CLIEngine.getFormatter = CLIEngine.prototype.getFormatter;
55 |
56 | module.exports = {
57 | CLIEngine,
58 | };
59 |
--------------------------------------------------------------------------------
/test/mock/eslint/lib/cli-engine/formatters/stylish.js:
--------------------------------------------------------------------------------
1 | module.exports = function formatter(result) {
2 | return JSON.stringify(result);
3 | };
4 |
--------------------------------------------------------------------------------
/test/mock/eslint/lib/formatters/stylish.js:
--------------------------------------------------------------------------------
1 | module.exports = function formatter(result) {
2 | return JSON.stringify(result);
3 | };
4 |
--------------------------------------------------------------------------------
/test/mock/eslint/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "eslint",
3 | "version": "5.16.0"
4 | }
5 |
--------------------------------------------------------------------------------
/test/multiple-engines.test.js:
--------------------------------------------------------------------------------
1 | import { join } from 'path';
2 |
3 | import pack from './utils/pack';
4 |
5 | describe('multiple engines', () => {
6 | it('should will create an engine for each unique config', (done) => {
7 | const loader = join(__dirname, '../src/index');
8 | const compiler = pack(
9 | 'good',
10 | {},
11 | {
12 | module: {
13 | rules: [
14 | {
15 | test: /\.js$/,
16 | exclude: /node_modules/,
17 | loader,
18 | options: {
19 | ignore: false,
20 | rules: {
21 | quotes: [1, 'single'],
22 | },
23 | },
24 | },
25 | {
26 | test: /\.js$/,
27 | exclude: /node_modules/,
28 | loader,
29 | options: {
30 | ignore: false,
31 | rules: {
32 | semi: [1, 'always'],
33 | },
34 | },
35 | },
36 | ],
37 | },
38 | }
39 | );
40 |
41 | compiler.run((err, stats) => {
42 | const { warnings } = stats.compilation;
43 | const quotes = warnings.find((warning) => /quotes/.test(warning));
44 | const semi = warnings.find((warning) => /semi/.test(warning));
45 |
46 | expect(warnings.length).toBe(2);
47 | expect(quotes).toBeTruthy();
48 | expect(semi).toBeTruthy();
49 | done();
50 | });
51 | });
52 | });
53 |
--------------------------------------------------------------------------------
/test/no-eslint-configuration.test.js:
--------------------------------------------------------------------------------
1 | import pack from './utils/pack';
2 |
3 | describe('no eslint configuration', () => {
4 | it('should emit warning when there is no eslint configuration', (done) => {
5 | const compiler = pack('good', { cwd: '/' });
6 |
7 | compiler.run((err, stats) => {
8 | expect(stats.hasWarnings()).toBe(true);
9 |
10 | const { warnings } = stats.compilation;
11 | expect(warnings[0].message).toMatch(/No ESLint configuration/i);
12 | done();
13 | });
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/test/ok.test.js:
--------------------------------------------------------------------------------
1 | import pack from './utils/pack';
2 |
3 | describe('ok', () => {
4 | it("should don't throw error if file is ok", (done) => {
5 | const compiler = pack('good');
6 |
7 | compiler.run((err, stats) => {
8 | expect(stats.hasWarnings()).toBe(false);
9 | expect(stats.hasErrors()).toBe(false);
10 | done();
11 | });
12 | });
13 | });
14 |
--------------------------------------------------------------------------------
/test/parameters.test.js:
--------------------------------------------------------------------------------
1 | import pack from './utils/pack';
2 |
3 | describe('parameters', () => {
4 | it('should supports query strings parameters', (done) => {
5 | const compiler = pack('good', { rules: { semi: 0 } });
6 |
7 | compiler.run((err, stats) => {
8 | expect(stats.hasWarnings()).toBe(false);
9 | expect(stats.hasErrors()).toBe(false);
10 | done();
11 | });
12 | });
13 | });
14 |
--------------------------------------------------------------------------------
/test/quiet.test.js:
--------------------------------------------------------------------------------
1 | import pack from './utils/pack';
2 |
3 | describe('quiet', () => {
4 | it('should not emit warnings if quiet is set', (done) => {
5 | const compiler = pack('warn', { quiet: true });
6 |
7 | compiler.run((err, stats) => {
8 | expect(stats.hasWarnings()).toBe(false);
9 | expect(stats.hasErrors()).toBe(false);
10 | done();
11 | });
12 | });
13 | });
14 |
--------------------------------------------------------------------------------
/test/utils/conf.js:
--------------------------------------------------------------------------------
1 | import { join } from 'path';
2 |
3 | export default (entry, loaderConf = {}, webpackConf = {}) => {
4 | const testDir = join(__dirname, '..');
5 | const fixturesDir = join(testDir, 'fixtures');
6 |
7 | return {
8 | entry: typeof entry === 'string' ? join(fixturesDir, `${entry}.js`) : entry,
9 | mode: 'development',
10 | output: {
11 | path: join(testDir, 'output'),
12 | filename: 'bundle.js',
13 | },
14 | module: {
15 | rules: [
16 | {
17 | test: /\.js$/,
18 | exclude: /node_modules/,
19 | use: [
20 | {
21 | loader: join(testDir, '../src/index'),
22 | options: {
23 | // this disables the use of .eslintignore, since it contains the fixtures
24 | // folder to skip it on the global linting, but here we want the opposite
25 | // (we only use .eslintignore on the test that checks this)
26 | ignore: false,
27 | ...loaderConf,
28 | },
29 | },
30 | ],
31 | },
32 | ],
33 | },
34 | ...webpackConf,
35 | };
36 | };
37 |
--------------------------------------------------------------------------------
/test/utils/pack.js:
--------------------------------------------------------------------------------
1 | import webpack from 'webpack';
2 |
3 | import conf from './conf';
4 |
5 | export default (entry, loaderConf = {}, webpackConf = {}) => {
6 | return webpack(conf(entry, loaderConf, webpackConf));
7 | };
8 |
--------------------------------------------------------------------------------
/test/warning.test.js:
--------------------------------------------------------------------------------
1 | import pack from './utils/pack';
2 |
3 | describe('warning', () => {
4 | it('should emit warnings', (done) => {
5 | const compiler = pack('warn');
6 |
7 | compiler.run((err, stats) => {
8 | expect(stats.hasWarnings()).toBe(true);
9 | expect(stats.hasErrors()).toBe(false);
10 | done();
11 | });
12 | });
13 | });
14 |
--------------------------------------------------------------------------------