view/js/bootstrap-wysihtml5/amd/handlebars.runtime.amd.js   F
last analyzed

Complexity

Total Complexity 97
Complexity/F 2.16

Size

Lines of Code 488
Function Count 45

Duplication

Duplicated Lines 463
Ratio 94.88 %

Importance

Changes 0
Metric Value
wmc 97
eloc 303
c 0
b 0
f 0
dl 463
loc 488
rs 2
mnd 52
bc 52
fnc 45
bpm 1.1555
cpm 2.1555
noi 16

15 Functions

Rating   Name   Duplication   Size   Complexity  
A handlebars.runtime.amd.js ➔ invokePartial 9 9 3
A handlebars.runtime.amd.js ➔ isEmpty 9 9 3
A handlebars.runtime.amd.js ➔ Exception 20 20 5
A handlebars.runtime.amd.js ➔ HandlebarsEnvironment 6 6 2
F handlebars.runtime.amd.js ➔ registerDefaultHelpers 99 99 36
A handlebars.runtime.amd.js ➔ extend 7 7 3
A handlebars.runtime.amd.js ➔ log 1 1 4
A handlebars.runtime.amd.js ➔ SafeString 0 3 2
A handlebars.runtime.amd.js ➔ program 10 10 2
A handlebars.runtime.amd.js ➔ noop 1 1 1
F handlebars.runtime.amd.js ➔ template 73 73 14
A handlebars.runtime.amd.js ➔ checkRevision 17 17 5
A handlebars.runtime.amd.js ➔ programWithDepth 12 12 2
A handlebars.runtime.amd.js ➔ escapeChar 3 3 3
C handlebars.runtime.amd.js ➔ escapeExpression 16 16 9

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like view/js/bootstrap-wysihtml5/amd/handlebars.runtime.amd.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/*!
2
3
 handlebars v1.3.0
4
5
Copyright (C) 2011 by Yehuda Katz
6
7
Permission is hereby granted, free of charge, to any person obtaining a copy
8
of this software and associated documentation files (the "Software"), to deal
9
in the Software without restriction, including without limitation the rights
10
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
copies of the Software, and to permit persons to whom the Software is
12
furnished to do so, subject to the following conditions:
13
14
The above copyright notice and this permission notice shall be included in
15
all copies or substantial portions of the Software.
16
17
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
THE SOFTWARE.
24
25
@license
26
*/
27
28
define(
29
  'handlebars/safe-string',["exports"],
30
  function(__exports__) {
31
    
32
    // Build out our basic SafeString type
33
    function SafeString(string) {
34
      this.string = string;
35
    }
36
37
    SafeString.prototype.toString = function() {
38
      return "" + this.string;
39
    };
40
41
    __exports__["default"] = SafeString;
42
  });
