Merge pull request #268 from mattermost/mm-1358

MM-1358, MM-1203 Adding preview of style guide and ESLint Javascript + JSX static analyzer
This commit is contained in:
Joram Wilander
2015-07-29 08:34:15 -04:00
4 changed files with 318 additions and 1 deletions

View File

@@ -5,6 +5,7 @@ GOFLAGS ?= $(GOFLAGS:)
BUILD_NUMBER ?= $(BUILD_NUMBER:)
GO=$(GOPATH)/bin/godep go
ESLINT=web/react/node_modules/eslint/bin/eslint.js
ifeq ($(BUILD_NUMBER),)
BUILD_NUMBER := dev
@@ -62,6 +63,14 @@ install:
@cd web/react/ && npm install
check: install
@echo Running ESLint...
@$(ESLINT) web/react/components/*
@$(ESLINT) web/react/dispatcher/*
@$(ESLINT) web/react/pages/*
@$(ESLINT) web/react/stores/*
@$(ESLINT) web/react/utils/*
test: install
@mkdir -p logs
@$(GO) test $(GOFLAGS) -run=$(TESTS) -test.v -test.timeout=180s ./api || exit 1

167
STYLE-GUIDE.md Normal file
View File

@@ -0,0 +1,167 @@
# Mattermost Style Guide
1. [GO](#go)
2. [Javascript](#javascript)
3. [React-JSX](#react-jsx)
## Go
All go code must follow the golang official [Style Guide](https://golang.org/doc/effective_go.html)
In addition all code must be run though the official go formatter tool [gofmt](https://golang.org/cmd/gofmt/)
## Javascript
Part of the build process is running ESLint. ESLint is the final authority on all style issues. PRs will not be accepted unless there are no errors or warnings running ESLint. The ESLint configuration file can be found in: [web/react/.eslintrc](https://github.com/mattermost/platform/blob/master/web/react/.eslintrc.json)
Instructions on how to use ESLint with your favourite editor can be found here: [http://eslint.org/docs/user-guide/integrations](http://eslint.org/docs/user-guide/integrations)
The following is an abridged version of the [Airbnb Javascript Style Guide](https://github.com/airbnb/javascript/blob/master/README.md#airbnb-javascript-style-guide-), with modifications. Anything that is unclear here follow that guide. If there is a conflict, follow what is said below.
### Whitespace
- Indentation is four spaces
- Use a space before the leading brace
- Use one space between the comma and the next argument in a bracketed list. No other space.
- Use whitespace to make code more readable.
- Do not use more than one newline to separate code blocks.
- Do not use a newline as the first line of a function
```javascript
// Correct
function myFunction(parm1, parm2) {
stuff...;
morestuff;
}
// Incorrect
function myFunction ( parm1, parm2 ){
stuff...;
morestuff;
}
```
### Semicolons
- You must use them always
```javascript
// Correct
var x = 1;
// Incorrect
var x = 1
```
### Variables
- Declarations must always use var, let or const.
- Prefer let or const over var.
- camelCase for all variable names.
```javascript
// Correct
let myVariable = 4;
// OK
var myVariable = 4;
// Incorrect
myVariable = 4;
var my_variable = 4;
```
### Blocks
- Braces must be used on all blocks.
- Braces must start on the same line as the statement starting the block.
- Else and else if must be on the same line as the if block closing brace.
```javascript
// Correct
if (somthing) {
stuff...;
} else if (otherthing) {
stuff...;
}
// Incorrect
if (somthing)
{
stuff...;
}
else
{
stuff...;
}
// Incorrect
if (somthing) stuff...;
if (somthing)
stuff...;
```
### Strings
- Use template strings instead of concatenation.
```javascript
// Correct
function getStr(stuff) {
return "This is the ${stuff} string";
}
// Incorrect
function wrongGetStr(stuff) {
return "This is the " + stuff + " string";
}
```
## React-JSX
Part of the build process is running ESLint. ESLint is the final authority on all style issues. PRs will not be accepted unless there are no errors or warnings running ESLint. The ESLint configuration file can be found in: [web/react/.eslintrc](https://github.com/mattermost/platform/blob/master/web/react/.eslintrc.json)
Instructions on how to use ESLint with your favourite editor can be found here: [http://eslint.org/docs/user-guide/integrations](http://eslint.org/docs/user-guide/integrations)
This is an abridged version of the [Airbnb React/JSX Style Guide](https://github.com/airbnb/javascript/tree/master/react#airbnb-reactjsx-style-guide). Anything that is unclear here follow that guide. If there is a conflict, follow what is said below.
### General
- Include only one React component per file.
- Use class \<name\> extends React.Component over React.createClass unless you need mixins
- CapitalCamelCase with .jsx extension for component filenames.
- Filenames should be the component name.
### Alignment
- Follow alignment styles shown below:
```xml
// Correct
<Tag
propertyOne="1"
propertyTwo="2"
>
<Child />
</Tag>
// Correct
<Tag propertyOne="1" />
```
### Naming
- Property names use camelCase.
- React component names use CapitalCamelCase.
- Do not use an understore for internal methods in a react component.
```xml
// Correct
<ReactComponent propertyOne="value" />
```

139
web/react/.eslintrc Normal file
View File

@@ -0,0 +1,139 @@
{
"ecmaFeatures": {
"jsx": true,
"blockBindings": true,
"modules": true
},
"plugins": [
"react"
],
"env": {
"browser": true,
"node": true,
"jquery": true,
"es6": true
},
"globals": {
"React": false
},
"rules": {
"comma-dangle": [2, "never"],
"no-cond-assign": [2, "except-parens"],
"no-console": 1,
"no-constant-condition": 1,
"no-debugger": 1,
"no-dupe-args": 2,
"no-dupe-keys": 2,
"no-duplicate-case": 2,
"no-empty": 1,
"no-ex-assign": 1,
"no-extra-semi": 2,
"no-func-assign": 1,
"no-inner-declarations": 0,
"no-invalid-regexp": 2,
"no-irregular-whitespace": 2,
"no-unreachable": 2,
"valid-typeof": 2,
"no-unexpected-multiline": 2,
"block-scoped-var": 1,
"complexity": [1, 8],
"consistent-return": 2,
"curly": [2, "all"],
"dot-notation": 2,
"dot-location": [2, "object"],
"eqeqeq": [2, "smart"],
"guard-for-in": 1,
"no-alert": 1,
"no-caller": 2,
"no-div-regex": 1,
"no-else-return": 1,
"no-eval": 2,
"no-extend-native": 2,
"no-floating-decimal": 2,
"no-labels": 2,
"no-lone-blocks": 1,
"no-multi-spaces": [2, { "exceptions": { "Property": false } }],
"no-multi-str": 0,
"no-param-reassign": 2,
"no-process-env": 2,
"no-redeclare": 2,
"no-return-assign": [2, "always"],
"no-script-url": 2,
"no-self-compare": 2,
"no-sequences": 2,
"no-throw-literal": 2,
"no-unused-expressions": 2,
"no-void": 2,
"no-warning-comments": 0,
"no-with": 2,
"radix": 2,
"vars-on-top": 0,
"wrap-iife": [2, "outside"],
"yoda": [2, "never", {"exceptRange": false, "onlyEquality": false}],
"no-undefined": 2,
"no-shadow": [2, {"hoist": "functions"}],
"no-unused-vars": [2, {"vars": "all", "args": "all"}],
"no-use-before-define": [2, "nofunc"],
// Style
"array-bracket-spacing": [2, "never"],
"brace-style": [2, "1tbs", { "allowSingleLine": false }],
"camelcase": [2, {"properties": "always"}],
"comma-spacing": [2, {"before": false, "after": true}],
"comma-style": [2, "last"],
"computed-property-spacing": [2, "never"],
"consistent-this": [2, "self"],
"func-names": 2,
"func-style": [2, "declaration"],
"indent": [2, 4, {"indentSwitchCase": false}],
"key-spacing": [2, {"beforeColon": false, "afterColon": true}],
"lines-around-comment": [2, { "beforeBlockComment": true, "beforeLineComment": true, "allowBlockStart": true, "allowBlockEnd": true }],
"linebreak-style": 2,
"new-cap": 2,
"new-parens": 2,
"no-lonely-if": 2,
"no-mixed-spaces-and-tabs": 2,
"no-multiple-empty-lines": [2, {"max": 1}],
"no-spaced-func": 2,
"no-ternary": 2,
"no-trailing-spaces": [2, { "skipBlankLines": false }],
"no-underscore-dangle": 2,
"no-unneeded-ternary": 2,
"object-curly-spacing": [2, "never"],
"one-var": [2, "never"],
"operator-linebreak": [2, "after"],
"padded-blocks": [2, "never"],
"quote-props": [2, "as-needed"],
"quotes": [2, "single", "avoid-escape"],
"semi-spacing": [2, {"before": false, "after": true}],
"semi": [2, "always"],
"space-after-keywords": [2, "always"],
"space-before-blocks": [2, "always"],
"space-before-function-paren": [2, "never"],
"space-in-parens": [2, "never"],
"space-infix-ops": 2,
"space-return-throw-case": 2,
"space-unary-ops": [2, { "words": true, "nonwords": false }],
"wrap-regex": 2,
// React Specific
"react/display-name": [2, { "acceptTranspilerName": true }],
"react/jsx-boolean-value": [2, "always"],
"react/jsx-curly-spacing": [2, "never"],
"react/jsx-no-duplicate-props": [2, { "ignoreCase": false }],
"react/jsx-no-undef": 2,
"react/jsx-quotes": [2, "single", "avoid-escape"],
"react/jsx-uses-react": 2,
"react/jsx-uses-vars": 2,
"react/no-danger": 0,
"react/no-did-mount-set-state": 2,
"react/no-did-update-set-state": 2,
"react/no-multi-comp": 2,
"react/no-unknown-property": 2,
"react/prop-types": 2,
"react/sort-comp": 0,
"react/wrap-multilines": 2
}
}

View File

@@ -16,7 +16,9 @@
"jest-cli": "~0.1.17",
"reactify": "^0.15.2",
"uglify-js": "~2.4.15",
"watchify": "^2.1.1"
"watchify": "^2.1.1",
"eslint": "^0.24.1",
"eslint-plugin-react": "^3.0.0"
},
"scripts": {
"start": "watchify --extension=jsx -o ../static/js/bundle.js -v -d ./**/*.jsx",