Skip to content
This repository has been archived by the owner on Oct 2, 2021. It is now read-only.

Commit

Permalink
feat(rule): add rule template-naming-convention
Browse files Browse the repository at this point in the history
closes #22
  • Loading branch information
dferber90 committed Mar 8, 2016
1 parent 0620a54 commit 12036a2
Show file tree
Hide file tree
Showing 5 changed files with 251 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ For a more thorough introduction, read the [setup guide](/docs/guides/setup.md).
* [no-zero-timeout](docs/rules/no-zero-timeout.md): Prevent usage of Meteor.setTimeout with zero delay
* [blaze-consistent-eventmap-params](docs/rules/blaze-consistent-eventmap-params.md): Force consistent event handler parameters in event maps
* [prefer-session-equals](docs/prefer-session-equals.md): Prefer `Session.equals` in conditions
* [template-naming-convention](docs/template-naming-convention.md): Naming convention for templates


## Core API
Expand Down
76 changes: 76 additions & 0 deletions docs/rules/template-naming-convention.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Force a naming convention for templates (template-naming-convention)

When it comes to naming templates there are multiple naming conventions available. Enforce one of them with this rule.


## Rule Details

This rule aims to enforce one naming convention for template names is used consistently.
It does this by checking references to the template from the JavaScript code.

It offers three different naming conventions, one of which can be chosen through the rule options.

The following patterns are considered warnings:

```js

/*eslint meteor/template-naming-convention: [2, "camel-case"]*/
Template.foo_bar.onCreated
Template.foo_bar.onRendered
Template.foo_bar.onDestroyed
Template.foo_bar.events
Template.foo_bar.helpers

Template.foo_bar.onCreated()
/* .. */

Template.FooBar.onCreated
/* .. */

```

The following patterns are not warnings:

```js

/*eslint meteor/template-naming-convention: [2, "camel-case"]*/
Template.fooBar.onCreated
Template.fooBar.onRendered
Template.fooBar.onDestroyed
Template.fooBar.events
Template.fooBar.helpers

/*eslint meteor/template-naming-convention: [2, "pascal-case"]*/
Template.FooBar.onCreated
/* .. */

/*eslint meteor/template-naming-convention: [2, "snake-case"]*/
Template.foo.onCreated
Template.foo_bar.onCreated

```

### Options

This rule accepts a single options argument with the following defaults:

```json
{
"rules": {
"template-naming-convention": [2, "camel-case"]
}
}
```

The second argument can have the following values:
- `camel-case`
- `pascal-case`
- `snake-case`

## Limitations

This rule can not warn for templates which are never referenced in JavaScript.

## When Not To Use It

If you are not using Blaze templates, it is okay to turn this rule off.
2 changes: 2 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module.exports = {
'no-zero-timeout': require('./rules/no-zero-timeout'),
'blaze-consistent-eventmap-params': require('./rules/blaze-consistent-eventmap-params'),
'prefer-session-equals': require('./rules/prefer-session-equals'),
'template-naming-convention': require('./rules/template-naming-convention'),
},
configs: {
parserOptions: {
Expand All @@ -21,6 +22,7 @@ module.exports = {
'meteor/no-zero-timeout': 2,
'meteor/blaze-consistent-eventmap-params': 2,
'meteor/prefer-session-equals': 0,
'meteor/template-naming-convention': 2,
},
},
},
Expand Down
68 changes: 68 additions & 0 deletions lib/rules/template-naming-convention.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* @fileoverview Force a naming convention for templates
* @author Dominik Ferber
* @copyright 2016 Dominik Ferber. All rights reserved.
* See LICENSE file in root directory for full license.
*/

// -----------------------------------------------------------------------------
// Rule Definition
// -----------------------------------------------------------------------------
const templateProps = new Set([
'onCreated',
'onRendered',
'onDestroyed',
'events',
'helpers',
'created',
'rendered',
'destroyed',
])

const NAMING_CONVENTIONS = {
CAMEL: 'camel-case',
PASCAL: 'pascal-case',
SNAKE: 'snake-case',
}