43
define(
44
  'handlebars/utils',["./safe-string","exports"],
45 View Code Duplication
  function(__dependency1__, __exports__) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
46
    
47
    /*jshint -W004 */
48
    var SafeString = __dependency1__["default"];
49
50
    var escape = {
51
      "&": "&",
52
      "<": "&lt;",
53
      ">": "&gt;",
54
      '"': "&quot;",
55
      "'": "&#x27;",
56
      "`": "&#x60;"
57
    };
58
59
    var badChars = /[&<>"'`]/g;
60
    var possible = /[&<>"'`]/;
61
62
    function escapeChar(chr) {
63
      return escape[chr] || "&amp;";
64
    }
65
66
    function extend(obj, value) {
67
      for(var key in value) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
68
        if(Object.prototype.hasOwnProperty.call(value, key)) {
69
          obj[key] = value[key];
70
        }
71
      }
72
    }
73
74
    __exports__.extend = extend;var toString = Object.prototype.toString;
75
    __exports__.toString = toString;
76
    // Sourced from lodash
77
    // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
78
    var isFunction = function(value) {
79
      return typeof value === 'function';
80
    };
81
    // fallback for older versions of Chrome and Safari
82
    if (isFunction(/x/)) {
83
      isFunction = function(value) {
84
        return typeof value === 'function' && toString.call(value) === '[object Function]';
85
      };
86
    }
87
    var isFunction;
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable isFunction already seems to be declared on line 78. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
88
    __exports__.isFunction = isFunction;
89
    var isArray = Array.isArray || function(value) {
90
      return (value && typeof value === 'object') ? toString.call(value) === '[object Array]' : false;
91
    };
92
    __exports__.isArray = isArray;
93
94
    function escapeExpression(string) {
95
      // don't escape SafeStrings, since they're already safe
96
      if (string instanceof SafeString) {
97
        return string.toString();
98
      } else if (!string && string !== 0) {
99
        return "";
100
      }
101
102
      // Force a string conversion as this will be done by the append regardless and
103
      // the regex test will do this transparently behind the scenes, causing issues if
104
      // an object's to string has escaped characters in it.
105
      string = "" + string;
106
107
      if(!possible.test(string)) { return string; }
108
      return string.replace(badChars, escapeChar);
109
    }
110
111
    __exports__.escapeExpression = escapeExpression;function isEmpty(value) {
112
      if (!value && value !== 0) {
113
        return true;
114
      } else if (isArray(value) && value.length === 0) {
115
        return true;
116
      } else {
117
        return false;
118
      }
119
    }
120
121
    __exports__.isEmpty = isEmpty;
122
  });
123
define(
124
  'handlebars/exception',["exports"],
125 View Code Duplication
  function(__exports__) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
126
    
127
128
    var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
129
130
    function Exception(message, node) {
131
      var line;
132
      if (node && node.firstLine) {
133
        line = node.firstLine;
134
135
        message += ' - ' + line + ':' + node.firstColumn;
136
      }
137
138
      var tmp = Error.prototype.constructor.call(this, message);
139
140
      // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
141
      for (var idx = 0; idx < errorProps.length; idx++) {
142
        this[errorProps[idx]] = tmp[errorProps[idx]];
143
      }
144
145
      if (line) {
146
        this.lineNumber = line;
147
        this.column = node.firstColumn;
148
      }
149
    }
150
151
    Exception.prototype = new Error();
152
153
    __exports__["default"] = Exception;
154
  });
