Subversion Repositories oidplus

Rev

Rev 1422 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
597 daniel-mar 1
/**
2
 * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
 * Licensed under the LGPL or a commercial license.
4
 * For LGPL see License.txt in the project root for license information.
5
 * For commercial licenses see https://www.tiny.cloud/
6
 *
1434 daniel-mar 7
 * Version: 5.10.9 (2023-11-15)
597 daniel-mar 8
 */
9
(function () {
10
    'use strict';
11
 
637 daniel-mar 12
    var global$3 = tinymce.util.Tools.resolve('tinymce.PluginManager');
597 daniel-mar 13
 
637 daniel-mar 14
    var eq = function (t) {
15
      return function (a) {
16
        return t === a;
597 daniel-mar 17
      };
18
    };
637 daniel-mar 19
    var isNull = eq(null);
597 daniel-mar 20
 
21
    var noop = function () {
22
    };
23
    var constant = function (value) {
24
      return function () {
25
        return value;
26
      };
27
    };
637 daniel-mar 28
    var identity = function (x) {
29
      return x;
30
    };
597 daniel-mar 31
    var never = constant(false);
32
    var always = constant(true);
33
 
34
    var none = function () {
35
      return NONE;
36
    };
37
    var NONE = function () {
38
      var call = function (thunk) {
39
        return thunk();
40
      };
637 daniel-mar 41
      var id = identity;
597 daniel-mar 42
      var me = {
43
        fold: function (n, _s) {
44
          return n();
45
        },
46
        isSome: never,
47
        isNone: always,
48
        getOr: id,
49
        getOrThunk: call,
50
        getOrDie: function (msg) {
51
          throw new Error(msg || 'error: getOrDie called on none.');
52
        },
53
        getOrNull: constant(null),
54
        getOrUndefined: constant(undefined),
55
        or: id,
56
        orThunk: call,
57
        map: none,
58
        each: noop,
59
        bind: none,
60
        exists: never,
61
        forall: always,
637 daniel-mar 62
        filter: function () {
63
          return none();
64
        },
597 daniel-mar 65
        toArray: function () {
66
          return [];
67
        },
68
        toString: constant('none()')
69
      };
70
      return me;
71
    }();
72
    var some = function (a) {
73
      var constant_a = constant(a);
74
      var self = function () {
75
        return me;
76
      };
77
      var bind = function (f) {
78
        return f(a);
79
      };
80
      var me = {
81
        fold: function (n, s) {
82
          return s(a);
83
        },
84
        isSome: always,
85
        isNone: never,
86
        getOr: constant_a,
87
        getOrThunk: constant_a,
88
        getOrDie: constant_a,
89
        getOrNull: constant_a,
90
        getOrUndefined: constant_a,
91
        or: self,
92
        orThunk: self,
93
        map: function (f) {
94
          return some(f(a));
95
        },
96
        each: function (f) {
97
          f(a);
98
        },
99
        bind: bind,
100
        exists: bind,
101
        forall: bind,
102
        filter: function (f) {
103
          return f(a) ? me : NONE;
104
        },
105
        toArray: function () {
106
          return [a];
107
        },
108
        toString: function () {
109
          return 'some(' + a + ')';
110
        }
111
      };
112
      return me;
113
    };
114
    var from = function (value) {
115
      return value === null || value === undefined ? NONE : some(value);
116
    };
117
    var Optional = {
118
      some: some,
119
      none: none,
120
      from: from
121
    };
122
 
637 daniel-mar 123
    var exists = function (xs, pred) {
124
      for (var i = 0, len = xs.length; i < len; i++) {
125
        var x = xs[i];
126
        if (pred(x, i)) {
127
          return true;
128
        }
129
      }
130
      return false;
131
    };
132
    var map$1 = function (xs, f) {
133
      var len = xs.length;
134
      var r = new Array(len);
135
      for (var i = 0; i < len; i++) {
136
        var x = xs[i];
137
        r[i] = f(x, i);
138
      }
139
      return r;
140
    };
141
    var each$1 = function (xs, f) {
142
      for (var i = 0, len = xs.length; i < len; i++) {
143
        var x = xs[i];
144
        f(x, i);
145
      }
146
    };
147
 
148
    var Cell = function (initial) {
149
      var value = initial;
150
      var get = function () {
151
        return value;
152
      };
153
      var set = function (v) {
154
        value = v;
155
      };
156
      return {
157
        get: get,
158
        set: set
159
      };
160
    };
161
 
162
    var last = function (fn, rate) {
163
      var timer = null;
164
      var cancel = function () {
165
        if (!isNull(timer)) {
166
          clearTimeout(timer);
167
          timer = null;
168
        }
169
      };
170
      var throttle = function () {
171
        var args = [];
172
        for (var _i = 0; _i < arguments.length; _i++) {
173
          args[_i] = arguments[_i];
174
        }
175
        cancel();
176
        timer = setTimeout(function () {
177
          timer = null;
178
          fn.apply(null, args);
179
        }, rate);
180
      };
181
      return {
182
        cancel: cancel,
183
        throttle: throttle
184
      };
185
    };
186
 
187
    var insertEmoticon = function (editor, ch) {
188
      editor.insertContent(ch);
189
    };
190
 
191
    var __assign = function () {
192
      __assign = Object.assign || function __assign(t) {
193
        for (var s, i = 1, n = arguments.length; i < n; i++) {
194
          s = arguments[i];
195
          for (var p in s)
196
            if (Object.prototype.hasOwnProperty.call(s, p))
197
              t[p] = s[p];
198
        }
199
        return t;
200
      };
201
      return __assign.apply(this, arguments);
202
    };
203
 
597 daniel-mar 204
    var keys = Object.keys;
637 daniel-mar 205
    var hasOwnProperty = Object.hasOwnProperty;
597 daniel-mar 206
    var each = function (obj, f) {
207
      var props = keys(obj);
208
      for (var k = 0, len = props.length; k < len; k++) {
209
        var i = props[k];
210
        var x = obj[i];
211
        f(x, i);
212
      }
213
    };
214
    var map = function (obj, f) {
215
      return tupleMap(obj, function (x, i) {
216
        return {
217
          k: i,
218
          v: f(x, i)
219
        };
220
      });
221
    };
222
    var tupleMap = function (obj, f) {
223
      var r = {};
224
      each(obj, function (x, i) {
225
        var tuple = f(x, i);
226
        r[tuple.k] = tuple.v;
227
      });
228
      return r;
229
    };
230
    var has = function (obj, key) {
637 daniel-mar 231
      return hasOwnProperty.call(obj, key);
597 daniel-mar 232
    };
233
 
637 daniel-mar 234
    var shallow = function (old, nu) {
235
      return nu;
236
    };
237
    var baseMerge = function (merger) {
238
      return function () {
239
        var objects = [];
240
        for (var _i = 0; _i < arguments.length; _i++) {
241
          objects[_i] = arguments[_i];
242
        }
243
        if (objects.length === 0) {
244
          throw new Error('Can\'t merge zero objects');
245
        }
246
        var ret = {};
247
        for (var j = 0; j < objects.length; j++) {
248
          var curObject = objects[j];
249
          for (var key in curObject) {
250
            if (has(curObject, key)) {
251
              ret[key] = merger(ret[key], curObject[key]);
252
            }
253
          }
254
        }
255
        return ret;
256
      };
257
    };
258
    var merge = baseMerge(shallow);
259
 
260
    var singleton = function (doRevoke) {
261
      var subject = Cell(Optional.none());
262
      var revoke = function () {
263
        return subject.get().each(doRevoke);
264
      };
265
      var clear = function () {
266
        revoke();
267
        subject.set(Optional.none());
268
      };
269
      var isSet = function () {
270
        return subject.get().isSome();
271
      };
272
      var get = function () {
273
        return subject.get();
274
      };
275
      var set = function (s) {
276
        revoke();
277
        subject.set(Optional.some(s));
278
      };
279
      return {
280
        clear: clear,
281
        isSet: isSet,
282
        get: get,
283
        set: set
284
      };
285
    };
286
    var value = function () {
287
      var subject = singleton(noop);
288
      var on = function (f) {
289
        return subject.get().each(f);
290
      };
291
      return __assign(__assign({}, subject), { on: on });
292
    };
293
 
597 daniel-mar 294
    var checkRange = function (str, substr, start) {
295
      return substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr;
296
    };
297
    var contains = function (str, substr) {
298
      return str.indexOf(substr) !== -1;
299
    };
300
    var startsWith = function (str, prefix) {
301
      return checkRange(str, prefix, 0);
302
    };
303
 
637 daniel-mar 304
    var global$2 = tinymce.util.Tools.resolve('tinymce.Resource');
597 daniel-mar 305
 
637 daniel-mar 306
    var global$1 = tinymce.util.Tools.resolve('tinymce.util.Delay');
597 daniel-mar 307
 
637 daniel-mar 308
    var global = tinymce.util.Tools.resolve('tinymce.util.Promise');
597 daniel-mar 309
 
637 daniel-mar 310
    var DEFAULT_ID = 'tinymce.plugins.emoticons';
311
    var getEmoticonDatabase = function (editor) {
312
      return editor.getParam('emoticons_database', 'emojis', 'string');
313
    };
314
    var getEmoticonDatabaseUrl = function (editor, pluginUrl) {
315
      var database = getEmoticonDatabase(editor);
316
      return editor.getParam('emoticons_database_url', pluginUrl + '/js/' + database + editor.suffix + '.js', 'string');
317
    };
318
    var getEmoticonDatabaseId = function (editor) {
319
      return editor.getParam('emoticons_database_id', DEFAULT_ID, 'string');
320
    };
321
    var getAppendedEmoticons = function (editor) {
322
      return editor.getParam('emoticons_append', {}, 'object');
323
    };
324
    var getEmotionsImageUrl = function (editor) {
325
      return editor.getParam('emoticons_images_url', 'https://twemoji.maxcdn.com/v/13.0.1/72x72/', 'string');
326
    };
327
 
597 daniel-mar 328
    var ALL_CATEGORY = 'All';
329
    var categoryNameMap = {
330
      symbols: 'Symbols',
331
      people: 'People',
332
      animals_and_nature: 'Animals and Nature',
333
      food_and_drink: 'Food and Drink',
334
      activity: 'Activity',
335
      travel_and_places: 'Travel and Places',
336
      objects: 'Objects',
337
      flags: 'Flags',
338
      user: 'User Defined'
339
    };
340
    var translateCategory = function (categories, name) {
341
      return has(categories, name) ? categories[name] : name;
342
    };
343
    var getUserDefinedEmoticons = function (editor) {
344
      var userDefinedEmoticons = getAppendedEmoticons(editor);
345
      return map(userDefinedEmoticons, function (value) {
346
        return __assign({
347
          keywords: [],
348
          category: 'user'
349
        }, value);
350
      });
351
    };
352
    var initDatabase = function (editor, databaseUrl, databaseId) {
637 daniel-mar 353
      var categories = value();
354
      var all = value();
597 daniel-mar 355
      var emojiImagesUrl = getEmotionsImageUrl(editor);
356
      var getEmoji = function (lib) {
357
        if (startsWith(lib.char, '<img')) {
358
          return lib.char.replace(/src="([^"]+)"/, function (match, url) {
359
            return 'src="' + emojiImagesUrl + url + '"';
360
          });
361
        } else {
362
          return lib.char;
363
        }
364
      };
