From 3e698e4b98cf1f8e51482c84d2fc0304bc487131 Mon Sep 17 00:00:00 2001 From: Markus Tacker Date: Wed, 2 Oct 2019 22:39:55 +0200 Subject: [PATCH] feat(twemoji): add types (#38719) --- types/twemoji/index.d.ts | 220 +++++++++++++++++++++++++++++++++ types/twemoji/tsconfig.json | 24 ++++ types/twemoji/tslint.json | 1 + types/twemoji/twemoji-tests.ts | 22 ++++ 4 files changed, 267 insertions(+) create mode 100644 types/twemoji/index.d.ts create mode 100644 types/twemoji/tsconfig.json create mode 100644 types/twemoji/tslint.json create mode 100644 types/twemoji/twemoji-tests.ts diff --git a/types/twemoji/index.d.ts b/types/twemoji/index.d.ts new file mode 100644 index 0000000000..d0c0f5b3c1 --- /dev/null +++ b/types/twemoji/index.d.ts @@ -0,0 +1,220 @@ +// Type definitions for twemoji 12.1 +// Project: https://github.com/twitter/twemoji +// Definitions by: Markus Tacker +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.2 + +/** + * default assets url, by default will be Twitter Inc. CDN + */ +export const base: string; + +/** + * default assets file extensions, by default '.png' + */ +export const ext: string; + +/** + * default assets/folder size, by default "72x72" + * available via Twitter CDN: 72 + */ +export const size: string; + +/** + * default class name, by default 'emoji' + */ +export const className: string; + +/** + * basic utilities / helpers to convert code points + * to JavaScript surrogates and vice versa + */ +export const convert: { + /** + * Given an HEX codepoint, returns UTF16 surrogate pairs. + * + * @param codepoint string generic codepoint, i.e. '1F4A9' + * @return string codepoint transformed into utf16 surrogates pair, + * i.e. \uD83D\uDCA9 + * + * @example + * twemoji.convert.fromCodePoint('1f1e8'); + * // "\ud83c\udde8" + * + * '1f1e8-1f1f3'.split('-').map(twemoji.convert.fromCodePoint).join('') + * // "\ud83c\udde8\ud83c\uddf3" + */ + fromCodePoint: (codepoint: string) => string; + + /** + * Given UTF16 surrogate pairs, returns the equivalent HEX codepoint. + * + * @param unicodeSurrogates string generic utf16 surrogates pair, i.e. \uD83D\uDCA9 + * @param sep string optional separator for double code points, default='-' + * @return string utf16 transformed into codepoint, i.e. '1F4A9' + * + * @example + * twemoji.convert.toCodePoint('\ud83c\udde8\ud83c\uddf3'); + * // "1f1e8-1f1f3" + * + * twemoji.convert.toCodePoint('\ud83c\udde8\ud83c\uddf3', '~'); + * // "1f1e8~1f1f3" + */ + toCodePoint: (unicodeSurrogates: string, sep?: string) => string; +}; + +/** + * User first: used to remove missing images + * preserving the original text intent when + * a fallback for network problems is desired. + * Automatically added to Image nodes via DOM + * It could be recycled for string operations via: + * $('img.emoji').on('error', twemoji.onerror) + */ +export function onerror(): void; + +/** + * Given a string, invokes the callback argument + * per each emoji found in such string. + * This is the most raw version used by + * the .parse(string) method itself. + * + * @param text string generic string to parse + * @param callback Function a generic callback that will be + * invoked to replace the content. + * This calback wil receive standard + * String.prototype.replace(str, callback) + * arguments such: + * callback( + * rawText, // the emoji match + * ); + * + * and others commonly received via replace. + */ +export function replace(text: string, callback: () => void): string; + +/** + * Simplify string tests against emoji. + * + * @param text string some text that might contain emoji + * @return boolean true if any emoji was found, false otherwise. + * + * @example + * + * if (twemoji.test(someContent)) { + * console.log("emoji All The Things!"); + * } + */ +export function test(text: string): boolean; + +/** + * If given to parse, this callback will be invoked per each found emoji. + * + * If this callback returns a falsy value instead of a valid `src` to use for the image, nothing will actually change for that specific emoji. + * + * @param icon the lower case HEX code point i.e. "1f4a9" + * @param options all info for this parsing operation + * @param variant the optional \uFE0F ("as image") variant, in case this info is anyhow meaningful. By default this is ignored. + */ +export type ParseCallback = (icon: string, options: object, variant: string) => string | false; + +/** + * If given to parse, this object with all properties will be used per each found emoji. + * + * callback Function the callback to invoke per each found emoji. + * base string the base url, by default twemoji.base + * ext string the image extension, by default twemoji.ext + * size string the assets size, by default twemoji.size + */ +export interface ParseObject { + /** + * the callback to invoke per each found emoji. + * + * default: the common replacer + */ + callback: ParseCallback; + /** + * The function to invoke in order to generate additional, custom attributes for the image tag. + * + * @param the lower case HEX code point i.e. "1f4a9" + * @param variant the optional \uFE0F ("as image") variant, in case this info is anyhow meaningful. By default this is ignored. + */ + attributes: (icon: string, variant: string) => object; + /** + * default: MaxCDN + */ + base: string; + /** + * default: ".png" + */ + ext: string; + /** + * default: "emoji" + */ + className: string; + /** + * default: "72x72" + */ + size: string | number; + /** + * in case it's specified it replaces .size info, if any + */ + folder: string; +} + +/** + * Main method/logic to generate either tags or HTMLImage nodes. + * "emojify" a generic text or DOM Element. + * + * @overloads + * + * String replacement for `innerHTML` or server side operations + * twemoji.parse(string); + * twemoji.parse(string, Function); + * twemoji.parse(string, Object); + * + * HTMLElement tree parsing for safer operations over existing DOM + * twemoji.parse(HTMLElement); + * twemoji.parse(HTMLElement, Function); + * twemoji.parse(HTMLElement, Object); + * + * @param what string|HTMLElement the source to parse and enrich with emoji. + * + * string replace emoji matches with tags. + * Mainly used to inject emoji via `innerHTML` + * It does **not** parse the string or validate it, + * it simply replaces found emoji with a tag. + * NOTE: be sure this won't affect security. + * + * HTMLElement walk through the DOM tree and find emoji + * that are inside **text node only** (nodeType === 3) + * Mainly used to put emoji in already generated DOM + * without compromising surrounding nodes and + * **avoiding** the usage of `innerHTML`. + * NOTE: Using DOM elements instead of strings should + * improve security without compromising too much + * performance compared with a less safe `innerHTML`. + * + * @param how object|Function + * + * @example + * + * twemoji.parse("I \u2764\uFE0F emoji!"); + * // I ❤️ emoji! + * + * + * twemoji.parse("I \u2764\uFE0F emoji!", function(iconId, options) { + * return '/assets/' + iconId + '.gif'; + * }); + * // I ❤️ emoji! + * + * + * twemoji.parse("I \u2764\uFE0F emoji!", { + * size: 72, + * callback: function(iconId, options) { + * return '/assets/' + options.size + '/' + iconId + options.ext; + * } + * }); + * // I ❤️ emoji! + */ +export function parse(what: string | HTMLElement, how?: Partial | ParseCallback): string; diff --git a/types/twemoji/tsconfig.json b/types/twemoji/tsconfig.json new file mode 100644 index 0000000000..800e02df46 --- /dev/null +++ b/types/twemoji/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6", + "dom" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": false, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "twemoji-tests.ts" + ] +} diff --git a/types/twemoji/tslint.json b/types/twemoji/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/twemoji/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" } diff --git a/types/twemoji/twemoji-tests.ts b/types/twemoji/twemoji-tests.ts new file mode 100644 index 0000000000..b11b687761 --- /dev/null +++ b/types/twemoji/twemoji-tests.ts @@ -0,0 +1,22 @@ +import twemoji = require('twemoji'); + +twemoji.parse('foo', { + base: 'https://cdnjs.cloudflare.com/ajax/libs/twemoji/12.0.4/2/', + folder: 'svg', + ext: '.svg', +}); + +const foo: HTMLElement = undefined; +twemoji.parse(foo, { + base: 'https://cdnjs.cloudflare.com/ajax/libs/twemoji/12.0.4/2/', + folder: 'svg', + ext: '.svg', +}); + +twemoji.convert.fromCodePoint('1f1e8'); + +twemoji.convert.toCodePoint('\ud83c\udde8\ud83c\uddf3'); + +if (twemoji.test("foo")) { + console.log("emoji All The Things!"); +}