155
define(
156
  'handlebars/base',["./utils","./exception","exports"],
157 View Code Duplication
  function(__dependency1__, __dependency2__, __exports__) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
158
    
159
    var Utils = __dependency1__;
160
    var Exception = __dependency2__["default"];
161
162
    var VERSION = "1.3.0";
163
    __exports__.VERSION = VERSION;var COMPILER_REVISION = 4;
164
    __exports__.COMPILER_REVISION = COMPILER_REVISION;
165
    var REVISION_CHANGES = {
166
      1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
167
      2: '== 1.0.0-rc.3',
168
      3: '== 1.0.0-rc.4',
169
      4: '>= 1.0.0'
170
    };
171
    __exports__.REVISION_CHANGES = REVISION_CHANGES;
172
    var isArray = Utils.isArray,
173
        isFunction = Utils.isFunction,
174
        toString = Utils.toString,
175
        objectType = '[object Object]';
176
177
    function HandlebarsEnvironment(helpers, partials) {
178
      this.helpers = helpers || {};
179
      this.partials = partials || {};
180
181
      registerDefaultHelpers(this);
182
    }
183
184
    __exports__.HandlebarsEnvironment = HandlebarsEnvironment;HandlebarsEnvironment.prototype = {
185
      constructor: HandlebarsEnvironment,
186
187
      logger: logger,
0 ignored issues
show
Bug introduced by
The variable logger seems to be never initialized.
Loading history...
188
      log: log,
189
190
      registerHelper: function(name, fn, inverse) {
191
        if (toString.call(name) === objectType) {
192
          if (inverse || fn) { throw new Exception('Arg not supported with multiple helpers'); }
193
          Utils.extend(this.helpers, name);
194
        } else {
195
          if (inverse) { fn.not = inverse; }
196
          this.helpers[name] = fn;
197
        }
198
      },
199
200
      registerPartial: function(name, str) {
201
        if (toString.call(name) === objectType) {
202
          Utils.extend(this.partials,  name);
203
        } else {
204
          this.partials[name] = str;
205
        }
206
      }
207
    };
208
209
    function registerDefaultHelpers(instance) {
210
      instance.registerHelper('helperMissing', function(arg) {
211
        if(arguments.length === 2) {
212
          return undefined;
213
        } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
214
          throw new Exception("Missing helper: '" + arg + "'");
215
        }
216
      });
217
218
      instance.registerHelper('blockHelperMissing', function(context, options) {
219
        var inverse = options.inverse || function() {}, fn = options.fn;
220
221
        if (isFunction(context)) { context = context.call(this); }
222
223
        if(context === true) {
224
          return fn(this);
225
        } else if(context === false || context == null) {
0 ignored issues
show
Best Practice introduced by
Comparing context to null using the == operator is not safe. Consider using === instead.
Loading history...
226
          return inverse(this);
227
        } else if (isArray(context)) {
228
          if(context.length > 0) {
229
            return instance.helpers.each(context, options);
230
          } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
231
            return inverse(this);
232
          }
233
        } else {
234
          return fn(context);
235
        }
236
      });
237
238
      instance.registerHelper('each', function(context, options) {
239
        var fn = options.fn, inverse = options.inverse;
240
        var i = 0, ret = "", data;
241
242
        if (isFunction(context)) { context = context.call(this); }
243
244
        if (options.data) {
245
          data = createFrame(options.data);
246
        }
247
248
        if(context && typeof context === 'object') {
249
          if (isArray(context)) {
250
            for(var j = context.length; i<j; i++) {
251
              if (data) {
252
                data.index = i;
253
                data.first = (i === 0);
254
                data.last  = (i === (context.length-1));
255
              }
256
              ret = ret + fn(context[i], { data: data });
0 ignored issues
show
Bug introduced by
The variable data does not seem to be initialized in case options.data on line 244 is false. Are you sure this can never be the case?
Loading history...
257
            }
258
          } else {
259
            for(var key in context) {
260
              if(context.hasOwnProperty(key)) {
261
                if(data) { 
262
                  data.key = key; 
263
                  data.index = i;
264
                  data.first = (i === 0);
265
                }
266
                ret = ret + fn(context[key], {data: data});
267
                i++;
268
              }
269
            }
270
          }
271
        }
272
273
        if(i === 0){
274
          ret = inverse(this);
275
        }
276
277
        return ret;
278
      });
279
280
      instance.registerHelper('if', function(conditional, options) {
281
        if (isFunction(conditional)) { conditional = conditional.call(this); }
282
283
        // Default behavior is to render the positive path if the value is truthy and not empty.
284
        // The `includeZero` option may be set to treat the condtional as purely not empty based on the
285
        // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
286
        if ((!options.hash.includeZero && !conditional) || Utils.isEmpty(conditional)) {
287
          return options.inverse(this);
288
        } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
289
          return options.fn(this);
290
        }
291
      });
292
293
      instance.registerHelper('unless', function(conditional, options) {
294
        return instance.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn, hash: options.hash});
295
      });
296
297
      instance.registerHelper('with', function(context, options) {
298
        if (isFunction(context)) { context = context.call(this); }
299
300
        if (!Utils.isEmpty(context)) return options.fn(context);
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
Complexity Best Practice introduced by
There is no return statement if !Utils.isEmpty(context) is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
301
      });