365
      var processEmojis = function (emojis) {
366
        var cats = {};
367
        var everything = [];
368
        each(emojis, function (lib, title) {
369
          var entry = {
370
            title: title,
371
            keywords: lib.keywords,
372
            char: getEmoji(lib),
373
            category: translateCategory(categoryNameMap, lib.category)
374
          };
375
          var current = cats[entry.category] !== undefined ? cats[entry.category] : [];
376
          cats[entry.category] = current.concat([entry]);
377
          everything.push(entry);
378
        });
637 daniel-mar 379
        categories.set(cats);
380
        all.set(everything);
597 daniel-mar 381
      };
382
      editor.on('init', function () {
637 daniel-mar 383
        global$2.load(databaseId, databaseUrl).then(function (emojis) {
597 daniel-mar 384
          var userEmojis = getUserDefinedEmoticons(editor);
385
          processEmojis(merge(emojis, userEmojis));
386
        }, function (err) {
387
          console.log('Failed to load emoticons: ' + err);
637 daniel-mar 388
          categories.set({});
389
          all.set([]);
597 daniel-mar 390
        });
391
      });
392
      var listCategory = function (category) {
393
        if (category === ALL_CATEGORY) {
394
          return listAll();
395
        }
396
        return categories.get().bind(function (cats) {
397
          return Optional.from(cats[category]);
398
        }).getOr([]);
399
      };
