Repository: vuejs/eslint-plugin-vue
Pull request #738 (2018-12-24 13:23:48)

feat: ignore anchor tags in multiline rule
While applying version 5 of `eslint-plugin-vue` to my personal page I realized that most of my anchor tags had additional whitespaces. This is the result of multi-attribute anchor tags + the `vue/singleline-html-element-content-newline`/`#
vue/multiline-html-element-content-newline` rule.


![image](https://user-images.githubusercontent.com/640208/50400462-43252d00-0787-11e9-8c4d-a353972c0e8d.png)

![image](https://user-images.githubusercontent.com/640208/50400466-4b7d6800-0787-11e9-9af6-44d5f59b1ab9.png)

I'd vote for more sensible defaults (by ignoring `a` as well) here :relaxed: 

mysticatea: Thank you for this issue.

But I'd like to oppose this change because `<a>` elements don't display whitespaces, as different to `<pre>` and `<textarea>` elements. I don't think that there is a reasonable reason in order to address `<a>` as special.
manniL: @mysticatea Thanks for the response!

The problem I suffer is visualized below. Anchor elements inside of other elements like `p` will honor a trailing whitespace

![image](https://user-images.githubusercontent.com/640208/50540076-959d8980-0b8b-11e9-9efd-a4a401fcb63e.png)
([CodePen](https://codepen.io/anon/pen/oJGJQb))
mysticatea: Oh, I got it. Thank you for the explanation.

OK, looks good to me. Would you update the documentation of the rule?
manniL: @mysticatea Will do :relaxed: 

Do you think including `nuxt-link`/`router-link` would make sense as well?
ota-meshi: I think that `singleline-html-element-content-newline` and `multiline-html-element-content-newline` rules should be turned off if your App is sensitive to whitespace in inline elements. Even if you exclude HTML inline elements, you can not report correctly if the user changes in CSS.

We may need to exclude `singleline-html-element-content-newline` and `multiline-html-element-content-newline` rules from config.

`singleline-html-element-content-newline` and `multiline-html-element-content-newline` rules are very effective when users want to unify code styles.
manniL: @ota-meshi Removing them from the defaults would be another "workaround" :thinking: 
michalsnik: Hi @manniL Nice to see you here, and thanks for the PR :)

What you might also want to consider in your specific scenario is to use `preserveWhitespace` option in `vue-loader`: https://vue-loader.vuejs.org/options.html#compileroptions
Though it's being deprecated now in favour of new `whitespace` option, that just have been merged: https://github.com/vuejs/vue/commit/e1abedb9e66b21da8a7e93e175b9dabe334dfebd

It will provide `condense` setting, that in V3 will probably be the default one, making our default configuration in eslint-plugin-vue a bit more justified.

I'm not sure we should ignore `a` tags by default. You might always opt-out, by updating configuration in your local `.eslintrc` file.
manniL: Hey @michalsnik :wave: 
Long time no see :speak_no_evil: 

I'm looking forward to the `condense` option *but* I think it won't solve the problem as `<a>   aaa  </a>` or 
```js
<a>
  aaa
</a>
``` will "just" be converted to `<a> aaa </a>` which still includes the leading and trailing space.

All in all, using `a` tags with the defaults for `html-element-content-newline` rules is a bit tedious. And changing the defaults for each project only to have normal link behavior (or use `v-text` which is my current workaround) shouldn't be necessary IMO :relaxed: 
michalsnik: Hmm, true @manniL 🤔

Another alternative solution might be to set `display: inline-block` on your `a` elements.

Though I'm not opposed to consider ignoring `a` tags, I'd love to hear @chrisvfritz opinion too :)
chrisvfritz: This is the formatting I typically prefer in this case:

```html
<a
  foo="a"
  bar="b"
  baz="c"
>content</a>
```

And for reference, Prettier will currently format to:

```html
<a
  foo="a"
  bar="b"
  baz="c"
  >content</a
>
```

Honestly not sure if that behavior is intentional or a bug though. 😄

Either way, I agree that the defaults should preserve whitespace, possibly for all elements since we can't really know its true `display`, if overridden in CSS.
ota-meshi: I checked the list of "inline" elements on Chrome and listed the elements of `display: inline;`.


[Inline elements | MDC | List of "inline" elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements#Elements)

<details><summary>the elements of `display: inline;`</summary>

```js
[
  "a",
  "abbr",
  "acronym",
  "audio",
  "b",
  "bdi",
  "bdo",
  "big",
  "br",
  // display: inline-block
  // "button",
  "canvas",
  "cite",
  "code",
  "data",
  // display: none
  // "datalist",
  "del",
  "dfn",
  "em",
  "embed",
  "i",
  "iframe",
  "img",
  // display: inline-block
  // "input",
  "ins",
  "kbd",
  "label",
  "map",
  "mark",
  // display: inline-block
  // "meter",
  "noscript",
  "object",
  "output",
  "picture",
  // display: inline-block
  // "progress",
  "q",
  "ruby",
  "s",
  "samp",
  // display: inline-block
  // "select",
  "small",
  "span",
  "strong",
  "sub",
  "sup",
  "svg",
  // display: inline-block
  // "textarea",
  "time",
  "u",
  "tt",
  "var",
  "video",
  "wbr"
]
```

</details>
<br>

We might be able to do something special process using this list.
michalsnik: And excluding void elements + elements not supported in HTML 5 we get the following list:
```
[
    "a",
    "abbr",
    "audio",
    "b",
    "bdi",
    "bdo",
    "canvas",
    "cite",
    "code",
    "data",
    "del",
    "dfn",
    "em",
    "i",
    "iframe",
    "ins",
    "kbd",
    "label",
    "map",
    "mark",
    "noscript",
    "object",
    "output",
    "picture",
    "q",
    "ruby",
    "s",
    "samp",
    "small",
    "span",
    "strong",
    "sub",
    "sup",
    "svg",
    "time",
    "u",
    "var",
    "video"
]
```
michalsnik: What do you guys think about current implementation? I ignore all inline elements implicitly now, no matter `ignores` setting. But I left `pre` + `textarea` as is, so one can override these. Should we also allow re-enabling this rule for other tags too?
manniL: I like the implementation @michalsnik ☺️ 

Regarding your question: Who would re-enable it for a few tags? Is the *need* there to do so (and not disabling the whole rule instead)?

michalsnik: Thanks @manniL I meant that one could want for example not to ignore `a` tags for some reason. And in the current implementation it's not possible as I'm implicitly ignoring it anyway no matter what user passes in `ignores` option.
michalsnik: On the other hand it might be an overhead for users.
If we allow overriding `ignores` completely, then if they would want to disable all inline elements but `label` - they'd have to copy whole list of inline elements except `label` and paste it in their `.eslintrc`, or alternatively we might create an extra `whitelist` option, but I doubt using both `ignores` and `whitelist` in one rule is a good solution, it'd be confusing AF :D

Btw. Did you know handlebars had whitespace trimmer built-in `{{~ foo ~}}`? :D
manniL: @michalsnik Well, we could just put the very broad default list in `ignores` and let them change it if they want. There is no way to "satisfy" all options (or make them all easy) 🙈 

So if ppl want to ignore all from the list but label, they have to add them all manually. That's more intuitive I guess.


PS: I did not 😄 
michalsnik: Fine 👍 thanks @manniL I needed that extra opinion
ota-meshi: Do we think that `<pre>` and `<textarea>` should also be ignored implicitly?

`html-indent` rule implicitly ignores `<pre>` and `<textarea>`.
manniL: @ota-meshi Good point. Yeah, for consistency reasons we should include them IMO.
michalsnik: I simplified the configuration in the last commit as agreed with @manniL: https://github.com/vuejs/eslint-plugin-vue/pull/738#issuecomment-451945598

Patch:
diff --git a/docs/rules/README.md b/docs/rules/README.md
index 4339b1e7..6b8b2df5 100644
--- a/docs/rules/README.md
+++ b/docs/rules/README.md
@@ -143,16 +143,20 @@ For example:
 | [vue/arrow-spacing](./arrow-spacing.md) | enforce consistent spacing before and after the arrow in arrow functions | :wrench: |
 | [vue/block-spacing](./block-spacing.md) | disallow or enforce spaces inside of blocks after opening block and before closing block | :wrench: |
 | [vue/brace-style](./brace-style.md) | enforce consistent brace style for blocks | :wrench: |
+| [vue/camelcase](./camelcase.md) | enforce camelcase naming convention |  |
+| [vue/comma-dangle](./comma-dangle.md) | require or disallow trailing commas | :wrench: |
 | [vue/component-name-in-template-casing](./component-name-in-template-casing.md) | enforce specific casing for the component naming style in template | :wrench: |
 | [vue/eqeqeq](./eqeqeq.md) | require the use of `===` and `!==` | :wrench: |
 | [vue/key-spacing](./key-spacing.md) | enforce consistent spacing between keys and values in object literal properties | :wrench: |
 | [vue/match-component-file-name](./match-component-file-name.md) | require component name property to match its file name |  |
+| [vue/no-boolean-default](./no-boolean-default.md) | disallow boolean defaults | :wrench: |
 | [vue/no-restricted-syntax](./no-restricted-syntax.md) | disallow specified syntax |  |
 | [vue/object-curly-spacing](./object-curly-spacing.md) | enforce consistent spacing inside braces | :wrench: |
 | [vue/require-direct-export](./require-direct-export.md) | require the component to be directly exported |  |
 | [vue/script-indent](./script-indent.md) | enforce consistent indentation in `<script>` | :wrench: |
 | [vue/space-infix-ops](./space-infix-ops.md) | require spacing around infix operators | :wrench: |
 | [vue/space-unary-ops](./space-unary-ops.md) | enforce consistent spacing before or after unary operators | :wrench: |
+| [vue/v-on-function-call](./v-on-function-call.md) | enforce or forbid parentheses after method calls without arguments in `v-on` directives | :wrench: |
 
 ## Deprecated
 
diff --git a/docs/rules/camelcase.md b/docs/rules/camelcase.md
new file mode 100644
index 00000000..c54c4445
--- /dev/null
+++ b/docs/rules/camelcase.md
@@ -0,0 +1,21 @@
+---
+pageClass: rule-details
+sidebarDepth: 0
+title: vue/camelcase
+description: enforce camelcase naming convention
+---
+# vue/camelcase
+> enforce camelcase naming convention
+
+This rule is the same rule as core [camelcase] rule but it applies to the expressions in `<template>`.
+
+## :books: Further reading
+
+- [camelcase]
+
+[camelcase]: https://eslint.org/docs/rules/camelcase
+
+## :mag: Implementation
+
+- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/camelcase.js)
+- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/camelcase.js)
diff --git a/docs/rules/comma-dangle.md b/docs/rules/comma-dangle.md
new file mode 100644
index 00000000..0ccdf151
--- /dev/null
+++ b/docs/rules/comma-dangle.md
@@ -0,0 +1,23 @@
+---
+pageClass: rule-details
+sidebarDepth: 0
+title: vue/comma-dangle
+description: require or disallow trailing commas
+---
+# vue/comma-dangle
+> require or disallow trailing commas
+
+- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
+
+This rule is the same rule as core [comma-dangle] rule but it applies to the expressions in `<template>`.
+
+## :books: Further reading
+
+- [comma-dangle]
+
+[comma-dangle]: https://eslint.org/docs/rules/comma-dangle
+
+## :mag: Implementation
+
+- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/comma-dangle.js)
+- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/comma-dangle.js)
diff --git a/docs/rules/multiline-html-element-content-newline.md b/docs/rules/multiline-html-element-content-newline.md
index 1004c1ee..c3eab2c2 100644
--- a/docs/rules/multiline-html-element-content-newline.md
+++ b/docs/rules/multiline-html-element-content-newline.md
@@ -74,11 +74,11 @@ This rule enforces a line break before and after the contents of a multiline ele
 
 ## :wrench: Options
 
