Skip to content

Rename and add options to this-in-template. #163

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 0 additions & 25 deletions docs/rules/no-this-in-template.md

This file was deleted.

2 changes: 1 addition & 1 deletion docs/rules/require-render-return.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Enforces render function to always return value (require-render-return)

This rule aims to enforce render function to allways return value
This rule aims to enforce render function to always return value

## :book: Rule Details

Expand Down
71 changes: 71 additions & 0 deletions docs/rules/this-in-template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# enforce usage of `this` in template. (this-in-template)

## :book: Rule Details

:-1: Examples of **incorrect** code for this rule:

```html
<template>
<a :href="this.link">{{this.text}}</a>
</template>
```

:+1: Examples of **correct** code for this rule:

```html
<template>
<a :href="link">{{text}}</a>
</template>
```

## :wrench: Options

Default is set to `never`.

```
'vue/this-in-template': [2, 'always'|'never']
```

### `"always"` - Always use `this` while accessing properties from vue

:+1: Examples of **correct** code`:

```html
<template>
<div :class="{'show': this.showFoo}">
{{ this.foo }}
</div>
</template>
```

:-1: Examples of **incorrect** code`:

```html
<template>
<div :class="{'show': showFoo}">
{{ foo }}
</div>
</template>
```

### `"never"` - Never use expresions that contain `this` keyword in expressions

:+1: Examples of **correct** code`:

```html
<template>
<div :class="{'show': this.showFoo}">
{{ this.foo }}
</div>
</template>
```

:-1: Examples of **incorrect** code`:

```html
<template>
<div :class="{'show': showFoo}">
{{ foo }}
</div>
</template>
```
47 changes: 0 additions & 47 deletions lib/rules/no-this-in-template.js

This file was deleted.

103 changes: 103 additions & 0 deletions lib/rules/this-in-template.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/**
* @fileoverview enforce usage of `this` in template.
* @author Armano
*/
'use strict'

// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------

const utils = require('../utils')
const RESERVED_NAMES = new Set(require('../utils/js-reserved.json'))

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------

module.exports = {
meta: {
docs: {
description: 'enforce usage of `this` in template.',
category: 'Best Practices',
recommended: false
},
fixable: null,
schema: [
{
enum: ['always', 'never']
}
]
},

/**
* Creates AST event handlers for this-in-template.
*
* @param {RuleContext} context - The rule context.
* @returns {Object} AST event handlers.
*/
create (context) {
const options = context.options[0] !== 'always' ? 'never' : 'always'
let scope = {
parent: null,
nodes: []
}

utils.registerTemplateBodyVisitor(context, Object.assign({
VElement (node) {
scope = {
parent: scope,
nodes: scope.nodes.slice() // make copy
}
if (node.variables) {
for (const variable of node.variables) {
const varNode = variable.id
const name = varNode.name
if (!scope.nodes.some(node => node.name === name)) { // Prevent adding duplicates
scope.nodes.push(varNode)
}
}
}
},
'VElement:exit' (node) {
scope = scope.parent
}
}, options === 'never'
? {
'VExpressionContainer MemberExpression > ThisExpression' (node) {
const propertyName = utils.getStaticPropertyName(node.parent.property)
if (!propertyName ||
scope.nodes.some(el => el.name === propertyName) ||
RESERVED_NAMES.has(propertyName) || // this.class | this['class']
/^[0-9].*$|[^a-zA-Z0-9_]/.test(propertyName) // this['0aaaa'] | this['foo-bar bas']
) {
return
}

context.report({
node,
loc: node.loc,
message: "Unexpected usage of 'this'."
})
}
}
: {
'VExpressionContainer' (node) {
if (node.references) {
for (const reference of node.references) {
if (!scope.nodes.some(el => el.name === reference.id.name)) {
context.report({
node: reference.id,
loc: reference.id.loc,
message: "Expected 'this'."
})
}
}
}
}
}
))

return {}
}
}
18 changes: 18 additions & 0 deletions lib/utils/js-reserved.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[
"abstract", "arguments", "await", "boolean",
"break", "byte", "case", "catch",
"char", "class", "const", "continue",
"debugger", "default", "delete", "do",
"double", "else", "enum", "eval",
"export", "extends", "false", "final",
"finally", "float", "for", "function",
"goto", "if", "implements", "import",
"in", "instanceof", "int", "interface",
"let", "long", "native", "new",
"null", "package", "private", "protected",
"public", "return", "short", "static",
"super", "switch", "synchronized", "this",
"throw", "throws", "transient", "true",
"try", "typeof", "var", "void",
"volatile", "while", "with", "yield"
]
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
},
"dependencies": {
"requireindex": "^1.1.0",
"vue-eslint-parser": "2.0.0-beta.7"
"vue-eslint-parser": "2.0.0-beta.10"
},
"devDependencies": {
"@types/node": "^4.2.16",
Expand Down
79 changes: 0 additions & 79 deletions tests/lib/rules/no-this-in-template.js

This file was deleted.

Loading