400
      var listAll = function () {
401
        return all.get().getOr([]);
402
      };
403
      var listCategories = function () {
404
        return [ALL_CATEGORY].concat(keys(categories.get().getOr({})));
405
      };
406
      var waitForLoad = function () {
407
        if (hasLoaded()) {
637 daniel-mar 408
          return global.resolve(true);
597 daniel-mar 409
        } else {
637 daniel-mar 410
          return new global(function (resolve, reject) {
597 daniel-mar 411
            var numRetries = 15;
637 daniel-mar 412
            var interval = global$1.setInterval(function () {
597 daniel-mar 413
              if (hasLoaded()) {
637 daniel-mar 414
                global$1.clearInterval(interval);
597 daniel-mar 415
                resolve(true);
416
              } else {
417
                numRetries--;
418
                if (numRetries < 0) {
419
                  console.log('Could not load emojis from url: ' + databaseUrl);
637 daniel-mar 420
                  global$1.clearInterval(interval);
597 daniel-mar 421
                  reject(false);
422
                }
423
              }
424
            }, 100);
425
          });
426
        }
427
      };
428
      var hasLoaded = function () {
637 daniel-mar 429
        return categories.isSet() && all.isSet();
597 daniel-mar 430
      };
431
      return {
432
        listCategories: listCategories,
433
        hasLoaded: hasLoaded,
434
        waitForLoad: waitForLoad,
435
        listAll: listAll,
436
        listCategory: listCategory
437
      };
