You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
6.1 KiB
162 lines
6.1 KiB
/**@license
|
|
* __ _____ ________ __
|
|
* / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / /
|
|
* __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ /
|
|
* / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__
|
|
* \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/
|
|
* \/ /____/
|
|
* http://terminal.jcubic.pl
|
|
*
|
|
* this is formatter for jQuery Terminal that add support for emoji
|
|
*
|
|
* Copyright (c) 2019-2021 Jakub Jankiewicz <https://jcubic.pl/me>
|
|
* Released under the MIT license
|
|
*
|
|
*/
|
|
/* global define */
|
|
(function(factory, undefined) {
|
|
var root = typeof window !== 'undefined' ? window : global;
|
|
if (typeof define === 'function' && define.amd) {
|
|
// AMD. Register as an anonymous module.
|
|
// istanbul ignore next
|
|
define(['jquery', 'jquery.terminal'], factory);
|
|
} else if (typeof module === 'object' && module.exports) {
|
|
// Node/CommonJS
|
|
module.exports = function(root, jQuery) {
|
|
if (jQuery === undefined) {
|
|
// require('jQuery') returns a factory that requires window to
|
|
// build a jQuery instance, we normalize how we use modules
|
|
// that require this pattern but the window provided is a noop
|
|
// if it's defined (how jquery works)
|
|
if (window !== undefined) {
|
|
jQuery = require('jquery');
|
|
} else {
|
|
jQuery = require('jquery')(root);
|
|
}
|
|
}
|
|
if (!jQuery.fn.terminal) {
|
|
if (window !== undefined) {
|
|
require('jquery.terminal');
|
|
} else {
|
|
require('jquery.terminal')(jQuery);
|
|
}
|
|
}
|
|
factory(jQuery);
|
|
return jQuery;
|
|
};
|
|
} else {
|
|
// Browser
|
|
// istanbul ignore next
|
|
factory(root.jQuery, root.Prism);
|
|
}
|
|
})(function($, undefined) {
|
|
// https://2ality.com/2013/09/javascript-unicode.html
|
|
function toUTF16(codePoint) {
|
|
var TEN_BITS = parseInt('1111111111', 2);
|
|
function u(codeUnit) {
|
|
return '\\u' + codeUnit.toString(16).toUpperCase();
|
|
}
|
|
|
|
if (codePoint <= 0xFFFF) {
|
|
return u(codePoint);
|
|
}
|
|
codePoint -= 0x10000;
|
|
|
|
// Shift right to get to most significant 10 bits
|
|
var leadSurrogate = 0xD800 + (codePoint >> 10);
|
|
|
|
// Mask to get least significant 10 bits
|
|
var tailSurrogate = 0xDC00 + (codePoint & TEN_BITS);
|
|
|
|
return u(leadSurrogate) + u(tailSurrogate);
|
|
}
|
|
// compare two arrays of numbers
|
|
function compare_nums(a, b) {
|
|
for (var i = 0; i < a.length; ++i) {
|
|
if (a[1] === undefined) {
|
|
return 1;
|
|
}
|
|
if (b[i] === undefined) {
|
|
return -1;
|
|
}
|
|
if (a[i] > b[i]) {
|
|
return -1;
|
|
} else if (a[i] < b[i]) {
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
function make_formatter(unified, short_name) {
|
|
var unicode = unified.split('-').map(function(u) {
|
|
var x = parseInt(u, 16);
|
|
if (x > 0xFFFF) {
|
|
return toUTF16(x);
|
|
}
|
|
return '\\u' + u;
|
|
}).join('');
|
|
var re = new RegExp('(' + unicode + ')', 'g');
|
|
return [re, '[[;;;emoji ' + short_name + ']⻇]'];
|
|
}
|
|
// create array of numbers out of unified field
|
|
function parse_unified(str) {
|
|
return str.split('-').map(function(num) {
|
|
return parseInt(num, 16);
|
|
});
|
|
}
|
|
// emoji_data param need to be JavaScript object from
|
|
// https://unpkg.com/emoji-datasource-twitter/emoji.json
|
|
$.terminal.emoji = function(emoji_data) {
|
|
var text = {};
|
|
var names = [];
|
|
emoji_data.forEach(function(emoji) {
|
|
if (emoji.text && !text[emoji.text]) {
|
|
text[emoji.text] = emoji.short_name;
|
|
}
|
|
names.push(emoji.short_name);
|
|
});
|
|
// new API from version 1.10.0, old one with function will still work but
|
|
// if you need to use replacement that change length of the input text
|
|
// you need to use [regex, str] or function formatter where you use
|
|
// $.terminal.tracking_replace that returns [string, position] the same
|
|
// should be returned by formatter, optionally you can check if options
|
|
// have position
|
|
$.terminal.defaults.formatters.push([
|
|
new RegExp(':(' + names.map(function(name) {
|
|
return $.terminal.escape_regex(name);
|
|
}).join('|') + '):', 'g'),
|
|
'[[;;;emoji $1]⻇]'
|
|
]);
|
|
Object.keys(text).forEach(function(name) {
|
|
$.terminal.defaults.formatters.push([
|
|
new RegExp($.terminal.escape_regex(name), 'g'),
|
|
'[[;;;emoji ' + text[name] + ']⻇]'
|
|
]);
|
|
});
|
|
for (var i = 0; i < emoji_data.length; ++i) {
|
|
var emoji = emoji_data[i];
|
|
emoji.sort = parse_unified(emoji.unified);
|
|
}
|
|
emoji_data = emoji_data.sort(function(a, b) {
|
|
return compare_nums(a.sort, b.sort);
|
|
});
|
|
var formatters = [];
|
|
emoji_data.forEach(function(emoji) {
|
|
formatters.push(make_formatter(emoji.unified, emoji.short_name));
|
|
if (emoji.skin_variations) {
|
|
var variations = Object.keys(emoji.skin_variations).map(function(key, i) {
|
|
var unified = emoji.skin_variations[key].unified;
|
|
var short_name = emoji.short_name + '-var-' + i;
|
|
return make_formatter(unified, short_name);
|
|
});
|
|
formatters = formatters.concat(variations);
|
|
}
|
|
});
|
|
// this is unicode emoji handling
|
|
$.terminal.defaults.formatters.push(function(string, options) {
|
|
return $.terminal.apply_formatters(string, $.extend(options, {
|
|
formatters: formatters
|
|
}));
|
|
});
|
|
};
|
|
});
|
|
|