-```json
+```js
 {
     "vue/multiline-html-element-content-newline": ["error", {
         "ignoreWhenEmpty": true,
-        "ignores": ["pre", "textarea"],
+        "ignores": ["pre", "textarea", ...INLINE_ELEMENTS],
         "allowEmptyLines": false
     }]
 }
@@ -86,11 +86,15 @@ This rule enforces a line break before and after the contents of a multiline ele
 
 - `ignoreWhenEmpty` ... disables reporting when element has no content.
     default `true`
-- `ignores` ... the configuration for element names to ignore line breaks style.  
-    default `["pre", "textarea"]`
+- `ignores` ... the configuration for element names to ignore line breaks style.
+    default `["pre", "textarea", ...INLINE_ELEMENTS]`.
 - `allowEmptyLines` ... if `true`, it allows empty lines around content. If you want to disallow multiple empty lines, use [no-multiple-empty-lines] in combination.  
     default `false`
 
+::: info
+  All inline non void elements can be found [here](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/utils/inline-non-void-elements.json).
+:::
+
 ### `"ignores": ["VueComponent", "pre", "textarea"]`
 
 <eslint-code-block fix :rules="{'vue/multiline-html-element-content-newline': ['error', { ignores: ['VueComponent', 'pre', 'textarea'] }]}">