438
    };
439
 
440
    var emojiMatches = function (emoji, lowerCasePattern) {
441
      return contains(emoji.title.toLowerCase(), lowerCasePattern) || exists(emoji.keywords, function (k) {
442
        return contains(k.toLowerCase(), lowerCasePattern);
443
      });
444
    };
445
    var emojisFrom = function (list, pattern, maxResults) {
446
      var matches = [];
447
      var lowerCasePattern = pattern.toLowerCase();
448
      var reachedLimit = maxResults.fold(function () {
449
        return never;
450
      }, function (max) {
451
        return function (size) {
452
          return size >= max;
453
        };
454
      });
455
      for (var i = 0; i < list.length; i++) {
456
        if (pattern.length === 0 || emojiMatches(list[i], lowerCasePattern)) {
457
          matches.push({
458
            value: list[i].char,
459
            text: list[i].title,
460
            icon: list[i].char
461
          });
462
          if (reachedLimit(matches.length)) {
463
            break;
464
          }
465
        }
466
      }
467
      return matches;
468
    };
469
 
470
    var patternName = 'pattern';
471
    var open = function (editor, database) {
472
      var initialState = {
473
        pattern: '',
474
        results: emojisFrom(database.listAll(), '', Optional.some(300))
475
      };
476
      var currentTab = Cell(ALL_CATEGORY);
477
      var scan = function (dialogApi) {
478
        var dialogData = dialogApi.getData();
479
        var category = currentTab.get();
480
        var candidates = database.listCategory(category);
481
        var results = emojisFrom(candidates, dialogData[patternName], category === ALL_CATEGORY ? Optional.some(300) : Optional.none());
482
        dialogApi.setData({ results: results });
483
      };
484
      var updateFilter = last(function (dialogApi) {
485
        scan(dialogApi);
486
      }, 200);
487
      var searchField = {
488
        label: 'Search',
489
        type: 'input',
490
        name: patternName
491
      };
492
      var resultsField = {
493
        type: 'collection',
494
        name: 'results'
495
      };
496
      var getInitialState = function () {
497
        var body = {
498
          type: 'tabpanel',
499
          tabs: map$1(database.listCategories(), function (cat) {
500
            return {
501
              title: cat,
502
              name: cat,
503
              items: [
504
                searchField,
505
                resultsField
506
              ]
507
            };
508
          })
509
        };
510
        return {
511
          title: 'Emoticons',
512
          size: 'normal',
513
          body: body,
514
          initialData: initialState,
515
          onTabChange: function (dialogApi, details) {
516
            currentTab.set(details.newTabName);
517
            updateFilter.throttle(dialogApi);
518
          },
519
          onChange: updateFilter.throttle,
520
          onAction: function (dialogApi, actionData) {
521
            if (actionData.name === 'results') {
522
              insertEmoticon(editor, actionData.value);
523
              dialogApi.close();
524
            }
525
          },
526
          buttons: [{
527
              type: 'cancel',
528
              text: 'Close',
529
              primary: true
530
            }]
531
        };
532
      };
533
      var dialogApi = editor.windowManager.open(getInitialState());
534
      dialogApi.focus(patternName);
535
      if (!database.hasLoaded()) {
536
        dialogApi.block('Loading emoticons...');
537
        database.waitForLoad().then(function () {
538
          dialogApi.redial(getInitialState());
539
          updateFilter.throttle(dialogApi);
540
          dialogApi.focus(patternName);
541
          dialogApi.unblock();
542
        }).catch(function (_err) {
543
          dialogApi.redial({
544
            title: 'Emoticons',
545
            body: {
546
              type: 'panel',
547
              items: [{
548
                  type: 'alertbanner',
549
                  level: 'error',
550
                  icon: 'warning',
551
                  text: '<p>Could not load emoticons</p>'
552
                }]
553
            },
554
            buttons: [{
555
                type: 'cancel',
556
                text: 'Close',
557
                primary: true
558
              }],
559
            initialData: {
560
              pattern: '',
561
              results: []
562
            }
563
          });
564
          dialogApi.focus(patternName);
565
          dialogApi.unblock();
566
        });
567
      }
568
    };
