import toArray from 'lodash.toarray'
import rawEmojisBase from './data/raw-emojis-base.js'
import rawEmojisCustom from './data/raw-emojis-custom.js'
import rawEmojisOverwrite from './data/raw-emojis-overwrite.js'
import messages from './data/messages.js'
import skinTones from './data/skin-tones.js'
export { default as emoji_categories } from './emoji_categories.json' with { type: 'json' }
const CATEGORY_RECENTS = 'recents'
const CATEGORY_CUSTOM = 'custom'
const dataByShortCode = new Map()
const dataByEmoji = new Map()
const dataByHex = new Map()
const customEmojisData = []
const allEmojisData = []
const allEmojisDataByTone = {}
const categories = []
const normalizeEmoji = (raw, { emojisPath }) => {
const { path, pathRiv, ...rest } = raw
const result = { ...rest }
if (path) {
result.url = `${emojisPath}${path}`
}
if (pathRiv) {
result.urlRiv = `${emojisPath}${pathRiv}`
}
return result
}
function fill(emojiData) {
for (const shortCode of emojiData.shortCodes) {
dataByShortCode.set(shortCode, emojiData)
}
dataByEmoji.set(emojiData.emoji, emojiData)
dataByHex.set(emojiData.hexcode, emojiData)
emojiData.skins?.forEach(fill)
}
function flatSlice(hits, maxResults) {
const result = []
for (const hit of hits) {
for (const emoji of hit) {
result.push(emoji)
if (result.length >= maxResults) {
break
}
}
if (result.length >= maxResults) {
break
}
}
return result
}
export function initEmojis({ emojisPath = '/assets/emojis/' }) {
rawEmojisCustom.forEach((raw) => {
const customEmojiData = normalizeEmoji(raw, { emojisPath })
const data = { ...customEmojiData, custom: true }
fill(data)
customEmojisData.push(data)
allEmojisData.push(data)
})
rawEmojisBase.forEach((emojiData) => {
if (rawEmojisOverwrite[emojiData.hexcode]) {
emojiData = { ...emojiData, ...rawEmojisOverwrite[emojiData.hexcode] }
}
fill(emojiData)
allEmojisData.push(emojiData)
})
categories.push(CATEGORY_RECENTS)
categories.push(CATEGORY_CUSTOM)
messages.groups.forEach(({ key }) => categories.push(key))
}
export function getEmojiData(any) {
return dataByHex.get(any) || dataByShortCode.get(any) || dataByEmoji.get(any)
}
export function getDataOfSkin(tone) {
if (!tone) return allEmojisData
if (!allEmojisDataByTone[tone]) {
allEmojisDataByTone[tone] = allEmojisData.map((emoji) => {
return emoji.skins?.find(skin => skin.tone === tone) || emoji
})
}
return allEmojisDataByTone[tone]
}
export function emojify(text, format) {
return text
.split(/:([a-zA-Z0-9_\-+]+):/g)
.map((string, index) => {
if (index % 2 === 0) {
return string
}
if (!dataByShortCode.has(string)) {
return `:${string}:`
}
const emojiData = dataByShortCode.get(string)
const { emoji, alt } = emojiData
if (format) {
return format(emoji, string, emojiData)
}
return alt || emoji
})
.join('')
}
export function unemojify(text) {
return toArray(text)
.map((char) => {
if (dataByEmoji.has(char)) {
return `:${dataByEmoji.get(char).shortCodes[0]}:`
}
const hex = char.codePointAt(0).toString(16).toUpperCase()
if (dataByHex.has(hex)) {
return `:${dataByHex.get(hex).shortCodes[0]}:`
}
return char
})
.join('')
}
export function getAllEmojisData() {
return allEmojisData
}
export function getCustomEmojisData() {
return customEmojisData
}
export function getEmojiMessages() {
return messages
}
export function getCategories() {
return categories
}
export function getSkinTones() {
return skinTones
}
export const emojiSearch = (data, termSearch, maxResults = 20) => {
if (!termSearch) return data.slice(0, maxResults)
const term = termSearch.toLowerCase()
const termWithPrefix = `:${term}`
const hits = [[], [], [], [], []]
for (const emoji of data) {
const { shortCodes = [], emoticon = [], tags = [] } = emoji
const emoticons = Array.isArray(emoticon) ? emoticon : [emoticon]
let prio = -1
if (shortCodes.some((code) => code === term) || emoticons.some((code) => code === termWithPrefix)) {
prio = 0
} else if (shortCodes.some((code) => code.startsWith(term))) {
prio = 1
} else if (shortCodes.some((code) => code.includes(term))) {
prio = 2
} else if (tags.some((tag) => tag.startsWith(term))) {
prio = 3
} else if (tags.some((tag) => tag.includes(term))) {
prio = 4
}
if (prio !== -1) {
hits[prio].push(emoji)
}
}
return flatSlice(hits, maxResults)
}