Giter Site home page Giter Site logo

eslint-plugin-html's Introduction

eslint-plugin-html

NPM version Tests Status

A ESLint plugin to lint and fix inline scripts contained in HTML files.

Usage

Simply install via npm install --save-dev eslint-plugin-html and add the plugin to your ESLint configuration. See ESLint documentation.

Example:

{
    "plugins": [
        "html"
    ]
}

Disabling ESLint

To temporarily disable ESLint, use the <!-- eslint-disable --> HTML comment. Re-enable it with <!-- eslint enable -->. Example:

<!-- eslint-disable -->
<script>
  var foo = 1
</script>
<!-- eslint-enable -->

To disable ESLint for the next script tag only, use the <!-- eslint-disable-next-script --> HTML comment. Example:

<!-- eslint-disable-next-script -->
<script>
  var foo = 1
</script>

Disabled script tags are completely ignored: their content will not be parsed as JavaScript. You can use this to disable script tags containing template syntax.

Linting HTML

This plugin focuses on applying ESLint rules on inline scripts contained in HTML. It does not provide any rule related to HTML. For that, you can use other plugins like @eslint-html or @angular-eslint. eslint-plugin-html is compatible with those plugins and can be used along them.

Multiple scripts tags in a HTML file

When linting a HTML with multiple script tags, this plugin tries to emulate the browser behavior by sharing the global scope between scripts by default. This behavior doesn't apply to "module" scripts (ie: <script type="module"> and most transpiled code), where each script tag gets its own top-level scope.

ESLint has already an option to tell the parser if the script are modules. eslint-plugin-html will use this option as well to know if the scopes should be shared (the default) or not. To change this, just set it in your ESLint configuration:

{
  "parserOptions": {
    "sourceType": "module"
  }
}

To illustrate this behavior, consider this HTML extract:

<script>
  var foo = 1
</script>

<script>
  alert(foo)
</script>

This is perfectly valid by default, and the ESLint rules no-unused-vars and no-undef shouldn't complain. But if those scripts are considerated as ES modules, no-unused-vars should report an error in the first script, and no-undef should report an error in the second script.

History

In eslint-plugin-html v1 and v2, script code were concatenated and linted in a single pass, so the scope were always shared. This caused some issues, so in v3 all scripts were linted separately, and scopes were never shared. In v4, the plugin still lint scripts separately, but makes sure global variables are declared and used correctly in the non-module case.

XML support

This plugin parses HTML and XML markup slightly differently, mainly when considering CDATA sections:

  • in XML, any data inside a CDATA section will be considered as raw text (not XML) and the CDATA delimiter will be droped ;
  • in HTML, there is no such thing for <script> tags: the CDATA delimiter is considered as normal text and thus, part of the script.

Settings

Note: all settings can be written either as "html/key": value or in a nested object "html": { "key": value }

html/html-extensions

By default, this plugin will only consider files ending with those extensions as HTML: .erb, .handlebars, .hbs, .htm, .html, .mustache, .nunjucks, .php, .tag, .twig, .we. You can set your own list of HTML extensions by using this setting. Example:

{
    "plugins": [ "html" ],
    "settings": {
        "html/html-extensions": [".html", ".we"],  // consider .html and .we files as HTML
    }
}

html/xml-extensions

By default, this plugin will only consider files ending with those extensions as XML: .xhtml, .xml. You can set your own list of XML extensions by using this setting. Example:

{
    "plugins": [ "html" ],
    "settings": {
        "html/xml-extensions": [".html"],  // consider .html files as XML
    }
}

html/indent

By default, the code between <script> tags is dedented according to the first non-empty line. The setting html/indent allows to ensure that every script tags follow an uniform indentation. Like the indent rule, you can pass a number of spaces, or "tab" to indent with one tab. Prefix this value with a + to be relative to the <script> tag indentation. Example:

{
    "plugins": [ "html" ],
    "settings": {
        "html/indent": "0",   // code should start at the beginning of the line (no initial indentation).
        "html/indent": "+2",  // indentation is the <script> indentation plus two spaces.
        "html/indent": "tab", // indentation is one tab at the beginning of the line.
    }
}

html/report-bad-indent

By default, this plugin won't warn if it encounters a problematic indentation (ex: a line is under indented). If you want to make sure the indentation is correct, use the html/report-bad-indent in conjunction with the indent rule. Pass "warn" or 1 to display warnings, "error" or 2 to display errors. Example:

{
    "plugins": [ "html" ],
    "settings": {
        "html/report-bad-indent": "error",
    }
}

html/javascript-tag-names

By default, the code between <script> tags is considered as JavaScript. You can customize which tags should be considered JavaScript by providing one or multiple tag names.

Example:

{
    "plugins": [ "html" ],
    "settings": {
        "html/javascript-tag-names": ["script", "customscript"],
    }
}

html/javascript-mime-types

By default, the code between <script> tags is considered as JavaScript code only if there is no type attribute or if its value matches the pattern (application|text)/(x-)?(javascript|babel|ecmascript-6) or module (case insensitive). You can customize the types that should be considered as JavaScript by providing one or multiple MIME types. If a MIME type starts with a /, it will be considered as a regular expression. Example:

{
    "plugins": [ "html" ],
    "settings": {
        "html/javascript-mime-types": ["text/javascript", "text/jsx"],  // also use script tags with a "text/jsx" type attribute
        "html/javascript-mime-types": "/^text\\/(javascript|jsx)$/",    // same thing
    }
}

html/ignore-tags-without-type

By default, the code between <script> tags is considered JavaScript if there is no type attribute. You can set this setting to true to ignore script tags without a type attribute. Example:

{
    "plugins": [ "html" ],
    "settings": {
        "html/ignore-tags-without-type": true,
    }
}

Troubleshooting

No file linted when running eslint on a directory

By default, when executing the eslint command on a directory, only .js files will be linted. You will have to specify extra extensions with the --ext option. Example: eslint --ext .html,.js src will lint both .html and .js files in the src directory. See ESLint documentation.

Linting templates (or PHP)

eslint-plugin-html won't evaluate or remove your template markup. If you have template markup in your script tags, the resulting script may not be valid JavaScript, so ESLint will fail to parse it. Here are some workarounds:

  • You can use HTML comments to disable ESLint for specific script tags.

  • For PHP, you can use eslint-plugin-php-markup to lint php files, it use a same way to process php markup like eslint-plugin-html.

  • Another possible hacky workaround to make sure the code is valid JavaScript is to put your template markup inside a comment. When the template is rendered, the generated JS code must start with a new line, so it will be written below the comment. PHP example:

<script>
  var mydata
  // <?= "\n mydata = " . json_encode($var) . ";" ?>
  console.log(mydata)
</script>

Linting VUE files

Initially, eslint-plugin-vue was using eslint-plugin-html to lint code inside script tags. Since v3, eslint-plugin-vue is using its own parser, so it is incompatible with eslint-plugin-html. You should use eslint-plugin-vue exclusively and remove eslint-plugin-html from your dependencies if you still have it.

Migration from older versions

To v4

eslint-plugin-html v4 requires at least ESLint v4.7. This is because a lot of internal changes occured in ESLint v4.7, including a new API to support autofixing in preprocessors. If you are still using an older version of ESLint, please consider upgrading, or keep using eslint-plugin-html v3.

The big feature (and breaking change) in eslint-plugin-html v4 is the ability to choose how scopes are shared between script tags in the same HTML file.

To v3

If you are considering upgrading to v3, please read this guide.

Credits

A big thank you to @kuceb for the logo image!

eslint-plugin-html's People

Contributors

adalinesimonian avatar ahmedelgabri avatar aleen42 avatar alexbeauchemin avatar ben52 avatar benoitzugmeyer avatar coliff avatar dependabot[bot] avatar dictav avatar gianlucaguarini avatar greggman avatar hlapp avatar junmer avatar juodumas avatar karelverschraegen avatar kmaglione avatar kriansa avatar krispy1298 avatar kuceb avatar liudangyi avatar logicer16 avatar nagy-tamas avatar noe132 avatar nschonni avatar philipp90 avatar platinumazure avatar tengattack avatar wesbos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

eslint-plugin-html's Issues

Scripts are treated as modules, when they aren't.

With version 3.0.0, all <script> tags are treated as modules, when they might not be.

This causes no-undef rules to fail when they currently are fine in the browser.

Is it possible to limit the new functionality to modules only or something?

Errors that occur at position 0 are not reported.

When the position that the rule is broken occurs at the very beginning of a script tag, the error does not seem to be reported.

Here is a bare minimum repository that can reproduce the issue:

https://github.com/mtbradle-ge/eslint-plugin-html-max-lines-bug

Just clone and run eslint . --ext .html

No errors are reported for the bug.html for max-lens or max-lines as specified in the config, even though they are clearly present.

This seems to be because line 84 of TransformableString.js:

      if (index < block.from + block.str.length) {
        return
      }

Changing the return to a break seemed to mitigate the issue...?

eol-last errors reported on the wrong line

Using this code:

<html>
<head>
  <title>Test page</title>
</head>
<body>
  <script>document.write("Hello world!");</script>
</body>
</html>

I get the output:

test.html
  9:1  error  Newline required at end of file but not found.  eol-last (eslint)

However, it should be saying the error is on line 6.

auto enable report-bad-indent

would it be possible to check for the existence of an html/indent setting, and if so automatically enable html/report-bad-indent? imo the indent setting should exist only to change the severity, not to enable the feature.

edit: or combine the two, eg html/indent: [2, 0]

edit: just make it a rule instead of a setting

Module build failed without reason

I am suffering a weird issue where module build failed without a reason. I tried to format my computer and make everything run again and i still get the same error but other computer run smoothly won't a problem.

Please help. Thanks

Attached Screenshot below:

bug

Plugin throws exception when <script> tag is only thing in HTML file

Try linting a file that has just a script tag, this is quite common when building webcomponents or polymer elements. Added an empty comment tag at the start of the file works around but this is ugly.

/usr/lib/node_modules/my-web-component/node_modules/eslint-plugin-html/src/extract.js:42
criptCode[scriptCode.length - 1] = scriptCode[scriptCode.length - 1].replace(/
                                                                    ^
TypeError: Cannot read property 'replace' of undefined
    at Object.htmlparser.Parser.onclosetag (/usr/lib/node_modules/my-web-component/node_modules/eslint-plugin-html/src/extract.js:42:76)
    at Parser.onclosetag (/usr/lib/node_modules/my-web-component/node_modules/eslint-plugin-html/node_modules/htmlparser2/lib/Parser.js:192:28)
    at Tokenizer._emitToken (/usr/lib/node_modules/my-web-component/node_modules/eslint-plugin-html/node_modules/htmlparser2/lib/Tokenizer.js:896:17)
    at Tokenizer._stateInCloseingTagName (/usr/lib/node_modules/my-web-component/node_modules/eslint-plugin-html/node_modules/htmlparser2/lib/Tokenizer.js:214:8)
    at Tokenizer._parse (/usr/lib/node_modules/my-web-component/node_modules/eslint-plugin-html/node_modules/htmlparser2/lib/Tokenizer.js:647:9)
    at Tokenizer.write (/usr/lib/node_modules/my-web-component/node_modules/eslint-plugin-html/node_modules/htmlparser2/lib/Tokenizer.js:632:7)
    at Tokenizer.end (/usr/lib/node_modules/my-web-component/node_modules/eslint-plugin-html/node_modules/htmlparser2/lib/Tokenizer.js:825:17)
    at Parser.end (/usr/lib/node_modules/my-web-component/node_modules/eslint-plugin-html/node_modules/htmlparser2/lib/Parser.js:335:18)
    at Parser.parseComplete (/usr/lib/node_modules/my-web-component/node_modules/eslint-plugin-html/node_modules/htmlparser2/lib/Parser.js:327:7)
    at extract (/usr/lib/node_modules/my-web-component/node_modules/eslint-plugin-html/src/extract.js:78:10)

Feature: custom file extensions

Hi!

there are files as .vue that have a script inside which your plugin could interpret perfectly, but as far as I know the supported file extensions are limited. Is there any possibility to set custom file extensions?

`no_unused_vars` triggered wrongly

Hi,

I have a file with the following structure, in which I get the following error:

'checkSubmit' is defined but never used

<form onsubmit="return checkSubmit(1)">
  ...
</form>

<script>
  function checkSubmit(num) {
    ...
  }
</script>

Clearly, checkSubmit is used as a listener. Maybe the html is ignored by the plugin, even though it may have an impact on rules like this one.

Thanks!

eslint-plugin-html installed globally doesnt seem to work

Hi,
Using eslint-plugin-html locally it works fine, but if I try to install it globally eslint cannot find it.

Local install:

▶ ./node_modules/.bin/eslint app.vue    

/tmp/2/app.vue
  16:14  error  Parsing error: Unexpected identifier

✖ 1 problem (1 error, 0 warnings)
{
  "private": true,
  "dependencies": {
    "babel-eslint": "^4.1.4",
    "eslint": "^1.8.0",
    "eslint-config-airbnb": "^0.1.0",
    "eslint-plugin-html": "^1.1.0",
    "eslint-plugin-react": "^3.7.1"
  }
}

Global install:

▶ eslint app.vue                        
module.js:339
    throw err;
    ^

Error: Cannot find module 'eslint-plugin-html'
    at Function.Module._resolveFilename (module.js:337:15)
    at Function.Module._load (module.js:287:25)
    at Module.require (module.js:366:17)
    at require (module.js:385:17)
    at /usr/local/lib/node_modules/eslint/lib/cli-engine.js:116:26
    at Array.forEach (native)
    at loadPlugins (/usr/local/lib/node_modules/eslint/lib/cli-engine.js:107:21)
    at processText (/usr/local/lib/node_modules/eslint/lib/cli-engine.js:194:5)
    at processFile (/usr/local/lib/node_modules/eslint/lib/cli-engine.js:254:18)
    at executeOnFile (/usr/local/lib/node_modules/eslint/lib/cli-engine.js:551:23)
▶ npm list --depth=0 -g             
/usr/lib
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]
▶ node -v
v4.2.2

