Passed
Push — master ( fdcd11...4b42b4 )
by Ron
07:37
created

public/js/tinymce/plugins/help/plugin.js   F

Complexity

Total Complexity 98
Complexity/F 1.32

Size

Lines of Code 688
Function Count 74

Duplication

Duplicated Lines 129
Ratio 18.75 %

Importance

Changes 0
Metric Value
eloc 501
c 0
b 0
f 0
dl 129
loc 688
rs 2
wmc 98
mnd 24
bc 24
fnc 74
bpm 0.3242
cpm 1.3243
noi 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 public/js/tinymce/plugins/help/plugin.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
(function () {
2
var help = (function () {
3
    'use strict';
4
5
    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
6
7
    var constant = function (value) {
8
      return function () {
9
        return value;
10
      };
11
    };
12
    function curry(fn) {
13
      var initialArgs = [];
14
      for (var _i = 1; _i < arguments.length; _i++) {
15
        initialArgs[_i - 1] = arguments[_i];
16
      }
17
      return function () {
18
        var restArgs = [];
19
        for (var _i = 0; _i < arguments.length; _i++) {
20
          restArgs[_i] = arguments[_i];
21
        }
22
        var all = initialArgs.concat(restArgs);
23
        return fn.apply(null, all);
24
      };
25
    }
26
    var not = function (f) {
27
      return function () {
28
        var args = [];
29
        for (var _i = 0; _i < arguments.length; _i++) {
30
          args[_i] = arguments[_i];
31
        }
32
        return !f.apply(null, args);
33
      };
34
    };
35
    var never = constant(false);
36
    var always = constant(true);
37
38
    var never$1 = never;
39
    var always$1 = always;
40
    var none = function () {
41
      return NONE;
42
    };
43
    var NONE = function () {
44
      var eq = function (o) {
45
        return o.isNone();
46
      };
47
      var call$$1 = function (thunk) {
48
        return thunk();
49
      };
50
      var id = function (n) {
51
        return n;
52
      };
53
      var noop$$1 = function () {
54
      };
55
      var nul = function () {
56
        return null;
57
      };
58
      var undef = function () {
59
        return undefined;
60
      };
61
      var me = {
62
        fold: function (n, s) {
63
          return n();
64
        },
65
        is: never$1,
66
        isSome: never$1,
67
        isNone: always$1,
68
        getOr: id,
69
        getOrThunk: call$$1,
70
        getOrDie: function (msg) {
71
          throw new Error(msg || 'error: getOrDie called on none.');
72
        },
73
        getOrNull: nul,
74
        getOrUndefined: undef,
75
        or: id,
76
        orThunk: call$$1,
77
        map: none,
78
        ap: none,
79
        each: noop$$1,
80
        bind: none,
81
        flatten: none,
82
        exists: never$1,
83
        forall: always$1,
84
        filter: none,
85
        equals: eq,
86
        equals_: eq,
87
        toArray: function () {
88
          return [];
89
        },
90
        toString: constant('none()')
91
      };
92
      if (Object.freeze)
93
        Object.freeze(me);
94
      return me;
95
    }();
96
    var some = function (a) {
97
      var constant_a = function () {
98
        return a;
99
      };
100
      var self = function () {
101
        return me;
102
      };
103
      var map = function (f) {
104
        return some(f(a));
105
      };
106
      var bind = function (f) {
107
        return f(a);
108
      };
109
      var me = {
110
        fold: function (n, s) {
111
          return s(a);
112
        },
113
        is: function (v) {
114
          return a === v;
115
        },
116
        isSome: always$1,
117
        isNone: never$1,
118
        getOr: constant_a,
119
        getOrThunk: constant_a,
120
        getOrDie: constant_a,
121
        getOrNull: constant_a,
122
        getOrUndefined: constant_a,
123
        or: self,
124
        orThunk: self,
125
        map: map,
126
        ap: function (optfab) {
127
          return optfab.fold(none, function (fab) {
128
            return some(fab(a));
129
          });
130
        },
131
        each: function (f) {
132
          f(a);
133
        },
134
        bind: bind,
135
        flatten: constant_a,
136
        exists: bind,
137
        forall: bind,
138
        filter: function (f) {
139
          return f(a) ? me : NONE;
140
        },
141
        equals: function (o) {
142
          return o.is(a);
143
        },
144
        equals_: function (o, elementEq) {
145
          return o.fold(never$1, function (b) {
146
            return elementEq(a, b);
147
          });
148
        },
149
        toArray: function () {
150
          return [a];
151
        },
152
        toString: function () {
153
          return 'some(' + a + ')';
154
        }
155
      };
156
      return me;
157
    };
158
    var from = function (value) {
159
      return value === null || value === undefined ? NONE : some(value);
160
    };
161
    var Option = {
162
      some: some,
163
      none: none,
164
      from: from
165
    };
166
167
    var typeOf = function (x) {
168
      if (x === null)
169
        return 'null';
170
      var t = typeof x;
171
      if (t === 'object' && Array.prototype.isPrototypeOf(x))
172
        return 'array';
173
      if (t === 'object' && String.prototype.isPrototypeOf(x))
174
        return 'string';
175
      return t;
176
    };
177
    var isType = function (type) {
178
      return function (value) {
179
        return typeOf(value) === type;
180
      };
181
    };
182
    var isFunction = isType('function');
183
184
    var rawIndexOf = function () {
185
      var pIndexOf = Array.prototype.indexOf;
186
      var fastIndex = function (xs, x) {
187
        return pIndexOf.call(xs, x);
188
      };
189
      var slowIndex = function (xs, x) {
190
        return slowIndexOf(xs, x);
191
      };
192
      return pIndexOf === undefined ? slowIndex : fastIndex;
193
    }();
194
    var contains = function (xs, x) {
195
      return rawIndexOf(xs, x) > -1;
196
    };
197
    var map = function (xs, f) {
198
      var len = xs.length;
199
      var r = new Array(len);
200
      for (var i = 0; i < len; i++) {
201
        var x = xs[i];
202
        r[i] = f(x, i, xs);
203
      }
204
      return r;
205
    };
206
    var filter = function (xs, pred) {
207
      var r = [];
208
      for (var i = 0, len = xs.length; i < len; i++) {
209
        var x = xs[i];
210
        if (pred(x, i, xs)) {
211
          r.push(x);
212
        }
213
      }
214
      return r;
215
    };
216
    var find = function (xs, pred) {
217
      for (var i = 0, len = xs.length; i < len; i++) {
218
        var x = xs[i];
219
        if (pred(x, i, xs)) {
220
          return Option.some(x);
221
        }
222
      }
223
      return Option.none();
224
    };
225
    var slowIndexOf = function (xs, x) {
226
      for (var i = 0, len = xs.length; i < len; ++i) {
227
        if (xs[i] === x) {
228
          return i;
229
        }
230
      }
231
      return -1;
232
    };
233
    var slice = Array.prototype.slice;
234
    var from$1 = isFunction(Array.from) ? Array.from : function (x) {
235
      return slice.call(x);
236
    };
237
238
    var global$1 = tinymce.util.Tools.resolve('tinymce.util.I18n');
239
240
    var global$2 = tinymce.util.Tools.resolve('tinymce.Env');
241
242
    var meta = global$2.mac ? '\u2318' : 'Ctrl';
243
    var access = global$2.mac ? 'Ctrl + Alt' : 'Shift + Alt';
244
    var shortcuts = [
245
      {
246
        shortcut: meta + ' + B',
247
        action: 'Bold'
248
      },
249
      {
250
        shortcut: meta + ' + I',
251
        action: 'Italic'
252
      },
253
      {
254
        shortcut: meta + ' + U',
255
        action: 'Underline'
256
      },
257
      {
258
        shortcut: meta + ' + A',
259
        action: 'Select all'
260
      },
261
      {
262
        shortcut: meta + ' + Y or ' + meta + ' + Shift + Z',
263
        action: 'Redo'
264
      },
265
      {
266
        shortcut: meta + ' + Z',
267
        action: 'Undo'
268
      },
269
      {
270
        shortcut: access + ' + 1',
271
        action: 'Header 1'
272
      },
273
      {
274
        shortcut: access + ' + 2',
275
        action: 'Header 2'
276
      },
277
      {
278
        shortcut: access + ' + 3',
279
        action: 'Header 3'
280
      },
281
      {
282
        shortcut: access + ' + 4',
283
        action: 'Header 4'
284
      },
285
      {
286
        shortcut: access + ' + 5',
287
        action: 'Header 5'
288
      },
289
      {
290
        shortcut: access + ' + 6',
291
        action: 'Header 6'
292
      },
293
      {
294
        shortcut: access + ' + 7',
295
        action: 'Paragraph'
296
      },
297
      {
298
        shortcut: access + ' + 8',
299
        action: 'Div'
300
      },
301
      {
302
        shortcut: access + ' + 9',
303
        action: 'Address'
304
      },
305
      {
306
        shortcut: 'Alt + F9',
307
        action: 'Focus to menubar'
308
      },
309
      {
310
        shortcut: 'Alt + F10',
311
        action: 'Focus to toolbar'
312
      },
313
      {
314
        shortcut: 'Alt + F11',
315
        action: 'Focus to element path'
316
      },
317
      {
318
        shortcut: 'Ctrl + F9',
319
        action: 'Focus to contextual toolbar'
320
      },
321
      {
322
        shortcut: meta + ' + K',
323
        action: 'Insert link (if link plugin activated)'
324
      },
325
      {
326
        shortcut: meta + ' + S',
327
        action: 'Save (if save plugin activated)'
328
      },
329
      {
330
        shortcut: meta + ' + F',
331
        action: 'Find (if searchreplace plugin activated)'
332
      }
333
    ];
334
    var KeyboardShortcuts = { shortcuts: shortcuts };
335
336
    var makeTab = function () {
337
      var makeAriaLabel = function (shortcut) {
338
        return 'aria-label="Action: ' + shortcut.action + ', Shortcut: ' + shortcut.shortcut.replace(/Ctrl/g, 'Control') + '"';
339
      };
340
      var shortcutLisString = map(KeyboardShortcuts.shortcuts, function (shortcut) {
341
        return '<tr data-mce-tabstop="1" tabindex="-1" ' + makeAriaLabel(shortcut) + '>' + '<td>' + global$1.translate(shortcut.action) + '</td>' + '<td>' + shortcut.shortcut + '</td>' + '</tr>';
342
      }).join('');
343
      return {
344
        title: 'Handy Shortcuts',
345
        type: 'container',
346
        style: 'overflow-y: auto; overflow-x: hidden; max-height: 250px',
347
        items: [{
348
            type: 'container',
349
            html: '<div>' + '<table class="mce-table-striped">' + '<thead>' + '<th>' + global$1.translate('Action') + '</th>' + '<th>' + global$1.translate('Shortcut') + '</th>' + '</thead>' + shortcutLisString + '</table>' + '</div>'
350
          }]
351
      };
352
    };
353
    var KeyboardShortcutsTab = { makeTab: makeTab };
354
355
    var keys = Object.keys;
356
357
    var supplant = function (str, obj) {
358
      var isStringOrNumber = function (a) {
359
        var t = typeof a;
360
        return t === 'string' || t === 'number';
361
      };
362
      return str.replace(/\$\{([^{}]*)\}/g, function (fullMatch, key) {
363
        var value = obj[key];
364
        return isStringOrNumber(value) ? value.toString() : fullMatch;
365
      });
366
    };
367
368
    var urls = [
369
      {
370
        key: 'advlist',
371
        name: 'Advanced List'
372
      },
373
      {
374
        key: 'anchor',
375
        name: 'Anchor'
376
      },
377
      {
378
        key: 'autolink',
379
        name: 'Autolink'
380
      },
381
      {
382
        key: 'autoresize',
383
        name: 'Autoresize'
384
      },
385
      {
386
        key: 'autosave',
387
        name: 'Autosave'
388
      },
389
      {
390
        key: 'bbcode',
391
        name: 'BBCode'
392
      },
393
      {
394
        key: 'charmap',
395
        name: 'Character Map'
396
      },
397
      {
398
        key: 'code',
399
        name: 'Code'
400
      },
401
      {
402
        key: 'codesample',
403
        name: 'Code Sample'
404
      },
405
      {
406
        key: 'colorpicker',
407
        name: 'Color Picker'
408
      },
409
      {
410
        key: 'compat3x',
411
        name: '3.x Compatibility'
412
      },
413
      {
414
        key: 'contextmenu',
415
        name: 'Context Menu'
416
      },
417
      {
418
        key: 'directionality',
419
        name: 'Directionality'
420
      },
421
      {
422
        key: 'emoticons',
423
        name: 'Emoticons'
424
      },
425
      {
426
        key: 'fullpage',
427
        name: 'Full Page'
428
      },
429
      {
430
        key: 'fullscreen',
431
        name: 'Full Screen'
432
      },
433
      {
434
        key: 'help',
435
        name: 'Help'
436
      },
437
      {
438
        key: 'hr',
439
        name: 'Horizontal Rule'
440
      },
441
      {
442
        key: 'image',
443
        name: 'Image'
444
      },
445
      {
446
        key: 'imagetools',
447
        name: 'Image Tools'
448
      },
449
      {
450
        key: 'importcss',
451
        name: 'Import CSS'
452
      },
453
      {
454
        key: 'insertdatetime',
455
        name: 'Insert Date/Time'
456
      },
457
      {
458
        key: 'legacyoutput',
459
        name: 'Legacy Output'
460
      },
461
      {
462
        key: 'link',
463
        name: 'Link'
464
      },
465
      {
466
        key: 'lists',
467
        name: 'Lists'
468
      },
469
      {
470
        key: 'media',
471
        name: 'Media'
472
      },
473
      {
474
        key: 'nonbreaking',
475
        name: 'Nonbreaking'
476
      },
477
      {
478
        key: 'noneditable',
479
        name: 'Noneditable'
480
      },
481
      {
482
        key: 'pagebreak',
483
        name: 'Page Break'
484
      },
485
      {
486
        key: 'paste',
487
        name: 'Paste'
488
      },
489
      {
490
        key: 'preview',
491
        name: 'Preview'
492
      },
493
      {
494
        key: 'print',
495
        name: 'Print'
496
      },
497
      {
498
        key: 'save',
499
        name: 'Save'
500
      },
501
      {
502
        key: 'searchreplace',
503
        name: 'Search and Replace'
504
      },
505
      {
506
        key: 'spellchecker',
507
        name: 'Spell Checker'
508
      },
509
      {
510
        key: 'tabfocus',
511
        name: 'Tab Focus'
512
      },
513
      {
514
        key: 'table',
515
        name: 'Table'
516
      },
517
      {
518
        key: 'template',
519
        name: 'Template'
520
      },
521
      {
522
        key: 'textcolor',
523
        name: 'Text Color'
524
      },
525
      {
526
        key: 'textpattern',
527
        name: 'Text Pattern'
528
      },
529
      {
530
        key: 'toc',
531
        name: 'Table of Contents'
532
      },
533
      {
534
        key: 'visualblocks',
535
        name: 'Visual Blocks'
536
      },
537
      {
538
        key: 'visualchars',
539
        name: 'Visual Characters'
540
      },
541
      {
542
        key: 'wordcount',
543
        name: 'Word Count'
544
      }
545
    ];
546
    var PluginUrls = { urls: urls };
547
548
    var makeLink = curry(supplant, '<a href="${url}" target="_blank" rel="noopener">${name}</a>');
549
    var maybeUrlize = function (editor, key) {
550
      return find(PluginUrls.urls, function (x) {
551
        return x.key === key;
552
      }).fold(function () {
553
        var getMetadata = editor.plugins[key].getMetadata;
554
        return typeof getMetadata === 'function' ? makeLink(getMetadata()) : key;
555
      }, function (x) {
556
        return makeLink({
557
          name: x.name,
558
          url: 'https://www.tinymce.com/docs/plugins/' + x.key
559
        });
560
      });
561
    };
562
    var getPluginKeys = function (editor) {
563
      var keys$$1 = keys(editor.plugins);
564
      return editor.settings.forced_plugins === undefined ? keys$$1 : filter(keys$$1, not(curry(contains, editor.settings.forced_plugins)));
565
    };
566
    var pluginLister = function (editor) {
567
      var pluginKeys = getPluginKeys(editor);
568
      var pluginLis = map(pluginKeys, function (key) {
569
        return '<li>' + maybeUrlize(editor, key) + '</li>';
570
      });
571
      var count = pluginLis.length;
572
      var pluginsString = pluginLis.join('');
573
      return '<p><b>' + global$1.translate([
574
        'Plugins installed ({0}):',
575
        count
576
      ]) + '</b></p>' + '<ul>' + pluginsString + '</ul>';
577
    };
578
    var installedPlugins = function (editor) {
579
      return {
580
        type: 'container',
581
        html: '<div style="overflow-y: auto; overflow-x: hidden; max-height: 230px; height: 230px;" data-mce-tabstop="1" tabindex="-1">' + pluginLister(editor) + '</div>',
582
        flex: 1
583
      };
584
    };
585
    var availablePlugins = function () {
586
      return {
587
        type: 'container',
588
        html: '<div style="padding: 10px; background: #e3e7f4; height: 100%;" data-mce-tabstop="1" tabindex="-1">' + '<p><b>' + global$1.translate('Premium plugins:') + '</b></p>' + '<ul>' + '<li>PowerPaste</li>' + '<li>Spell Checker Pro</li>' + '<li>Accessibility Checker</li>' + '<li>Advanced Code Editor</li>' + '<li>Enhanced Media Embed</li>' + '<li>Link Checker</li>' + '</ul><br />' + '<p style="float: right;"><a href="https://www.tinymce.com/pricing/?utm_campaign=editor_referral&utm_medium=help_dialog&utm_source=tinymce" target="_blank">' + global$1.translate('Learn more...') + '</a></p>' + '</div>',
589
        flex: 1
590
      };
591
    };
592
    var makeTab$1 = function (editor) {
593
      return {
594
        title: 'Plugins',
595
        type: 'container',
596
        style: 'overflow-y: auto; overflow-x: hidden;',
597
        layout: 'flex',
598
        padding: 10,
599
        spacing: 10,
600
        items: [
601
          installedPlugins(editor),
602
          availablePlugins()
603
        ]
604
      };
605
    };
606
    var PluginsTab = { makeTab: makeTab$1 };
607
608
    var global$3 = tinymce.util.Tools.resolve('tinymce.EditorManager');
609
610
    var getVersion = function (major, minor) {
611
      return major.indexOf('@') === 0 ? 'X.X.X' : major + '.' + minor;
612
    };
613
    var makeRow = function () {
614
      var version = getVersion(global$3.majorVersion, global$3.minorVersion);
615
      var changeLogLink = '<a href="https://www.tinymce.com/docs/changelog/?utm_campaign=editor_referral&utm_medium=help_dialog&utm_source=tinymce" target="_blank">TinyMCE ' + version + '</a>';
616
      return [
617
        {
618
          type: 'label',
619
          html: global$1.translate([
620
            'You are using {0}',
621
            changeLogLink
622
          ])
623
        },
624
        {
625
          type: 'spacer',
626
          flex: 1
627
        },
628
        {
629
          text: 'Close',
630
          onclick: function () {
631
            this.parent().parent().close();
632
          }
633
        }
634
      ];
635
    };
636
    var ButtonsRow = { makeRow: makeRow };
637
638
    var open = function (editor, pluginUrl) {
639
      return function () {
640
        editor.windowManager.open({
641
          title: 'Help',
642
          bodyType: 'tabpanel',
643
          layout: 'flex',
644
          body: [
645
            KeyboardShortcutsTab.makeTab(),
646
            PluginsTab.makeTab(editor)
647
          ],
648
          buttons: ButtonsRow.makeRow(),
649
          onPostRender: function () {
650
            var title = this.getEl('title');
651
            title.innerHTML = '<img src="' + pluginUrl + '/img/logo.png" alt="TinyMCE Logo" style="display: inline-block; width: 200px; height: 50px">';
652
          }
653
        });
654
      };
655
    };
656
    var Dialog = { open: open };
657
658
    var register = function (editor, pluginUrl) {
659
      editor.addCommand('mceHelp', Dialog.open(editor, pluginUrl));
660
    };
661
    var Commands = { register: register };
662
663
    var register$1 = function (editor, pluginUrl) {
664
      editor.addButton('help', {
665
        icon: 'help',
666
        onclick: Dialog.open(editor, pluginUrl)
667
      });
668
      editor.addMenuItem('help', {
669
        text: 'Help',
670
        icon: 'help',
671
        context: 'help',
672
        onclick: Dialog.open(editor, pluginUrl)
673
      });
674
    };
675
    var Buttons = { register: register$1 };
676
677
    global.add('help', function (editor, pluginUrl) {
678
      Buttons.register(editor, pluginUrl);
679
      Commands.register(editor, pluginUrl);
680
      editor.shortcuts.add('Alt+0', 'Open help dialog', 'mceHelp');
681
    });
682
    function Plugin () {
683
    }
684
685
    return Plugin;
686
687
}());
688
})();
689