From 7729aa956bfe4dae1cd0956626d6db3cb07e3bc6 Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Sat, 21 Oct 2017 15:42:27 +0200 Subject: [PATCH 1/2] Update grunt-eslint to 20.1.0 --- .eslintrc | 200 ------------------ .eslintrc.js | 129 +++++++++++ bench/templates/complex.js | 2 +- lib/handlebars/compiler/code-gen.js | 2 +- lib/handlebars/compiler/helpers.js | 6 +- .../compiler/javascript-compiler.js | 8 +- lib/handlebars/logger.js | 4 +- lib/precompiler.js | 2 +- package.json | 2 +- spec/ast.js | 2 + spec/helpers.js | 2 +- spec/parser.js | 12 +- spec/spec.js | 4 +- spec/tokenizer.js | 10 +- 14 files changed, 157 insertions(+), 228 deletions(-) delete mode 100644 .eslintrc create mode 100644 .eslintrc.js diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 8cd3bd6fe..000000000 --- a/.eslintrc +++ /dev/null @@ -1,200 +0,0 @@ -{ - "globals": { - "self": false - }, - "env": { - "node": true - }, - "ecmaFeatures": { - // Enabling features that can be implemented without polyfills. Want to avoid polyfills at this time. - "arrowFunctions": true, - "blockBindings": true, - "defaultParams": true, - "destructuring": true, - "modules": true, - "objectLiteralComputedProperties": true, - "objectLiteralDuplicateProperties": true, - "objectLiteralShorthandMethods": true, - "objectLiteralShorthandProperties": true, - "restParams": true, - "spread": true, - "templateStrings": true - }, - "rules": { - // Possible Errors // - //-----------------// - - "comma-dangle": [2, "never"], - "no-cond-assign": [2, "except-parens"], - - // Allow for debugging - "no-console": 1, - - "no-constant-condition": 2, - "no-control-regex": 2, - - // Allow for debugging - "no-debugger": 1, - - "no-dupe-args": 2, - "no-dupe-keys": 2, - "no-duplicate-case": 2, - "no-empty": 2, - "no-empty-character-class": 2, - "no-ex-assign": 2, - "no-extra-boolean-cast": 2, - "no-extra-parens": 0, - "no-extra-semi": 2, - "no-func-assign": 0, - - // Stylistic... might consider disallowing in the future - "no-inner-declarations": 0, - - "no-invalid-regexp": 2, - "no-irregular-whitespace": 2, - "no-negated-in-lhs": 2, - "no-obj-calls": 2, - "no-regex-spaces": 2, - "quote-props": [2, "as-needed", {"keywords": true}], - "no-sparse-arrays": 0, - - // Optimizer and coverage will handle/highlight this and can be useful for debugging - "no-unreachable": 1, - - "use-isnan": 2, - "valid-jsdoc": 0, - "valid-typeof": 2, - - - // Best Practices // - //----------------// - "block-scoped-var": 0, - "complexity": 0, - "consistent-return": 0, - "curly": 2, - "default-case": 1, - "dot-notation": [2, {"allowKeywords": false}], - "eqeqeq": 0, - "guard-for-in": 1, - "no-alert": 2, - "no-caller": 2, - "no-div-regex": 1, - "no-else-return": 0, - "no-empty-label": 2, - "no-eq-null": 0, - "no-eval": 2, - "no-extend-native": 2, - "no-extra-bind": 2, - "no-fallthrough": 2, - "no-floating-decimal": 2, - "no-implied-eval": 2, - "no-iterator": 2, - "no-labels": 2, - "no-lone-blocks": 2, - "no-loop-func": 2, - "no-multi-spaces": 2, - "no-multi-str": 1, - "no-native-reassign": 2, - "no-new": 2, - "no-new-func": 2, - "no-new-wrappers": 2, - "no-octal": 2, - "no-octal-escape": 2, - "no-param-reassign": 0, - "no-process-env": 2, - "no-proto": 2, - "no-redeclare": 2, - "no-return-assign": 2, - "no-script-url": 2, - "no-self-compare": 2, - "no-sequences": 2, - "no-throw-literal": 2, - "no-unused-expressions": 2, - "no-void": 0, - "no-warning-comments": 1, - "no-with": 2, - "radix": 2, - "vars-on-top": 0, - "wrap-iife": 2, - "yoda": 0, - - - // Strict // - //--------// - "strict": 0, - - - // Variables // - //-----------// - "no-catch-shadow": 2, - "no-delete-var": 2, - "no-label-var": 2, - "no-shadow": 0, - "no-shadow-restricted-names": 2, - "no-undef": 2, - "no-undef-init": 2, - "no-undefined": 0, - "no-unused-vars": [2, {"vars": "all", "args": "after-used"}], - "no-use-before-define": [2, "nofunc"], - - - // Node.js // - //---------// - // Others left to environment defaults - "no-mixed-requires": 0, - - - // Stylistic // - //-----------// - "indent": 0, - "brace-style": [2, "1tbs", {"allowSingleLine": true}], - "camelcase": 2, - "comma-spacing": [2, {"before": false, "after": true}], - "comma-style": [2, "last"], - "consistent-this": [1, "self"], - "eol-last": 2, - "func-names": 0, - "func-style": [2, "declaration"], - "key-spacing": [2, { - "beforeColon": false, - "afterColon": true - }], - "max-nested-callbacks": 0, - "new-cap": 2, - "new-parens": 2, - "newline-after-var": 0, - "no-array-constructor": 2, - "no-continue": 0, - "no-inline-comments": 0, - "no-lonely-if": 2, - "no-mixed-spaces-and-tabs": 2, - "no-multiple-empty-lines": 0, - "no-nested-ternary": 1, - "no-new-object": 2, - "no-spaced-func": 2, - "no-ternary": 0, - "no-trailing-spaces": 2, - "no-underscore-dangle": 0, - "no-extra-parens": [2, "functions"], - "one-var": 0, - "operator-assignment": 0, - "padded-blocks": 0, - "quote-props": 0, - "quotes": [2, "single", "avoid-escape"], - "semi": 2, - "semi-spacing": [2, {"before": false, "after": true}], - "sort-vars": 0, - "space-after-keywords": [2, "always"], - "space-before-blocks": [2, "always"], - "space-before-function-paren": [2, {"anonymous": "never", "named": "never"}], - "space-in-brackets": 0, - "space-in-parens": [2, "never"], - "space-infix-ops": 2, - "space-return-throw-case": 2, - "space-unary-ops": 2, - "spaced-comment": [2, "always", {"markers": [","]}], - "wrap-regex": 1, - - "no-var": 1 - } -} \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..34daed78d --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,129 @@ +module.exports = { + "extends": "eslint:recommended", + "globals": { + "self": false + }, + "env": { + "node": true + }, + "ecmaFeatures": { + // Enabling features that can be implemented without polyfills. Want to avoid polyfills at this time. + "arrowFunctions": true, + "blockBindings": true, + "defaultParams": true, + "destructuring": true, + "modules": true, + "objectLiteralComputedProperties": true, + "objectLiteralDuplicateProperties": true, + "objectLiteralShorthandMethods": true, + "objectLiteralShorthandProperties": true, + "restParams": true, + "spread": true, + "templateStrings": true + }, + "rules": { + // overrides eslint:recommended defaults + "no-sparse-arrays": "off", + "no-func-assign": "off", + "no-console": "warn", + "no-debugger": "warn", + "no-unreachable": "warn", + + // Possible Errors // + //-----------------// + "no-unsafe-negation": "error", + + + // Best Practices // + //----------------// + "curly": "error", + "default-case": "warn", + "dot-notation": ["error", { "allowKeywords": false }], + "guard-for-in": "warn", + "no-alert": "error", + "no-caller": "error", + "no-div-regex": "warn", + "no-eval": "error", + "no-extend-native": "error", + "no-extra-bind": "error", + "no-floating-decimal": "error", + "no-implied-eval": "error", + "no-iterator": "error", + "no-labels": "error", + "no-lone-blocks": "error", + "no-loop-func": "error", + "no-multi-spaces": "error", + "no-multi-str": "warn", + "no-global-assign": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-wrappers": "error", + "no-octal-escape": "error", + "no-process-env": "error", + "no-proto": "error", + "no-return-assign": "error", + "no-script-url": "error", + "no-self-compare": "error", + "no-sequences": "error", + "no-throw-literal": "error", + "no-unused-expressions": "error", + "no-warning-comments": "warn", + "no-with": "error", + "radix": "error", + "wrap-iife": "error", + + + // Variables // + //-----------// + "no-catch-shadow": "error", + "no-label-var": "error", + "no-shadow-restricted-names": "error", + "no-undef-init": "error", + "no-use-before-define": ["error", "nofunc"], + + + // Stylistic Issues // + //------------------// + "comma-dangle": ["error", "never"], + "quote-props": ["error", "as-needed", { "keywords": true, "unnecessary": false }], + "brace-style": ["error", "1tbs", { "allowSingleLine": true }], + "camelcase": "error", + "comma-spacing": ["error", { "before": false, "after": true }], + "comma-style": ["error", "last"], + "consistent-this": ["warn", "self"], + "eol-last": "error", + "func-style": ["error", "declaration"], + "key-spacing": ["error", { + "beforeColon": false, + "afterColon": true + }], + "new-cap": "error", + "new-parens": "error", + "no-array-constructor": "error", + "no-lonely-if": "error", + "no-mixed-spaces-and-tabs": "error", + "no-nested-ternary": "warn", + "no-new-object": "error", + "no-spaced-func": "error", + "no-trailing-spaces": "error", + "no-extra-parens": ["error", "functions"], + "quotes": ["error", "single", "avoid-escape"], + "semi": "error", + "semi-spacing": ["error", { "before": false, "after": true }], + "keyword-spacing": "error", + "space-before-blocks": ["error", "always"], + "space-before-function-paren": ["error", { "anonymous": "never", "named": "never" }], + "space-in-parens": ["error", "never"], + "space-infix-ops": "error", + "space-unary-ops": "error", + "spaced-comment": ["error", "always", { "markers": [","] }], + "wrap-regex": "warn", + + // ECMAScript 6 // + //--------------// + "no-var": "warn" + }, + "parserOptions": { + "sourceType": "module" + } +} \ No newline at end of file diff --git a/bench/templates/complex.js b/bench/templates/complex.js index feba874dd..3e5e26c4e 100644 --- a/bench/templates/complex.js +++ b/bench/templates/complex.js @@ -5,7 +5,7 @@ module.exports = { header: function() { return 'Colors'; }, - hasItems: true, // To make things fairer in mustache land due to no `{{if}}` construct on arrays + hasItems: true, // To make things fairer in mustache land due to no `{{if}}` construct on arrays items: [ {name: 'red', current: true, url: '#Red'}, {name: 'green', current: false, url: '#Green'}, diff --git a/lib/handlebars/compiler/code-gen.js b/lib/handlebars/compiler/code-gen.js index 5ec052f77..43c0481bc 100644 --- a/lib/handlebars/compiler/code-gen.js +++ b/lib/handlebars/compiler/code-gen.js @@ -118,7 +118,7 @@ CodeGen.prototype = { .replace(/"/g, '\\"') .replace(/\n/g, '\\n') .replace(/\r/g, '\\r') - .replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4 + .replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4 .replace(/\u2029/g, '\\u2029') + '"'; }, diff --git a/lib/handlebars/compiler/helpers.js b/lib/handlebars/compiler/helpers.js index e09a08df9..432df877c 100644 --- a/lib/handlebars/compiler/helpers.js +++ b/lib/handlebars/compiler/helpers.js @@ -38,7 +38,7 @@ export function stripFlags(open, close) { } export function stripComment(comment) { - return comment.replace(/^\{\{~?\!-?-?/, '') + return comment.replace(/^\{\{~?!-?-?/, '') .replace(/-?-?~?\}\}$/, ''); } @@ -47,8 +47,7 @@ export function preparePath(data, parts, loc) { let original = data ? '@' : '', dig = [], - depth = 0, - depthString = ''; + depth = 0; for (let i = 0, l = parts.length; i < l; i++) { let part = parts[i].part, @@ -62,7 +61,6 @@ export function preparePath(data, parts, loc) { throw new Exception('Invalid path: ' + original, {loc}); } else if (part === '..') { depth++; - depthString += '../'; } } else { dig.push(part); diff --git a/lib/handlebars/compiler/javascript-compiler.js b/lib/handlebars/compiler/javascript-compiler.js index bf4be8af9..471144dd3 100644 --- a/lib/handlebars/compiler/javascript-compiler.js +++ b/lib/handlebars/compiler/javascript-compiler.js @@ -133,7 +133,7 @@ JavaScriptCompiler.prototype = { }; if (this.decorators) { - ret.main_d = this.decorators; // eslint-disable-line camelcase + ret.main_d = this.decorators; // eslint-disable-line camelcase ret.useDecorators = true; } @@ -209,7 +209,7 @@ JavaScriptCompiler.prototype = { // aliases will not be used, but this case is already being run on the client and // we aren't concern about minimizing the template size. let aliasCount = 0; - for (let alias in this.aliases) { // eslint-disable-line guard-for-in + for (let alias in this.aliases) { // eslint-disable-line guard-for-in let node = this.aliases[alias]; if (this.aliases.hasOwnProperty(alias) && node.children && node.referenceCount > 1) { @@ -776,12 +776,12 @@ JavaScriptCompiler.prototype = { for (let i = 0, l = children.length; i < l; i++) { child = children[i]; - compiler = new this.compiler(); // eslint-disable-line new-cap + compiler = new this.compiler(); // eslint-disable-line new-cap let existing = this.matchExistingProgram(child); if (existing == null) { - this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children + this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children let index = this.context.programs.length; child.index = index; child.name = 'program' + index; diff --git a/lib/handlebars/logger.js b/lib/handlebars/logger.js index 1ab0051f5..1e916a995 100644 --- a/lib/handlebars/logger.js +++ b/lib/handlebars/logger.js @@ -24,10 +24,10 @@ let logger = { if (typeof console !== 'undefined' && logger.lookupLevel(logger.level) <= level) { let method = logger.methodMap[level]; - if (!console[method]) { // eslint-disable-line no-console + if (!console[method]) { // eslint-disable-line no-console method = 'log'; } - console[method](...message); // eslint-disable-line no-console + console[method](...message); // eslint-disable-line no-console } } }; diff --git a/lib/precompiler.js b/lib/precompiler.js index 64608f1e9..330f4bb18 100644 --- a/lib/precompiler.js +++ b/lib/precompiler.js @@ -60,7 +60,7 @@ function loadStrings(opts, callback) { function loadFiles(opts, callback) { // Build file extension pattern - let extension = (opts.extension || 'handlebars').replace(/[\\^$*+?.():=!|{}\-\[\]]/g, function(arg) { return '\\' + arg; }); + let extension = (opts.extension || 'handlebars').replace(/[\\^$*+?.():=!|{}\-[\]]/g, function(arg) { return '\\' + arg; }); extension = new RegExp('\\.' + extension + '$'); let ret = [], diff --git a/package.json b/package.json index b458985ea..f09eb8ae9 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "grunt-contrib-requirejs": "0.x", "grunt-contrib-uglify": "0.x", "grunt-contrib-watch": "0.x", - "grunt-eslint": "^17.1.0", + "grunt-eslint": "^20.1.0", "grunt-saucelabs": "8.x", "grunt-webpack": "^1.0.8", "istanbul": "^0.3.0", diff --git a/spec/ast.js b/spec/ast.js index 8f346d882..e43438be7 100644 --- a/spec/ast.js +++ b/spec/ast.js @@ -59,6 +59,7 @@ describe('ast', function() { equals(node.loc.end.column, lastColumn); } + /* eslint-disable no-multi-spaces */ ast = Handlebars.parse( 'line 1 {{line1Token}}\n' // 1 + ' line 2 {{line2token}}\n' // 2 @@ -71,6 +72,7 @@ describe('ast', function() { + '{{else inverse}}\n' // 9 + '{{else}}\n' // 10 + '{{/open}}'); // 11 + /* eslint-enable no-multi-spaces */ body = ast.body; it('gets ContentNode line numbers', function() { diff --git a/spec/helpers.js b/spec/helpers.js index 94e503f12..15bc2f121 100644 --- a/spec/helpers.js +++ b/spec/helpers.js @@ -113,7 +113,7 @@ describe('helpers', function() { { 'name': 'Yehuda', 'id': 2 } ]}; - shouldCompileTo(source, [data, {link: link}], ''); + shouldCompileTo(source, [data, {link: link}], ''); }); it('block helper for undefined value', function() { diff --git a/spec/parser.js b/spec/parser.js index 4527d19c1..856031c3b 100644 --- a/spec/parser.js +++ b/spec/parser.js @@ -51,7 +51,7 @@ describe('parser', function() { }); it('parses mustaches with string parameters', function() { - equals(astFor('{{foo bar \"baz\" }}'), '{{ PATH:foo [PATH:bar, "baz"] }}\n'); + equals(astFor('{{foo bar "baz" }}'), '{{ PATH:foo [PATH:bar, "baz"] }}\n'); }); it('parses mustaches with NUMBER parameters', function() { @@ -87,10 +87,10 @@ describe('parser', function() { equals(astFor("{{foo bat='bam'}}"), '{{ PATH:foo [] HASH{bat="bam"} }}\n'); - equals(astFor('{{foo omg bar=baz bat=\"bam\"}}'), '{{ PATH:foo [PATH:omg] HASH{bar=PATH:baz, bat="bam"} }}\n'); - equals(astFor('{{foo omg bar=baz bat=\"bam\" baz=1}}'), '{{ PATH:foo [PATH:omg] HASH{bar=PATH:baz, bat="bam", baz=NUMBER{1}} }}\n'); - equals(astFor('{{foo omg bar=baz bat=\"bam\" baz=true}}'), '{{ PATH:foo [PATH:omg] HASH{bar=PATH:baz, bat="bam", baz=BOOLEAN{true}} }}\n'); - equals(astFor('{{foo omg bar=baz bat=\"bam\" baz=false}}'), '{{ PATH:foo [PATH:omg] HASH{bar=PATH:baz, bat="bam", baz=BOOLEAN{false}} }}\n'); + equals(astFor('{{foo omg bar=baz bat="bam"}}'), '{{ PATH:foo [PATH:omg] HASH{bar=PATH:baz, bat="bam"} }}\n'); + equals(astFor('{{foo omg bar=baz bat="bam" baz=1}}'), '{{ PATH:foo [PATH:omg] HASH{bar=PATH:baz, bat="bam", baz=NUMBER{1}} }}\n'); + equals(astFor('{{foo omg bar=baz bat="bam" baz=true}}'), '{{ PATH:foo [PATH:omg] HASH{bar=PATH:baz, bat="bam", baz=BOOLEAN{true}} }}\n'); + equals(astFor('{{foo omg bar=baz bat="bam" baz=false}}'), '{{ PATH:foo [PATH:omg] HASH{bar=PATH:baz, bat="bam", baz=BOOLEAN{false}} }}\n'); }); it('parses contents followed by a mustache', function() { @@ -136,7 +136,7 @@ describe('parser', function() { }); it('parses a multi-line comment', function() { - equals(astFor('{{!\nthis is a multi-line comment\n}}'), "{{! \'\nthis is a multi-line comment\n\' }}\n"); + equals(astFor('{{!\nthis is a multi-line comment\n}}'), "{{! '\nthis is a multi-line comment\n' }}\n"); }); it('parses an inverse section', function() { diff --git a/spec/spec.js b/spec/spec.js index 221d32ec2..805609d01 100644 --- a/spec/spec.js +++ b/spec/spec.js @@ -25,8 +25,8 @@ describe('spec', function() { // We nest the entire response from partials, not just the literals || (name === 'partials.json' && test.name === 'Standalone Indentation') - || (/\{\{\=/).test(test.template) - || _.any(test.partials, function(partial) { return (/\{\{\=/).test(partial); })) { + || (/\{\{=/).test(test.template) + || _.any(test.partials, function(partial) { return (/\{\{=/).test(partial); })) { it.skip(name + ' - ' + test.name); return; } diff --git a/spec/tokenizer.js b/spec/tokenizer.js index 428804e01..1a361b754 100644 --- a/spec/tokenizer.js +++ b/spec/tokenizer.js @@ -282,13 +282,13 @@ describe('Tokenizer', function() { }); it('tokenizes mustaches with String params as "OPEN ID ID STRING CLOSE"', function() { - var result = tokenize('{{ foo bar \"baz\" }}'); + var result = tokenize('{{ foo bar "baz" }}'); shouldMatchTokens(result, ['OPEN', 'ID', 'ID', 'STRING', 'CLOSE']); shouldBeToken(result[3], 'STRING', 'baz'); }); it('tokenizes mustaches with String params using single quotes as "OPEN ID ID STRING CLOSE"', function() { - var result = tokenize("{{ foo bar \'baz\' }}"); + var result = tokenize("{{ foo bar 'baz' }}"); shouldMatchTokens(result, ['OPEN', 'ID', 'ID', 'STRING', 'CLOSE']); shouldBeToken(result[3], 'STRING', 'baz'); }); @@ -365,13 +365,13 @@ describe('Tokenizer', function() { result = tokenize('{{ foo bar\n baz=bat }}'); shouldMatchTokens(result, ['OPEN', 'ID', 'ID', 'ID', 'EQUALS', 'ID', 'CLOSE']); - result = tokenize('{{ foo bar baz=\"bat\" }}'); + result = tokenize('{{ foo bar baz="bat" }}'); shouldMatchTokens(result, ['OPEN', 'ID', 'ID', 'ID', 'EQUALS', 'STRING', 'CLOSE']); - result = tokenize('{{ foo bar baz=\"bat\" bam=wot }}'); + result = tokenize('{{ foo bar baz="bat" bam=wot }}'); shouldMatchTokens(result, ['OPEN', 'ID', 'ID', 'ID', 'EQUALS', 'STRING', 'ID', 'EQUALS', 'ID', 'CLOSE']); - result = tokenize('{{foo omg bar=baz bat=\"bam\"}}'); + result = tokenize('{{foo omg bar=baz bat="bam"}}'); shouldMatchTokens(result, ['OPEN', 'ID', 'ID', 'ID', 'EQUALS', 'ID', 'ID', 'EQUALS', 'STRING', 'CLOSE']); shouldBeToken(result[2], 'ID', 'omg'); }); From 73d56375640e47ddd54ebc636b30dab9b68538b7 Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Sat, 21 Oct 2017 16:09:33 +0200 Subject: [PATCH 2/2] Update dependencies "async" to 2.5.0 and "source-map" to 0.6.1 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f09eb8ae9..589b87ba1 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,9 @@ "node": ">=0.4.7" }, "dependencies": { - "async": "^1.4.0", + "async": "^2.5.0", "optimist": "^0.6.1", - "source-map": "^0.4.4" + "source-map": "^0.6.1" }, "optionalDependencies": { "uglify-js": "^2.6"