.eslintrc:

{
  "plugins": [
    "html"
  ]
}

Support fixing eol-last rule

Follow up: #23 (comment)

The next version of this plugin supports eslint --fix, but it looks like eol-last is causing an issue because the extracted JS does not have a newline at the end, and eol-last is trying to fix it by adding a new line, which will be ignored during the next pass of fixes (because it will not be present in the extracted JS).

Let's keep the end-of-file newlines in the extracted JS so the rule can work as expected.

Vue lint rules not being applied beyond entry point (not traversing subdirectories).

To help out others… I spent more hours on this than I care to count… for those trying to setup auto ESlinting with webpack 3.x eslint-plugin-vue v3.x, eslint-friendly-formatter v3.x and eslint-html-plugin v3.x, read on (note I’m using Sublime Text 3):

If I comment out .vue from eslint-plugin-html settings everything seems to work:

to help others, in the .eslintrc.js:

module.exports = {
  env: {
    browser: true,
    commonjs: true,
    es6: true,
    node: true,
  },
  plugins: [
        'html',
  ],
  settings: {
        // if you have .vue active for eslint-html-plugin settings
        // linting will not progress through all subdirectories
        // it conflicts with eslint-plugin-vue (latest v3.5.0)
        // it will stop at the main entry point.
        "html/html-extensions": [".html", /* ".vue" */],  // consider .html files as XML
        "html/report-bad-indent": "error",
  },
  extends: [
    'eslint:recommended',
    'plugin:vue/recommended' // or 'plugin:vue/base'
  ],
  parserOptions: {
    sourceType: 'module',
  },
  rules: {
    'comma-dangle': ['error', 'always-multiline'],
    indent: ['error', 2],
    'linebreak-style': ['error', 'unix'],
    quotes: ['error', 'single'],
    semi: ['error', 'always'],
    'no-unused-vars': ['warn'],
    'no-console': 0,
    'vue/order-in-components': [2, {
      order: [
        ['name', 'delimiters', 'functional', 'model'],
        ['components', 'directives', 'filters'],
        ['parent', 'mixins', 'extends', 'provide', 'inject'],
        'el',
        'template',
        'props',
        'propsData',
        'data',
        'computed',
        'watch',
        'lifecycle_hooks',
        'methods',
        'render',
        'renderError'
      ]
    }] // END order
  },
};

in the ignore file:

# ESlint #
##########
/tmp/**
test.js
webpack.config.js
/webpack.config.js
**/webpack.config.js
in the webpack config:

in the webpack config

// within rules

{
      enforce: 'pre', // with this eslint will not process files done by babel-loader
      test: /\.(vue|js)$/, // /\.js$/,
      loader: 'eslint-loader',
      exclude: /node_modules/,
      options: {
        emitWarning: true,
        // community formatter
        formatter: require('eslint-friendly-formatter'),
        // cache: DEVELOPMENT,        
        fix: true, // Set to true for eslint autofixing
        // quite: true, // Process report errors only and ignore warnings
      },
    }, {
        test: /\.vue$/,
        loader: 'vue-loader', // Used for Vue Templates. Also Hot Module Replacement only works with .vue files
        options: {
          loaders: {
          }
          // other vue-loader options go here
        }
      },

error Unexpected token <

Hello

and thx for you plugin
I have tried to use it but I got this error

/home/peponi/Code/private_projects/FirefoxOS/Wallet_WebApp/app/index.html
  1:1  error  Unexpected token <

seems the htmlparser2 won't work or so

may be you can tell me what I'm doing wrong

here is my gulp task

gulp.task('eslint', function () {
    return gulp.src(['app/js/**/*.js','app/index.html'])
        .pipe(eslint({
            plugins: ["html"]
        }))
        .pipe(eslint.format())
        .pipe(eslint.failOnError());
});

.eslintrc

...
  vm: true
  xtag: true
  ViewModel: true
plugins: 
  - html
rules: 
  block-scoped-var: true
  camelcase: true
...

and package.json

  "devDependencies": {
    "eslint-plugin-html": "^1.0.0",
    "gulp": "^3.8.11",
    "gulp-eslint": "^0.9.0"
  },

Possible bug w/ viewing in Sublime text 3

With the plugin installed globally, and SublimeLinter working with eslint in .js files with no issue, when I add "plugins": [ "html" ] to my .eslintrc file, the linting does not give any feedback in my .html file with script tags however, it does give feed back when the command is run in terminal. When I remove "plugins": [ "html" ] the linting displays errors in Sublime but not in the terminal.

I don't need it in terminal and Sublime, was just curious if I'm missing a setting somewhere? Possibly in SublimeLinter itself that you know of?

Thanks

"Can't replace slice" error with xhtml files and script tags with minimised tag syntax

Attempting to update from 1.5.2 to 2.0.1 on the Mozilla code base gives an error:

Can't replace slice
Error: Can't replace slice
    at TransformableString.replace (/Users/mark/dev/gecko/node_modules/eslint-plugin-html/src/TransformableString.js:75:48)
    at iterateScripts (/Users/mark/dev/gecko/node_modules/eslint-plugin-html/src/extract.js:171:23)
    at emitChunk (/Users/mark/dev/gecko/node_modules/eslint-plugin-html/src/extract.js:33:9)
    at iterateScripts (/Users/mark/dev/gecko/node_modules/eslint-plugin-html/src/extract.js:92:3)
    at extract (/Users/mark/dev/gecko/node_modules/eslint-plugin-html/src/extract.js:159:3)
    at EventEmitter.eslint.verify (/Users/mark/dev/gecko/node_modules/eslint-plugin-html/src/index.js:157:28)
    at processText (/Users/mark/dev/gecko/node_modules/eslint/lib/cli-engine.js:264:31)
    at processFile (/Users/mark/dev/gecko/node_modules/eslint/lib/cli-engine.js:303:18)
    at executeOnFile (/Users/mark/dev/gecko/node_modules/eslint/lib/cli-engine.js:672:25)
    at fileList.forEach.fileInfo (/Users/mark/dev/gecko/node_modules/eslint/lib/cli-engine.js:710:13)

Investigations reveals that this is happening with at least some of our xhtml files, a minimal version is below:

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <script type="text/javascript"
            src="chrome://browser/content/abouthome/aboutHome.js"/>
  </head>
  <body>
  </body>
</html>

If I change the script statement to:

    <script type="text/javascript"
            src="chrome://browser/content/abouthome/aboutHome.js"></script>

then the file is processed correctly.

Either eslint-plugin-html should handle the alternate case, or there should be a reported error, with the file & lines at issue.

2.0.2 npm ERR! cb() never called!

on yarn install

error An unexpected error occurred: "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-2.0.2.tgz: invalid tar file".

on npm install [email protected]

npm ERR! cb() never called!

npm ERR! This is an error with npm itself. Please report this error at:
npm ERR!     <https://github.com/npm/npm/issues>

Support .we extension

.we and .vue are similar, and your plugin could interpret perfectly.

BTW: Perhaps this will be better to make htmlExtensions configurable.

Support for <![CDATA[ ]]> in <script>

This plugin will gladly look at .xhtml files but fails when encountering a CDATA section in a <script> tag:

<script><![CDATA[
var foo = "bar";
]]></script>

The workaround is to change our XHTML files to add // comments before the CDATA opening and closing but since we actually use an XML/XHTML parser, this is added noise.

Ideally the plugin would use an XML parser to handle this for .xhtml files or automatically treat it like there are // before the opening and closing.

Support for script tag with type text/babel

Hi! I would like to use this plugin to lint .vue files, however to get my IDE to recognize ES6, I have to specify type="text/babel" on my script tags, which prevents the linter from linting my javascript.

Investigate "Invalid slice indexes" in v2

Follow up: #44 (comment)

Invalid slice indexes
Error: Invalid slice indexes
    at TransformableString.replace (.../node_modules/eslint-plugin-html/src/TransformableString.js:67:13)
    at iterateScripts (.../node_modules/eslint-plugin-html/src/extract.js:161:23)
    at emitChunk (.../node_modules/eslint-plugin-html/src/extract.js:31:9)
    at iterateScripts (.../node_modules/eslint-plugin-html/src/extract.js:90:3)
    at extract (.../node_modules/eslint-plugin-html/src/extract.js:157:3)
    at EventEmitter.eslint.verify (.../node_modules/eslint-plugin-html/src/index.js:157:28)
    at EventEmitter.patchedVerify [as verify] (.../node_modules/eslint-plugin-vue/node_modules/eslint-plugin-html/src/index.js:82:29)
    at parsedBlocks.forEach.block (.../node_modules/eslint/lib/cli-engine.js:245:45)
    at Array.forEach (native)
    at processText (.../node_modules/eslint/lib/cli-engine.js:244:22)

HTML code:

<template>
  <div class="file-uploader-wrapper">
    <input type="file" name="files" ref="files" @change="onFileSelected" multiple hidden>

    <modal :show="uploading" :dismissable="false">
      <div class="card mb-0">
        <h5 class="card-header text-primary py-2">Uploading</h5>
        <div class="card-block">
          <progress class="progress mb-0" :value="progress" max="100">
            <div class="progress">
              <span class="progress-bar" :style="{ width: progress + '%' }"></span>
              <span class="text-xs-center">Uploading...</span>
            </div>
          </progress>
        </div>
      </div>
    </modal>

    <modal ref="info" :dismissable="false">
      <div class="card mb-0">
        <h5 class="card-header bg-white text-primary py-2">About the files</h5>

        <div class="card-block">
          <template v-for="(title, index) of titles">
            <div v-if="index === 0" class="form-group">
              <label for="file-uploader-1">Name of the file</label>
              <div class="input-group">
                <span class="input-group-addon">
                  <i class="fa fa-fw" :class="[getClassFor(index)]"></i>
                </span>
                <input type="text" v-model="titles[index]" class="form-control" id="file-uploader-1">
              </div>
            </div>
            <div class="form-group" v-else>
              <div class="input-group">
                <span class="input-group-addon">
                  <i class="fa fa-fw" :class="[getClassFor(index)]"></i>
                </span>
                <input type="text" v-model="titles[index]" class="form-control" id="file-uploader-1">
              </div>
            </div>
          </template>

          <input-textarea class="mt-2" title="Add a message (optional)" v-model="message"></input-textarea>
        </div>
        <div class="card-footer bg-white pt-2 pb-1">
          <a role="button" class="btn btn-secondary btn-cancel" tabindex @click="onCancel">Cancel</a>
          <a role="button" class="btn btn-primary" tabindex @click="onUpload">Share</a>
        </div>
      </div>
    </modal>
  </div>
</template>
<script type='babel'>
import toArray from 'lodash/toArray';
import Modal from './Modal.vue';