302
303
      instance.registerHelper('log', function(context, options) {
304
        var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
0 ignored issues
show
Best Practice introduced by
Comparing options.data.level to null using the != operator is not safe. Consider using !== instead.
Loading history...
305
        instance.log(level, context);
306
      });
307
    }
308
309
    var logger = {
310
      methodMap: { 0: 'debug', 1: 'info', 2: 'warn', 3: 'error' },
311
312
      // State enum
313
      DEBUG: 0,
314
      INFO: 1,
315
      WARN: 2,
316
      ERROR: 3,
317
      level: 3,
318
319
      // can be overridden in the host environment
320
      log: function(level, obj) {
321
        if (logger.level <= level) {
322
          var method = logger.methodMap[level];
323
          if (typeof console !== 'undefined' && console[method]) {
324
            console[method].call(console, obj);
325
          }
326
        }
327
      }
328
    };
329
    __exports__.logger = logger;
330
    function log(level, obj) { logger.log(level, obj); }
331
332
    __exports__.log = log;var createFrame = function(object) {
333
      var obj = {};
334
      Utils.extend(obj, object);
335
      return obj;
336
    };
337
    __exports__.createFrame = createFrame;
338
  });
339
define(
340
  'handlebars/runtime',["./utils","./exception","./base","exports"],
341 View Code Duplication
  function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
342
    
343
    var Utils = __dependency1__;
344
    var Exception = __dependency2__["default"];
345
    var COMPILER_REVISION = __dependency3__.COMPILER_REVISION;
346
    var REVISION_CHANGES = __dependency3__.REVISION_CHANGES;
347
348
    function checkRevision(compilerInfo) {
349
      var compilerRevision = compilerInfo && compilerInfo[0] || 1,
350
          currentRevision = COMPILER_REVISION;
351
352
      if (compilerRevision !== currentRevision) {
353
        if (compilerRevision < currentRevision) {
354
          var runtimeVersions = REVISION_CHANGES[currentRevision],
355
              compilerVersions = REVISION_CHANGES[compilerRevision];
356
          throw new Exception("Template was precompiled with an older version of Handlebars than the current runtime. "+
357
                "Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").");
358
        } else {
359
          // Use the embedded version info since the runtime doesn't know about this revision yet
360
          throw new Exception("Template was precompiled with a newer version of Handlebars than the current runtime. "+
361
                "Please update your runtime to a newer version ("+compilerInfo[1]+").");
362
        }
363
      }
364
    }
365
366
    __exports__.checkRevision = checkRevision;// TODO: Remove this line and break up compilePartial
367
368
    function template(templateSpec, env) {
369
      if (!env) {
370
        throw new Exception("No environment passed to template");
371
      }
372
373
      // Note: Using env.VM references rather than local var references throughout this section to allow
374
      // for external users to override these as psuedo-supported APIs.
375
      var invokePartialWrapper = function(partial, name, context, helpers, partials, data) {
376
        var result = env.VM.invokePartial.apply(this, arguments);
377
        if (result != null) { return result; }
0 ignored issues
show
Best Practice introduced by
Comparing result to null using the != operator is not safe. Consider using !== instead.
Loading history...
378
379
        if (env.compile) {
380
          var options = { helpers: helpers, partials: partials, data: data };
381
          partials[name] = env.compile(partial, { data: data !== undefined }, env);
382
          return partials[name](context, options);
383
        } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
384
          throw new Exception("The partial " + name + " could not be compiled when running in runtime-only mode");
385
        }
386
      };
387
388
      // Just add water
389
      var container = {
390
        escapeExpression: Utils.escapeExpression,
391
        invokePartial: invokePartialWrapper,
392
        programs: [],
393
        program: function(i, fn, data) {
394
          var programWrapper = this.programs[i];
395
          if(data) {
396
            programWrapper = program(i, fn, data);
397
          } else if (!programWrapper) {
398
            programWrapper = this.programs[i] = program(i, fn);
399
          }
400
          return programWrapper;
401
        },
402
        merge: function(param, common) {
403
          var ret = param || common;
404
405
          if (param && common && (param !== common)) {
406
            ret = {};
407
            Utils.extend(ret, common);
408
            Utils.extend(ret, param);
409
          }
410
          return ret;
411
        },
412
        programWithDepth: env.VM.programWithDepth,
413
        noop: env.VM.noop,
414
        compilerInfo: null
415
      };
416
417
      return function(context, options) {
418
        options = options || {};
419
        var namespace = options.partial ? options : env,
420
            helpers,
421
            partials;
422
423
        if (!options.partial) {
424
          helpers = options.helpers;
425
          partials = options.partials;
426
        }
427
        var result = templateSpec.call(
428
              container,
429
              namespace, context,
430
              helpers,
0 ignored issues
show
Bug introduced by
The variable helpers does not seem to be initialized in case !options.partial on line 423 is false. Are you sure the function call handles undefined variables?
Loading history...
431
              partials,
0 ignored issues
show
Bug introduced by
The variable partials does not seem to be initialized in case !options.partial on line 423 is false. Are you sure the function call handles undefined variables?
Loading history...
432
              options.data);
433
434
        if (!options.partial) {
435
          env.VM.checkRevision(container.compilerInfo);
436
        }
437
438
        return result;
439
      };
440
    }