diff --git a/docs/rules/no-boolean-default.md b/docs/rules/no-boolean-default.md
new file mode 100644
index 00000000..74e53f92
--- /dev/null
+++ b/docs/rules/no-boolean-default.md
@@ -0,0 +1,49 @@
+---
+pageClass: rule-details
+sidebarDepth: 0
+title: vue/no-boolean-default
+description: disallow boolean defaults
+---
+# vue/no-boolean-default
+> disallow boolean defaults
+
+- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
+
+The rule prevents Boolean props from having a default value.
+
+
+## :book: Rule Details
+The rule is to enforce the HTML standard of always defaulting boolean attributes to false.
+
+<eslint-code-block fix :rules="{'vue/no-boolean-default': ['error']}">
+
+```vue
+<script>
+export default {
+  props: {
+    foo: {
+      type: Boolean,
+      default: true
+    },
+    bar: {
+      type: Boolean
+    }
+  }
+}
+</script>
+```
+
+</eslint-code-block>
+
+## :wrench: Options
+- `'no-default'` (default) allows a prop definition object, but enforces that the `default` property not be defined.
+- `'default-false'` enforces that the default can be set but must be set to `false`.
+
+```json
+  "vue/no-boolean-default": ["error", "no-default|default-false"]
+```
+
+## :mag: Implementation
+
+- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-boolean-default.js)
+- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-boolean-default.js)
diff --git a/docs/rules/singleline-html-element-content-newline.md b/docs/rules/singleline-html-element-content-newline.md
index 92f5f90d..6ff57bc5 100644
--- a/docs/rules/singleline-html-element-content-newline.md
+++ b/docs/rules/singleline-html-element-content-newline.md
@@ -50,12 +50,12 @@ This rule enforces a line break before and after the contents of a singleline el
 
 ## :wrench: Options
 