export default{
  props: {
    dest: {
      type: String,
      required: true,
    },
    name: {
      type: String,
      default: 'file',
    },
  },
  components: { Modal },
  data() {
    return {
      uploading: false,
      progress: 0,
      partials: [],
      count: 0,
      errors: [],
      results: [],
      handler: null,
      index: 0,
      titles: [],
      message: '',
    };
  },
  created() {
     this.$on('upload', () => {
       const input = $(this.$refs.files);
       input.replaceWith(input.val('').clone(true));
       input.click();
     });
  },
  methods: {
    onFileSelected(event) {
      const files = event.target.files;

      if (!files.length) return;

      this.uploading = false;
      this.count = files.length;
      this.progress = 0;
      this.partials = [];
      this.errors = [];
      this.results = [];

      this.errors[files.length - 1] = undefined;

      this.$refs.info.$emit('show');

      let start = null;

      const chain = new Promise((resolve) => {
        start = resolve;
      });

      chain.then(() => this.getFileMeta(toArray(files)))
           .then((uploads) => Promise.all(uploads.map(meta => this.upload(meta))))
           .then(() => {
             this.uploading = false;

             this.$emit('uploaded', this.results, this.errors);
           })
           .catch(error => error);

      start()
    },
    getFileMeta(files) {
      const uploads = files.map((file, index) => {
        const payload = new FormData();
        const filename = file.name;

        payload.append(this.name, file);
        this.message = '';

        return { index, payload, filename };
      });

      this.titles = uploads.map(({filename}) => filename);

      return new Promise((resolve, reject) => {

        this.handler = (state) => {
          if (state) {
            uploads[0].message = this.message;

            this.titles.forEach((title, index) => {
              if (uploads[index].filename !== title) {
                uploads[index].payload.append('title', title);
              }
            });

            resolve(uploads);
          } else {
            reject({ message: 'User cancelled upload.' });
          }
        };
      });
    },
    upload({ payload, index, filename, message }) {
      this.uploading = true;

      return this.$http.post(this.dest, payload, {
          progress: (event) => {
            if (event.lengthComputable) {
              this.updateProgress(event.loaded / event.total * 100, index);
            }
          },
        })
        .then(response => response.json())
        .then((result) => {
          this.results[index] = { message, originalFilename: filename, ...result };
        })
        .catch((response) => {
          response.json()
            .then((result) => {
              this.errors[index] = {
                message: result.errors[this.name],
                payload,
                dest: this.dest,
                name: this.name,
              };
            })
            .catch(() => {
              this.errors[index] = {
                message: `Failed to upload: ${filename}`,
                payload,
                dest: this.dest,
                name: this.name,
              };
            });
        });
    },
    onCancel() {
      this.$refs.info.$emit('hide');
      if (this.handler) {
        setTimeout(() => this.handler(false), 0);
      }
    },
    onUpload() {
      if (this.handler) {
        this.$refs.info.$emit('hide');
        setTimeout(() => this.handler(true), 0);
      }
    },
    updateProgress(item, index) {
      this.partials[index] = item;

      this.progress = this.partials.reduce((r, c) => r + (c || 0), 0) / this.count;
    },
    getClassFor(index) {
      const file = this.$refs.files.files[index];

      switch (this.getExtension(file)) {
        case 'webp':
        case 'tiff':
        case 'bmp':
        case 'svg':
        case 'jpeg':
        case 'jpg':
        case 'gif':
        case 'png': return 'fa-file-picture-o';
        case '7z':
        case 'gz':
        case 'tar':
        case 'rar':
        case 'zip': return 'fa-file-zip-o';
        case 'rtf':
        case 'odt':
        case 'pages':
        case 'doc':
        case 'docx': return 'fa-file-word-o';
        case 'ods':
        case 'numbers':
        case 'xls':
        case 'csv':
        case 'xlsx': return 'fa-file-excel-o';
        case 'odp':
        case 'keynote':
        case 'ppt':
        case 'pptx': return 'fa-file-powerpoint';
        case 'eps':
        case 'ps':
        case 'pdf': return 'fa-file-pdf-o';
        case 'txt': return 'fa-file-text-o';
        default: return 'fa-file-o';
      }
    },
    getExtension(file) {
      if (!file) return null;

      return file.name.split('.').pop().toLowerCase();
    },
  },
};

</script>

<style lang="scss" scoped>
@import "../styles/variables";
@import "../styles/methods";

.file-upload-wrapper {
  position: relative;
}

.btn-cancel {
  margin-right: .5rem;
}
</style>

Unexpected Token < in .vue files when <script> tag is present

as issued here, when I lint a vue single-file-component this one:

App.vue

<template>
  <div class="app" id="app"></div>
</template>

<script>
  import store from '../store';
  import router from '../router';

  export default {
    store,
    router,
  };
</script>

I get error Parsing error: Unexpected token < on line 1. That is always the case as soon as I add a script tag to the file.

Is there anything I did wrong (config or something) or is this a bug?

Can't install 2.0.2

yarn add eslint-plugin-html:

error An unexpected error occurred: "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-2.0.2.tgz: Invalid tar header. Maybe the tar is corrupted or it needs to be gunzipped?".

npm install eslint-plugin-html:

npm ERR! cb() never called!

yarn version is 0.23.3. Npm version is 4.5.0

xhtml files report trailing spaces not allowed and newline required at end of file

Using a test xhtml file as follows:

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Test page</title>
  <script type="application/javascript"><![CDATA[
    document.write("Hello world!");
  ]]></script>
</head>
<body>
</body>
</html>

This reports:

test.xhtml
   7:1  error  Trailing spaces not allowed.                    no-trailing-spaces (eslint)
  12:1  error  Newline required at end of file but not found.  eol-last (eslint)

The only way I can seem to fix it is to remove the indent before the ]]></script>

Run all html files in a folder

How do I run all html files in a folder and its sub folders. Currently it works for me only if I give one file at a time.

Parsing a PHP file raises an error: Unexpected token

When I test
eslint index.php

I get the following error
16:38 error Parsing error: Unexpected token e

The index.php is this and is also attached in a zip file

<!DOCTYPE html>
<html>
<head>
<title>PHP test</title>

<?php
$my_array = array("a"=>"red","b"=>"green","c"=>"blue","d"=>"yellow","e"=>"purple");
?>

<script type="text/javascript">

function OnLoadPage()
{
var x = "<?php echo $my_array["e"]; ?>";
alert("OnLoadPage '" + x+ "' ");
}
</script>

</head>

<body onload="OnLoadPage();">
</body>