441
442
    __exports__.template = template;function programWithDepth(i, fn, data /*, $depth */) {
443
      var args = Array.prototype.slice.call(arguments, 3);
444
445
      var prog = function(context, options) {
446
        options = options || {};
447
448
        return fn.apply(this, [context, options.data || data].concat(args));
449
      };
450
      prog.program = i;
451
      prog.depth = args.length;
452
      return prog;
453
    }
454
455
    __exports__.programWithDepth = programWithDepth;function program(i, fn, data) {
456
      var prog = function(context, options) {
457
        options = options || {};
458
459
        return fn(context, options.data || data);
460
      };
461
      prog.program = i;
462
      prog.depth = 0;
463
      return prog;
464
    }
465
466
    __exports__.program = program;function invokePartial(partial, name, context, helpers, partials, data) {
467
      var options = { partial: true, helpers: helpers, partials: partials, data: data };
468
469
      if(partial === undefined) {
470
        throw new Exception("The partial " + name + " could not be found");
471
      } else if(partial instanceof Function) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if partial instanceof Function is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
472
        return partial(context, options);
473
      }
474
    }
475
476
    __exports__.invokePartial = invokePartial;function noop() { return ""; }
477
478
    __exports__.noop = noop;
479
  });
480
define(
481
  'handlebars.runtime',["./handlebars/base","./handlebars/safe-string","./handlebars/exception","./handlebars/utils","./handlebars/runtime","exports"],
482 View Code Duplication
  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
483
    
484
    /*globals Handlebars: true */
485
    var base = __dependency1__;
486
487
    // Each of these augment the Handlebars object. No need to setup here.
488
    // (This is done to easily share code between commonjs and browse envs)
489
    var SafeString = __dependency2__["default"];
490
    var Exception = __dependency3__["default"];
491
    var Utils = __dependency4__;
492
    var runtime = __dependency5__;
493
494
    // For compatibility and usage outside of module systems, make the Handlebars object a namespace
495
    var create = function() {
496
      var hb = new base.HandlebarsEnvironment();
497
498
      Utils.extend(hb, base);
499
      hb.SafeString = SafeString;
500
      hb.Exception = Exception;
501
      hb.Utils = Utils;
502
503
      hb.VM = runtime;
504
      hb.template = function(spec) {
505
        return runtime.template(spec, hb);
506
      };
507
508
      return hb;
509
    };
510
511
    var Handlebars = create();
512
    Handlebars.create = create;
513
514
    __exports__["default"] = Handlebars;
515
  });