@involvex/emoji-cli 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,53 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { emojify } from './emojify.js'
4
+
5
+ describe('emojify', () => {
6
+ it('handles flags correctly', () => {
7
+ expect(
8
+ emojify('Mexico :mexico: and Morocco :morocco: are not the same'),
9
+ ).toBe('Mexico πŸ‡²πŸ‡½ and Morocco πŸ‡²πŸ‡¦ are not the same')
10
+ })
11
+
12
+ it('leaves unknown emoji when no fallback is provided', () => {
13
+ expect(emojify('I :unknown_emoji: :star: :another_one:')).toBe(
14
+ 'I :unknown_emoji: ⭐ :another_one:',
15
+ )
16
+ })
17
+
18
+ it('replaces unknown emoji with the fallback when a fallback string is provided', () => {
19
+ expect(
20
+ emojify('I :unknown_emoji: :star: :another_one:', {
21
+ fallback: 'unknown',
22
+ }),
23
+ ).toBe('I unknown ⭐ unknown')
24
+ })
25
+
26
+ it('replaces unknown emoji with the fallback when a fallback function is provided', () => {
27
+ expect(
28
+ emojify('I :unknown_emoji: :star: :another_one:', {
29
+ fallback: part => `(${part})`,
30
+ }),
31
+ ).toBe('I (unknown_emoji) ⭐ (another_one)')
32
+ })
33
+
34
+ it('parses a single :emoji: in a string when there is only one emoji', () => {
35
+ expect(emojify(':coffee:!')).toBe('β˜•!')
36
+ })
37
+
38
+ it('parses multiple :emoji: in a string when there are multiple emoji', () => {
39
+ expect(
40
+ emojify(
41
+ 'I :heart: :coffee:! - :hushed::star::heart_eyes: ::: test : : :+1:+',
42
+ ),
43
+ ).toBe('I ❀️ β˜•! - 😯⭐😍 ::: test : : πŸ‘+')
44
+ })
45
+
46
+ it('formats emoji when given a format function', () => {
47
+ expect(
48
+ emojify('I :unknown_emoji: :star: :another_one:', {
49
+ format: name => `[${name}]`,
50
+ }),
51
+ ).toBe('I [:unknown_emoji:] [⭐] [:another_one:]')
52
+ })
53
+ })
package/src/emojify.ts ADDED
@@ -0,0 +1,50 @@
1
+ import is from '@sindresorhus/is'
2
+
3
+ import { findByName } from './findByName.js'
4
+ import { asFunction, normalizeName } from './utils.js'
5
+
6
+ export type EmojifyFormat = (
7
+ name: string,
8
+ part?: string,
9
+ input?: string,
10
+ ) => string
11
+
12
+ export interface EmojifyOptions {
13
+ /**
14
+ * The string to fallback to if an emoji was not found.
15
+ */
16
+ fallback?: ((part: string) => string) | string
17
+
18
+ /**
19
+ * Adds a middleware layer to modify each matched emoji after parsing.
20
+ */
21
+ format?: EmojifyFormat
22
+ }
23
+
24
+ /**
25
+ * Parse all markdown-encoded emojis in a string.
26
+ */
27
+ export const emojify = (
28
+ input: string,
29
+ { fallback, format = name => name }: EmojifyOptions = {},
30
+ ) => {
31
+ const fallbackFunction =
32
+ fallback === undefined ? fallback : asFunction(fallback)
33
+
34
+ is.assert.string(input)
35
+ is.assert.any([is.default.undefined, is.default.function_], fallbackFunction)
36
+ is.assert.function_(format)
37
+
38
+ return input.replace(/:[\w\-+]+:/g, part => {
39
+ const found = findByName(part)
40
+ if (found) {
41
+ return format(found.emoji, part, input)
42
+ }
43
+
44
+ if (fallbackFunction) {
45
+ return format(fallbackFunction(normalizeName(part)))
46
+ }
47
+
48
+ return format(part)
49
+ })
50
+ }
@@ -0,0 +1,4 @@
1
+ // Types for emojilib@v2
2
+ declare module 'emojilib' {
3
+ export const lib: Record<string, { char: string }>
4
+ }
@@ -0,0 +1,29 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { find } from './find.js'
4
+
5
+ describe('find', () => {
6
+ it('returns an emoji when given a name', () => {
7
+ expect(find('heart')).toEqual({ emoji: '❀️', key: 'heart' })
8
+ })
9
+
10
+ it('returns an emoji when given a :name:', () => {
11
+ expect(find(':heart:')).toEqual({ emoji: '❀️', key: 'heart' })
12
+ })
13
+
14
+ it('returns an emoji when given a code', () => {
15
+ expect(find('❀')).toEqual({ emoji: '❀', key: 'heart' })
16
+ })
17
+
18
+ it('returns the base emoji when given an alternate emoji code', () => {
19
+ expect(find('❀️')).toEqual({ emoji: '❀', key: 'heart' })
20
+ })
21
+
22
+ it('returns undefined when given an unknown name', () => {
23
+ expect(find('unknown_emoji')).toBeUndefined()
24
+ })
25
+
26
+ it('returns undefined when given an unknown :name:', () => {
27
+ expect(find('unknown_emoji')).toBeUndefined()
28
+ })
29
+ })
package/src/find.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { findByCode } from './findByCode.js'
2
+ import { findByName } from './findByName.js'
3
+
4
+ /**
5
+ * Get the name and character of an emoji.
6
+ */
7
+ export const find = (codeOrName: string) => {
8
+ return findByCode(codeOrName) ?? findByName(codeOrName)
9
+ }
@@ -0,0 +1,21 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { findByCode } from './findByCode.js'
4
+
5
+ describe('findByCode', () => {
6
+ it('returns undefined when given a name', () => {
7
+ expect(findByCode('heart')).toBeUndefined()
8
+ })
9
+
10
+ it('returns undefined when given a :name:', () => {
11
+ expect(findByCode(':heart:')).toBeUndefined()
12
+ })
13
+
14
+ it('returns the emoji when given an emoji code', () => {
15
+ expect(findByCode('❀')).toEqual({ emoji: '❀', key: 'heart' })
16
+ })
17
+
18
+ it('returns the base emoji when given an alternate emoji code', () => {
19
+ expect(findByCode('❀️')).toEqual({ emoji: '❀', key: 'heart' })
20
+ })
21
+ })
@@ -0,0 +1,13 @@
1
+ import { assert } from '@sindresorhus/is'
2
+
3
+ import { emojiNamesByCode } from './data.js'
4
+ import { normalizeCode } from './utils.js'
5
+
6
+ export const findByCode = (code: string) => {
7
+ assert.string(code)
8
+
9
+ const emojiNormalized = normalizeCode(code)
10
+ const key = emojiNamesByCode.get(emojiNormalized)
11
+
12
+ return key ? { emoji: emojiNormalized, key } : undefined
13
+ }
@@ -0,0 +1,29 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { findByName } from './findByName.js'
4
+
5
+ describe('findByName', () => {
6
+ it('returns an emoji when given a name', () => {
7
+ expect(findByName('heart')).toEqual({ emoji: '❀️', key: 'heart' })
8
+ })
9
+
10
+ it('returns an emoji when given a :name:', () => {
11
+ expect(findByName(':heart:')).toEqual({ emoji: '❀️', key: 'heart' })
12
+ })
13
+
14
+ it('returns undefined when given an emoji code', () => {
15
+ expect(findByName('❀')).toBeUndefined()
16
+ })
17
+
18
+ it('returns undefined when given an alternate emoji code', () => {
19
+ expect(findByName('❀️')).toBeUndefined()
20
+ })
21
+
22
+ it('returns undefined when given an unknown name', () => {
23
+ expect(findByName('unknown_emoji')).toBeUndefined()
24
+ })
25
+
26
+ it('returns undefined when given an unknown :name:', () => {
27
+ expect(findByName('unknown_emoji')).toBeUndefined()
28
+ })
29
+ })
@@ -0,0 +1,13 @@
1
+ import { assert } from '@sindresorhus/is'
2
+
3
+ import { emojiCodesByName } from './data.js'
4
+ import { normalizeName } from './utils.js'
5
+
6
+ export const findByName = (name: string) => {
7
+ assert.string(name)
8
+
9
+ const nameNormalized = normalizeName(name)
10
+ const emoji = emojiCodesByName.get(nameNormalized)
11
+
12
+ return emoji ? { emoji, key: nameNormalized } : undefined
13
+ }
@@ -0,0 +1,21 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { get } from './get.js'
4
+
5
+ describe('get', () => {
6
+ it('returns an emoji code when given a string', () => {
7
+ expect(get('coffee')).toBe('β˜•')
8
+ })
9
+
10
+ it('returns the contained emoji code when given markdown emoji', () => {
11
+ expect(get(':coffee:')).toBe('β˜•')
12
+ })
13
+
14
+ it('returns undefined when given an emoji', () => {
15
+ expect(get('πŸ‘―')).toBeUndefined()
16
+ })
17
+
18
+ it('returns undefined when given an unknown word', () => {
19
+ expect(get('unknown')).toBeUndefined()
20
+ })
21
+ })
package/src/get.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { assert } from '@sindresorhus/is'
2
+
3
+ import { emojiCodesByName } from './data.js'
4
+ import { normalizeName } from './utils.js'
5
+
6
+ /**
7
+ * Get an emoji from an emoji name.
8
+ */
9
+ export const get = (codeOrName: string) => {
10
+ assert.string(codeOrName)
11
+
12
+ return emojiCodesByName.get(normalizeName(codeOrName))
13
+ }
@@ -0,0 +1,37 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { has } from './has.js'
4
+
5
+ describe('has', () => {
6
+ it('returns true when given an emoji', () => {
7
+ expect(has('β˜•')).toBe(true)
8
+ })
9
+
10
+ it('returns true when given the name of an emoji', () => {
11
+ expect(has('coffee')).toBe(true)
12
+ })
13
+
14
+ it('returns true when given a markdown emoji name', () => {
15
+ expect(has(':coffee:')).toBe(true)
16
+ })
17
+
18
+ it('returns false when given unrelated text', () => {
19
+ expect(has('nonexistent')).toBe(false)
20
+ })
21
+
22
+ it('returns false when given an unknown markdown name', () => {
23
+ expect(has(':nonexistent:')).toBe(false)
24
+ })
25
+
26
+ it('returns true when given a emoji in base form', () => {
27
+ expect(has('❀️')).toBe(true)
28
+ })
29
+
30
+ it('returns true when given an emoji in code text form', () => {
31
+ expect(has('❀')).toBe(true)
32
+ })
33
+
34
+ it('returns false when given multiple emoji codes', () => {
35
+ expect(has('πŸ•β€οΈβ€πŸ’‹β€β˜•')).toBe(false)
36
+ })
37
+ })
package/src/has.ts ADDED
@@ -0,0 +1,16 @@
1
+ import { assert } from '@sindresorhus/is'
2
+
3
+ import { emojiCodesByName, emojiNamesByCode } from './data.js'
4
+ import { normalizeCode, normalizeName } from './utils.js'
5
+
6
+ /**
7
+ * Check if this library supports a specific emoji.
8
+ */
9
+ export const has = (codeOrName: string) => {
10
+ assert.string(codeOrName)
11
+
12
+ return (
13
+ emojiCodesByName.has(normalizeName(codeOrName)) ||
14
+ emojiNamesByCode.has(normalizeCode(codeOrName))
15
+ )
16
+ }
package/src/index.ts ADDED
@@ -0,0 +1,10 @@
1
+ export * from './emojify.js'
2
+ export * from './find.js'
3
+ export * from './get.js'
4
+ export * from './has.js'
5
+ export * from './random.js'
6
+ export * from './replace.js'
7
+ export * from './search.js'
8
+ export * from './strip.js'
9
+ export * from './unemojify.js'
10
+ export * from './which.js'
@@ -0,0 +1,14 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { get } from './get.js'
4
+ import { has } from './has.js'
5
+ import { random } from './random.js'
6
+
7
+ describe('random', () => {
8
+ it('returns a random emoji and the corresponding key', () => {
9
+ const result = random()
10
+
11
+ expect(has(result.name)).toBe(true)
12
+ expect(result.emoji).toBe(get(result.name))
13
+ })
14
+ })
package/src/random.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { emojiData } from './data.js'
2
+ import { randomItem } from './utils.js'
3
+
4
+ /**
5
+ * Get a random emoji.
6
+ */
7
+ export const random = () => {
8
+ const [name, emoji] = randomItem(emojiData)
9
+ return { emoji, name }
10
+ }
@@ -0,0 +1,64 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { replace } from './replace.js'
4
+
5
+ describe('replace', () => {
6
+ it('returns an empty string when given an empty string', () => {
7
+ expect(replace('', 'b')).toBe('')
8
+ })
9
+
10
+ it('returns the input text when given text without emojis', () => {
11
+ expect(replace('no emojis', 'b')).toBe('no emojis')
12
+ })
13
+
14
+ it('returns a single emoji replacement when given text with one emoji', () => {
15
+ expect(replace('a β˜• c', 'b')).toBe('a bc')
16
+ })
17
+
18
+ it('returns multiple emoji replacement when given text with multiple emojis', () => {
19
+ expect(replace('a β˜• c πŸ• d', 'b')).toBe('a bc bd')
20
+ })
21
+
22
+ it('preserves spaces around emojis when preserveSpaces is true', () => {
23
+ expect(replace('a β˜• c πŸ• d', 'b', { preserveSpaces: true })).toBe(
24
+ 'a b c b d',
25
+ )
26
+ })
27
+
28
+ it('replaces with the replacer when given a replacer', () => {
29
+ expect(replace('a 🌭 c', ({ emoji }) => `>${emoji}<`)).toBe('a >🌭<c')
30
+ })
31
+
32
+ it('replaces with the replacer and preserves spaces when given a replacer and preserveSpaces', () => {
33
+ expect(
34
+ replace('a 🌭 c', ({ emoji }) => `>${emoji}<`, {
35
+ preserveSpaces: true,
36
+ }),
37
+ ).toBe('a >🌭< c')
38
+ })
39
+
40
+ it('calls the replacer again when given multiple emojis', () => {
41
+ expect(
42
+ replace(
43
+ 'a 🌭 b 🌭 πŸ΅β˜• c',
44
+ (() => {
45
+ let counter = 0
46
+ const letters = ['w', 'x', 'y', 'z']
47
+ return () => letters[counter++]
48
+ })(),
49
+ ),
50
+ ).toBe('a wb xyzc') // cspell:disable-line
51
+ })
52
+
53
+ it('strips complex emojis', () => {
54
+ expect(replace('before πŸ‘©β€β€οΈβ€πŸ’‹β€πŸ‘© after', '')).toBe('before after')
55
+ })
56
+
57
+ it('strips flag emojis', () => {
58
+ expect(replace('There is no flag πŸ‡²πŸ‡½', '')).toBe('There is no flag ')
59
+ })
60
+
61
+ it('ignores known existing complex emojis', () => {
62
+ expect(replace('Some πŸ•β€οΈβ€πŸ’‹β€β˜• emoji', '')).toBe('Some β€οΈβ€πŸ’‹β€β˜• emoji')
63
+ })
64
+ })
package/src/replace.ts ADDED
@@ -0,0 +1,46 @@
1
+ import { assert } from '@sindresorhus/is'
2
+
3
+ import { Emoji } from './data.js'
4
+ import { findByCode } from './findByCode.js'
5
+ import { asFunction, charRegexMatcher } from './utils.js'
6
+
7
+ export type ReplaceReplacement = (
8
+ emoji: Emoji,
9
+ index: number,
10
+ string: string,
11
+ ) => string
12
+
13
+ /**
14
+ * Replace the emojis in a string.
15
+ */
16
+ export const replace = (
17
+ input: string,
18
+ replacement: ReplaceReplacement | string,
19
+ { preserveSpaces = false } = {},
20
+ ) => {
21
+ const replace = asFunction(replacement)
22
+
23
+ assert.string(input)
24
+ assert.function_(replace)
25
+ assert.boolean(preserveSpaces)
26
+
27
+ const characters = input.match(charRegexMatcher)
28
+ if (characters === null) {
29
+ return input
30
+ }
31
+
32
+ return characters
33
+ .map((character, index) => {
34
+ const found = findByCode(character)
35
+ if (!found) {
36
+ return character
37
+ }
38
+
39
+ if (!preserveSpaces && characters[index + 1] === ' ') {
40
+ characters[index + 1] = ''
41
+ }
42
+
43
+ return replace(found, index, input)
44
+ })
45
+ .join('')
46
+ }
@@ -0,0 +1,73 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { search } from './search.js'
4
+
5
+ describe('search', () => {
6
+ it('returns a single pair when given a one-of emoji name', () => {
7
+ expect(search('100')).toEqual([{ emoji: 'πŸ’―', name: '100' }])
8
+ })
9
+
10
+ it('returns a single pair when given one-of emoji name as regular expression', () => {
11
+ expect(search(/100/)).toEqual([{ emoji: 'πŸ’―', name: '100' }])
12
+ })
13
+
14
+ it('returns multiple emojis when given a common substring', () => {
15
+ expect(search('cartwheel')).toEqual([
16
+ {
17
+ emoji: 'πŸ€Έβ€β™€οΈ',
18
+ name: 'woman_cartwheeling',
19
+ },
20
+ {
21
+ emoji: 'πŸ€Έβ€β™‚οΈ',
22
+ name: 'man_cartwheeling',
23
+ },
24
+ ])
25
+ })
26
+
27
+ it('returns multiple emojis when given a common regular expression', () => {
28
+ expect(search(/cartwheel/)).toEqual([
29
+ {
30
+ emoji: 'πŸ€Έβ€β™€οΈ',
31
+ name: 'woman_cartwheeling',
32
+ },
33
+ {
34
+ emoji: 'πŸ€Έβ€β™‚οΈ',
35
+ name: 'man_cartwheeling',
36
+ },
37
+ ])
38
+ })
39
+
40
+ it('should match when you include the colon', () => {
41
+ expect(search(':cartwheel:')).toEqual([
42
+ {
43
+ emoji: 'πŸ€Έβ€β™€οΈ',
44
+ name: 'woman_cartwheeling',
45
+ },
46
+ {
47
+ emoji: 'πŸ€Έβ€β™‚οΈ',
48
+ name: 'man_cartwheeling',
49
+ },
50
+ ])
51
+ })
52
+
53
+ it('should match when you include the colon in the regular expression', () => {
54
+ expect(search(/:cartwheel:/)).toEqual([
55
+ {
56
+ emoji: 'πŸ€Έβ€β™€οΈ',
57
+ name: 'woman_cartwheeling',
58
+ },
59
+ {
60
+ emoji: 'πŸ€Έβ€β™‚οΈ',
61
+ name: 'man_cartwheeling',
62
+ },
63
+ ])
64
+ })
65
+
66
+ it('returns an empty array when no matching emojis are found for a string search', () => {
67
+ expect(search('notAnEmoji')).toEqual([])
68
+ })
69
+
70
+ it('returns an empty array when no matching emojis are found for a regular expression search', () => {
71
+ expect(search(/notAnEmoji/)).toEqual([])
72
+ })
73
+ })
package/src/search.ts ADDED
@@ -0,0 +1,24 @@
1
+ import is, { assert } from '@sindresorhus/is'
2
+
3
+ import { emojiData } from './data.js'
4
+ import { normalizeName } from './utils.js'
5
+
6
+ /**
7
+ * Search for emojis containing the provided name or pattern in their name.
8
+ */
9
+ export const search = (keyword: RegExp | string) => {
10
+ assert.any([is.default.string, is.default.regExp], keyword)
11
+
12
+ if (is.default.string(keyword)) {
13
+ keyword = normalizeName(keyword)
14
+ }
15
+
16
+ if (is.default.regExp(keyword)) {
17
+ const normalizedPattern = normalizeName(keyword.source)
18
+ keyword = new RegExp(normalizedPattern)
19
+ }
20
+
21
+ return emojiData
22
+ .filter(([name]) => name.match(keyword))
23
+ .map(([name, emoji]) => ({ emoji, name }))
24
+ }
@@ -0,0 +1,25 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { strip } from './strip.js'
4
+
5
+ describe('strip', () => {
6
+ it('returns an empty string when given an empty string', () => {
7
+ expect(strip('')).toBe('')
8
+ })
9
+
10
+ it('returns an the input string when given a string with no emojis', () => {
11
+ expect(strip('abc')).toBe('abc')
12
+ })
13
+
14
+ it('returns an input string with an emoji removed when given an input string with one emoji', () => {
15
+ expect(strip('a β˜• c')).toBe('a c')
16
+ })
17
+
18
+ it('returns an input string with multiple emojis removed when given an input string with multiple emojis', () => {
19
+ expect(strip('a β˜• b πŸ• c')).toBe('a b c')
20
+ })
21
+
22
+ it('preserves spaces around emoji when preserveSpaces is true', () => {
23
+ expect(strip('a β˜• c', { preserveSpaces: true })).toBe('a c')
24
+ })
25
+ })
package/src/strip.ts ADDED
@@ -0,0 +1,14 @@
1
+ import { replace } from './replace.js'
2
+
3
+ export interface StripOptions {
4
+ /**
5
+ * Whether to keep the extra space after a stripped emoji.
6
+ */
7
+ preserveSpaces?: boolean
8
+ }
9
+
10
+ /**
11
+ * Remove all the emojis from a string.
12
+ */
13
+ export const strip = (input: string, { preserveSpaces }: StripOptions = {}) =>
14
+ replace(input, '', { preserveSpaces })
@@ -0,0 +1,43 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { unemojify } from './unemojify.js'
4
+
5
+ describe('unemojify', () => {
6
+ it('returns a blank string when given a blank string', () => {
7
+ expect(unemojify('')).toBe('')
8
+ })
9
+
10
+ it('returns a replaced emoji name when given a string with one emoji', () => {
11
+ expect(unemojify('a β˜• c')).toBe('a :coffee: c')
12
+ })
13
+
14
+ it('returns multiple replaced emoji names when given a string with multiple emojis', () => {
15
+ expect(unemojify('a β˜• 🌭 c')).toBe('a :coffee: :hotdog: c')
16
+ })
17
+
18
+ it('returns a complex emoji name when given a complex emoji:', () => {
19
+ expect(unemojify('before πŸ‘©β€β€οΈβ€πŸ’‹β€πŸ‘© after')).toBe(
20
+ 'before :couplekiss_woman_woman: after',
21
+ )
22
+ })
23
+
24
+ it('parses emojis with names next to non-space characters', () => {
25
+ expect(unemojify('I ❀️ β˜•οΈ! - 😯⭐️😍 ::: test : : πŸ‘+')).toBe(
26
+ 'I :heart: :coffee:! - :hushed::star::heart_eyes: ::: test : : :+1:+',
27
+ )
28
+ })
29
+
30
+ it('ignores only unknown emoji when given a string with some valid, some unknown emojis', () => {
31
+ // Emoji :melting_face: (U+1FAE0) Unicode 14.0 draft: https://emojipedia.org/unicode-14.0
32
+ expect(unemojify('I ⭐️ :another_one: 🫠')).toBe(
33
+ 'I :star: :another_one: 🫠',
34
+ )
35
+ })
36
+
37
+ // see issue #21
38
+ it('should parse flags correctly', () => {
39
+ expect(unemojify('The flags of πŸ‡²πŸ‡½ and πŸ‡²πŸ‡¦ are not the same')).toBe(
40
+ 'The flags of :mexico: and :morocco: are not the same',
41
+ )
42
+ })
43
+ })
@@ -0,0 +1,20 @@
1
+ import { assert } from '@sindresorhus/is'
2
+
3
+ import { charRegexMatcher } from './utils.js'
4
+ import { which } from './which.js'
5
+
6
+ /**
7
+ * Convert all emojis in a string to their markdown-encoded counterparts.
8
+ */
9
+ export const unemojify = (input: string) => {
10
+ assert.string(input)
11
+
12
+ const characters = input.match(charRegexMatcher)
13
+ if (characters === null) {
14
+ return input
15
+ }
16
+
17
+ return characters
18
+ .map(character => which(character, { markdown: true }) ?? character)
19
+ .join('')
20
+ }