Commit af70a62b authored by Nick Stenning's avatar Nick Stenning Committed by GitHub

Merge pull request #27 from hypothesis/eslint

Add ESLint configuration and use it to replace JSCS / JSHint
parents d18f6e74 bc38011a
build/**
**/vendor/**/*.js
{
"env": {
"mocha": true,
"commonjs": true,
"browser": true,
},
"extends": "eslint:recommended",
"globals": {
"assert": false,
"sinon": false,
"Promise": false,
},
"rules": {
"array-callback-return": "error",
"block-scoped-var": "error",
"curly": "error",
"eqeqeq": "error",
"no-console": [
"error",
{ allow: ["warn", "error"] },
],
"no-self-compare": "error",
"no-throw-literal": "error",
"no-unused-expressions": "error",
"no-use-before-define": [
"error",
{"functions": false},
],
"semi": "error",
"strict": ["error", "safe"],
},
"parserOptions": {
"ecmaVersion": 6,
}
}
{
"preset": "google",
"requireSemicolons": true,
"excludeFiles": [
".tox/**",
"build/**",
"docs/_build/**",
"dist/**",
"h/browser/chrome/content/**",
"h/static/scripts/vendor/**",
"h/static/styles/vendor/**",
"node_modules/**"
],
"disallowSpacesInAnonymousFunctionExpression": null,
"disallowSpacesInFunctionDeclaration": {
"beforeOpeningRoundBrace": true
},
"disallowSpacesInFunctionExpression": null,
"disallowSpacesInNamedFunctionExpression": {
"beforeOpeningRoundBrace": true
},
"requireSpacesInFunctionDeclaration": null,
"requireSpacesInFunctionExpression": null,
"requireSpacesInAnonymousFunctionExpression": {
"beforeOpeningRoundBrace": true,
"beforeOpeningCurlyBrace": true
}
}
build/
docs/
node_modules/
h/browser/chrome/content/
h/static/scripts/vendor/
h/templates/
**/*.min.js
{
"bitwise": true,
"curly": true,
"eqeqeq": true,
"forin": true,
"freeze": true,
"latedef": "nofunc",
"maxcomplexity": 10,
"strict": "global",
"undef": true,
"unused": true,
"esnext": true,
"globals": {
"chrome": false,
"Promise": false,
"chai": false,
"sinon": false,
"JSON": false
},
"browser": true,
"browserify": true,
"mocha": true,
"phantom": true,
"jquery": true,
"predef": [
"Promise",
"URL",
"after",
"afterEach",
"assert",
"before",
"beforeEach",
"chrome",
"context",
"describe",
"it",
"require",
"sinon"
]
}
language: node_js language: node_js
node_js: '4.3'
cache: cache:
directories: directories:
- node_modules - node_modules
...@@ -7,3 +6,12 @@ notifications: ...@@ -7,3 +6,12 @@ notifications:
slack: slack:
rooms: rooms:
- secure: "iYTftqYShXlMgoeuC7nfmBNwS59ZubIppTD4rpKg6m2PNLal9MtmH5vNlQMfFe+kuLV1pMuPOMfp9y+o3lJGO08lKHKlu+ziAuQcnPW2koR5ViYQcU3NCCZ2Pk4lsolcxwZrS6mbSbL3P/Sv6uYnU+QUNSVPCCeOLxKG+f3Vav+qQx3gduTOLRJEGVtpUpTLmSf8+WZpSM88Y00XK3LVUqOOy2Fq8e13PSERhfWbC391EnuOHpanHtzAdwE5rrWG+EaCYctT//zc/gmy4Cf+coq60RwC0WMhK+zEyLciXRGpBDn0JrGR+24rnI84y9AxdMHXv68OOVx1hZixaKt/8gvpJ78iDRGhEDOrjpGVRrTIApabx02YUsMfJB6XpyCVNRt31LYTW6I4F2+B76UKIEahzdir4LjGbdDhEn+f5adO9bOi46TuCAIhOai220mq/CMv70I4bk8WACuqW1nNq4UaLOZztF0ahmFmHbeGhko5Vlmd3IXhE2tgVN4bk+niOqFWXyJ7Yw/jpe18SkiDoM8jSy6tfQ2ycfwQRHCUHATALAGPYkXFkzKdqrkoRuQBb4hS8MWcOgVdNQwsekul7yR/RFZMBBEj4tUQdBQDP+S1WyCPj9yG5lJ1Ph9jxZ76lBDt3fW2J60UfFtELk4f0f3WR5ipyFSbVqSEmaXad2E=" - secure: "iYTftqYShXlMgoeuC7nfmBNwS59ZubIppTD4rpKg6m2PNLal9MtmH5vNlQMfFe+kuLV1pMuPOMfp9y+o3lJGO08lKHKlu+ziAuQcnPW2koR5ViYQcU3NCCZ2Pk4lsolcxwZrS6mbSbL3P/Sv6uYnU+QUNSVPCCeOLxKG+f3Vav+qQx3gduTOLRJEGVtpUpTLmSf8+WZpSM88Y00XK3LVUqOOy2Fq8e13PSERhfWbC391EnuOHpanHtzAdwE5rrWG+EaCYctT//zc/gmy4Cf+coq60RwC0WMhK+zEyLciXRGpBDn0JrGR+24rnI84y9AxdMHXv68OOVx1hZixaKt/8gvpJ78iDRGhEDOrjpGVRrTIApabx02YUsMfJB6XpyCVNRt31LYTW6I4F2+B76UKIEahzdir4LjGbdDhEn+f5adO9bOi46TuCAIhOai220mq/CMv70I4bk8WACuqW1nNq4UaLOZztF0ahmFmHbeGhko5Vlmd3IXhE2tgVN4bk+niOqFWXyJ7Yw/jpe18SkiDoM8jSy6tfQ2ycfwQRHCUHATALAGPYkXFkzKdqrkoRuQBb4hS8MWcOgVdNQwsekul7yR/RFZMBBEj4tUQdBQDP+S1WyCPj9yG5lJ1Ph9jxZ76lBDt3fW2J60UfFtELk4f0f3WR5ipyFSbVqSEmaXad2E="
matrix:
include:
# 'node_js' is listed for each job to ensure that only two builds are run.
# See https://github.com/hypothesis/client/pull/27#discussion_r70611726
- env: ACTION=lint
node_js: '4.3'
script: npm run lint
- env: ACTION=test
node_js: '4.3'
...@@ -15,6 +15,10 @@ clean: ...@@ -15,6 +15,10 @@ clean:
test: node_modules/.uptodate test: node_modules/.uptodate
npm test npm test
.PHONY: lint
lint: node_modules/.uptodate
npm run lint
################################################################################ ################################################################################
build/manifest.json: node_modules/.uptodate build/manifest.json: node_modules/.uptodate
......
/* eslint-env node */
'use strict'; 'use strict';
require('core-js/es6/promise'); require('core-js/es6/promise');
...@@ -119,7 +121,7 @@ gulp.task('build-app-js', ['build-vendor-js'], function () { ...@@ -119,7 +121,7 @@ gulp.task('build-app-js', ['build-vendor-js'], function () {
}); });
gulp.task('watch-app-js', ['build-vendor-js'], function () { gulp.task('watch-app-js', ['build-vendor-js'], function () {
appBundleConfigs.map(function (config) { appBundleConfigs.forEach(function (config) {
createBundle(config, {watch: true}); createBundle(config, {watch: true});
}); });
}); });
......
...@@ -67,9 +67,8 @@ function forEachNodeInRange(range, callback) { ...@@ -67,9 +67,8 @@ function forEachNodeInRange(range, callback) {
var nodeIter = root.ownerDocument.createNodeIterator(root, var nodeIter = root.ownerDocument.createNodeIterator(root,
NodeFilter.SHOW_ALL, null /* filter */, false /* expandEntityReferences */); NodeFilter.SHOW_ALL, null /* filter */, false /* expandEntityReferences */);
/* jshint -W084 */
var currentNode; var currentNode;
while (currentNode = nodeIter.nextNode()) { while (currentNode = nodeIter.nextNode()) { // eslint-disable-line no-cond-assign
if (isNodeInRange(range, currentNode)) { if (isNodeInRange(range, currentNode)) {
callback(currentNode); callback(currentNode);
} }
......
'use strict'; 'use strict';
require('./polyfills');
var queryString = require('query-string'); var queryString = require('query-string');
require('./polyfills');
var raven;
// Initialize Raven. This is required at the top of this file // Initialize Raven. This is required at the top of this file
// so that it happens early in the app's startup flow // so that it happens early in the app's startup flow
var settings = require('./settings')(document); var settings = require('./settings')(document);
Object.assign(settings, queryString.parse(window.location.search)); Object.assign(settings, queryString.parse(window.location.search));
if (settings.raven) { if (settings.raven) {
var raven = require('./raven'); raven = require('./raven');
raven.init(settings.raven); raven.init(settings.raven);
} }
......
...@@ -121,7 +121,7 @@ function threadAnnotations(annotations) { ...@@ -121,7 +121,7 @@ function threadAnnotations(annotations) {
// Collect the set of threads which have no parent as // Collect the set of threads which have no parent as
// children of the thread root // children of the thread root
var roots = []; var roots = [];
Object.keys(threads).map(function (id) { Object.keys(threads).forEach(function (id) {
if (!threads[id].parent) { if (!threads[id].parent) {
// Top-level threads are collapsed by default // Top-level threads are collapsed by default
threads[id].collapsed = true; threads[id].collapsed = true;
......
'use strict';
// cached date formatting instance. // cached date formatting instance.
// See https://github.com/hypothesis/h/issues/2820#issuecomment-166285361 // See https://github.com/hypothesis/h/issues/2820#issuecomment-166285361
var formatter; var formatter;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// @ngInject // @ngInject
function DropdownMenuBtnController($scope, $timeout) { function DropdownMenuBtnController($scope, $timeout) {
this.onClick = function($event) { this.onClick = function () {
$scope.onClick(); $scope.onClick();
}; };
...@@ -11,7 +11,7 @@ function DropdownMenuBtnController($scope, $timeout) { ...@@ -11,7 +11,7 @@ function DropdownMenuBtnController($scope, $timeout) {
$timeout(function () { $timeout(function () {
$scope.onToggleDropdown(); $scope.onToggleDropdown();
}, 0); }, 0);
} };
} }
module.exports = function () { module.exports = function () {
......
'use strict'; 'use strict';
var events = require('../events');
// @ngInject // @ngInject
function GroupListController($scope, $window, groups) { function GroupListController($scope, $window, groups) {
$scope.leaveGroup = function (groupId) { $scope.leaveGroup = function (groupId) {
...@@ -11,11 +9,11 @@ function GroupListController($scope, $window, groups) { ...@@ -11,11 +9,11 @@ function GroupListController($scope, $window, groups) {
if ($window.confirm(message)) { if ($window.confirm(message)) {
groups.leave(groupId); groups.leave(groupId);
} }
} };
$scope.focusGroup = function (groupId) { $scope.focusGroup = function (groupId) {
groups.focus(groupId); groups.focus(groupId);
} };
} }
/** /**
...@@ -28,12 +26,12 @@ function GroupListController($scope, $window, groups) { ...@@ -28,12 +26,12 @@ function GroupListController($scope, $window, groups) {
function groupList( $window, groups, settings) { function groupList( $window, groups, settings) {
return { return {
controller: GroupListController, controller: GroupListController,
link: function ($scope, elem, attrs) { link: function ($scope) {
$scope.groups = groups; $scope.groups = groups;
$scope.createNewGroup = function() { $scope.createNewGroup = function() {
$window.open(settings.serviceUrl + 'groups/new', '_blank'); $window.open(settings.serviceUrl + 'groups/new', '_blank');
} };
}, },
restrict: 'E', restrict: 'E',
scope: { scope: {
...@@ -41,7 +39,7 @@ function groupList( $window, groups, settings) { ...@@ -41,7 +39,7 @@ function groupList( $window, groups, settings) {
}, },
template: require('../../../templates/client/group_list.html'), template: require('../../../templates/client/group_list.html'),
}; };
}; }
module.exports = { module.exports = {
directive: groupList, directive: groupList,
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
module.exports = function() { module.exports = function() {
return { return {
restrict: 'A', restrict: 'A',
link: function($scope, $element, $attrs) { link: function($scope, $element) {
$element[0].focus(); $element[0].focus();
} }
}; };
......
'use strict'; 'use strict';
var angular = require('angular');
var debounce = require('lodash.debounce'); var debounce = require('lodash.debounce');
var commands = require('../markdown-commands'); var commands = require('../markdown-commands');
......
...@@ -16,15 +16,15 @@ module.exports = function () { ...@@ -16,15 +16,15 @@ module.exports = function () {
this.publishDestination = function () { this.publishDestination = function () {
return this.isShared ? this.group.name : this.privateLabel; return this.isShared ? this.group.name : this.privateLabel;
} };
this.groupType = function () { this.groupType = function () {
return this.group.public ? 'public' : 'group'; return this.group.public ? 'public' : 'group';
} };
this.setPrivacy = function (level) { this.setPrivacy = function (level) {
this.onSetPrivacy({level: level}); this.onSetPrivacy({level: level});
} };
}, },
controllerAs: 'vm', controllerAs: 'vm',
restrict: 'E', restrict: 'E',
...@@ -38,4 +38,4 @@ module.exports = function () { ...@@ -38,4 +38,4 @@ module.exports = function () {
}, },
template: require('../../../templates/client/publish_annotation_btn.html'), template: require('../../../templates/client/publish_annotation_btn.html'),
}; };
} };
'use strict';
module.exports = ['$animate', function($animate) { module.exports = ['$animate', function($animate) {
'use strict';
return { return {
link: function(scope, elem) { link: function(scope, elem) {
// ngAnimate conflicts with the spinners own CSS // ngAnimate conflicts with the spinners own CSS
......
...@@ -29,7 +29,7 @@ function annotationDirective() { ...@@ -29,7 +29,7 @@ function annotationDirective() {
username: noop, username: noop,
}, },
'../annotation-metadata': { '../annotation-metadata': {
domainAndTitle: function (annot) { domainAndTitle: function (annot) { // eslint-disable-line no-unused-vars
return fakeDocumentMeta; return fakeDocumentMeta;
}, },
} }
......
...@@ -6,7 +6,6 @@ var groupList = require('../group-list'); ...@@ -6,7 +6,6 @@ var groupList = require('../group-list');
var util = require('./util'); var util = require('./util');
describe('groupList', function () { describe('groupList', function () {
var $rootScope;
var $window; var $window;
var GROUP_LINK = 'https://hypothes.is/groups/hdevs'; var GROUP_LINK = 'https://hypothes.is/groups/hdevs';
...@@ -32,8 +31,7 @@ describe('groupList', function () { ...@@ -32,8 +31,7 @@ describe('groupList', function () {
angular.mock.module('app'); angular.mock.module('app');
}); });
beforeEach(angular.mock.inject(function (_$rootScope_, _$window_) { beforeEach(angular.mock.inject(function (_$window_) {
$rootScope = _$rootScope_;
$window = _$window_; $window = _$window_;
groups = [{ groups = [{
......
...@@ -57,7 +57,7 @@ describe('publishAnnotationBtn', function () { ...@@ -57,7 +57,7 @@ describe('publishAnnotationBtn', function () {
type: 'group' type: 'group'
}, },
isShared: true isShared: true
}) });
var buttons = element.find('button'); var buttons = element.find('button');
assert.equal(buttons[0].innerHTML, 'Post to Research Lab'); assert.equal(buttons[0].innerHTML, 'Post to Research Lab');
}); });
......
'use strict';
var angular = require('angular');
var module = angular.mock.module; var module = angular.mock.module;
var inject = angular.mock.inject; var inject = angular.mock.inject;
describe('spinner', function () { describe('spinner', function () {
var $animate = null; var $animate = null;
var $element = null var $element = null;
var sandbox = null; var sandbox = null;
before(function () { before(function () {
......
'use strict';
var angular = require('angular');
var inject = angular.mock.inject; var inject = angular.mock.inject;
var windowScroll = require('../window-scroll'); var windowScroll = require('../window-scroll');
...@@ -97,7 +101,7 @@ describe('windowScroll', function () { ...@@ -97,7 +101,7 @@ describe('windowScroll', function () {
assert.calledOnce(callback); assert.calledOnce(callback);
view.scrollY = 1800; view.scrollY = 1800;
handler() handler();
assert.calledTwice(callback); assert.calledTwice(callback);
}); });
}); });
......
var angular = require('angular'); 'use strict';
module.exports = function () { module.exports = function () {
return { return {
......
'use strict';
/** /**
* Parses H account names of the form 'acct:<username>@<provider>' * Parses H account names of the form 'acct:<username>@<provider>'
* into a {username, provider} object or null if the input does not * into a {username, provider} object or null if the input does not
......
'use strict';
var persona = require('../persona'); var persona = require('../persona');
describe('persona', function () { describe('persona', function () {
......
'use strict';
/* eslint curly: "off" */
/** This software is released under the MIT license: /** This software is released under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
......
'use strict'; 'use strict';
/* eslint no-console: "off" */
var queryString = require('query-string'); var queryString = require('query-string');
var Socket = require('./websocket'); var Socket = require('./websocket');
......
...@@ -44,7 +44,7 @@ function extractMath(content) { ...@@ -44,7 +44,7 @@ function extractMath(content) {
var pos = 0; var pos = 0;
var replacedContent = content; var replacedContent = content;
while (true) { while (true) { // eslint-disable-line no-constant-condition
var blockMathStart = replacedContent.indexOf('$$', pos); var blockMathStart = replacedContent.indexOf('$$', pos);
var inlineMathStart = replacedContent.indexOf('\\(', pos); var inlineMathStart = replacedContent.indexOf('\\(', pos);
......
'use strict';
// Expose the sinon assertions. // Expose the sinon assertions.
sinon.assert.expose(assert, {prefix: null}); sinon.assert.expose(assert, {prefix: null});
......
...@@ -8,7 +8,7 @@ var proxyquire = require('proxyquire'); ...@@ -8,7 +8,7 @@ var proxyquire = require('proxyquire');
// the most recently created FakeSocket instance // the most recently created FakeSocket instance
var fakeWebSocket = null; var fakeWebSocket = null;
function FakeSocket(url) { function FakeSocket() {
fakeWebSocket = this; fakeWebSocket = this;
this.messages = []; this.messages = [];
...@@ -25,7 +25,7 @@ function FakeSocket(url) { ...@@ -25,7 +25,7 @@ function FakeSocket(url) {
}; };
this.close = function () { this.close = function () {
this.didClose = true this.didClose = true;
}; };
} }
inherits(FakeSocket, EventEmitter); inherits(FakeSocket, EventEmitter);
...@@ -36,11 +36,10 @@ describe('streamer', function () { ...@@ -36,11 +36,10 @@ describe('streamer', function () {
var fakeRootScope; var fakeRootScope;
var fakeSession; var fakeSession;
var fakeSettings; var fakeSettings;
var activeStreamer;
var streamer; var streamer;
function createDefaultStreamer() { function createDefaultStreamer() {
activeStreamer = streamer.connect( streamer.connect(
fakeRootScope, fakeRootScope,
fakeAnnotationMapper, fakeAnnotationMapper,
fakeGroups, fakeGroups,
...@@ -81,7 +80,7 @@ describe('streamer', function () { ...@@ -81,7 +80,7 @@ describe('streamer', function () {
}); });
it('should not create a websocket connection if websocketUrl is not provided', function () { it('should not create a websocket connection if websocketUrl is not provided', function () {
fakeSettings = {} fakeSettings = {};
createDefaultStreamer(); createDefaultStreamer();
assert.isNull(fakeWebSocket); assert.isNull(fakeWebSocket);
}); });
...@@ -95,9 +94,8 @@ describe('streamer', function () { ...@@ -95,9 +94,8 @@ describe('streamer', function () {
it('should close any existing socket', function () { it('should close any existing socket', function () {
createDefaultStreamer(); createDefaultStreamer();
var oldStreamer = activeStreamer;
var oldWebSocket = fakeWebSocket; var oldWebSocket = fakeWebSocket;
var newStreamer = streamer.connect( streamer.connect(
fakeRootScope, fakeRootScope,
fakeAnnotationMapper, fakeAnnotationMapper,
fakeGroups, fakeGroups,
......
...@@ -61,7 +61,6 @@ describe('WidgetController', function () { ...@@ -61,7 +61,6 @@ describe('WidgetController', function () {
var fakeStreamer; var fakeStreamer;
var fakeStreamFilter; var fakeStreamFilter;
var sandbox; var sandbox;
var viewer;
before(function () { before(function () {
angular.module('h', []) angular.module('h', [])
...@@ -138,7 +137,7 @@ describe('WidgetController', function () { ...@@ -138,7 +137,7 @@ describe('WidgetController', function () {
$rootScope = _$rootScope_; $rootScope = _$rootScope_;
$scope = $rootScope.$new(); $scope = $rootScope.$new();
annotationUI = _annotationUI_; annotationUI = _annotationUI_;
viewer = $controller('WidgetController', {$scope: $scope}); $controller('WidgetController', {$scope: $scope});
})); }));
afterEach(function () { afterEach(function () {
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
"end-of-stream": "^1.1.0", "end-of-stream": "^1.1.0",
"escape-html": "^1.0.3", "escape-html": "^1.0.3",
"escape-string-regexp": "^1.0.5", "escape-string-regexp": "^1.0.5",
"eslint": "^3.0.1",
"exorcist": "^0.4.0", "exorcist": "^0.4.0",
"extend": "^2.0.0", "extend": "^2.0.0",
"gulp": "^3.9.1", "gulp": "^3.9.1",
...@@ -51,7 +52,6 @@ ...@@ -51,7 +52,6 @@
"inherits": "^2.0.1", "inherits": "^2.0.1",
"jquery": "1.11.1", "jquery": "1.11.1",
"js-polyfills": "^0.1.16", "js-polyfills": "^0.1.16",
"jscs": "^3.0.2",
"karma": "^1.1.0", "karma": "^1.1.0",
"karma-browserify": "^5.0.5", "karma-browserify": "^5.0.5",
"karma-chai": "^0.1.0", "karma-chai": "^0.1.0",
...@@ -135,6 +135,7 @@ ...@@ -135,6 +135,7 @@
"scripts": { "scripts": {
"build": "gulp build-app", "build": "gulp build-app",
"deps": "check-dependencies", "deps": "check-dependencies",
"lint": "eslint .",
"test": "gulp test-app", "test": "gulp test-app",
"preversion": "npm run test", "preversion": "npm run test",
"version": "make clean all && ./scripts/update-changelog.js && git add CHANGELOG.md", "version": "make clean all && ./scripts/update-changelog.js && git add CHANGELOG.md",
......
{
"env": {
"node": true,
},
"rules": {
"no-console": "off",
},
}
#!/usr/bin/env node #!/usr/bin/env node
'use strict';
/** /**
* Creates a GitHub release for the repository. * Creates a GitHub release for the repository.
* *
......
...@@ -81,10 +81,9 @@ function stripUnnecessaryReturns(js) { ...@@ -81,10 +81,9 @@ function stripUnnecessaryReturns(js) {
for (var i=0; i < stripReturnPatterns.length; i++) { for (var i=0; i < stripReturnPatterns.length; i++) {
if (remainder.match(stripReturnPatterns[i])) { if (remainder.match(stripReturnPatterns[i])) {
return remainder; return remainder;
} else {
return remainder;
} }
} }
return line;
} else { } else {
return line; return line;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment