UNPKG

11.1 kBMarkdownView Raw
1<div align="center">
2 <img src="media/logo.svg" width="150" height="150">
3 <h1>eslint-plugin-html</h1>
4 <a href="https://www.npmjs.com/package/eslint-plugin-html"><img alt="NPM version" src="https://img.shields.io/npm/v/eslint-plugin-html"></a>
5 <a href="https://github.com/BenoitZugmeyer/eslint-plugin-html/actions/workflows/tests.yml"><img alt="Tests Status" src="https://img.shields.io/github/actions/workflow/status/BenoitZugmeyer/eslint-plugin-html/tests.yml"></a>
6 <p>A <a href="http://eslint.org">ESLint</a> plugin to lint and fix inline scripts contained in HTML files.</p>
7</div>
8
9- [Usage](#usage)
10- [Disabling ESLint](#disabling-eslint)
11- [Linting HTML](#linting-html)
12- [Multiple scripts tags in a HTML file](#multiple-scripts-tags-in-a-html-file)
13 - [History](#history)
14- [XML support](#xml-support)
15- [Settings](#settings)
16 - [`html/html-extensions`](#htmlhtml-extensions)
17 - [`html/xml-extensions`](#htmlxml-extensions)
18 - [`html/indent`](#htmlindent)
19 - [`html/report-bad-indent`](#htmlreport-bad-indent)
20 - [`html/javascript-tag-names`](#htmljavascript-tag-names)
21 - [`html/javascript-mime-types`](#htmljavascript-mime-types)
22 - [`html/ignore-tags-without-type`](#htmlignore-tags-without-type)
23- [Troubleshooting](#troubleshooting)
24 - [No file linted when running `eslint` on a directory](#no-file-linted-when-running-eslint-on-a-directory)
25 - [Linting templates (or PHP)](#linting-templates-or-php)
26 - [Linting VUE files](#linting-vue-files)
27- [Migration from older versions](#migration-from-older-versions)
28 - [To v4](#to-v4)
29 - [To v3](#to-v3)
30- [Credits](#credits)
31
32## Usage
33
34Simply install via `npm install --save-dev eslint-plugin-html` and add the plugin to your ESLint
35configuration. See
36[ESLint documentation](http://eslint.org/docs/user-guide/configuring#configuring-plugins).
37
38Example:
39
40```javascript
41{
42 "plugins": [
43 "html"
44 ]
45}
46```
47
48## Disabling ESLint
49
50To temporarily disable ESLint, use the `<!-- eslint-disable -->` HTML comment. Re-enable it with
51`<!-- eslint enable -->`. Example:
52
53```html
54<!-- eslint-disable -->
55<script>
56 var foo = 1
57</script>
58<!-- eslint-enable -->
59```
60
61To disable ESLint for the next script tag only, use the `<!-- eslint-disable-next-script -->` HTML
62comment. Example:
63
64```html
65<!-- eslint-disable-next-script -->
66<script>
67 var foo = 1
68</script>
69```
70
71Disabled script tags are completely ignored: their content will not be parsed as JavaScript. You can
72use this to disable script tags containing template syntax.
73
74## Linting HTML
75
76This plugin focuses on applying ESLint rules on inline scripts contained in HTML. It does not
77provide any rule related to HTML. For that, you can use other plugins like
78[`@eslint-html`](https://yeonjuan.github.io/html-eslint/) or
79[@angular-eslint](https://github.com/angular-eslint/angular-eslint). `eslint-plugin-html` is
80compatible with those plugins and can be used along them.
81
82## Multiple scripts tags in a HTML file
83
84When linting a HTML with multiple script tags, this plugin tries to emulate the browser behavior by
85sharing the global scope between scripts by default. This behavior doesn't apply to "module"
86scripts (ie: `<script type="module">` and most transpiled code), where [each script tag gets its own
87top-level scope](http://exploringjs.com/es6/ch_modules.html#_modules).
88
89ESLint has already [an
90option](https://eslint.org/docs/user-guide/configuring#specifying-parser-options) to tell the parser
91if the script are modules. `eslint-plugin-html` will use this option as well to know if the scopes
92should be shared (the default) or not. To change this, just set it in your ESLint configuration:
93
94```
95{
96 "parserOptions": {
97 "sourceType": "module"
98 }
99}
100```
101
102To illustrate this behavior, consider this HTML extract:
103
104```html
105<script>
106 var foo = 1
107</script>
108
109<script>
110 alert(foo)
111</script>
112```
113
114This is perfectly valid by default, and the ESLint rules `no-unused-vars` and `no-undef` shouldn't
115complain. But if those scripts are considerated as ES modules, `no-unused-vars` should report an
116error in the first script, and `no-undef` should report an error in the second script.
117
118### History
119
120In `eslint-plugin-html` v1 and v2, script code were concatenated and linted in a single pass, so
121the scope were always shared. This caused [some issues](MIGRATION_TO_V3.md), so in v3 all scripts
122were linted separately, and scopes were never shared. In v4, the plugin still lint scripts
123separately, but makes sure global variables are declared and used correctly in the non-module case.
124
125## XML support
126
127This plugin parses HTML and XML markup slightly differently, mainly when considering `CDATA`
128sections:
129
130- in XML, any data inside a `CDATA` section will be considered as raw text (not XML) and the `CDATA`
131 delimiter will be droped ;
132- in HTML, there is no such thing for `<script>` tags: the `CDATA` delimiter is considered as normal
133 text and thus, part of the script.
134
135## Settings
136
137> Note: all settings can be written either as `"html/key": value` or in a nested object `"html": { "key": value }`
138
139### `html/html-extensions`
140
141By default, this plugin will only consider files ending with those extensions as HTML: `.erb`,
142`.handlebars`, `.hbs`, `.htm`, `.html`, `.mustache`, `.nunjucks`, `.php`, `.tag`, `.twig`, `.we`.
143You can set your own list of HTML extensions by using this setting. Example:
144
145```javascript
146{
147 "plugins": [ "html" ],
148 "settings": {
149 "html/html-extensions": [".html", ".we"], // consider .html and .we files as HTML
150 }
151}
152```
153
154### `html/xml-extensions`
155
156By default, this plugin will only consider files ending with those extensions as XML: `.xhtml`,
157`.xml`. You can set your own list of XML extensions by using this setting. Example:
158
159```javascript
160{
161 "plugins": [ "html" ],
162 "settings": {
163 "html/xml-extensions": [".html"], // consider .html files as XML
164 }
165}
166```
167
168### `html/indent`
169
170By default, the code between `<script>` tags is dedented according to the first non-empty line. The
171setting `html/indent` allows to ensure that every script tags follow an uniform indentation. Like
172the `indent` rule, you can pass a number of spaces, or `"tab"` to indent with one tab. Prefix this
173value with a `+` to be relative to the `<script>` tag indentation. Example:
174
175```javascript
176{
177 "plugins": [ "html" ],
178 "settings": {
179 "html/indent": "0", // code should start at the beginning of the line (no initial indentation).
180 "html/indent": "+2", // indentation is the <script> indentation plus two spaces.
181 "html/indent": "tab", // indentation is one tab at the beginning of the line.
182 }
183}
184```
185
186### `html/report-bad-indent`
187
188By default, this plugin won't warn if it encounters a problematic indentation (ex: a line is under
189indented). If you want to make sure the indentation is correct, use the `html/report-bad-indent` in
190conjunction with the `indent` rule. Pass `"warn"` or `1` to display warnings, `"error"` or `2` to
191display errors. Example:
192
193```javascript
194{
195 "plugins": [ "html" ],
196 "settings": {
197 "html/report-bad-indent": "error",
198 }
199}
200```
201
202### `html/javascript-tag-names`
203
204By default, the code between `<script>` tags is considered as JavaScript. You can customize which
205tags should be considered JavaScript by providing one or multiple tag names.
206
207Example:
208
209```javascript
210{
211 "plugins": [ "html" ],
212 "settings": {
213 "html/javascript-tag-names": ["script", "customscript"],
214 }
215}
216```
217
218### `html/javascript-mime-types`
219
220By default, the code between `<script>` tags is considered as JavaScript code only if there is no
221`type` attribute or if its value matches the pattern
222`(application|text)/(x-)?(javascript|babel|ecmascript-6)` or `module` (case insensitive). You can
223customize the types that should be considered as JavaScript by providing one or multiple MIME types.
224If a MIME type starts with a `/`, it will be considered as a regular expression. Example:
225
226```javascript
227{
228 "plugins": [ "html" ],
229 "settings": {
230 "html/javascript-mime-types": ["text/javascript", "text/jsx"], // also use script tags with a "text/jsx" type attribute
231 "html/javascript-mime-types": "/^text\\/(javascript|jsx)$/", // same thing
232 }
233}
234```
235
236### `html/ignore-tags-without-type`
237
238By default, the code between `<script>` tags is considered JavaScript if there is no `type`
239attribute. You can set this setting to `true` to ignore script tags without a `type` attribute.
240Example:
241
242```javascript
243{
244 "plugins": [ "html" ],
245 "settings": {
246 "html/ignore-tags-without-type": true,
247 }
248}
249```
250
251## Troubleshooting
252
253### No file linted when running `eslint` on a directory
254
255By default, when executing the `eslint` command on a directory, only `.js` files will be linted. You
256will have to specify extra extensions with the `--ext` option. Example: `eslint --ext .html,.js src`
257will lint both `.html` and `.js` files in the `src` directory. See [ESLint
258documentation](http://eslint.org/docs/user-guide/command-line-interface#ext).
259
260### Linting templates (or PHP)
261
262`eslint-plugin-html` won't evaluate or remove your template markup. If you have template markup in
263your script tags, the resulting script may not be valid JavaScript, so `ESLint` will fail to parse
264it. Here are some workarounds:
265
266- You can use [HTML comments to disable ESLint](#disabling-eslint) for specific script tags.
267
268- For PHP, you can use
269 [`eslint-plugin-php-markup`](https://github.com/tengattack/eslint-plugin-php-markup) to lint php
270 files, it use a same way to process php markup like `eslint-plugin-html`.
271
272- Another possible hacky workaround to make sure the code is valid JavaScript is to put your
273 template markup inside a comment. When the template is rendered, the generated JS code must start
274 with a new line, so it will be written below the comment. PHP example:
275
276```html
277<script>
278 var mydata
279 // <?= "\n mydata = " . json_encode($var) . ";" ?>
280 console.log(mydata)
281</script>
282```
283
284### Linting VUE files
285
286Initially, [`eslint-plugin-vue`](https://github.com/vuejs/eslint-plugin-vue) was using
287`eslint-plugin-html` to lint code inside script tags. Since v3, `eslint-plugin-vue` is using its
288own parser, so it is _incompatible_ with `eslint-plugin-html`. You should use `eslint-plugin-vue`
289exclusively and remove `eslint-plugin-html` from your dependencies if you still have it.
290
291## Migration from older versions
292
293### To v4
294
295`eslint-plugin-html` v4 requires at least ESLint v4.7. This is because a lot of internal changes
296occured in ESLint v4.7, including a [new API to support autofixing in
297preprocessors](https://eslint.org/docs/developer-guide/working-with-plugins#processors-in-plugins).
298If you are still using an older version of ESLint, please consider upgrading, or keep using
299`eslint-plugin-html` v3.
300
301The big feature (and breaking change) in `eslint-plugin-html` v4 is the ability to choose how [scopes
302are shared between script tags in the same HTML file](#multiple-scripts-tags-in-a-html-file).
303
304### To v3
305
306If you are considering upgrading to v3, please read [this guide](MIGRATION_TO_V3.md).
307
308## Credits
309
310A big thank you to [@kuceb](https://github.com/kuceb) for the logo image!