1 | eslint-plugin-html
|
2 | ==================
|
3 |
|
4 | [![NPM version](https://img.shields.io/npm/v/eslint-plugin-html.svg)](https://www.npmjs.com/package/eslint-plugin-html)
|
5 | [![Build Status](https://travis-ci.org/BenoitZugmeyer/eslint-plugin-html.svg?branch=master)](https://travis-ci.org/BenoitZugmeyer/eslint-plugin-html)
|
6 |
|
7 |
|
8 | This [`ESLint`](http://eslint.org) plugin allows linting and fixing inline scripts contained in HTML
|
9 | files.
|
10 |
|
11 | Migration to v4
|
12 | ---------------
|
13 |
|
14 | `eslint-plugin-html` v4 requires at least ESLint v4.7. This is because a lot of internal changes
|
15 | occured in ESLint v4.7, including a [new API to support autofixing in
|
16 | preprocessors](https://eslint.org/docs/developer-guide/working-with-plugins#processors-in-plugins).
|
17 | If you are still using an older version of ESLint, please consider upgrading, or keep using
|
18 | `eslint-plugin-html` v3.
|
19 |
|
20 | The big feature (and breaking change) in `eslint-plugin-html` v4 is the ability to chose how [scopes
|
21 | are shared between script tags in the same HTML file](#multiple-scripts-tags-in-a-html-file).
|
22 |
|
23 |
|
24 | Migration to v3
|
25 | ---------------
|
26 |
|
27 | If you are considering upgrading to v3, please read [this guide](MIGRATION_TO_V3.md).
|
28 |
|
29 | Usage
|
30 | -----
|
31 |
|
32 | Simply install via `npm install --save-dev eslint-plugin-html` and add the plugin to your ESLint
|
33 | configuration. See
|
34 | [ESLint documentation](http://eslint.org/docs/user-guide/configuring#configuring-plugins).
|
35 |
|
36 | Example:
|
37 |
|
38 | ```javascript
|
39 | {
|
40 | "plugins": [
|
41 | "html"
|
42 | ]
|
43 | }
|
44 | ```
|
45 |
|
46 | Note: by default, when executing the `eslint` command on a directory, only `.js` files will be
|
47 | linted. You will have to specify extra extensions with the `--ext` option. Example: `eslint --ext
|
48 | .html,.js src` will lint both `.html` and `.js` files in the `src` directory. See [ESLint
|
49 | documentation](http://eslint.org/docs/user-guide/command-line-interface#ext).
|
50 |
|
51 | Multiple scripts tags in a HTML file
|
52 | ------------------------------------
|
53 |
|
54 | When linting a HTML with multiple script tags, this plugin tries to emulate the browser behavior by
|
55 | sharing the global scope between scripts by default. This behavior doesn't apply to "module"
|
56 | scripts (ie: `<script type="module">` and most transpiled code), where [each script tag gets its own
|
57 | top-level scope](http://exploringjs.com/es6/ch_modules.html#_modules).
|
58 |
|
59 | ESLint has already [an
|
60 | option](https://eslint.org/docs/user-guide/configuring#specifying-parser-options) to tell the parser
|
61 | if the script are modules. `eslint-plugin-html` will use this option as well to know if the scopes
|
62 | should be shared (the default) or not. To change this, just set it in your ESLint configuration:
|
63 |
|
64 | ```
|
65 | {
|
66 | "parserOptions": {
|
67 | "sourceType": "module"
|
68 | }
|
69 | }
|
70 | ```
|
71 |
|
72 | To illustrate this behavior, consider this HTML extract:
|
73 |
|
74 | ```html
|
75 | <script>
|
76 | var foo = 1;
|
77 | </script>
|
78 |
|
79 | <script>
|
80 | alert(foo);
|
81 | </script>
|
82 | ```
|
83 |
|
84 | This is perfectly valid by default, and the ESLint rules `no-unused-vars` and `no-undef` shouldn't
|
85 | complain. But if those scripts are considerated as ES modules, `no-unused-vars` should report an
|
86 | error in the first script, and `no-undef` should report an error in the second script.
|
87 |
|
88 | ### History
|
89 |
|
90 | In `eslint-plugin-html` v1 and v2, script code were concatenated and linted in a single pass, so
|
91 | the scope were always shared. This caused [some issues](MIGRATION_TO_V3.md), so in v3 all scripts
|
92 | were linted separately, and scopes were never shared. In v4, the plugin still lint scripts
|
93 | separately, but makes sure global variables are declared and used correctly in the non-module case.
|
94 |
|
95 |
|
96 | XML support
|
97 | -----------
|
98 |
|
99 | This plugin parses HTML and XML markup slightly differently, mainly when considering `CDATA`
|
100 | sections:
|
101 | * in XML, any data inside a `CDATA` section will be considered as raw text (not XML) and the `CDATA`
|
102 | delimiter will be droped ;
|
103 | * in HTML, there is no such thing for `<script>` tags: the `CDATA` delimiter is considered as normal
|
104 | text and thus, part of the script.
|
105 |
|
106 |
|
107 | Settings
|
108 | --------
|
109 |
|
110 | > Note: all settings can be written either as `"html/key": value` or in a nested object `"html": {
|
111 | > "key": value }`
|
112 |
|
113 | ### `html/html-extensions`
|
114 |
|
115 | By default, this plugin will only consider files ending with those extensions as HTML: `.erb`,
|
116 | `.handlebars`, `.hbs`, `.htm`, `.html`, `.mustache`, `.nunjucks`, `.php`, `.tag`, `.twig`, `.we`.
|
117 | You can set your own list of HTML extensions by using this setting. Example:
|
118 |
|
119 | ```javascript
|
120 | {
|
121 | "plugins": [ "html" ],
|
122 | "settings": {
|
123 | "html/html-extensions": [".html", ".we"], // consider .html and .we files as HTML
|
124 | }
|
125 | }
|
126 | ```
|
127 |
|
128 |
|
129 | ### `html/xml-extensions`
|
130 |
|
131 | By default, this plugin will only consider files ending with those extensions as XML: `.xhtml`,
|
132 | `.xml`. You can set your own list of XML extensions by using this setting. Example:
|
133 |
|
134 | ```javascript
|
135 | {
|
136 | "plugins": [ "html" ],
|
137 | "settings": {
|
138 | "html/xml-extensions": [".html"], // consider .html files as XML
|
139 | }
|
140 | }
|
141 | ```
|
142 |
|
143 |
|
144 | ### `html/indent`
|
145 |
|
146 | By default, the code between `<script>` tags is dedented according to the first non-empty line. The
|
147 | setting `html/indent` allows to ensure that every script tags follow an uniform indentation. Like
|
148 | the `indent` rule, you can pass a number of spaces, or `"tab"` to indent with one tab. Prefix this
|
149 | value with a `+` to be relative to the `<script>` tag indentation. Example:
|
150 |
|
151 | ```javascript
|
152 | {
|
153 | "plugins": [ "html" ],
|
154 | "settings": {
|
155 | "html/indent": "0", // code should start at the beginning of the line (no initial indentation).
|
156 | "html/indent": "+2", // indentation is the <script> indentation plus two spaces.
|
157 | "html/indent": "tab", // indentation is one tab at the beginning of the line.
|
158 | }
|
159 | }
|
160 | ```
|
161 |
|
162 |
|
163 | ### `html/report-bad-indent`
|
164 |
|
165 | By default, this plugin won't warn if it encounters a problematic indentation (ex: a line is under
|
166 | indented). If you want to make sure the indentation is correct, use the `html/report-bad-indent` in
|
167 | conjunction with the `indent` rule. Pass `"warn"` or `1` to display warnings, `"error"` or `2` to
|
168 | display errors. Example:
|
169 |
|
170 | ```javascript
|
171 | {
|
172 | "plugins": [ "html" ],
|
173 | "settings": {
|
174 | "html/report-bad-indent": "error",
|
175 | }
|
176 | }
|
177 | ```
|
178 |
|
179 |
|
180 | ### `html/javascript-mime-types`
|
181 |
|
182 | By default, the code between `<script>` tags is considered as JavaScript code only if there is no
|
183 | `type` attribute or if its value matches the pattern
|
184 | `(application|text)/(x-)?(javascript|babel|ecmascript-6)` or `module` (case insensitive). You can
|
185 | customize the types that should be considered as JavaScript by providing one or multiple MIME types.
|
186 | If a MIME type starts with a `/`, it will be considered as a regular expression. Example:
|
187 |
|
188 | ```javascript
|
189 | {
|
190 | "plugins": [ "html" ],
|
191 | "settings": {
|
192 | "html/javascript-mime-types": ["text/javascript", "text/jsx"], // also use script tags with a "text/jsx" type attribute
|
193 | "html/javascript-mime-types": "/^text\\/(javascript|jsx)$/", // same thing
|
194 | }
|
195 | }
|
196 | ```
|
197 |
|
198 | Troubleshooting
|
199 | ---------------
|
200 |
|
201 | ### Linting templates (or PHP)
|
202 |
|
203 | `eslint-plugin-html` won't evaluate or remove your template markup. If you have template markup in
|
204 | your script tags, the resulting script may not be valid JavaScript, so `ESLint` will fail to parse
|
205 | it.
|
206 |
|
207 | One possible hacky workaround to make sure the code is valid JavaScript is to put your template
|
208 | markup inside a comment. When the template is rendered, the generated JS code must start with a new
|
209 | line, so it will be written below the comment. PHP example:
|
210 |
|
211 | ```html
|
212 | <script>
|
213 | var mydata;
|
214 | // <?= "\n mydata = " . json_encode($var) . ";" ?>
|
215 | console.log(mydata);
|
216 | </script>
|
217 | ```
|
218 |
|
219 |
|
220 | ### Linting VUE files
|
221 |
|
222 | Initially, [`eslint-plugin-vue`](https://github.com/vuejs/eslint-plugin-vue) was using
|
223 | `eslint-plugin-html` to lint code inside script tags. Since v3, `eslint-plugin-vue` is using its
|
224 | own parser, so it is *incompatible* with `eslint-plugin-html`. You should use `eslint-plugin-vue`
|
225 | exclusively and remove `eslint-plugin-html` from your dependencies if you still have it.
|