diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..7652eaed9 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,9 @@ +dist/ +docs/ +examples/ +misc/ +test/ +gulpfile.js +index.js +/src/js/ace/**/*.* +/src/js/assets/**/*.* \ No newline at end of file diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 000000000..18fd45b8c --- /dev/null +++ b/.eslintrc @@ -0,0 +1,25 @@ +{ + "env": { + "browser": true + }, + "plugins": [], + "rules": { + "strict": 0, + "indent": ["error", 2, { "SwitchCase": 1, "VariableDeclarator": 2 }], + "semi": ["error", "always"], + "semi-spacing": ["error", {"before": false, "after": true}], + "no-extra-semi": 2, + "no-trailing-spaces": 1, + //"max-len": ["error", 80] + "quotes": ["error", "single"], + "brace-style": ["error", "stroustrup", { "allowSingleLine": true }], + "one-var": ["error", { "var": "never" }], + "camelcase": "error", + "new-cap": ["error", { "capIsNewExceptions": ["Ajv"] }], + "quote-props": ["error", "as-needed"], + "comma-style": ["error", "last"], + //"eqeqeq": "error", + "no-extend-native": "error" + //"max-statements": ["error", 10] + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 844710c57..837f7d1be 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ build downloads node_modules *.zip -npm-debug.log \ No newline at end of file +npm-debug.log +.eslintcache \ No newline at end of file diff --git a/package.json b/package.json index 5632e4526..b76545c87 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "scripts": { "build": "gulp", "watch": "gulp watch", - "test": "mocha test" + "test": "mocha test", + "lint": "eslint -c .eslintrc --cache ." }, "dependencies": { "ajv": "4.11.6", @@ -28,6 +29,7 @@ "javascript-natural-sort": "0.7.1" }, "devDependencies": { + "eslint": "^3.19.0", "gulp": "3.9.1", "gulp-clean-css": "3.0.4", "gulp-concat-css": "2.3.0", diff --git a/src/js/ContextMenu.js b/src/js/ContextMenu.js index 216a1bcc1..e5b637c3f 100644 --- a/src/js/ContextMenu.js +++ b/src/js/ContextMenu.js @@ -339,7 +339,10 @@ ContextMenu.prototype._onKeyDown = function (event) { var target = event.target; var keynum = event.which; var handled = false; - var buttons, targetIndex, prevButton, nextButton; + var buttons; + var targetIndex; + var prevButton; + var nextButton; if (keynum == 27) { // ESC // hide the menu on ESC key diff --git a/src/js/History.js b/src/js/History.js index 1a8b0bf66..63208ba3d 100644 --- a/src/js/History.js +++ b/src/js/History.js @@ -16,62 +16,62 @@ function History (editor) { // map with all supported actions this.actions = { - 'editField': { - 'undo': function (params) { + editField: { + undo: function (params) { params.node.updateField(params.oldValue); }, - 'redo': function (params) { + redo: function (params) { params.node.updateField(params.newValue); } }, - 'editValue': { - 'undo': function (params) { + editValue: { + undo: function (params) { params.node.updateValue(params.oldValue); }, - 'redo': function (params) { + redo: function (params) { params.node.updateValue(params.newValue); } }, - 'changeType': { - 'undo': function (params) { + changeType: { + undo: function (params) { params.node.changeType(params.oldType); }, - 'redo': function (params) { + redo: function (params) { params.node.changeType(params.newType); } }, - 'appendNodes': { - 'undo': function (params) { + appendNodes: { + undo: function (params) { params.nodes.forEach(function (node) { params.parent.removeChild(node); }); }, - 'redo': function (params) { + redo: function (params) { params.nodes.forEach(function (node) { params.parent.appendChild(node); }); } }, - 'insertBeforeNodes': { - 'undo': function (params) { + insertBeforeNodes: { + undo: function (params) { params.nodes.forEach(function (node) { params.parent.removeChild(node); }); }, - 'redo': function (params) { + redo: function (params) { params.nodes.forEach(function (node) { params.parent.insertBefore(node, params.beforeNode); }); } }, - 'insertAfterNodes': { - 'undo': function (params) { + insertAfterNodes: { + undo: function (params) { params.nodes.forEach(function (node) { params.parent.removeChild(node); }); }, - 'redo': function (params) { + redo: function (params) { var afterNode = params.afterNode; params.nodes.forEach(function (node) { params.parent.insertAfter(params.node, afterNode); @@ -79,27 +79,27 @@ function History (editor) { }); } }, - 'removeNodes': { - 'undo': function (params) { + removeNodes: { + undo: function (params) { var parent = params.parent; var beforeNode = parent.childs[params.index] || parent.append; params.nodes.forEach(function (node) { parent.insertBefore(node, beforeNode); }); }, - 'redo': function (params) { + redo: function (params) { params.nodes.forEach(function (node) { params.parent.removeChild(node); }); } }, - 'duplicateNodes': { - 'undo': function (params) { + duplicateNodes: { + undo: function (params) { params.nodes.forEach(function (node) { params.parent.removeChild(node); }); }, - 'redo': function (params) { + redo: function (params) { var afterNode = params.afterNode; params.nodes.forEach(function (node) { params.parent.insertAfter(node, afterNode); @@ -107,28 +107,28 @@ function History (editor) { }); } }, - 'moveNodes': { - 'undo': function (params) { + moveNodes: { + undo: function (params) { params.nodes.forEach(function (node) { params.oldBeforeNode.parent.moveBefore(node, params.oldBeforeNode); }); }, - 'redo': function (params) { + redo: function (params) { params.nodes.forEach(function (node) { params.newBeforeNode.parent.moveBefore(node, params.newBeforeNode); }); } }, - 'sort': { - 'undo': function (params) { + sort: { + undo: function (params) { var node = params.node; node.hideChilds(); node.sort = params.oldSort; node.childs = params.oldChilds; node.showChilds(); }, - 'redo': function (params) { + redo: function (params) { var node = params.node; node.hideChilds(); node.sort = params.newSort; @@ -162,9 +162,9 @@ History.prototype.onChange = function () {}; History.prototype.add = function (action, params) { this.index++; this.history[this.index] = { - 'action': action, - 'params': params, - 'timestamp': new Date() + action: action, + params: params, + timestamp: new Date() }; // remove redo actions which are invalid now diff --git a/src/js/JSONEditor.js b/src/js/JSONEditor.js index 7420d4951..019dc97a1 100644 --- a/src/js/JSONEditor.js +++ b/src/js/JSONEditor.js @@ -344,7 +344,8 @@ JSONEditor.prototype.refresh = function () { * @param {Object | Array} mode A mode object or an array with multiple mode objects. */ JSONEditor.registerMode = function (mode) { - var i, prop; + var i; + var prop; if (util.isArray(mode)) { // multiple modes diff --git a/src/js/ModeSwitcher.js b/src/js/ModeSwitcher.js index 77c6c496d..b3f1977ff 100644 --- a/src/js/ModeSwitcher.js +++ b/src/js/ModeSwitcher.js @@ -14,37 +14,37 @@ function ModeSwitcher(container, modes, current, onSwitch) { // available modes var availableModes = { code: { - 'text': 'Code', - 'title': 'Switch to code highlighter', - 'click': function () { - onSwitch('code') + text: 'Code', + title: 'Switch to code highlighter', + click: function () { + onSwitch('code'); } }, form: { - 'text': 'Form', - 'title': 'Switch to form editor', - 'click': function () { + text: 'Form', + title: 'Switch to form editor', + click: function () { onSwitch('form'); } }, text: { - 'text': 'Text', - 'title': 'Switch to plain text editor', - 'click': function () { + text: 'Text', + title: 'Switch to plain text editor', + click: function () { onSwitch('text'); } }, tree: { - 'text': 'Tree', - 'title': 'Switch to tree editor', - 'click': function () { + text: 'Tree', + title: 'Switch to tree editor', + click: function () { onSwitch('tree'); } }, view: { - 'text': 'View', - 'title': 'Switch to tree view', - 'click': function () { + text: 'View', + title: 'Switch to tree view', + click: function () { onSwitch('view'); } } diff --git a/src/js/Node.js b/src/js/Node.js index beb5565fb..7ac1b9163 100644 --- a/src/js/Node.js +++ b/src/js/Node.js @@ -261,7 +261,8 @@ Node.prototype.getField = function() { * 'array', 'object', or 'string' */ Node.prototype.setValue = function(value, type) { - var childValue, child; + var childValue; + var child; // first clear all current childs (if any) var childs = this.childs; @@ -566,8 +567,8 @@ Node.prototype.appendChild = function(node) { node.showChilds(); } - this.updateDom({'updateIndexes': true}); - node.updateDom({'recurse': true}); + this.updateDom({updateIndexes: true}); + node.updateDom({recurse: true}); } }; @@ -668,8 +669,8 @@ Node.prototype.insertBefore = function(node, beforeNode) { node.showChilds(); } - this.updateDom({'updateIndexes': true}); - node.updateDom({'recurse': true}); + this.updateDom({updateIndexes: true}); + node.updateDom({recurse: true}); } }; @@ -715,8 +716,8 @@ Node.prototype.search = function(text) { if (index != -1) { this.searchField = true; results.push({ - 'node': this, - 'elem': 'field' + node: this, + elem: 'field' }); } @@ -756,8 +757,8 @@ Node.prototype.search = function(text) { if (index != -1) { this.searchValue = true; results.push({ - 'node': this, - 'elem': 'value' + node: this, + elem: 'value' }); } } @@ -985,7 +986,7 @@ Node.prototype.removeChild = function(node) { var removedNode = this.childs.splice(index, 1)[0]; removedNode.parent = null; - this.updateDom({'updateIndexes': true}); + this.updateDom({updateIndexes: true}); return removedNode; } @@ -1103,7 +1104,7 @@ Node.prototype.changeType = function (newType) { this.focus(); } - this.updateDom({'updateIndexes': true}); + this.updateDom({updateIndexes: true}); }; /** @@ -1282,7 +1283,7 @@ Node.prototype._updateDomValue = function () { // create select box when this node has an enum object if (!this.dom.select) { this.dom.select = document.createElement('select'); - this.id = this.field + "_" + new Date().getUTCMilliseconds(); + this.id = this.field + '_' + new Date().getUTCMilliseconds(); this.dom.select.id = this.id; this.dom.select.name = this.dom.select.id; @@ -1312,14 +1313,15 @@ Node.prototype._updateDomValue = function () { // If the enum is inside a composite type display // both the simple input and the dropdown field if(this.schema && ( - !this.schema.hasOwnProperty("oneOf") && - !this.schema.hasOwnProperty("anyOf") && - !this.schema.hasOwnProperty("allOf")) + !this.schema.hasOwnProperty('oneOf') && + !this.schema.hasOwnProperty('anyOf') && + !this.schema.hasOwnProperty('allOf')) ) { this.valueFieldHTML = this.dom.tdValue.innerHTML; this.dom.tdValue.style.visibility = 'hidden'; this.dom.tdValue.innerHTML = ''; - } else { + } + else { delete this.valueFieldHTML; } } @@ -1438,7 +1440,7 @@ Node.prototype.validate = function () { error: { message: 'duplicate key "' + node.field + '"' } - } + }; }); } } @@ -1516,7 +1518,7 @@ Node.prototype.getDom = function() { dom.tree = this._createDomTree(); tdField.appendChild(dom.tree); - this.updateDom({'updateIndexes': true}); + this.updateDom({updateIndexes: true}); return dom.tr; }; @@ -1587,9 +1589,20 @@ Node.onDrag = function (nodes, event) { var editor = nodes[0].editor; var mouseY = event.pageY - editor.drag.offsetY; var mouseX = event.pageX; - var trThis, trPrev, trNext, trFirst, trLast, trRoot; - var nodePrev, nodeNext; - var topThis, topPrev, topFirst, heightThis, bottomNext, heightNext; + var trThis; + var trPrev; + var trNext; + var trFirst; + var trLast; + var trRoot; + var nodePrev; + var nodeNext; + var topThis; + var topPrev; + var topFirst; + var heightThis; + var bottomNext; + var heightNext; var moved = false; // TODO: add an ESC option, which resets to the original position @@ -2022,13 +2035,13 @@ Node._findEnum = function (schema) { var composite = schema.oneOf || schema.anyOf || schema.allOf; if (composite) { - var match = composite.filter(function (entry) {return entry.enum}); + var match = composite.filter(function (entry) {return entry.enum;}); if (match.length > 0) { return match[0].enum; } } - return null + return null; }; /** @@ -2044,14 +2057,14 @@ Node._findSchema = function (schema, path) { for (var i = 0; i < path.length && childSchema; i++) { var key = path[i]; if (typeof key === 'string' && childSchema.properties) { - childSchema = childSchema.properties[key] || null + childSchema = childSchema.properties[key] || null; } else if (typeof key === 'number' && childSchema.items) { - childSchema = childSchema.items + childSchema = childSchema.items; } } - return childSchema + return childSchema; }; /** @@ -2203,11 +2216,11 @@ Node.prototype._createDomTree = function () { * @param {Event} event */ Node.prototype.onEvent = function (event) { - var type = event.type, - target = event.target || event.srcElement, - dom = this.dom, - node = this, - expandable = this._hasChilds(); + var type = event.type; + var target = event.target || event.srcElement; + var dom = this.dom; + var node = this; + var expandable = this._hasChilds(); // check if mouse is on menu or on dragarea. // If so, highlight current row and its childs @@ -2392,7 +2405,10 @@ Node.prototype.onKeyDown = function (event) { var shiftKey = event.shiftKey; var altKey = event.altKey; var handled = false; - var prevNode, nextNode, nextDom, nextDom2; + var prevNode; + var nextNode; + var nextDom; + var nextDom2; var editable = this.editor.options.mode === 'tree'; var oldSelection; var oldBeforeNode; @@ -3163,14 +3179,14 @@ Node.prototype._hasChilds = function () { // titles with explanation for the different types Node.TYPE_TITLES = { - 'auto': 'Field type "auto". ' + + auto: 'Field type "auto". ' + 'The field type is automatically determined from the value ' + 'and can be a string, number, boolean, or null.', - 'object': 'Field type "object". ' + + object: 'Field type "object". ' + 'An object contains an unordered set of key/value pairs.', - 'array': 'Field type "array". ' + + array: 'Field type "array". ' + 'An array contains an ordered collection of values.', - 'string': 'Field type "string". ' + + string: 'Field type "string". ' + 'Field type is not determined from the value, ' + 'but always returned as string.' }; @@ -3267,7 +3283,7 @@ Node.prototype.showContextMenu = function (anchor, onClose) { if (items.length) { // create a separator items.push({ - 'type': 'separator' + type: 'separator' }); } @@ -3419,9 +3435,9 @@ Node.prototype._getType = function(value) { * @private */ Node.prototype._stringCast = function(str) { - var lower = str.toLowerCase(), - num = Number(str), // will nicely fail with '123ab' - numFloat = parseFloat(str); // will nicely fail with ' ' + var lower = str.toLowerCase(); + var num = Number(str); // will nicely fail with '123ab' + var numFloat = parseFloat(str); // will nicely fail with ' ' if (str == '') { return ''; diff --git a/src/js/appendNodeFactory.js b/src/js/appendNodeFactory.js index 494dcb61c..1e1151965 100644 --- a/src/js/appendNodeFactory.js +++ b/src/js/appendNodeFactory.js @@ -137,43 +137,43 @@ function appendNodeFactory(Node) { var items = [ // create append button { - 'text': 'Append', - 'title': 'Append a new field with type \'auto\' (Ctrl+Shift+Ins)', - 'submenuTitle': 'Select the type of the field to be appended', - 'className': 'jsoneditor-insert', - 'click': function () { + text: 'Append', + title: 'Append a new field with type \'auto\' (Ctrl+Shift+Ins)', + submenuTitle: 'Select the type of the field to be appended', + className: 'jsoneditor-insert', + click: function () { node._onAppend('', '', 'auto'); }, - 'submenu': [ + submenu: [ { - 'text': 'Auto', - 'className': 'jsoneditor-type-auto', - 'title': titles.auto, - 'click': function () { + text: 'Auto', + className: 'jsoneditor-type-auto', + title: titles.auto, + click: function () { node._onAppend('', '', 'auto'); } }, { - 'text': 'Array', - 'className': 'jsoneditor-type-array', - 'title': titles.array, - 'click': function () { + text: 'Array', + className: 'jsoneditor-type-array', + title: titles.array, + click: function () { node._onAppend('', []); } }, { - 'text': 'Object', - 'className': 'jsoneditor-type-object', - 'title': titles.object, - 'click': function () { + text: 'Object', + className: 'jsoneditor-type-object', + title: titles.object, + click: function () { node._onAppend('', {}); } }, { - 'text': 'String', - 'className': 'jsoneditor-type-string', - 'title': titles.string, - 'click': function () { + text: 'String', + className: 'jsoneditor-type-string', + title: titles.string, + click: function () { node._onAppend('', '', 'string'); } } diff --git a/src/js/textmode.js b/src/js/textmode.js index 7076fde58..d8ba6523e 100644 --- a/src/js/textmode.js +++ b/src/js/textmode.js @@ -291,7 +291,7 @@ textmode.destroy = function () { } this.textarea = null; - + this._debouncedValidate = null; }; @@ -451,7 +451,7 @@ textmode.validate = function () { if (limit) { errors = errors.slice(0, MAX_ERRORS); var hidden = this.validateSchema.errors.length - MAX_ERRORS; - errors.push('(' + hidden + ' more errors...)') + errors.push('(' + hidden + ' more errors...)'); } var validationErrors = document.createElement('div'); @@ -467,7 +467,7 @@ textmode.validate = function () { '