-```json
+```js
 {
   "vue/singleline-html-element-content-newline": ["error", {
     "ignoreWhenNoAttributes": true,
     "ignoreWhenEmpty": true,
-    "ignores": ["pre", "textarea"]
+    "ignores": ["pre", "textarea", ...INLINE_ELEMENTS]
   }]
 }
 ```
@@ -64,8 +64,13 @@ This rule enforces a line break before and after the contents of a singleline el
     default `true`
 - `ignoreWhenEmpty` ... disables reporting when element has no content.
     default `true`
-- `ignores` ... the configuration for element names to ignore line breaks style.  
-    default `["pre", "textarea"]`
+- `ignores` ... the configuration for element names to ignore line breaks style.
+    default `["pre", "textarea", ...INLINE_ELEMENTS]`.
+
+
+::: info
+  All inline non void elements can be found [here](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/utils/inline-non-void-elements.json).
+:::
 
 
 ### `"ignoreWhenNoAttributes": true`
diff --git a/docs/rules/v-on-function-call.md b/docs/rules/v-on-function-call.md
new file mode 100644
index 00000000..a3a5a3c8
--- /dev/null
+++ b/docs/rules/v-on-function-call.md
@@ -0,0 +1,77 @@
+---
+pageClass: rule-details
+sidebarDepth: 0
+title: vue/v-on-function-call
+description: enforce or forbid parentheses after method calls without arguments in `v-on` directives
+---
+# vue/v-on-function-call
+> enforce or forbid parentheses after method calls without arguments in `v-on` directives
+
+- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
+
+## :book: Rule Details
+
+:-1: Example of **incorrect** code for this rule:
+
+```html
+<button v-on:click="closeModal()">
+  Close
+</button>
+```
+
+:+1: Example of **correct** code for this rule:
+
+```html
+<button v-on:click="closeModal">
+  Close
+</button>
+```
+
+## :wrench: Options
+
+Default is set to `never`.
+
+```
+'vue/v-on-parens': [2, 'always'|'never']
+```
+
+### `"always"` - Always use parentheses in `v-on` directives
+
+:-1: Example of **incorrect** code:
+
+```html
+<button v-on:click="closeModal">
+  Close
+</button>
+```
+
+:+1: Example of **correct** code:
+
+```html
+<button v-on:click="closeModal()">
+  Close
+</button>
+```
+
+### `"never"` - Never use parentheses in `v-on` directives for method calls without arguments
+
+:-1: Example of **incorrect** code:
+
+```html
+<button v-on:click="closeModal()">
+  Close
+</button>
+```
+
+:+1: Example of **correct** code:
+
+```html
+<button v-on:click="closeModal">
+  Close
+</button>
+```
+
+## :mag: Implementation
+
+- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/v-on-function-call.js)
+- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/v-on-function-call.js)
diff --git a/lib/configs/no-layout-rules.js b/lib/configs/no-layout-rules.js
index d6bea10c..2b23f1e6 100644
--- a/lib/configs/no-layout-rules.js
+++ b/lib/configs/no-layout-rules.js
@@ -9,6 +9,7 @@ module.exports = {
     'vue/arrow-spacing': 'off',
     'vue/block-spacing': 'off',
     'vue/brace-style': 'off',
+    'vue/comma-dangle': 'off',
     'vue/html-closing-bracket-newline': 'off',
     'vue/html-closing-bracket-spacing': 'off',
     'vue/html-indent': 'off',
diff --git a/lib/index.js b/lib/index.js
index 5f28d6b2..a7627fca 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -13,6 +13,8 @@ module.exports = {
     'attributes-order': require('./rules/attributes-order'),
     'block-spacing': require('./rules/block-spacing'),
     'brace-style': require('./rules/brace-style'),
+    'camelcase': require('./rules/camelcase'),
+    'comma-dangle': require('./rules/comma-dangle'),
     'comment-directive': require('./rules/comment-directive'),
     'component-name-in-template-casing': require('./rules/component-name-in-template-casing'),
     'eqeqeq': require('./rules/eqeqeq'),
@@ -30,6 +32,7 @@ module.exports = {
     'mustache-interpolation-spacing': require('./rules/mustache-interpolation-spacing'),
     'name-property-casing': require('./rules/name-property-casing'),
     'no-async-in-computed-properties': require('./rules/no-async-in-computed-properties'),
+    'no-boolean-default': require('./rules/no-boolean-default'),
     'no-confusing-v-for-v-if': require('./rules/no-confusing-v-for-v-if'),
     'no-dupe-keys': require('./rules/no-dupe-keys'),
     'no-duplicate-attributes': require('./rules/no-duplicate-attributes'),
@@ -66,6 +69,7 @@ module.exports = {
     'this-in-template': require('./rules/this-in-template'),
     'use-v-on-exact': require('./rules/use-v-on-exact'),
     'v-bind-style': require('./rules/v-bind-style'),
+    'v-on-function-call': require('./rules/v-on-function-call'),
     'v-on-style': require('./rules/v-on-style'),
     'valid-template-root': require('./rules/valid-template-root'),
     'valid-v-bind': require('./rules/valid-v-bind'),
diff --git a/lib/rules/camelcase.js b/lib/rules/camelcase.js
new file mode 100644
index 00000000..c0ca0417
--- /dev/null
+++ b/lib/rules/camelcase.js
@@ -0,0 +1,9 @@
+/**
+ * @author Yosuke Ota
+ */
+'use strict'
+
+const { wrapCoreRule } = require('../utils')
+
+// eslint-disable-next-line
+module.exports = wrapCoreRule(require('eslint/lib/rules/camelcase'))
diff --git a/lib/rules/comma-dangle.js b/lib/rules/comma-dangle.js
new file mode 100644
index 00000000..cfd0a418
--- /dev/null
+++ b/lib/rules/comma-dangle.js
@@ -0,0 +1,9 @@
+/**
+ * @author Yosuke Ota
+ */
+'use strict'
+
+const { wrapCoreRule } = require('../utils')
+
+// eslint-disable-next-line
+module.exports = wrapCoreRule(require('eslint/lib/rules/comma-dangle'))
diff --git a/lib/rules/multiline-html-element-content-newline.js b/lib/rules/multiline-html-element-content-newline.js
index 8e900b6e..6b7e5248 100644
--- a/lib/rules/multiline-html-element-content-newline.js
+++ b/lib/rules/multiline-html-element-content-newline.js
@@ -10,6 +10,7 @@
 
 const utils = require('../utils')
 const casing = require('../utils/casing')
+const INLINE_ELEMENTS = require('../utils/inline-non-void-elements.json')
 
 // ------------------------------------------------------------------------------
 // Helpers
@@ -21,7 +22,7 @@ function isMultilineElement (element) {
 
 function parseOptions (options) {
   return Object.assign({
-    ignores: ['pre', 'textarea'],
+    ignores: ['pre', 'textarea'].concat(INLINE_ELEMENTS),
     ignoreWhenEmpty: true,
     allowEmptyLines: false
   }, options)
diff --git a/lib/rules/no-boolean-default.js b/lib/rules/no-boolean-default.js
new file mode 100644
index 00000000..d0e3f36a
--- /dev/null
+++ b/lib/rules/no-boolean-default.js
@@ -0,0 +1,92 @@
+/**
+ * @fileoverview Prevents boolean defaults from being set
+ * @author Hiroki Osame
+ */
+'use strict'
+
+const utils = require('../utils')
+
+// ------------------------------------------------------------------------------
+// Rule Definition
+// ------------------------------------------------------------------------------
+
+function isBooleanProp (prop) {
+  return (
+    prop.type === 'Property' &&
+    prop.key.type === 'Identifier' &&
+    prop.key.name === 'type' &&
+    prop.value.type === 'Identifier' &&
+    prop.value.name === 'Boolean'
+  )
+}
+
+function getBooleanProps (props) {
+  return props
+    .filter(prop => (
+      prop.value &&
+      prop.value.properties &&
+      prop.value.properties.find(isBooleanProp)
+    ))
+}
+
+function getDefaultNode (propDef) {
+  return propDef.value.properties.find(p => {
+    return (
+      p.type === 'Property' &&
+      p.key.type === 'Identifier' &&
+      p.key.name === 'default'
+    )
+  })
+}
+
+module.exports = {
+  meta: {
+    type: 'suggestion',
+    docs: {
+      description: 'disallow boolean defaults',
+      category: undefined,
+      url: 'https://eslint.vuejs.org/rules/no-boolean-default.html'
+    },
+    fixable: 'code',
+    schema: [
+      {
+        enum: ['default-false', 'no-default']
+      }
+    ]
+  },
+
+  create (context) {
+    return utils.executeOnVueComponent(context, (obj) => {
+      const props = utils.getComponentProps(obj)
+      const booleanProps = getBooleanProps(props)
+
+      if (!booleanProps.length) return
+
+      const booleanType = context.options[0] || 'no-default'
+
+      booleanProps.forEach((propDef) => {
+        const defaultNode = getDefaultNode(propDef)
+
+        switch (booleanType) {
+          case 'no-default':
+            if (defaultNode) {
+              context.report({
+                node: defaultNode,
+                message: 'Boolean prop should not set a default (Vue defaults it to false).'
+              })
+            }
+            break
+
+          case 'default-false':
+            if (defaultNode.value.value !== false) {
+              context.report({
+                node: defaultNode,
+                message: 'Boolean prop should be defaulted to false.'
+              })
+            }
+            break
+        }
+      })
+    })
+  }
+}
diff --git a/lib/rules/order-in-components.js b/lib/rules/order-in-components.js
index d41798c8..a63b477e 100644
--- a/lib/rules/order-in-components.js
+++ b/lib/rules/order-in-components.js
@@ -22,6 +22,8 @@ const defaultOrder = [
   'data',
   'computed',
   'watch',
+  'asyncData',
+  'fetch',
   'LIFECYCLE_HOOKS',
   'methods',
   ['template', 'render'],
diff --git a/lib/rules/singleline-html-element-content-newline.js b/lib/rules/singleline-html-element-content-newline.js
index 5cf4e0f7..f6202519 100644
--- a/lib/rules/singleline-html-element-content-newline.js
+++ b/lib/rules/singleline-html-element-content-newline.js
@@ -10,6 +10,7 @@
 
 const utils = require('../utils')
 const casing = require('../utils/casing')
+const INLINE_ELEMENTS = require('../utils/inline-non-void-elements.json')
 
 // ------------------------------------------------------------------------------
 // Helpers
@@ -21,7 +22,7 @@ function isSinglelineElement (element) {
 
 function parseOptions (options) {
   return Object.assign({
-    ignores: ['pre', 'textarea'],
+    ignores: ['pre', 'textarea'].concat(INLINE_ELEMENTS),
     ignoreWhenNoAttributes: true,
     ignoreWhenEmpty: true
   }, options)
diff --git a/lib/rules/v-on-function-call.js b/lib/rules/v-on-function-call.js
new file mode 100644
index 00000000..5dd76b2e
--- /dev/null
+++ b/lib/rules/v-on-function-call.js
@@ -0,0 +1,60 @@
+/**
+ * @author Niklas Higi
+ */
+'use strict'
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+const utils = require('../utils')
+
+// ------------------------------------------------------------------------------
+// Rule Definition
+// ------------------------------------------------------------------------------
+
+module.exports = {
+  meta: {
+    type: 'suggestion',
+    docs: {
+      description: 'enforce or forbid parentheses after method calls without arguments in `v-on` directives',
+      category: undefined,
+      url: 'https://eslint.vuejs.org/rules/v-on-function-call.html'
+    },
+    fixable: 'code',
+    schema: [
+      { enum: ['always', 'never'] }
+    ]
+  },
+
+  create (context) {
+    const always = context.options[0] === 'always'
+
+    return utils.defineTemplateBodyVisitor(context, {
+      "VAttribute[directive=true][key.name='on'][key.argument!=null] > VExpressionContainer > Identifier" (node) {
+        if (!always) return
+        context.report({
+          node,
+          loc: node.loc,
+          message: "Method calls inside of 'v-on' directives must have parentheses."
+        })
+      },
+
+      "VAttribute[directive=true][key.name='on'][key.argument!=null] VOnExpression > ExpressionStatement > *" (node) {
+        if (!always && node.type === 'CallExpression' && node.arguments.length === 0) {
+          context.report({
+            node,
+            loc: node.loc,
+            message: "Method calls without arguments inside of 'v-on' directives must not have parentheses.",
+            fix: fixer => {
+              const nodeString = context.getSourceCode().getText().substring(node.range[0], node.range[1])
+              // This ensures that parens are also removed if they contain whitespace
+              const parensLength = nodeString.match(/\(\s*\)\s*$/)[0].length
+              return fixer.removeRange([node.end - parensLength, node.end])
+            }
+          })
+        }
+      }
+    })
+  }
+}
diff --git a/lib/utils/inline-non-void-elements.json b/lib/utils/inline-non-void-elements.json
new file mode 100644
index 00000000..b3dda839
--- /dev/null
+++ b/lib/utils/inline-non-void-elements.json
@@ -0,0 +1,40 @@
+[
+  "a",
+  "abbr",
+  "audio",
+  "b",
+  "bdi",
+  "bdo",
+  "canvas",
+  "cite",
+  "code",
+  "data",
+  "del",
+  "dfn",
+  "em",
+  "i",
+  "iframe",
+  "ins",
+  "kbd",
+  "label",
+  "map",
+  "mark",
+  "noscript",
+  "object",
+  "output",
+  "picture",
+  "q",
+  "ruby",
+  "s",
+  "samp",
+  "small",
+  "span",
+  "strong",
+  "sub",
+  "sup",
+  "svg",
+  "time",
+  "u",
+  "var",
+  "video"
+]


Test patch:
diff --git a/tests/lib/rules/camelcase.js b/tests/lib/rules/camelcase.js
new file mode 100644
index 00000000..d12dda26
--- /dev/null
+++ b/tests/lib/rules/camelcase.js
@@ -0,0 +1,57 @@
+/**
+ * @author Yosuke Ota
+ */
+'use strict'
+
+const RuleTester = require('eslint').RuleTester
+const rule = require('../../../lib/rules/camelcase')
+
+const tester = new RuleTester({
+  parser: 'vue-eslint-parser',
+  parserOptions: { ecmaVersion: 2015 }
+})
+
+tester.run('camelcase', rule, {
+  valid: [
+    `<template>
+      <div :attr="{ myPref: 1 }" />
+    </template>`,
+    {
+      code: `
+        <template>
+          <div @click="($event) => {
+            const { my_pref } = $event
+          }" />
+        </template>`,
+      options: [{ ignoreDestructuring: true }]
+    }
+  ],
+  invalid: [
+    {
+      code: `
+        <template>
+          <div :attr="{ my_pref: 1 }" />
+        </template>`,
+      errors: [
+        {
+          message: 'Identifier \'my_pref\' is not in camel case.',
+          line: 3
+        }
+      ]
+    },
+    {
+      code: `
+        <template>
+          <div @click="($event) => {
+            const { my_pref } = $event
+          }" />
+        </template>`,
+      errors: [
+        {
+          message: 'Identifier \'my_pref\' is not in camel case.',
+          line: 4
+        }
+      ]
+    }
+  ]
+})
diff --git a/tests/lib/rules/comma-dangle.js b/tests/lib/rules/comma-dangle.js
new file mode 100644
index 00000000..aca71019
--- /dev/null
+++ b/tests/lib/rules/comma-dangle.js
@@ -0,0 +1,108 @@
+/**
+ * @author Yosuke Ota
+ */
+'use strict'
+
+const RuleTester = require('eslint').RuleTester
+const rule = require('../../../lib/rules/comma-dangle')
+
+const tester = new RuleTester({
+  parser: 'vue-eslint-parser',
+  parserOptions: { ecmaVersion: 2018 }
+})
+
+tester.run('comma-dangle', rule, {
+  valid: [
+    `<template>
+      <button @click="() => fn([a, b])" ></button>
+    </template>`,
+    {
+      code: `
+        <template>
+          <CustomButton @click="($event) => fn()" />
+        </template>`,
+      options: [{
+        'functions': 'never'
+      }]
+    },
+    {
+      code: `
+        <template>
+          <button @click="() => fn([a, b, ])" ></button>
+        </template>`,
+      options: [{
+        'arrays': 'ignore'
+      }]
+    }
+  ],
+  invalid: [
+    {
+      code: `
+        <template>
+          <button @click="() => fn([a, b,])" ></button>
+        </template>`,
+      output: `
+        <template>
+          <button @click="() => fn([a, b])" ></button>
+        </template>`,
+      errors: [
+        {
+          message: 'Unexpected trailing comma.',
+          line: 3
+        }
+      ]
+    },
+    {
+      code: `
+        <template>
+          <CustomButton @click="($event, ) => fn()" />
+        </template>`,
+      options: [{
+        'functions': 'never'
+      }],
+      output: `
+        <template>
+          <CustomButton @click="($event ) => fn()" />
+        </template>`,
+      errors: [
+        {
+          message: 'Unexpected trailing comma.',
+          line: 3
+        }
+      ]
+    },
+    {
+      code: `
+        <template>
+          <button @click="() => {
+            fn([a, b, ])
+            fn([
+              a,
+              b
+            ])
+          }"></button>
+        </template>`,
+      options: ['always-multiline'],
+      output: `
+        <template>
+          <button @click="() => {
+            fn([a, b ])
+            fn([
+              a,
+              b,
+            ])
+          }"></button>
+        </template>`,
+      errors: [
+        {
+          message: 'Unexpected trailing comma.',
+          line: 4
+        },
+        {
+          message: 'Missing trailing comma.',
+          line: 7
+        }
+      ]
+    }
+  ]
+})
diff --git a/tests/lib/rules/multiline-html-element-content-newline.js b/tests/lib/rules/multiline-html-element-content-newline.js
index 8f2f707b..a99591dd 100644
--- a/tests/lib/rules/multiline-html-element-content-newline.js
+++ b/tests/lib/rules/multiline-html-element-content-newline.js
@@ -44,7 +44,8 @@ tester.run('multiline-html-element-content-newline', rule, {
         <div class="panel">
           content
         </div>
-      </template>`,
+      </template>
+    `,
     `
       <template>
         <div
@@ -52,7 +53,71 @@ tester.run('multiline-html-element-content-newline', rule, {
         >
           content
         </div>
-      </template>`,
+      </template>
+    `,
+    `
+      <template>
+        <a
+          href="/"
+          class="link"
+        >Home</a>
+      </template>
+    `,
+    `
+      <template>
+        <a
+          href="/"
+          class="link"
+        >Home
+        </a>
+      </template>
+    `,
+    `
+      <template>
+        <a
+          href="/"
+          class="link"
+        >
+          Home
+        </a>
+      </template>
+    `,
+    `
+      <template>
+        <div>
+          <label
+            for="test"
+            class="label"
+          >Foo</label>
+          <input id="test">
+        </div>
+      </template>
+    `,
+    `
+      <template>
+        <div>
+          <label
+            for="test"
+            class="label"
+          >Foo
+          </label>
+          <input id="test">
+        </div>
+      </template>
+    `,
+    `
+      <template>
+        <div>
+          <label
+            for="test"
+            class="label"
+          >
+            Foo
+          </label>
+          <input id="test">
+        </div>
+      </template>
+    `,
     `
       <template>
         <div>
@@ -61,9 +126,13 @@ tester.run('multiline-html-element-content-newline', rule, {
             content
           </div>
         </div>
-      </template>`,
-    `<div>multiline end tag</div
-      >`,
+      </template>
+    `,
+    `
+      <div>multiline end tag</div
+      >
+    `,
+
     // empty
     `<template><div class="panel"></div></template>`,
     `
@@ -71,7 +140,9 @@ tester.run('multiline-html-element-content-newline', rule, {
         <div
           class="panel">
         </div>
-      </template>`,
+      </template>
+    `,
+
     // allowEmptyLines
     {
       code: `
@@ -109,11 +180,14 @@ tester.run('multiline-html-element-content-newline', rule, {
         </template>`,
       options: [{ allowEmptyLines: true }]
     },
+
     // self closing
     `
       <template>
         <self-closing />
-      </template>`,
+      </template>
+    `,
+
     // ignores
     `
       <template>
@@ -180,6 +254,7 @@ tester.run('multiline-html-element-content-newline', rule, {
         ignores: ['IgnoreTag']
       }]
     },
+
     // Ignore if no closing brackets
     `
       <template>
diff --git a/tests/lib/rules/no-boolean-default.js b/tests/lib/rules/no-boolean-default.js
new file mode 100644
index 00000000..9f87a3a3
--- /dev/null
+++ b/tests/lib/rules/no-boolean-default.js
@@ -0,0 +1,163 @@
+/**
+ * @fileoverview Prevents boolean defaults from being set
+ * @author Hiroki Osame
+ */
+'use strict'
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+var rule = require('../../../lib/rules/no-boolean-default')
+
+var RuleTester = require('eslint').RuleTester
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+var ruleTester = new RuleTester({
+  parserOptions: {
+    ecmaVersion: 2018,
+    sourceType: 'module'
+  }
+})
+ruleTester.run('no-boolean-default', rule, {
+
+  valid: [
+    {
+      filename: 'test.vue',
+      code: `
+        export default {
+          props: {
+            enabled: Boolean
+          }
+        }
+      `
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const props = {};
+        export default {
+          props: {
+            ...props,
+            enabled: Boolean
+          }
+        }
+      `
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const data = {};
+        export default {
+          props: {
+            enabled: {
+              type: Boolean,
+              ...data
+            }
+          }
+        }
+      `,
+      options: ['no-default']
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const data = {};
+        export default {
+          props: {
+            enabled: {
+              type: Boolean,
+              default: false,
+              ...data
+            }
+          }
+        }
+      `,
+      options: ['default-false']
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const data = {};
+        export default {
+          props: {
+            enabled: data
+          }
+        }
+      `
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        const data = {};
+        export default {
+          props: {
+            enabled: {
+              ...data
+            }
+          }
+        }
+      `
+    }
+  ],
+
+  invalid: [
+    {
+      filename: 'test.vue',
+      code: `
+        export default {
+          props: {
+            enabled: {
+              type: Boolean,
+              default: true,
+            }
+          }
+        }
+      `,
+      options: ['default-false'],
+      errors: [{
+        message: 'Boolean prop should be defaulted to false.',
+        line: 6
+      }]
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        export default {
+          props: {
+            enabled: {
+              type: Boolean,
+              default: null,
+            }
+          }
+        }
+      `,
+      options: ['default-false'],
+      errors: [{
+        message: 'Boolean prop should be defaulted to false.',
+        line: 6
+      }]
+    },
+    {
+      filename: 'test.vue',
+      code: `
+        export default {
+          props: {
+            enabled: {
+              type: Boolean,
+              default: false,
+            }
+          }
+        }
+      `,
+      options: ['no-default'],
+      errors: [{
+        message: 'Boolean prop should not set a default (Vue defaults it to false).',
+        line: 6
+      }]
+    }
+  ]
+})
diff --git a/tests/lib/rules/singleline-html-element-content-newline.js b/tests/lib/rules/singleline-html-element-content-newline.js
index 679e4868..bc4c0af9 100644
--- a/tests/lib/rules/singleline-html-element-content-newline.js
+++ b/tests/lib/rules/singleline-html-element-content-newline.js
@@ -33,39 +33,59 @@ tester.run('singleline-html-element-content-newline', rule, {
         <div class="panel">
           content
         </div>
-      </template>`,
+      </template>
+    `,
     `
       <template>
         <div class="panel">
           <div>
           </div>
         </div>
-      </template>`,
+      </template>
+    `,
     `
       <template>
         <div class="panel">
           <!-- comment -->
         </div>
-      </template>`,
+      </template>
+    `,
     `
       <template>
         <div>
           content
         </div>
-      </template>`,
+      </template>
+    `,
     `
       <template>
         <div>
           <div>
           </div>
         </div>
-      </template>`,
+      </template>
+    `,
     `
       <template>
         <div>
           <!-- comment -->
         </div>
-      </template>`,
+      </template>
+    `,
+    `
+      <template>
+        <a href="/">Home</a>
+      </template>
+    `,
+    `
+      <template>
+        <form>
+          <label for="test">Home</label>
+          <input id="test" name="test">
+        </form>
+      </template>
+    `,
+
     // ignoreWhenNoAttributes: true
     `
       <template>
@@ -91,6 +111,7 @@ tester.run('singleline-html-element-content-newline', rule, {
       <template>
         <div>    </div>
       </template>`,
+
     // ignoreWhenNoAttributes: false
     {
       code: `
diff --git a/tests/lib/rules/v-on-function-call.js b/tests/lib/rules/v-on-function-call.js
new file mode 100644
index 00000000..cfcbc005
--- /dev/null
+++ b/tests/lib/rules/v-on-function-call.js
@@ -0,0 +1,72 @@
+/**
+ * @author Niklas Higi
+ */
+'use strict'
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+const RuleTester = require('eslint').RuleTester
+const rule = require('../../../lib/rules/v-on-function-call')
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+const tester = new RuleTester({
+  parser: 'vue-eslint-parser',
+  parserOptions: { ecmaVersion: 2015 }
+})
+
+tester.run('v-on-function-call', rule, {
+  valid: [
+    {
+      filename: 'test.vue',
+      code: ''
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div @click="foo(123)"></div></template>',
+      options: ['always']
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div @click="foo(123)"></div></template>',
+      options: ['never']
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div @click="foo()"></div></template>',
+      options: ['always']
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div @click="foo"></div></template>',
+      options: ['never']
+    }
+  ],
+  invalid: [
+    {
+      filename: 'test.vue',
+      code: '<template><div @click="foo"></div></template>',
+      output: `<template><div @click="foo"></div></template>`,
+      errors: ["Method calls inside of 'v-on' directives must have parentheses."],
+      options: ['always']
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div @click="foo()"></div></template>',
+      output: `<template><div @click="foo"></div></template>`,
+      errors: ["Method calls without arguments inside of 'v-on' directives must not have parentheses."],
+      options: ['never']
+    },
+    {
+      filename: 'test.vue',
+      code: '<template><div @click="foo( )"></div></template>',
+      output: `<template><div @click="foo"></div></template>`,
+      errors: ["Method calls without arguments inside of 'v-on' directives must not have parentheses."],
+      options: ['never']
+    }
+  ]
+})