{"id":14978261,"url":"https://github.com/benoitzugmeyer/eslint-plugin-html","last_synced_at":"2025-05-14T18:05:00.128Z","repository":{"id":29909001,"uuid":"33454800","full_name":"BenoitZugmeyer/eslint-plugin-html","owner":"BenoitZugmeyer","description":"An ESLint plugin to extract and lint scripts from HTML files.","archived":false,"fork":false,"pushed_at":"2025-03-03T15:11:50.000Z","size":1357,"stargazers_count":440,"open_issues_count":14,"forks_count":54,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-05-14T18:04:58.555Z","etag":null,"topics":["eslint","eslint-plugin","html","javascript"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/BenoitZugmeyer.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-04-05T20:51:21.000Z","updated_at":"2025-04-21T15:02:31.000Z","dependencies_parsed_at":"2024-01-02T23:42:59.081Z","dependency_job_id":"4facdb0a-d034-4dd5-9b5f-0b00c24b271d","html_url":"https://github.com/BenoitZugmeyer/eslint-plugin-html","commit_stats":{"total_commits":388,"total_committers":32,"mean_commits":12.125,"dds":"0.18556701030927836","last_synced_commit":"bbbad6b18ccb8da0ce4c7cf9fac4596830b47a8e"},"previous_names":[],"tags_count":59,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BenoitZugmeyer%2Feslint-plugin-html","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BenoitZugmeyer%2Feslint-plugin-html/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BenoitZugmeyer%2Feslint-plugin-html/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BenoitZugmeyer%2Feslint-plugin-html/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BenoitZugmeyer","download_url":"https://codeload.github.com/BenoitZugmeyer/eslint-plugin-html/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254198514,"owners_count":22030965,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["eslint","eslint-plugin","html","javascript"],"created_at":"2024-09-24T13:57:11.122Z","updated_at":"2025-05-14T18:05:00.076Z","avatar_url":"https://github.com/BenoitZugmeyer.png","language":"JavaScript","readme":"\u003cdiv align=\"center\"\u003e\n    \u003cimg src=\"media/logo.svg\" width=\"150\" height=\"150\"\u003e\n    \u003ch1\u003eeslint-plugin-html\u003c/h1\u003e\n    \u003ca href=\"https://www.npmjs.com/package/eslint-plugin-html\"\u003e\u003cimg alt=\"NPM version\" src=\"https://img.shields.io/npm/v/eslint-plugin-html\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/BenoitZugmeyer/eslint-plugin-html/actions/workflows/tests.yml\"\u003e\u003cimg alt=\"Tests Status\" src=\"https://img.shields.io/github/actions/workflow/status/BenoitZugmeyer/eslint-plugin-html/tests.yml\"\u003e\u003c/a\u003e\n    \u003cp\u003eA \u003ca href=\"http://eslint.org\"\u003eESLint\u003c/a\u003e plugin to lint and fix inline scripts contained in HTML files.\u003c/p\u003e\n\u003c/div\u003e\n\n- [Usage](#usage)\n- [Disabling ESLint](#disabling-eslint)\n- [Linting HTML](#linting-html)\n- [Multiple scripts tags in a HTML file](#multiple-scripts-tags-in-a-html-file)\n  - [History](#history)\n- [XML support](#xml-support)\n- [Settings](#settings)\n  - [`html/html-extensions`](#htmlhtml-extensions)\n  - [`html/xml-extensions`](#htmlxml-extensions)\n  - [`html/indent`](#htmlindent)\n  - [`html/report-bad-indent`](#htmlreport-bad-indent)\n  - [`html/javascript-tag-names`](#htmljavascript-tag-names)\n  - [`html/javascript-mime-types`](#htmljavascript-mime-types)\n  - [`html/ignore-tags-without-type`](#htmlignore-tags-without-type)\n- [Troubleshooting](#troubleshooting)\n  - [No file linted when running `eslint` on a directory](#no-file-linted-when-running-eslint-on-a-directory)\n  - [Linting templates (or PHP)](#linting-templates-or-php)\n  - [Linting VUE files](#linting-vue-files)\n- [Migration from older versions](#migration-from-older-versions)\n  - [To v4](#to-v4)\n  - [To v3](#to-v3)\n- [Credits](#credits)\n\n## Usage\n\nSimply install via `npm install --save-dev eslint-plugin-html` and add the plugin to your ESLint\nconfiguration. See\n[ESLint documentation](http://eslint.org/docs/user-guide/configuring#configuring-plugins).\n\n\u003cdetails open\u003e\n  \u003csummary\u003eExample with ESLint 9 and above (flat config)\u003c/summary\u003e\n\n```javascript\nimport html from \"eslint-plugin-html\"\n\nexport default [\n  {\n    files: [\"**/*.html\"],\n    plugins: { html },\n  },\n]\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eExample with ESLint 8 and below\u003c/summary\u003e\n\n```json\n{\n  \"plugins\": [\"html\"]\n}\n```\n\n\u003c/details\u003e\n\n## Disabling ESLint\n\nTo temporarily disable ESLint, use the `\u003c!-- eslint-disable --\u003e` HTML comment. Re-enable it with\n`\u003c!-- eslint enable --\u003e`. Example:\n\n```html\n\u003c!-- eslint-disable --\u003e\n\u003cscript\u003e\n  var foo = 1\n\u003c/script\u003e\n\u003c!-- eslint-enable --\u003e\n```\n\nTo disable ESLint for the next script tag only, use the `\u003c!-- eslint-disable-next-script --\u003e` HTML\ncomment. Example:\n\n```html\n\u003c!-- eslint-disable-next-script --\u003e\n\u003cscript\u003e\n  var foo = 1\n\u003c/script\u003e\n```\n\nDisabled script tags are completely ignored: their content will not be parsed as JavaScript. You can\nuse this to disable script tags containing template syntax.\n\n## Linting HTML\n\nThis plugin focuses on applying ESLint rules on inline scripts contained in HTML. It does not\nprovide any rule related to HTML. For that, you can use other plugins like\n[`@eslint-html`](https://yeonjuan.github.io/html-eslint/) or\n[@angular-eslint](https://github.com/angular-eslint/angular-eslint). `eslint-plugin-html` is\ncompatible with those plugins and can be used along them.\n\n## Multiple scripts tags in a HTML file\n\nWhen linting a HTML with multiple script tags, this plugin tries to emulate the browser behavior by\nsharing the global scope between scripts by default. This behavior doesn't apply to \"module\"\nscripts (ie: `\u003cscript type=\"module\"\u003e` and most transpiled code), where [each script tag gets its own\ntop-level scope](http://exploringjs.com/es6/ch_modules.html#_modules).\n\nESLint has already [an\noption](https://eslint.org/docs/user-guide/configuring#specifying-parser-options) to tell the parser\nif the script are modules. `eslint-plugin-html` will use this option as well to know if the scopes\nshould be shared (the default) or not. To change this, just set it in your ESLint configuration:\n\n\u003cdetails open\u003e\n\u003csummary\u003eESLint 9 and above (flat config)\u003c/summary\u003e\n\n```javascript\nexport default [\n  {\n    // ...\n    languageOptions: {\n      sourceType: \"module\",\n    },\n  },\n]\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eESLint 8 and below\u003c/summary\u003e\n\n```json\n{\n  \"parserOptions\": {\n    \"sourceType\": \"module\"\n  }\n}\n```\n\n\u003c/details\u003e\n\nTo illustrate this behavior, consider this HTML extract:\n\n```html\n\u003cscript\u003e\n  var foo = 1\n\u003c/script\u003e\n\n\u003cscript\u003e\n  alert(foo)\n\u003c/script\u003e\n```\n\nThis is perfectly valid by default, and the ESLint rules `no-unused-vars` and `no-undef` shouldn't\ncomplain. But if those scripts are considerated as ES modules, `no-unused-vars` should report an\nerror in the first script, and `no-undef` should report an error in the second script.\n\n### History\n\nIn `eslint-plugin-html` v1 and v2, script code were concatenated and linted in a single pass, so\nthe scope were always shared. This caused [some issues](MIGRATION_TO_V3.md), so in v3 all scripts\nwere linted separately, and scopes were never shared. In v4, the plugin still lint scripts\nseparately, but makes sure global variables are declared and used correctly in the non-module case.\n\n## XML support\n\nThis plugin parses HTML and XML markup slightly differently, mainly when considering `CDATA`\nsections:\n\n- in XML, any data inside a `CDATA` section will be considered as raw text (not XML) and the `CDATA`\n  delimiter will be droped ;\n- in HTML, there is no such thing for `\u003cscript\u003e` tags: the `CDATA` delimiter is considered as normal\n  text and thus, part of the script.\n\n## Settings\n\n\u003e Note: all settings can be written either as `\"html/key\": value` or in a nested object `\"html\": { \"key\": value }`\n\n### `html/html-extensions`\n\nBy default, this plugin will only consider files ending with those extensions as HTML: `.erb`,\n`.handlebars`, `.hbs`, `.htm`, `.html`, `.mustache`, `.nunjucks`, `.php`, `.tag`, `.twig`, `.we`.\nYou can set your own list of HTML extensions by using this setting. Example:\n\n\u003cdetails open\u003e\n  \u003csummary\u003eESLint 9 and above (flat config)\u003c/summary\u003e\n\n```javascript\nexport default [\n  {\n    files: [\"**/*.html\", \"**/*.we\"],\n    plugins: { html },\n    settings: {\n      \"html/html-extensions\": [\".html\", \".we\"], // consider .html and .we files as HTML\n    },\n  },\n]\n```\n\nNote: you need to specify extensions twice, which is not ideal. This should be imporved in the\nfuture.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eESLint 8 and below\u003c/summary\u003e\n\n```json\n{\n  \"plugins\": [\"html\"],\n  \"settings\": {\n    \"html/html-extensions\": [\".html\", \".we\"] // consider .html and .we files as HTML\n  }\n}\n```\n\n\u003c/details\u003e\n\n### `html/xml-extensions`\n\nBy default, this plugin will only consider files ending with those extensions as XML: `.xhtml`,\n`.xml`. You can set your own list of XML extensions by using this setting. Example:\n\n\u003cdetails open\u003e\n  \u003csummary\u003eESLint 9 and above (flat config)\u003c/summary\u003e\n\n```javascript\nexport default [\n  {\n    files: [\"**/*.html\"],\n    plugins: { html },\n    settings: {\n      \"html/xml-extensions\": [\".html\"], // consider .html files as XML\n    },\n  },\n]\n```\n\nNote: you need to specify extensions twice, which is not ideal. This should be imporved in the\nfuture.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eESLint 8 and below\u003c/summary\u003e\n\n```json\n{\n  \"plugins\": [\"html\"],\n  \"settings\": {\n    \"html/xml-extensions\": [\".html\"] // consider .html files as XML\n  }\n}\n```\n\n\u003c/details\u003e\n\n### `html/indent`\n\nBy default, the code between `\u003cscript\u003e` tags is dedented according to the first non-empty line. The\nsetting `html/indent` allows to ensure that every script tags follow an uniform indentation. Like\nthe `indent` rule, you can pass a number of spaces, or `\"tab\"` to indent with one tab. Prefix this\nvalue with a `+` to be relative to the `\u003cscript\u003e` tag indentation. Example:\n\n\u003cdetails open\u003e\n  \u003csummary\u003eESLint 9 and above (flat config)\u003c/summary\u003e\n\n```javascript\nexport default [\n  {\n    files: [\"**/*.html\"],\n    plugins: { html },\n    settings: {\n      \"html/indent\": \"0\", // code should start at the beginning of the line (no initial indentation).\n      \"html/indent\": \"+2\", // indentation is the \u003cscript\u003e indentation plus two spaces.\n      \"html/indent\": \"tab\", // indentation is one tab at the beginning of the line.\n    },\n  },\n]\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eESLint 8 and below\u003c/summary\u003e\n\n```json\n{\n  \"plugins\": [\"html\"],\n  \"settings\": {\n    \"html/indent\": \"0\", // code should start at the beginning of the line (no initial indentation).\n    \"html/indent\": \"+2\", // indentation is the \u003cscript\u003e indentation plus two spaces.\n    \"html/indent\": \"tab\" // indentation is one tab at the beginning of the line.\n  }\n}\n```\n\n\u003c/details\u003e\n\n### `html/report-bad-indent`\n\nBy default, this plugin won't warn if it encounters a problematic indentation (ex: a line is under\nindented). If you want to make sure the indentation is correct, use the `html/report-bad-indent` in\nconjunction with the `indent` rule. Pass `\"warn\"` or `1` to display warnings, `\"error\"` or `2` to\ndisplay errors. Example:\n\n\u003cdetails open\u003e\n  \u003csummary\u003eESLint 9 and above (flat config)\u003c/summary\u003e\n\n```javascript\nexport default [\n  {\n    files: [\"**/*.html\"],\n    plugins: { html },\n    settings: {\n      \"html/report-bad-indent\": \"error\",\n    },\n  },\n]\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eESLint 8 and below\u003c/summary\u003e\n\n```json\n{\n  \"plugins\": [\"html\"],\n  \"settings\": {\n    \"html/report-bad-indent\": \"error\"\n  }\n}\n```\n\n\u003c/details\u003e\n\n### `html/javascript-tag-names`\n\nBy default, the code between `\u003cscript\u003e` tags is considered as JavaScript. You can customize which\ntags should be considered JavaScript by providing one or multiple tag names.\n\nExample:\n\n\u003cdetails open\u003e\n  \u003csummary\u003eESLint 9 and above (flat config)\u003c/summary\u003e\n\n```javascript\nexport default [\n  {\n    files: [\"**/*.html\"],\n    plugins: { html },\n    settings: {\n      \"html/javascript-tag-names\": [\"script\", \"customscript\"],\n    },\n  },\n]\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eESLint 8 and below\u003c/summary\u003e\n\n```json\n{\n  \"plugins\": [\"html\"],\n  \"settings\": {\n    \"html/javascript-tag-names\": [\"script\", \"customscript\"]\n  }\n}\n```\n\n\u003c/details\u003e\n\n### `html/javascript-mime-types`\n\nBy default, the code between `\u003cscript\u003e` tags is considered as JavaScript code only if there is no\n`type` attribute or if its value matches the pattern\n`(application|text)/(x-)?(javascript|babel|ecmascript-6)` or `module` (case insensitive). You can\ncustomize the types that should be considered as JavaScript by providing one or multiple MIME types.\nIf a MIME type starts with a `/`, it will be considered as a regular expression. Example:\n\n\u003cdetails open\u003e\n  \u003csummary\u003eESLint 9 and above (flat config)\u003c/summary\u003e\n\n```javascript\nexport default [\n  {\n    files: [\"**/*.html\"],\n    plugins: { html },\n    settings: {\n      \"html/javascript-mime-types\": [\"text/javascript\", \"text/jsx\"], // also use script tags with a \"text/jsx\" type attribute\n      \"html/javascript-mime-types\": \"/^text\\\\/(javascript|jsx)$/\", // same thing\n    },\n  },\n]\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eESLint 8 and below\u003c/summary\u003e\n\n```json\n{\n  \"plugins\": [\"html\"],\n  \"settings\": {\n    \"html/javascript-mime-types\": [\"text/javascript\", \"text/jsx\"], // also use script tags with a \"text/jsx\" type attribute\n    \"html/javascript-mime-types\": \"/^text\\\\/(javascript|jsx)$/\" // same thing\n  }\n}\n```\n\n\u003c/details\u003e\n\n### `html/ignore-tags-without-type`\n\nBy default, the code between `\u003cscript\u003e` tags is considered JavaScript if there is no `type`\nattribute. You can set this setting to `true` to ignore script tags without a `type` attribute.\nExample:\n\n\u003cdetails open\u003e\n  \u003csummary\u003eESLint 9 and above (flat config)\u003c/summary\u003e\n\n```javascript\nexport default [\n  {\n    files: [\"**/*.html\"],\n    plugins: { html },\n    settings: {\n      \"html/ignore-tags-without-type\": true,\n    },\n  },\n]\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eESLint 8 and below\u003c/summary\u003e\n\n```json\n{\n  \"plugins\": [\"html\"],\n  \"settings\": {\n    \"html/ignore-tags-without-type\": true\n  }\n}\n```\n\n\u003c/details\u003e\n\n## Troubleshooting\n\n### No file linted when running `eslint` on a directory\n\nBy default, when executing the `eslint` command on a directory, only `.js` files will be linted. You\nwill have to specify extra extensions with the `--ext` option. Example: `eslint --ext .html,.js src`\nwill lint both `.html` and `.js` files in the `src` directory. See [ESLint\ndocumentation](http://eslint.org/docs/user-guide/command-line-interface#ext).\n\n### Linting templates (or PHP)\n\n`eslint-plugin-html` won't evaluate or remove your template markup. If you have template markup in\nyour script tags, the resulting script may not be valid JavaScript, so `ESLint` will fail to parse\nit. Here are some workarounds:\n\n- You can use [HTML comments to disable ESLint](#disabling-eslint) for specific script tags.\n\n- For PHP, you can use\n  [`eslint-plugin-php-markup`](https://github.com/tengattack/eslint-plugin-php-markup) to lint php\n  files, it use a same way to process php markup like `eslint-plugin-html`.\n\n- Another possible hacky workaround to make sure the code is valid JavaScript is to put your\n  template markup inside a comment. When the template is rendered, the generated JS code must start\n  with a new line, so it will be written below the comment. PHP example:\n\n```html\n\u003cscript\u003e\n  var mydata\n  // \u003c?= \"\\n mydata = \" . json_encode($var) . \";\" ?\u003e\n  console.log(mydata)\n\u003c/script\u003e\n```\n\n### Linting VUE files\n\nInitially, [`eslint-plugin-vue`](https://github.com/vuejs/eslint-plugin-vue) was using\n`eslint-plugin-html` to lint code inside script tags. Since v3, `eslint-plugin-vue` is using its\nown parser, so it is _incompatible_ with `eslint-plugin-html`. You should use `eslint-plugin-vue`\nexclusively and remove `eslint-plugin-html` from your dependencies if you still have it.\n\n## Migration from older versions\n\n### To v4\n\n`eslint-plugin-html` v4 requires at least ESLint v4.7. This is because a lot of internal changes\noccured in ESLint v4.7, including a [new API to support autofixing in\npreprocessors](https://eslint.org/docs/developer-guide/working-with-plugins#processors-in-plugins).\nIf you are still using an older version of ESLint, please consider upgrading, or keep using\n`eslint-plugin-html` v3.\n\nThe big feature (and breaking change) in `eslint-plugin-html` v4 is the ability to choose how [scopes\nare shared between script tags in the same HTML file](#multiple-scripts-tags-in-a-html-file).\n\n### To v3\n\nIf you are considering upgrading to v3, please read [this guide](MIGRATION_TO_V3.md).\n\n## Credits\n\nA big thank you to [@kuceb](https://github.com/kuceb) for the logo image!\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenoitzugmeyer%2Feslint-plugin-html","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbenoitzugmeyer%2Feslint-plugin-html","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenoitzugmeyer%2Feslint-plugin-html/lists"}