eslint-config-jessy
v0.1.0
Published
Jessy JavaScript Style - ESLint Shareable Config
Downloads
3
Maintainers
Readme
Jessy, A Javascript Coding Style
Just another Javascript coding style with an eslint shareable config.
Install
npm install --save-dev eslint-config-jessy
Then inside your .eslintrc.js
file, you can write
{ extends: 'jessy' // https://github.com/lucidogen/jessy
, 'rules': // add your custom rules here
{
}
}
Motivation
With the release of Javascript ES2015 (ES6), we can take the chance to change some habits regarding the code we write in Javascript, especially regarding punctuation. For this 'exercise', let's try to view Javascript as a totally new language and not let ourselves driven away by styling rules that seem weird at first sight.
Javascript is not english. We do not write phrases ending with dots or use parenthesis, commas and semicolon in the same way as in english (or french or any spoken language). We can stick to the old conventions for any good or bad reason, but with this document, we felt it could be fun to read the Javascript specs and get the most out of it in terms of:
- Readability
Adding spaces between expressions adds visual identification of the elements and helps readability. This means adding a space before and after parenthesis, around symbols and other punctuation marks.
- Scope readability
Some eyes are not perfect balls (astigmatism) so it is hard for some people to align things with identation. We should try to help by having some kind of consistency between opening and closing scope character positioning. Basically, it should look obvious if we missed out a comma or some punctuation or if we replaced a brace with a parenthesis or vice versa. This is particularly true for the actual trend in 'declarative Javascript' where we find ourselves often defining objects and less often writing procedural code.
- Refactoring ease
If we need to move code around, we should not need to change too much punctuation or indentation in order to 'sit' this code in the new context.
- Single line commit changes
It is nice if we can keep changes from spilling on lines not really concerned by the change. For example, adding an element in a list should not make it as if we changed neighboring elements in the same operation.
- Orthogonality
This goal is to try to find a styling guide that is as consistent as possible across conditionals, object definitions, callbacks, etc.
Proposal
So here is the proposal. If you feel there is something that can be enhanced regarding the goals above, please send a pull request.
Object definition
Very short objects can be defined on a single line as so:
let foo = { title: 'hello' }
Longer objects should be defined on multiple lines, with commas at the start of each element. In this manner, all punctuation for the object definition align (opening curly bracket, commas and closing curly bracket). Note that we are not indenting the first curly bracket.
let person =
{ firstName: 'John'
, lastName: 'Difool'
, age: 45
}
Nested object definitions should follow the same rule, with increasing indentation corresponding to nesting depth.
let effect =
{ fx: 'mix'
, mix: 0.5
, source1:
{ fx: 'video'
, src: '/my/crazy/cat.mp4'
, rate: 0.6
}
, source2:
{ fx: 'quasicrystals'
, saturation: 0.8
}
}
Object definition with functions should follow the same rules.
let handler =
{ url: '/foo/bar/baz'
, callback ( msg ) {
console.log ( 'Receiving', msg.url, msg.value )
}
}
Conditional
We use 'stroustrup' brace style for functions and conditionals. Regarding parenthesis, we use spaces just as with object definitions (more on parenthesis further down).
if ( hero.isHome ) {
hero.rest ()
hero.giveSomeLove ()
}
else {
hero.explore ( World )
}
Single line blocks in conditionals can be simplified by removing curly braces. But execution block never goes on the same line as the condition.
if ( hero.isHome )
hero.rest ()
else
hero.explore ( World )
Function definition
Function definitions look similar to conditionals. The function keyword and parameters should be on the same line as the equal sign if there is one.
const setup = function ( params ) {
console.log ( 'Starting setup...' )
callMum ()
sayHelloToDad ( params.wordOfTheDay )
makeCoffee ()
}
When using return with a new object, we need to bend the rules a little since we cannot simply describe the object on the next line. In this case, we put the opening brace with the return statement.
export function mockUser ( firstName, lastName ) {
return {
firstName
, lastName
, login: firstName
, password: 'testing'
}
}
When returning a complex expression, we should split it into multiple lines, aligning elements after the return keyword.
let test = function ( a, b, c, d ) {
return a
&& b
&& ! c
&& d
}
Arrow function
Without a block, these are treated like any expression. With a block, we consider them like function definitions:
let foo = bar.map ( e => e.replace ( /foo/, 'bar' ) )
const setup = ( params ) => {
console.log ( 'Starting setup...' )
callMum ()
sayHelloToDad ( params.wordOfTheDay )
makeCoffee ()
}
let foo = baz.map
( ( e, i ) => {
let name = ID_TO_NAME [ e ]
return `param ${ i }: ${ name }`
}
)
Try / catch
These are treated like conditionals, with the block starting on the next line.
try {
doThis ()
doThat ()
}
catch ( e ) {
rescueThat ( e )
}
An empty 'catch' will have both curly braces on the next line. Having an empty catch can usually be avoided and makes the code easier to read.
Function call
Long function calls should go on multiple lines. Create a newline after the function name in case of assignment. This makes code slightly more readable and avoids too many lines with a single variable or function name:
let compiledWrapper = runInThisContext ( wrapper, { filename: filename } )
// or
let compiledWrapper = runInThisContext
( wrapper
, { filename: filename
, more: options
, blah: blih
}
)
Chained calls are either contained on a single line (rare case) or split on different lines, new calls should start on the same line as the first call.
this.get ( 'model' )
.set ( 'title', title )
.set ( 'description', description )
Accessing object properties
We treat square brackets in the same manner as parenthesis or curly braces:
let c = components [ name ]
String interpolation
Use a space around interpolated elements.
throw new Error
( `Cannot watch path '${ path }' (not a relative or absolute path).` )
Real-world example
Here are some examples in order to evaluate if the desired goals are or seem to be reached by comparing some real-world examples.
Defining an animation in Ember's Liquid-fire.
// Jessy style
import { animate, stop, Promise } from 'liquid-fire'
export default function crossFade ( opts = {} ) {
stop ( this.oldElement )
return Promise.all
( [ animate
( this.oldElement
, { opacity: 0 }
, opts
)
, animate
( this.newElement
, { opacity: [ opts.maxOpacity || 1, 0 ] }
, opts
)
]
)
}
Compared to:
// Classic style
import { animate, stop, Promise } from 'liquid-fire';
export default function crossFade(opts = {}) {
stop(this.oldElement);
return Promise.all([
animate(this.oldElement, {opacity: 0}, opts),
animate(this.newElement, {opacity: [opts.maxOpacity || 1, 0]}, opts)
]);
}