569
 
637 daniel-mar 570
    var register$1 = function (editor, database) {
571
      editor.addCommand('mceEmoticons', function () {
572
        return open(editor, database);
573
      });
574
    };
575
 
576
    var setup = function (editor) {
577
      editor.on('PreInit', function () {
578
        editor.parser.addAttributeFilter('data-emoticon', function (nodes) {
579
          each$1(nodes, function (node) {
580
            node.attr('data-mce-resize', 'false');
581
            node.attr('data-mce-placeholder', '1');
582
          });
583
        });
584
      });
585
    };
586
 
587
    var init = function (editor, database) {
588
      editor.ui.registry.addAutocompleter('emoticons', {
589
        ch: ':',
590
        columns: 'auto',
591
        minChars: 2,
592
        fetch: function (pattern, maxResults) {
593
          return database.waitForLoad().then(function () {
594
            var candidates = database.listAll();
595
            return emojisFrom(candidates, pattern, Optional.some(maxResults));
596
          });
597
        },
598
        onAction: function (autocompleteApi, rng, value) {
599
          editor.selection.setRng(rng);
600
          editor.insertContent(value);
601
          autocompleteApi.hide();
602
        }
603
      });
604
    };
605
 
606
    var register = function (editor) {
597 daniel-mar 607
      var onAction = function () {
637 daniel-mar 608
        return editor.execCommand('mceEmoticons');
597 daniel-mar 609
      };
610
      editor.ui.registry.addButton('emoticons', {
611
        tooltip: 'Emoticons',
612
        icon: 'emoji',
613
        onAction: onAction
614
      });
615
      editor.ui.registry.addMenuItem('emoticons', {
616
        text: 'Emoticons...',
617
        icon: 'emoji',
618
        onAction: onAction
619
      });
620
    };
621
 
622
    function Plugin () {
637 daniel-mar 623
      global$3.add('emoticons', function (editor, pluginUrl) {
597 daniel-mar 624
        var databaseUrl = getEmoticonDatabaseUrl(editor, pluginUrl);
625
        var databaseId = getEmoticonDatabaseId(editor);
626
        var database = initDatabase(editor, databaseUrl, databaseId);
637 daniel-mar 627
        register$1(editor, database);
628
        register(editor);
597 daniel-mar 629
        init(editor, database);
630
        setup(editor);
631
      });
632
    }
633
 
634
    Plugin();
635
 
636
}());