const isTemplateMemberExpression = node => (
node.object.type === 'MemberExpression' &&
node.object.object.type === 'Identifier' &&
node.object.object.name === 'Template' &&
node.object.property.type === 'Identifier' &&
node.property.type === 'Identifier' &&
templateProps.has(node.property.name)
)

const getErrorMessage = expected => `Invalid template naming convention, expected "${expected}"`

module.exports = context => ({
MemberExpression: node => {
if (!isTemplateMemberExpression(node)) return

const [namingConvention] = context.options
const templateName = node.object.property.name
switch (namingConvention) {
case NAMING_CONVENTIONS.PASCAL:
if (!/^[A-Z]([A-Z]|[a-z]|[0-9])*$/.test(templateName)) {
context.report(node, getErrorMessage(NAMING_CONVENTIONS.PASCAL))
}
break
case NAMING_CONVENTIONS.SNAKE:
if (templateName.toLowerCase() !== templateName) {
context.report(node, getErrorMessage(NAMING_CONVENTIONS.SNAKE))
}
break
case NAMING_CONVENTIONS.CAMEL:
default:
if (!/^[a-z]([A-Z]|[a-z]|[0-9])+$/.test(templateName)) {
context.report(node, getErrorMessage(NAMING_CONVENTIONS.CAMEL))
}
break
}
},
})

module.exports.schema = [
{ enum: Object.values(NAMING_CONVENTIONS) },
]
104 changes: 104 additions & 0 deletions tests/lib/rules/template-naming-convention.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/**
* @fileoverview Force a naming convention for templates
* @author Dominik Ferber
* @copyright 2016 Dominik Ferber. All rights reserved.
* See LICENSE file in root directory for full license.
*/

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

const rule = require('../../../dist/rules/template-naming-convention')
const RuleTester = require('eslint').RuleTester
const ruleTester = new RuleTester()

ruleTester.run('template-naming-convention', rule, {
valid: [
'Template.foo.helpers',
'Template.foo01.helpers',
'Template.foo19bar.helpers',
'Template.fooBar.helpers',
'Template.fooBar.helpers({})',
{
code: 'Template.FooBar.helpers({})',
options: ['pascal-case'],
},
{
code: 'Template.foo_bar.helpers({})',
options: ['snake-case'],
},
{
code: 'Template.fooBar.helpers({})',
options: ['camel-case'],
},
{
code: 'Template.fooBar.helpers({})',
options: [],
},
],

invalid: [
{
code: 'Template.foo_bar.onCreated',
errors: [
{ message: 'Invalid template naming convention, expected "camel-case"', type: 'MemberExpression' },
],
},
{
code: 'Template.foo_bar.onRendered',
errors: [
{ message: 'Invalid template naming convention, expected "camel-case"', type: 'MemberExpression' },
],
},
{
code: 'Template.foo_bar.onDestroyed',
errors: [
{ message: 'Invalid template naming convention, expected "camel-case"', type: 'MemberExpression' },
],
},
{
code: 'Template.foo_bar.events',
errors: [
{ message: 'Invalid template naming convention, expected "camel-case"', type: 'MemberExpression' },
],
},
{
code: 'Template.foo_bar.helpers',
errors: [
{ message: 'Invalid template naming convention, expected "camel-case"', type: 'MemberExpression' },
],
},
{
code: 'Template.foo_bar.created',
errors: [
{ message: 'Invalid template naming convention, expected "camel-case"', type: 'MemberExpression' },
],
},
{
code: 'Template.foo_bar.rendered',
errors: [
{ message: 'Invalid template naming convention, expected "camel-case"', type: 'MemberExpression' },
],
},
{
code: 'Template.foo_bar.destroyed',
errors: [
{ message: 'Invalid template naming convention, expected "camel-case"', type: 'MemberExpression' },
],
},
{
code: 'Template.foo_bar.helpers({})',
errors: [
{ message: 'Invalid template naming convention, expected "camel-case"', type: 'MemberExpression' },
],
},
{
code: 'Template.fooBar.helpers({})',
options: ['snake-case'],
errors: [
{ message: 'Invalid template naming convention, expected "snake-case"', type: 'MemberExpression' },
],
},
],
})

0 comments on commit 12036a2

Please sign in to comment.