`

index.zip

Cannot read property 'map' of undefined

Hi guys,

I'm trying to use your extremely useful plugin in the default Vue.js webpack template. It comes preconfigured and is required in its latest version (@1.5.1). Using Atom, normal JS files lint just well, but in .vue components I receive the following error:

Error: Cannot read property 'map' of undefined
TypeError: Cannot read property 'map' of undefined
    at /Users/robin/Development/skappbar.dev/node_modules/eslint-plugin-html/src/index.js:86:39
    at Array.forEach (native)
    at Object.postprocess (/Users/robin/Development/skappbar.dev/node_modules/eslint-plugin-html/src/index.js:85:19)
    at processText (/Users/robin/Development/skappbar.dev/node_modules/eslint/lib/cli-engine.js:252:30)
    at CLIEngine.executeOnText (/Users/robin/Development/skappbar.dev/node_modules/eslint/lib/cli-engine.js:761:26)
    at Object.cli.execute (/Users/robin/Development/skappbar.dev/node_modules/eslint/lib/cli.js:181:36)
    at lintJob (/Users/robin/.atom/packages/linter-eslint/lib/worker.js:35:10)
    at /Users/robin/.atom/packages/linter-eslint/lib/worker.js:69:20
    at Emitter.emit (/Users/robin/.atom/packages/linter-eslint/node_modules/process-communication/node_modules/sb-event-kit/lib/emitter.js:70:19)
    at /Users/robin/.atom/packages/linter-eslint/node_modules/process-communication/node_modules/sb-communication/lib/main.js:22:23

While typing / saving the file.

The file is the default Hello.vue from the webpack template:

<template>
  <div class="hello">
    <h1>{{ msg }}<span>hello World!!!</span></h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // note: changing this line won't causes changes
      // with hot-reload because the reloaded component
      // preserves its current state and we are modifying
      // its initial state.
      msg: 'Hello World!',
    };
  },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
h1 {
  color: #42b983;
  span {
      color: red;
  }
}
</style>

My package.json:

{
  "name": "skappbar.dev",
  "version": "1.0.0",
  "description": "XXX",
  "author": "XXX",
  "private": true,
  "scripts": {
    "dev": "node build/dev-server.js",
    "build": "node build/build.js",
    "unit": "karma start test/unit/karma.conf.js --single-run",
    "e2e": "node test/e2e/runner.js",
    "test": "npm run unit && npm run e2e",
    "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs"
  },
  "dependencies": {
    "vue": "^1.0.21",
    "babel-runtime": "^6.0.0"
  },
  "devDependencies": {
    "babel-core": "^6.0.0",
    "babel-eslint": "^6.1.2",
    "babel-loader": "^6.0.0",
    "babel-plugin-transform-runtime": "^6.0.0",
    "babel-preset-es2015": "^6.0.0",
    "babel-preset-stage-2": "^6.0.0",
    "babel-register": "^6.0.0",
    "chai": "^3.5.0",
    "chromedriver": "^2.21.2",
    "connect-history-api-fallback": "^1.1.0",
    "cross-spawn": "^2.1.5",
    "css-loader": "^0.23.0",
    "eslint": "^2.10.2",
    "eslint-config-airbnb-base": "^3.0.1",
    "eslint-friendly-formatter": "^2.0.5",
    "eslint-loader": "^1.3.0",
    "eslint-plugin-html": "^1.3.0",
    "eslint-plugin-import": "^1.8.1",
    "eventsource-polyfill": "^0.9.6",
    "express": "^4.13.3",
    "extract-text-webpack-plugin": "^1.0.1",
    "file-loader": "^0.8.4",
    "function-bind": "^1.0.2",
    "html-webpack-plugin": "^2.8.1",
    "http-proxy-middleware": "^0.12.0",
    "inject-loader": "^2.0.1",
    "isparta-loader": "^2.0.0",
    "json-loader": "^0.5.4",
    "karma": "^0.13.15",
    "karma-coverage": "^0.5.5",
    "karma-mocha": "^0.2.2",
    "karma-phantomjs-launcher": "^1.0.0",
    "karma-sinon-chai": "^1.2.0",
    "karma-sourcemap-loader": "^0.3.7",
    "karma-spec-reporter": "0.0.24",
    "karma-webpack": "^1.7.0",
    "lolex": "^1.4.0",
    "mocha": "^2.4.5",
    "nightwatch": "^0.8.18",
    "ora": "^0.2.0",
    "phantomjs-prebuilt": "^2.1.3",
    "sass-loader": "^4.0.0",
    "selenium-server": "2.53.0",
    "shelljs": "^0.6.0",
    "sinon": "^1.17.3",
    "sinon-chai": "^2.8.0",
    "url-loader": "^0.5.7",
    "vue-hot-reload-api": "^1.2.0",
    "vue-html-loader": "^1.0.0",
    "vue-loader": "^8.3.0",
    "vue-style-loader": "^1.0.0",
    "webpack": "^1.12.2",
    "webpack-dev-middleware": "^1.4.0",
    "webpack-hot-middleware": "^2.6.0",
    "webpack-merge": "^0.8.3"
  }
}

Using it on node a v6.3.1 and everything else runs smoothly.

Any idea on why this is happening and how it can be fixed would be greatly appreciated.

Warning: Unexpected token ...

Getting the error 'Warning: Unexpected token ... Use --force to continue' when running version 3.1.0. Did not happen in 3.0.0.

Cannot read property 'map' of undefined

I get this error when trying to run eslint through webpack for .vue files.

eslint versions:

"eslint": "^3.5.0",
"eslint-config-airbnb-base": "^7.1.0",
"eslint-loader": "^1.5.0",
"eslint-plugin-html": "^1.5.2",
"eslint-plugin-import": "^1.15.0",

webpack versions: "webpack": "^1.12.2",

.eslintrc.js file:

module.exports = {
  root: true,
  parserOptions: {
    sourceType: 'module'
  },

  extends: 'airbnb-base',
  // required to lint *.vue files
  plugins: [
    'html'
  ],
  // add your custom rules here
  rules: {
    'import/no-unresolved': 0,

    // allow debugger during development
    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
    // allow console.log in dev.
    'no-console': process.env.NODE_ENV === 'production' ? 2 : 0,

    'no-param-reassign': 0,
    'default-case': 0,

    // Sometimes we add propery starting with `_` e.g _type to make
    // sure we dont colide with an existing object property named type.
    'no-underscore-dangle': 0,

    'no-unused-vars': [1, {'vars': 'local', 'args': 'none'}],
  },
}

webpack config:

module: {
    preLoaders: [
      { test: /\.vue$/, loader: 'eslint', exclude: /node_modules/ }
    ],
},
eslint: {
    failOnWarning: false,
    failOnError: true
},

Didn't do anything

What i am doing wrong?

node 6.4.0

package.json

{
  "name": "eslint-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "lint": "eslint src"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "eslint": "^3.12.2",
    "eslint-plugin-html": "^1.7.0"
  }
}

.eslintrc / .eslintrc.json

{
  "plugins": [
    "html"
  ],
  "settings": {
    "html/indent": "10",
    "html/report-bad-indent": 1
  }
}

src/test.vue

<script>
x = x
</script>

$ npm run lint

Result:

> [email protected] lint /home/rottmann/test/eslint-test
> eslint src

No error, nothing else.

ESLint HTML cannot understand templates

When using a template heavy language like Django, ESLint wont work on the HTML files because it sees the template markers of {{ }} and {% %} as general errors and wont lint the rest of the file. I don't know if there is a way to trick it to ignore them or not but it makes the plugin useless for templated languages. It seems like if the tags are inside quotes (as to make it seem like a string) it works but outside of quotes it breaks.

Provided ESLint Auto fix information have incorrect positions

.eslintrc.json

{
    "plugins": [
        "html"
    ],
    "env": {
        "browser": true,
        "commonjs": true,
        "es6": true,
        "node": true
    },
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        },
        "sourceType": "module"
    },
    "rules": {
        "no-const-assign": "warn",
        "no-this-before-super": "warn",
        "no-undef": "warn",
        "no-unreachable": "warn",
        "no-unused-vars": "warn",
        "constructor-super": "warn",
        "valid-typeof": "warn",
        "no-extra-semi": "warn"
    }
}

test.html

<!DOCTYPE html>
<html lang="en">
	<script>
		function foo() {
		}
		foo();;
	</script>
</html>

This correct reports the following error:
'Unnecessary semicolon. (no-extra-semi)'

However the auto fix information attached to the reported problem when using ESLints node API has the following information:
{
range: [75, 76]
text: ""
}

which will delete the second 'o' of foo();;

The content of the html file passed to ESLint as a string looks like:

capture

I guess that the html plugin does some offset magic and might not apply it to the fixes attached to a problem.

Add an option for eol-last to apply to the whole file rather than individual scripts.

I think the spirit of eol-last is to ensure there's always a newline at the end of the file. Certainly for Mozilla we tend to ensure it, as it makes diffs simpler.

Therefore, I'd like to request an option so that we can have eol-last apply to the whole html file, rather than individual scripts as I don't think there is much value for the script tag.

Error when parsing HTML file

When a HTML page starts like this:

<!DOCTYPE html>
<html>
<head>

The plugin throws the following error:

  1:2  error  Unexpected token !

Nested "html" setting support

For now, settings need to be written like:

"settings": {
  "html/html-extensions": ...,
  "html/indent": ...
}

I'd like to support the following format too:

"settings": {
  "html": {
    "html-extensions": ...,
    "indent": ...
  }
}

eslint-plugin-html error: It seems that eslint is not loaded.

[Enter steps to reproduce:]

  1. ...
  2. ...

Atom: 1.15.0 x64
Electron: 1.3.13
OS: Mac OS X 10.12.3
Thrown From: eslint-plugin-html package 2.0.1

Stack Trace

Failed to load the eslint-plugin-html package

At eslint-plugin-html error: It seems that eslint is not loaded. If you think it is a bug, please file a report at https://github.com/BenoitZugmeyer/eslint-plugin-html/issues

Error: eslint-plugin-html error: It seems that eslint is not loaded. If you think it is a bug, please file a report at https://github.com/BenoitZugmeyer/eslint-plugin-html/issues
    at iterateESLintModules (/packages/eslint-plugin-html/src/index.js:65:11)
    at /packages/eslint-plugin-html/src/index.js:36:1)
    at Module._compile (/app.asar/src/native-compile-cache.js:109:30)
    at /app.asar/src/compile-cache.js:216:21)
    at Module.load (module.js:473:32)
    at tryModuleLoad (module.js:432:12)
    at Function.Module._load (module.js:424:3)
    at Module.require (module.js:483:17)
    at require (/app.asar/src/native-compile-cache.js:50:27)
    at Package.module.exports.Package.requireMainModule (/app.asar/src/package.js:796:27)
    at /app.asar/src/package.js:123:28
    at Package.module.exports.Package.measure (/app.asar/src/package.js:96:15)
    at Package.module.exports.Package.load (/app.asar/src/package.js:110:12)
    at PackageManager.module.exports.PackageManager.loadPackage (/app.asar/src/package-manager.js:468:14)
    at /app.asar/src/package-manager.js:412:19
    at Config.module.exports.Config.transact (/app.asar/src/config.js:312:16)
    at PackageManager.module.exports.PackageManager.loadPackages (/app.asar/src/package-manager.js:407:19)
    at /app.asar/src/atom-environment.js:792:28

Commands

Non-Core Packages

advanced-open-file 0.16.5 
atom-beautify 0.29.17 
editorconfig 2.2.2 
javascript-snippets 1.2.1 
pigments 0.39.0 
project-folder 1.2.1 
project-manager 3.3.3 
Sublime-Style-Column-Selection 1.7.3 
svg-preview 0.11.0 
language-vue 0.21.2 
autocomplete-paths 1.0.5 
docblockr 0.9.1 
emmet 2.4.3 
eslint-plugin-html 2.0.1 
file-type-icons 1.3.3 
git-plus 7.3.3 
highlight-selected 0.12.0 
linter 1.11.23 
linter-eslint 8.1.3 
linter-jshint 3.0.3 
merge-conflicts 1.4.4 
minimap 4.26.8 
minimap-cursorline 0.2.0 
minimap-find-and-replace 4.5.2 
minimap-highlight-selected 4.5.0 
sync-settings 0.8.1 
terminal-plus 0.14.5 

eslint is not loaded

When I try to use eslint --ext html . from the shell - it throws the following error
Also, I have installed another plugin called eslint-plugin-template from here. Not sure if the other plugin has any compatibility issues with your plugin, but here is the plugins section of the .eslintrc.json file

"plugins": [
    "template"
]

which causes the below error

eslint-plugin-html error: It seems that eslint is not loaded. If you think it is a bug, please file a report at https://github.com/BenoitZugmeyer/eslint-plugin-html/issues
Error: eslint-plugin-html error: It seems that eslint is not loaded. If you think it is a bug, please file a report at https://github.com/BenoitZugmeyer/eslint-plugin-html/issues
    at Object.<anonymous> (/usr/local/lib/node_modules/eslint-plugin-template/node_modules/eslint-plugin-html/src/index.js:48:9)
    at Module._compile (module.js:410:26)
    at Object.Module._extensions..js (module.js:417:10)
    at Module.load (module.js:344:32)
    at Function.Module._load (module.js:301:12)
    at Module.require (module.js:354:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (/usr/local/lib/node_modules/eslint-plugin-template/eslint-plugin-template.js:2:12)
    at Module._compile (module.js:410:26)
    at Object.Module._extensions..js (module.js:417:10)

Incompatability with eslint-plugin-eslint-comments

The eslint-plugin-eslint-comments plugin seems to have 2 rules that require the column of the reported failure to be -1. This causes errors in this plugin as the TransformableString.locationToIndex checks for a 'valid' column of >= 0. I raised the issue with that project, but it was deemed necessary to have a value of -1. Is it possible to relax the rule here to allow for a negative value for column?

mysticatea/eslint-plugin-eslint-comments#1

Recalculate code location after dedent

This is a plunker to reproduce the problem: http://plnkr.co/edit/SKvcqNj8S3KiG4x7GRsL .

I installed eslint-plugin-html and eslint-friendly-formatter to lint my code. But I found if I let eslint-plugin-html to dedent by default, I'll get a wrong message.
e.g. for this code:

<script>
    function a(){
        function b () {
        }
    }
</script>

The code violates space-before-blocks and space-before-function-paren rules, but error messages from formatter shows:

  ✘  http://eslint.org/docs/rules/space-before-blocks          Missing space before opening brace            
  index.html:2:17
  function a(){
                   ^

  ✘  http://eslint.org/docs/rules/space-before-function-paren  Unexpected space before function parentheses  
  index.html:3:19
      function b () {
                     ^

And I write a simple formatter.js, and just return some fields from reports structure, get

{"column":17,"sourceLength":13,"source":"function a(){"}
{"column":19,"sourceLength":19,"source":"    function b () {"}

You can see the source code is dedented, but the code location isn't recalculated, so we get a wrong column field.

I've tried modifying line 107 in TransformableString.js to

    const originalIndex = this.originalIndex(index) - 4

then we'll get correct column field. Though it works, I haven't completely figure out how plugin works. Hope you can find a better way to subtract the dedent length.

eslint-plugin-html error: It seems that eslint is not loaded.

I upgraded to eslint 4.0 the other day and received this error. I figured a version compatible plugin update was coming. I saw today a v3 release, so I upgraded. I'm getting the same error.

It's very possible this is related to the vue plugin or eslint, but due to the error message, I thought I would start here.

Error Message

Error: eslint-plugin-html error: It seems that eslint is not loaded. If you think it is a bug, please file a report at https://github.com/BenoitZugmeyer/eslint-plugin-html/issues
    at iterateESLintModules (/Users/alex/dev/projects/artisanhd-v2/node_modules/eslint-plugin-vue/node_modules/eslint-plugin-html/src/index.js:65:11)
    at Object.<anonymous> (/Users/alex/dev/projects/artisanhd-v2/node_modules/eslint-plugin-vue/node_modules/eslint-plugin-html/src/index.js:36:1)
    at Module._compile (module.js:569:30)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:503:32)
    at tryModuleLoad (module.js:466:12)
    at Function.Module._load (module.js:458:3)
    at Module.require (module.js:513:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/Users/alex/dev/projects/artisanhd-v2/node_modules/eslint-plugin-vue/index.js:3:1)
error Command failed with exit code 1.

Run Command

eslint --ext vue ./src/js

.eslintrc.json

{
    "root": true,
    "env": {
        "browser": true,
        "node": true
    },
    "plugins": ["vue", "html"],
    "extensions": ["vue"],
    "settings": {
        "html/html-extensions": [".html", ".vue", ".php", ".twig"]
    },
    "parserOptions": {
        "ecmaVersion": 2017,
        "sourceType": "module",
        "ecmaFeatures": {
            "impliedStrict": true,
            "experimentalObjectRestSpread": true,
            "jsx": true
        }
    },
    "globals": {
        "ajax": true,
        "axios": true,
        "Tether": true,
        "Promise": true
    },
    "extends": "eslint:recommended",
    "rules": {
        "indent": ["error", 4, {
            "SwitchCase": 1
        }],
        "linebreak-style": ["error", "unix"],
        "semi": ["error", "never"],
        "comma-dangle": ["warn", {
            "arrays": "ignore",
            "objects": "ignore",
            "imports": "ignore",
            "exports": "ignore",
            "functions": "never"
        }],
        "comma-style": ["error", "last"],
        "computed-property-spacing": ["error", "never"],
        "no-console": ["error", { "allow": ["warn", "error"] }],
        "no-alert": "error",
        "no-dupe-args": "error",
        "no-duplicate-case": "error",
        "no-duplicate-imports": "error",
        "no-empty": "error"
    }
}

Inline scripts trigger no-multiple-empty-lines incorrectly

I updated recently eslint-plugin-html to 3.0.0, and now I have false flags on my .vue components.

"warning Too many blank lines at the beginning of file. Max of 0 allowed no-multiple-empty-lines"

<template>
<div>
</div>
</template>
<script> <- Too many blank lines here
import stuff
export default {
};
</script>

eslint-disable-* Has No Effect on Single Line Script

Thank you for the great plugin! I'm a new user and found a very minor issue. eslint-disable-* comments don't work on script opening and closing tags that appear on the same line:

<script>SystemJS.import('/index.js') // eslint-disable-line no-undef</script>

The following alternatives all work fine:

<script>
  // eslint-disable-next-line no-undef
  SystemJS.import('/index.js')
</script>

<script>
  SystemJS.import('/index.js') // eslint-disable-line no-undef
</script>

<script>SystemJS.import('/index.js') // eslint-disable-line no-undef
</script>

Unit tests will fail with the next ESLint version

Just a heads up, we've changed the error message coming from the indent rule to be more specific, and that's causing some of your tests to fail:

 1) plugin html/indent setting should work with a zero absolute indentation descriptor:

      AssertionError: 'Expected indentation of 0 spaces but found 2.' == 'Expected indentation of 0 space characters but found 2.'
      + expected - actual

      -Expected indentation of 0 spaces but found 2.
      +Expected indentation of 0 space characters but found 2.

      at Context.<anonymous> (test/plugin.js:91:14)

  2) plugin html/indent setting should work with a non-zero absolute indentation descriptor:

      AssertionError: 'Expected indentation of 2 spaces but found 0.' == 'Expected indentation of 2 space characters but found 0.'
      + expected - actual

      -Expected indentation of 2 spaces but found 0.
      +Expected indentation of 2 space characters but found 0.

      at Context.<anonymous> (test/plugin.js:115:14)

  3) plugin html/indent setting should work with relative indentation descriptor:

      AssertionError: 'Expected indentation of 0 spaces but found 2.' == 'Expected indentation of 0 space characters but found 2.'
      + expected - actual

      -Expected indentation of 0 spaces but found 2.
      +Expected indentation of 0 space characters but found 2.

      at Context.<anonymous> (test/plugin.js:156:14)

In general, we recommend that you not rely on the exact error message produced by rules in your tests because they can change over time.

ESLint 4 support

ESLint changed its internal API and this plugin rely heavily on patching this API.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.