# Style guides and linting See the relevant style guides for our guidelines and for information on linting: ## JavaScript We defer to [Airbnb][airbnb-js-style-guide] on most style-related conventions and enforce them with eslint. See [our current .eslintrc][eslintrc] for specific rules and patterns. ### Common #### ESlint - **Never** disable eslint rules unless you have a good reason. You may see a lot of legacy files with `/* eslint-disable some-rule, some-other-rule */` at the top, but legacy files are a special case. Any time you develop a new feature or refactor an existing one, you should abide by the eslint rules. - **Never Ever EVER** disable eslint globally for a file ```javascript // bad /* eslint-disable */ // better /* eslint-disable some-rule, some-other-rule */ // best // nothing :) ``` - If you do need to disable a rule for a single violation, try to do it as locally as possible ```javascript // bad /* eslint-disable no-new */ import Foo from 'foo'; new Foo(); // better import Foo from 'foo'; // eslint-disable-next-line no-new new Foo(); ``` - When they are needed _always_ place ESlint directive comment blocks on the first line of a script, followed by any global declarations, then a blank newline prior to any imports or code. ```javascript // bad /* global Foo */ /* eslint-disable no-new */ import Bar from './bar'; // good /* eslint-disable no-new */ /* global Foo */ import Bar from './bar'; ``` - **Never** disable the `no-undef` rule. Declare globals with `/* global Foo */` instead. - When declaring multiple globals, always use one `/* global [name] */` line per variable. ```javascript // bad /* globals Flash, Cookies, jQuery */ // good /* global Flash */ /* global Cookies */ /* global jQuery */ ``` #### Modules, Imports, and Exports - Use ES module syntax to import modules ```javascript // bad require('foo'); // good import Foo from 'foo'; // bad module.exports = Foo; // good export default Foo; ``` - Relative paths Unless you are writing a test, always reference other scripts using relative paths instead of `~` In **app/assets/javascripts**: ```javascript // bad import Foo from '~/foo' // good import Foo from '../foo'; ``` In **spec/javascripts**: ```javascript // bad import Foo from '../../app/assets/javascripts/foo' // good import Foo from '~/foo'; ``` - Avoid using IIFE. Although we have a lot of examples of files which wrap their contents in IIFEs (immediately-invoked function expressions), this is no longer necessary after the transition from Sprockets to webpack. Do not use them anymore and feel free to remove them when refactoring legacy code. - Avoid adding to the global namespace. ```javascript // bad window.MyClass = class { /* ... */ }; // good export default class MyClass { /* ... */ } ``` - Side effects are forbidden in any script which contains exports ```javascript // bad export default class MyClass { /* ... */ } document.addEventListener("DOMContentLoaded", function(event) { new MyClass(); } ``` #### Data Mutation and Pure functions - Strive to write many small pure functions, and minimize where mutations occur. ```javascript // bad const values = {foo: 1}; function impureFunction(items) { const bar = 1; items.foo = items.a * bar + 2; return items.a; } const c = impureFunction(values); // good var values = {foo: 1}; function pureFunction (foo) { var bar = 1; foo = foo * bar + 2; return foo; } var c = pureFunction(values.foo); ``` - Avoid constructors with side-effects #### Parse Strings into Numbers - `parseInt()` is preferable over `Number()` or `+` ```javascript // bad +'10' // 10 // good Number('10') // 10 // better parseInt('10', 10); ``` ### Vue.js #### Basic Rules - Only include one Vue.js component per file. - Export components as plain objects: ```javascript export default { template: `