react-emoji-text 1.0.0-alpha.0
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.
- package/LICENSE +21 -0
- package/README.md +408 -0
- package/dist/adapters/emoji-mart.cjs +9 -0
- package/dist/adapters/emoji-mart.d.cts +7 -0
- package/dist/adapters/emoji-mart.d.cts.map +1 -0
- package/dist/adapters/emoji-mart.d.mts +7 -0
- package/dist/adapters/emoji-mart.d.mts.map +1 -0
- package/dist/adapters/emoji-mart.mjs +10 -0
- package/dist/adapters/emoji-mart.mjs.map +1 -0
- package/dist/adapters/emojibase.cjs +71 -0
- package/dist/adapters/emojibase.d.cts +38 -0
- package/dist/adapters/emojibase.d.cts.map +1 -0
- package/dist/adapters/emojibase.d.mts +38 -0
- package/dist/adapters/emojibase.d.mts.map +1 -0
- package/dist/adapters/emojibase.mjs +72 -0
- package/dist/adapters/emojibase.mjs.map +1 -0
- package/dist/compat/index.cjs +93 -0
- package/dist/compat/index.d.cts +32 -0
- package/dist/compat/index.d.cts.map +1 -0
- package/dist/compat/index.d.mts +32 -0
- package/dist/compat/index.d.mts.map +1 -0
- package/dist/compat/index.mjs +90 -0
- package/dist/compat/index.mjs.map +1 -0
- package/dist/core.cjs +10 -0
- package/dist/core.d.cts +4 -0
- package/dist/core.d.mts +4 -0
- package/dist/core.mjs +2 -0
- package/dist/index-B39vk6JI.d.mts +23 -0
- package/dist/index-B39vk6JI.d.mts.map +1 -0
- package/dist/index-DPd10zCJ.d.cts +23 -0
- package/dist/index-DPd10zCJ.d.cts.map +1 -0
- package/dist/index-DXKnU6tZ.d.cts +398 -0
- package/dist/index-DXKnU6tZ.d.cts.map +1 -0
- package/dist/index-UT6qWHp1.d.mts +398 -0
- package/dist/index-UT6qWHp1.d.mts.map +1 -0
- package/dist/index.cjs +18 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.mjs +5 -0
- package/dist/indexes-3fK5ySH8.d.cts +20 -0
- package/dist/indexes-3fK5ySH8.d.cts.map +1 -0
- package/dist/indexes-BMCSN-X0.d.mts +20 -0
- package/dist/indexes-BMCSN-X0.d.mts.map +1 -0
- package/dist/react/index.cjs +8 -0
- package/dist/react/index.d.cts +2 -0
- package/dist/react/index.d.mts +2 -0
- package/dist/react/index.mjs +3 -0
- package/dist/react-9EdWn0Gg.mjs +196 -0
- package/dist/react-9EdWn0Gg.mjs.map +1 -0
- package/dist/react-C8xGkPhi.cjs +211 -0
- package/dist/render-C7VPZ7if.cjs +140 -0
- package/dist/render-DzloPAWX.mjs +119 -0
- package/dist/render-DzloPAWX.mjs.map +1 -0
- package/dist/tokenize-BUKMZ9Yg.mjs +313 -0
- package/dist/tokenize-BUKMZ9Yg.mjs.map +1 -0
- package/dist/tokenize-CyKMb3O9.cjs +364 -0
- package/dist/types-Dyzdpq-R.d.cts +92 -0
- package/dist/types-Dyzdpq-R.d.cts.map +1 -0
- package/dist/types-o0mRO30y.d.mts +92 -0
- package/dist/types-o0mRO30y.d.mts.map +1 -0
- package/package.json +108 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-DzloPAWX.mjs","names":[],"sources":["../src/react/image-url.ts","../src/react/keys.ts","../src/react/render.tsx"],"sourcesContent":["import type { GetImageUrl, SpriteConfig } from '../core/types';\n\nexport interface ResolveImageUrlOptions {\n getImageUrl?: GetImageUrl;\n imageUrlTemplate?: string;\n sprite?: SpriteConfig;\n}\n\nfunction interpolateTemplate(template: string, values: Record<string, string>) {\n return Object.entries(values).reduce(\n (result, [key, value]) => result.split(`{${key}}`).join(value),\n template,\n );\n}\n\nexport function resolveImageUrlFn({\n getImageUrl,\n sprite,\n imageUrlTemplate,\n}: ResolveImageUrlOptions): GetImageUrl | undefined {\n if (getImageUrl) return getImageUrl;\n if (sprite) return undefined;\n if (!imageUrlTemplate) return undefined;\n\n return (_emoji, context) =>\n interpolateTemplate(imageUrlTemplate, {\n set: context.set,\n skin: String(context.skin),\n unified: context.unified,\n });\n}\n","import type { Token } from '../core/types';\n\nfunction tokenKeyBase(token: Token): string {\n switch (token.type) {\n case 'text':\n return `text:${token.value}`;\n case 'unknown':\n return `unknown:${token.match}`;\n case 'emoji':\n return [\n 'emoji',\n token.emoji.id,\n token.source,\n token.shortcode ?? '',\n token.match,\n token.native,\n ].join(':');\n }\n}\n\nexport function createTokenKeyFactory() {\n const seen = new Map<string, number>();\n\n return (token: Token) => {\n const base = tokenKeyBase(token);\n const occurrence = seen.get(base) ?? 0;\n seen.set(base, occurrence + 1);\n return occurrence === 0 ? base : `${base}:${occurrence}`;\n };\n}\n","'use client';\n\nimport type { ReactNode } from 'react';\nimport type {\n EmojiImageContext,\n EmojiSet,\n EmojiSkin,\n EmojiToken,\n GetImageUrl,\n SpriteConfig,\n Token,\n UnknownToken,\n} from '../core/types';\n\nexport interface DefaultRenderOptions {\n set: EmojiSet;\n getImageUrl?: GetImageUrl;\n sprite?: SpriteConfig;\n emojiClassName?: string;\n}\n\nexport function renderTokenDefault(token: Token, options: DefaultRenderOptions): ReactNode {\n switch (token.type) {\n case 'text':\n return token.value;\n case 'emoji':\n return renderEmojiDefault(token, options);\n case 'unknown':\n return renderUnknownDefault(token);\n }\n}\n\nfunction renderEmojiDefault(token: EmojiToken, options: DefaultRenderOptions): ReactNode {\n if (token.source === 'custom') {\n const src = token.emoji.skins[0]?.src;\n if (!src) return token.match;\n\n return (\n <img\n src={src}\n alt={token.shortcode ?? token.emoji.id}\n className={options.emojiClassName}\n style={emojiImageStyle}\n />\n );\n }\n\n if (options.set === 'native') {\n return token.native;\n }\n\n const skinEntry = getResolvedSkinEntry(token);\n\n if (options.getImageUrl) {\n const context: EmojiImageContext = {\n set: options.set,\n skin: token.skin ?? 1,\n unified: skinEntry?.unified ?? '',\n };\n const src = options.getImageUrl(token.emoji, context);\n\n return (\n <img\n src={src}\n alt={token.native}\n className={options.emojiClassName}\n style={emojiImageStyle}\n />\n );\n }\n\n if (options.sprite && skinEntry) {\n return renderSpriteEmoji(token, skinEntry, options.sprite, options.emojiClassName);\n }\n\n return token.native;\n}\n\nfunction getResolvedSkinEntry(token: EmojiToken): EmojiSkin | undefined {\n if (token.skin) {\n return token.emoji.skins[token.skin - 1] ?? token.emoji.skins[0];\n }\n\n return token.emoji.skins.find((skin) => skin.native === token.native) ?? token.emoji.skins[0];\n}\n\nfunction findSpriteCoordinates(\n sprite: SpriteConfig,\n unified: string,\n): { x: number; y: number } | undefined {\n return (\n sprite.sheet[unified] ??\n sprite.sheet[unified.toLowerCase()] ??\n sprite.sheet[unified.toUpperCase()]\n );\n}\n\nfunction renderSpriteEmoji(\n token: EmojiToken,\n skinEntry: EmojiSkin,\n sprite: SpriteConfig,\n emojiClassName?: string,\n): ReactNode {\n const coordinates = findSpriteCoordinates(sprite, skinEntry.unified);\n if (!coordinates) return token.native;\n\n return (\n <span\n role=\"img\"\n aria-label={token.native}\n className={emojiClassName}\n style={{\n backgroundImage: `url(${sprite.src})`,\n backgroundPosition: `-${coordinates.x * sprite.size}px -${coordinates.y * sprite.size}px`,\n backgroundSize: `${sprite.columns * sprite.size}px auto`,\n display: 'inline-block',\n height: `${sprite.size}px`,\n verticalAlign: '-0.1em',\n width: `${sprite.size}px`,\n }}\n />\n );\n}\n\nfunction renderUnknownDefault(token: UnknownToken): ReactNode {\n return token.match;\n}\n\nconst emojiImageStyle = {\n display: 'inline',\n height: '1em',\n verticalAlign: '-0.1em',\n width: '1em',\n};\n\nexport function isOnlyEmoji(tokens: Token[]): boolean {\n return (\n tokens.some((token) => token.type === 'emoji') &&\n tokens.every(\n (token) => token.type === 'emoji' || (token.type === 'text' && token.value.trim() === ''),\n )\n );\n}\n"],"mappings":";;AAQA,SAAS,oBAAoB,UAAkB,QAAgC;AAC7E,QAAO,OAAO,QAAQ,OAAO,CAAC,QAC3B,QAAQ,CAAC,KAAK,WAAW,OAAO,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,MAAM,EAC9D,SACD;;AAGH,SAAgB,kBAAkB,EAChC,aACA,QACA,oBACkD;AAClD,KAAI,YAAa,QAAO;AACxB,KAAI,OAAQ,QAAO,KAAA;AACnB,KAAI,CAAC,iBAAkB,QAAO,KAAA;AAE9B,SAAQ,QAAQ,YACd,oBAAoB,kBAAkB;EACpC,KAAK,QAAQ;EACb,MAAM,OAAO,QAAQ,KAAK;EAC1B,SAAS,QAAQ;EAClB,CAAC;;;;AC3BN,SAAS,aAAa,OAAsB;AAC1C,SAAQ,MAAM,MAAd;EACE,KAAK,OACH,QAAO,QAAQ,MAAM;EACvB,KAAK,UACH,QAAO,WAAW,MAAM;EAC1B,KAAK,QACH,QAAO;GACL;GACA,MAAM,MAAM;GACZ,MAAM;GACN,MAAM,aAAa;GACnB,MAAM;GACN,MAAM;GACP,CAAC,KAAK,IAAI;;;AAIjB,SAAgB,wBAAwB;CACtC,MAAM,uBAAO,IAAI,KAAqB;AAEtC,SAAQ,UAAiB;EACvB,MAAM,OAAO,aAAa,MAAM;EAChC,MAAM,aAAa,KAAK,IAAI,KAAK,IAAI;AACrC,OAAK,IAAI,MAAM,aAAa,EAAE;AAC9B,SAAO,eAAe,IAAI,OAAO,GAAG,KAAK,GAAG;;;;;ACNhD,SAAgB,mBAAmB,OAAc,SAA0C;AACzF,SAAQ,MAAM,MAAd;EACE,KAAK,OACH,QAAO,MAAM;EACf,KAAK,QACH,QAAO,mBAAmB,OAAO,QAAQ;EAC3C,KAAK,UACH,QAAO,qBAAqB,MAAM;;;AAIxC,SAAS,mBAAmB,OAAmB,SAA0C;AACvF,KAAI,MAAM,WAAW,UAAU;EAC7B,MAAM,MAAM,MAAM,MAAM,MAAM,IAAI;AAClC,MAAI,CAAC,IAAK,QAAO,MAAM;AAEvB,SACE,oBAAC,OAAD;GACO;GACL,KAAK,MAAM,aAAa,MAAM,MAAM;GACpC,WAAW,QAAQ;GACnB,OAAO;GACP,CAAA;;AAIN,KAAI,QAAQ,QAAQ,SAClB,QAAO,MAAM;CAGf,MAAM,YAAY,qBAAqB,MAAM;AAE7C,KAAI,QAAQ,aAAa;EACvB,MAAM,UAA6B;GACjC,KAAK,QAAQ;GACb,MAAM,MAAM,QAAQ;GACpB,SAAS,WAAW,WAAW;GAChC;AAGD,SACE,oBAAC,OAAD;GACE,KAJQ,QAAQ,YAAY,MAAM,OAAO,QAIjC;GACR,KAAK,MAAM;GACX,WAAW,QAAQ;GACnB,OAAO;GACP,CAAA;;AAIN,KAAI,QAAQ,UAAU,UACpB,QAAO,kBAAkB,OAAO,WAAW,QAAQ,QAAQ,QAAQ,eAAe;AAGpF,QAAO,MAAM;;AAGf,SAAS,qBAAqB,OAA0C;AACtE,KAAI,MAAM,KACR,QAAO,MAAM,MAAM,MAAM,MAAM,OAAO,MAAM,MAAM,MAAM,MAAM;AAGhE,QAAO,MAAM,MAAM,MAAM,MAAM,SAAS,KAAK,WAAW,MAAM,OAAO,IAAI,MAAM,MAAM,MAAM;;AAG7F,SAAS,sBACP,QACA,SACsC;AACtC,QACE,OAAO,MAAM,YACb,OAAO,MAAM,QAAQ,aAAa,KAClC,OAAO,MAAM,QAAQ,aAAa;;AAItC,SAAS,kBACP,OACA,WACA,QACA,gBACW;CACX,MAAM,cAAc,sBAAsB,QAAQ,UAAU,QAAQ;AACpE,KAAI,CAAC,YAAa,QAAO,MAAM;AAE/B,QACE,oBAAC,QAAD;EACE,MAAK;EACL,cAAY,MAAM;EAClB,WAAW;EACX,OAAO;GACL,iBAAiB,OAAO,OAAO,IAAI;GACnC,oBAAoB,IAAI,YAAY,IAAI,OAAO,KAAK,MAAM,YAAY,IAAI,OAAO,KAAK;GACtF,gBAAgB,GAAG,OAAO,UAAU,OAAO,KAAK;GAChD,SAAS;GACT,QAAQ,GAAG,OAAO,KAAK;GACvB,eAAe;GACf,OAAO,GAAG,OAAO,KAAK;GACvB;EACD,CAAA;;AAIN,SAAS,qBAAqB,OAAgC;AAC5D,QAAO,MAAM;;AAGf,MAAM,kBAAkB;CACtB,SAAS;CACT,QAAQ;CACR,eAAe;CACf,OAAO;CACR;AAED,SAAgB,YAAY,QAA0B;AACpD,QACE,OAAO,MAAM,UAAU,MAAM,SAAS,QAAQ,IAC9C,OAAO,OACJ,UAAU,MAAM,SAAS,WAAY,MAAM,SAAS,UAAU,MAAM,MAAM,MAAM,KAAK,GACvF"}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
//#region src/core/ascii.ts
|
|
2
|
+
const CURATED_ASCII = {
|
|
3
|
+
":)": "slightly_smiling_face",
|
|
4
|
+
":-)": "slightly_smiling_face",
|
|
5
|
+
":(": "slightly_frowning_face",
|
|
6
|
+
":-(": "slightly_frowning_face",
|
|
7
|
+
";)": "wink",
|
|
8
|
+
";-)": "wink",
|
|
9
|
+
":P": "stuck_out_tongue",
|
|
10
|
+
":-P": "stuck_out_tongue",
|
|
11
|
+
":p": "stuck_out_tongue",
|
|
12
|
+
":-p": "stuck_out_tongue",
|
|
13
|
+
":D": "grinning",
|
|
14
|
+
":-D": "grinning",
|
|
15
|
+
"<3": "heart",
|
|
16
|
+
":|": "neutral_face",
|
|
17
|
+
":-|": "neutral_face",
|
|
18
|
+
":/": "confused",
|
|
19
|
+
":-/": "confused",
|
|
20
|
+
":'(": "cry",
|
|
21
|
+
":O": "open_mouth",
|
|
22
|
+
":-O": "open_mouth",
|
|
23
|
+
":o": "open_mouth",
|
|
24
|
+
":-o": "open_mouth",
|
|
25
|
+
">:(": "angry",
|
|
26
|
+
"B)": "sunglasses",
|
|
27
|
+
"B-)": "sunglasses"
|
|
28
|
+
};
|
|
29
|
+
function buildAsciiIndex(data) {
|
|
30
|
+
const index = /* @__PURE__ */ new Map();
|
|
31
|
+
for (const [ascii, emojiId] of Object.entries(data.aliases)) if (/^[^a-zA-Z0-9]/.test(ascii) && ascii.length <= 4) index.set(ascii, emojiId);
|
|
32
|
+
for (const [ascii, emojiId] of Object.entries(CURATED_ASCII)) if (!index.has(ascii) && data.emojis[emojiId]) index.set(ascii, emojiId);
|
|
33
|
+
return index;
|
|
34
|
+
}
|
|
35
|
+
function buildAsciiCandidates(asciiIndex) {
|
|
36
|
+
return Array.from(asciiIndex.keys()).sort((first, second) => second.length - first.length);
|
|
37
|
+
}
|
|
38
|
+
const BOUNDARY_BEFORE = /(?:^|[\s\n])$/;
|
|
39
|
+
const BOUNDARY_AFTER = /^(?:[\s\n]|$)/;
|
|
40
|
+
function matchAscii(input, position, asciiIndex, asciiCandidates = buildAsciiCandidates(asciiIndex)) {
|
|
41
|
+
const before = input.slice(0, position);
|
|
42
|
+
if (position > 0 && !BOUNDARY_BEFORE.test(before)) return;
|
|
43
|
+
for (const ascii of asciiCandidates) {
|
|
44
|
+
if (!input.startsWith(ascii, position)) continue;
|
|
45
|
+
const after = input.slice(position + ascii.length);
|
|
46
|
+
if (BOUNDARY_AFTER.test(after)) {
|
|
47
|
+
const emojiId = asciiIndex.get(ascii);
|
|
48
|
+
if (emojiId) return {
|
|
49
|
+
ascii,
|
|
50
|
+
emojiId
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
//#region src/core/indexes.ts
|
|
57
|
+
function unifiedToNative(unified) {
|
|
58
|
+
return unified.split("-").map((hex) => String.fromCodePoint(Number.parseInt(hex, 16))).join("");
|
|
59
|
+
}
|
|
60
|
+
function escapeRegex(value) {
|
|
61
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
62
|
+
}
|
|
63
|
+
function buildIndexes(data, customEmojis, extraAliases) {
|
|
64
|
+
const unicodeMap = /* @__PURE__ */ new Map();
|
|
65
|
+
const emojiMap = /* @__PURE__ */ new Map();
|
|
66
|
+
const shortcodeIndex = /* @__PURE__ */ new Map();
|
|
67
|
+
const unicodeChars = [];
|
|
68
|
+
for (const [emojiId, emoji] of Object.entries(data.emojis)) {
|
|
69
|
+
emojiMap.set(emojiId, emoji);
|
|
70
|
+
shortcodeIndex.set(emojiId, { emojiId });
|
|
71
|
+
if (emoji.aliases) for (const alias of emoji.aliases) shortcodeIndex.set(alias, { emojiId });
|
|
72
|
+
for (const skin of emoji.skins) {
|
|
73
|
+
const native = skin.native ?? unifiedToNative(skin.unified);
|
|
74
|
+
unicodeMap.set(native, emojiId);
|
|
75
|
+
unicodeChars.push(escapeRegex(native));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
for (const [alias, emojiId] of Object.entries(data.aliases)) if (!shortcodeIndex.has(alias)) shortcodeIndex.set(alias, { emojiId });
|
|
79
|
+
if (customEmojis) for (const category of customEmojis) for (const emoji of category.emojis) {
|
|
80
|
+
const entry = {
|
|
81
|
+
id: emoji.id,
|
|
82
|
+
name: emoji.name,
|
|
83
|
+
keywords: emoji.keywords ?? [],
|
|
84
|
+
skins: emoji.skins.map((skin) => ({
|
|
85
|
+
unified: "",
|
|
86
|
+
native: "",
|
|
87
|
+
src: skin.src
|
|
88
|
+
}))
|
|
89
|
+
};
|
|
90
|
+
emojiMap.set(emoji.id, entry);
|
|
91
|
+
shortcodeIndex.set(emoji.id, {
|
|
92
|
+
emojiId: emoji.id,
|
|
93
|
+
isCustom: true
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
if (extraAliases) for (const [alias, emojiId] of Object.entries(extraAliases)) {
|
|
97
|
+
const cleanAlias = alias.replace(/^:|:$/g, "");
|
|
98
|
+
const resolvedEmojiId = emojiMap.has(emojiId) ? emojiId : shortcodeIndex.get(emojiId)?.emojiId ?? emojiId;
|
|
99
|
+
const isCustom = shortcodeIndex.get(resolvedEmojiId)?.isCustom;
|
|
100
|
+
shortcodeIndex.set(cleanAlias, {
|
|
101
|
+
emojiId: resolvedEmojiId,
|
|
102
|
+
isCustom
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
unicodeChars.sort((first, second) => second.length - first.length);
|
|
106
|
+
const unicodeRegex = unicodeChars.length > 0 ? new RegExp(unicodeChars.join("|"), "y") : /(?!)/y;
|
|
107
|
+
const asciiIndex = buildAsciiIndex(data);
|
|
108
|
+
return {
|
|
109
|
+
asciiCandidates: buildAsciiCandidates(asciiIndex),
|
|
110
|
+
unicodeRegex,
|
|
111
|
+
unicodeMap,
|
|
112
|
+
shortcodeIndex,
|
|
113
|
+
asciiIndex,
|
|
114
|
+
emojiMap
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region src/core/skin.ts
|
|
119
|
+
const SKIN_TONE_MODIFIERS = {
|
|
120
|
+
"1f3fb": 2,
|
|
121
|
+
"1f3fc": 3,
|
|
122
|
+
"1f3fd": 4,
|
|
123
|
+
"1f3fe": 5,
|
|
124
|
+
"1f3ff": 6
|
|
125
|
+
};
|
|
126
|
+
function detectSkinToneFromUnified(unified) {
|
|
127
|
+
const normalizedUnified = unified.toLowerCase();
|
|
128
|
+
for (const [modifier, tone] of Object.entries(SKIN_TONE_MODIFIERS)) if (normalizedUnified.includes(modifier)) return tone;
|
|
129
|
+
}
|
|
130
|
+
function resolveSkin(emoji, explicitSkin, defaultSkin) {
|
|
131
|
+
const tone = explicitSkin ?? defaultSkin;
|
|
132
|
+
if (!tone || tone === 1 || emoji.skins.length <= 1) return {
|
|
133
|
+
native: emoji.skins[0]?.native ?? "",
|
|
134
|
+
skin: explicitSkin
|
|
135
|
+
};
|
|
136
|
+
const skinIndex = tone - 1;
|
|
137
|
+
return {
|
|
138
|
+
native: (emoji.skins[skinIndex] ?? emoji.skins[0])?.native ?? emoji.skins[0]?.native ?? "",
|
|
139
|
+
skin: tone
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function skinToneShortcodeToTone(shortcode) {
|
|
143
|
+
const toneMatch = /^skin-tone-([1-6])$/.test(shortcode) ? shortcode.charAt(shortcode.length - 1) : void 0;
|
|
144
|
+
if (toneMatch) return Number.parseInt(toneMatch, 10);
|
|
145
|
+
}
|
|
146
|
+
//#endregion
|
|
147
|
+
//#region src/core/tokenize.ts
|
|
148
|
+
const SHORTCODE_RE = /^:([a-zA-Z0-9_+-]+):/;
|
|
149
|
+
const SKIN_TONE_SHORTCODE_RE = /^:skin-tone-([1-6]):/;
|
|
150
|
+
const indexCache = /* @__PURE__ */ new WeakMap();
|
|
151
|
+
function getIndexes(options) {
|
|
152
|
+
if (options.indexes) return options.indexes;
|
|
153
|
+
const cachedEntries = indexCache.get(options.data);
|
|
154
|
+
const cachedEntry = cachedEntries?.find((entry) => entry.customEmojis === options.customEmojis && entry.extraAliases === options.extraAliases);
|
|
155
|
+
if (cachedEntry) return cachedEntry.indexes;
|
|
156
|
+
const indexes = buildIndexes(options.data, options.customEmojis, options.extraAliases);
|
|
157
|
+
const nextEntry = {
|
|
158
|
+
customEmojis: options.customEmojis,
|
|
159
|
+
extraAliases: options.extraAliases,
|
|
160
|
+
indexes
|
|
161
|
+
};
|
|
162
|
+
if (cachedEntries) cachedEntries.push(nextEntry);
|
|
163
|
+
else indexCache.set(options.data, [nextEntry]);
|
|
164
|
+
return indexes;
|
|
165
|
+
}
|
|
166
|
+
function tryMatchUnicode(input, position, indexes) {
|
|
167
|
+
indexes.unicodeRegex.lastIndex = position;
|
|
168
|
+
const regexResult = indexes.unicodeRegex.exec(input);
|
|
169
|
+
if (regexResult) {
|
|
170
|
+
const native = regexResult[0];
|
|
171
|
+
const emojiId = indexes.unicodeMap.get(native);
|
|
172
|
+
if (emojiId) return {
|
|
173
|
+
native,
|
|
174
|
+
emojiId,
|
|
175
|
+
unified: (indexes.emojiMap.get(emojiId)?.skins.find((skinEntry) => skinEntry.native === native))?.unified
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function tryMatchShortcode(input, position, indexes) {
|
|
180
|
+
const remaining = input.slice(position);
|
|
181
|
+
const regexResult = SHORTCODE_RE.exec(remaining);
|
|
182
|
+
if (regexResult?.[1]) {
|
|
183
|
+
const shortcode = regexResult[1];
|
|
184
|
+
const entry = indexes.shortcodeIndex.get(shortcode);
|
|
185
|
+
if (entry) return {
|
|
186
|
+
shortcode,
|
|
187
|
+
emojiId: entry.emojiId,
|
|
188
|
+
fullMatch: regexResult[0],
|
|
189
|
+
isCustom: entry.isCustom
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function tryMatchUnknownShortcode(input, position) {
|
|
194
|
+
const remaining = input.slice(position);
|
|
195
|
+
const regexResult = SHORTCODE_RE.exec(remaining);
|
|
196
|
+
if (regexResult?.[1]) return {
|
|
197
|
+
shortcode: regexResult[1],
|
|
198
|
+
fullMatch: regexResult[0]
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function tokenize(input, options) {
|
|
202
|
+
return tokenizeWithIndexes(input, options);
|
|
203
|
+
}
|
|
204
|
+
function tokenizeWithIndexes(input, options) {
|
|
205
|
+
const indexes = getIndexes(options);
|
|
206
|
+
const tokens = [];
|
|
207
|
+
const ascii = options.ascii ?? true;
|
|
208
|
+
let position = 0;
|
|
209
|
+
let textBuffer = "";
|
|
210
|
+
function flushText() {
|
|
211
|
+
if (textBuffer.length > 0) {
|
|
212
|
+
tokens.push({
|
|
213
|
+
type: "text",
|
|
214
|
+
value: textBuffer
|
|
215
|
+
});
|
|
216
|
+
textBuffer = "";
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
while (position < input.length) {
|
|
220
|
+
let matched = false;
|
|
221
|
+
const unicodeResult = tryMatchUnicode(input, position, indexes);
|
|
222
|
+
if (unicodeResult) {
|
|
223
|
+
flushText();
|
|
224
|
+
const detectedSkin = detectSkinToneFromUnified(unicodeResult.unified ?? "");
|
|
225
|
+
const emoji = indexes.emojiMap.get(unicodeResult.emojiId);
|
|
226
|
+
if (emoji) {
|
|
227
|
+
const resolved = resolveSkin(emoji, detectedSkin, options.defaultSkin);
|
|
228
|
+
tokens.push({
|
|
229
|
+
type: "emoji",
|
|
230
|
+
emoji,
|
|
231
|
+
native: resolved.native || unicodeResult.native,
|
|
232
|
+
skin: resolved.skin,
|
|
233
|
+
match: unicodeResult.native,
|
|
234
|
+
source: "unicode"
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
position += unicodeResult.native.length;
|
|
238
|
+
matched = true;
|
|
239
|
+
}
|
|
240
|
+
if (!matched) {
|
|
241
|
+
const shortcodeResult = tryMatchShortcode(input, position, indexes);
|
|
242
|
+
if (shortcodeResult) {
|
|
243
|
+
flushText();
|
|
244
|
+
let skinTone;
|
|
245
|
+
let totalLength = shortcodeResult.fullMatch.length;
|
|
246
|
+
const afterShortcode = input.slice(position + totalLength);
|
|
247
|
+
const skinRegexResult = SKIN_TONE_SHORTCODE_RE.exec(afterShortcode);
|
|
248
|
+
if (skinRegexResult?.[1]) {
|
|
249
|
+
skinTone = skinToneShortcodeToTone(`skin-tone-${skinRegexResult[1]}`);
|
|
250
|
+
totalLength += skinRegexResult[0].length;
|
|
251
|
+
}
|
|
252
|
+
const emoji = indexes.emojiMap.get(shortcodeResult.emojiId);
|
|
253
|
+
if (emoji) {
|
|
254
|
+
const isCustom = shortcodeResult.isCustom;
|
|
255
|
+
const resolved = resolveSkin(emoji, skinTone, options.defaultSkin);
|
|
256
|
+
tokens.push({
|
|
257
|
+
type: "emoji",
|
|
258
|
+
emoji,
|
|
259
|
+
native: resolved.native,
|
|
260
|
+
skin: resolved.skin,
|
|
261
|
+
shortcode: shortcodeResult.shortcode,
|
|
262
|
+
match: input.slice(position, position + totalLength),
|
|
263
|
+
source: isCustom ? "custom" : "shortcode"
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
position += totalLength;
|
|
267
|
+
matched = true;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
if (!matched) {
|
|
271
|
+
const unknownResult = tryMatchUnknownShortcode(input, position);
|
|
272
|
+
if (unknownResult) {
|
|
273
|
+
flushText();
|
|
274
|
+
tokens.push({
|
|
275
|
+
type: "unknown",
|
|
276
|
+
shortcode: unknownResult.shortcode,
|
|
277
|
+
match: unknownResult.fullMatch
|
|
278
|
+
});
|
|
279
|
+
position += unknownResult.fullMatch.length;
|
|
280
|
+
matched = true;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (!matched && ascii) {
|
|
284
|
+
const asciiResult = matchAscii(input, position, indexes.asciiIndex, indexes.asciiCandidates);
|
|
285
|
+
if (asciiResult) {
|
|
286
|
+
flushText();
|
|
287
|
+
const emoji = indexes.emojiMap.get(asciiResult.emojiId);
|
|
288
|
+
if (emoji) {
|
|
289
|
+
const resolved = resolveSkin(emoji, void 0, options.defaultSkin);
|
|
290
|
+
tokens.push({
|
|
291
|
+
type: "emoji",
|
|
292
|
+
emoji,
|
|
293
|
+
native: resolved.native,
|
|
294
|
+
match: asciiResult.ascii,
|
|
295
|
+
source: "ascii"
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
position += asciiResult.ascii.length;
|
|
299
|
+
matched = true;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (!matched) {
|
|
303
|
+
textBuffer += input[position];
|
|
304
|
+
position += 1;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
flushText();
|
|
308
|
+
return tokens;
|
|
309
|
+
}
|
|
310
|
+
//#endregion
|
|
311
|
+
export { skinToneShortcodeToTone as a, buildAsciiIndex as c, resolveSkin as i, matchAscii as l, tokenizeWithIndexes as n, buildIndexes as o, detectSkinToneFromUnified as r, buildAsciiCandidates as s, tokenize as t };
|
|
312
|
+
|
|
313
|
+
//# sourceMappingURL=tokenize-BUKMZ9Yg.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokenize-BUKMZ9Yg.mjs","names":[],"sources":["../src/core/ascii.ts","../src/core/indexes.ts","../src/core/skin.ts","../src/core/tokenize.ts"],"sourcesContent":["import type { EmojiData } from './types';\n\nconst CURATED_ASCII: Record<string, string> = {\n ':)': 'slightly_smiling_face',\n ':-)': 'slightly_smiling_face',\n ':(': 'slightly_frowning_face',\n ':-(': 'slightly_frowning_face',\n ';)': 'wink',\n ';-)': 'wink',\n ':P': 'stuck_out_tongue',\n ':-P': 'stuck_out_tongue',\n ':p': 'stuck_out_tongue',\n ':-p': 'stuck_out_tongue',\n ':D': 'grinning',\n ':-D': 'grinning',\n '<3': 'heart',\n ':|': 'neutral_face',\n ':-|': 'neutral_face',\n ':/': 'confused',\n ':-/': 'confused',\n \":'(\": 'cry',\n ':O': 'open_mouth',\n ':-O': 'open_mouth',\n ':o': 'open_mouth',\n ':-o': 'open_mouth',\n '>:(': 'angry',\n 'B)': 'sunglasses',\n 'B-)': 'sunglasses',\n};\n\nexport function buildAsciiIndex(data: EmojiData): Map<string, string> {\n const index = new Map<string, string>();\n\n for (const [ascii, emojiId] of Object.entries(data.aliases)) {\n if (/^[^a-zA-Z0-9]/.test(ascii) && ascii.length <= 4) {\n index.set(ascii, emojiId);\n }\n }\n\n for (const [ascii, emojiId] of Object.entries(CURATED_ASCII)) {\n if (!index.has(ascii) && data.emojis[emojiId]) {\n index.set(ascii, emojiId);\n }\n }\n\n return index;\n}\n\nexport function buildAsciiCandidates(asciiIndex: Map<string, string>): string[] {\n return Array.from(asciiIndex.keys()).sort((first, second) => second.length - first.length);\n}\n\nconst BOUNDARY_BEFORE = /(?:^|[\\s\\n])$/;\nconst BOUNDARY_AFTER = /^(?:[\\s\\n]|$)/;\n\nexport function matchAscii(\n input: string,\n position: number,\n asciiIndex: Map<string, string>,\n asciiCandidates = buildAsciiCandidates(asciiIndex),\n): { ascii: string; emojiId: string } | undefined {\n const before = input.slice(0, position);\n if (position > 0 && !BOUNDARY_BEFORE.test(before)) {\n return undefined;\n }\n\n for (const ascii of asciiCandidates) {\n if (!input.startsWith(ascii, position)) continue;\n\n const after = input.slice(position + ascii.length);\n if (BOUNDARY_AFTER.test(after)) {\n const emojiId = asciiIndex.get(ascii);\n if (emojiId) {\n return { ascii, emojiId };\n }\n }\n }\n\n return undefined;\n}\n","import { buildAsciiCandidates, buildAsciiIndex } from './ascii';\nimport type { CustomEmojiCategory, EmojiData, EmojiEntry, SkinTone } from './types';\n\nexport interface ShortcodeEntry {\n emojiId: string;\n skin?: SkinTone;\n isCustom?: boolean;\n}\n\nexport interface EmojiIndexes {\n unicodeRegex: RegExp;\n unicodeMap: Map<string, string>;\n shortcodeIndex: Map<string, ShortcodeEntry>;\n asciiIndex: Map<string, string>;\n asciiCandidates: string[];\n emojiMap: Map<string, EmojiEntry>;\n}\n\nfunction unifiedToNative(unified: string): string {\n return unified\n .split('-')\n .map((hex) => String.fromCodePoint(Number.parseInt(hex, 16)))\n .join('');\n}\n\nfunction escapeRegex(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function buildIndexes(\n data: EmojiData,\n customEmojis?: CustomEmojiCategory[],\n extraAliases?: Record<string, string>,\n): EmojiIndexes {\n const unicodeMap = new Map<string, string>();\n const emojiMap = new Map<string, EmojiEntry>();\n const shortcodeIndex = new Map<string, ShortcodeEntry>();\n const unicodeChars: string[] = [];\n\n for (const [emojiId, emoji] of Object.entries(data.emojis)) {\n emojiMap.set(emojiId, emoji);\n shortcodeIndex.set(emojiId, { emojiId });\n\n if (emoji.aliases) {\n for (const alias of emoji.aliases) {\n shortcodeIndex.set(alias, { emojiId });\n }\n }\n\n for (const skin of emoji.skins) {\n const native = skin.native ?? unifiedToNative(skin.unified);\n unicodeMap.set(native, emojiId);\n unicodeChars.push(escapeRegex(native));\n }\n }\n\n for (const [alias, emojiId] of Object.entries(data.aliases)) {\n if (!shortcodeIndex.has(alias)) {\n shortcodeIndex.set(alias, { emojiId });\n }\n }\n\n if (customEmojis) {\n for (const category of customEmojis) {\n for (const emoji of category.emojis) {\n const entry: EmojiEntry = {\n id: emoji.id,\n name: emoji.name,\n keywords: emoji.keywords ?? [],\n skins: emoji.skins.map((skin) => ({\n unified: '',\n native: '',\n src: skin.src,\n })),\n };\n emojiMap.set(emoji.id, entry);\n shortcodeIndex.set(emoji.id, { emojiId: emoji.id, isCustom: true });\n }\n }\n }\n\n if (extraAliases) {\n for (const [alias, emojiId] of Object.entries(extraAliases)) {\n const cleanAlias = alias.replace(/^:|:$/g, '');\n const resolvedEmojiId = emojiMap.has(emojiId)\n ? emojiId\n : (shortcodeIndex.get(emojiId)?.emojiId ?? emojiId);\n const isCustom = shortcodeIndex.get(resolvedEmojiId)?.isCustom;\n shortcodeIndex.set(cleanAlias, { emojiId: resolvedEmojiId, isCustom });\n }\n }\n\n unicodeChars.sort((first, second) => second.length - first.length);\n\n const unicodeRegex = unicodeChars.length > 0 ? new RegExp(unicodeChars.join('|'), 'y') : /(?!)/y;\n\n const asciiIndex = buildAsciiIndex(data);\n\n return {\n asciiCandidates: buildAsciiCandidates(asciiIndex),\n unicodeRegex,\n unicodeMap,\n shortcodeIndex,\n asciiIndex,\n emojiMap,\n };\n}\n","import type { EmojiEntry, SkinTone } from './types';\n\nconst SKIN_TONE_MODIFIERS: Record<string, SkinTone> = {\n '1f3fb': 2,\n '1f3fc': 3,\n '1f3fd': 4,\n '1f3fe': 5,\n '1f3ff': 6,\n};\n\nconst SKIN_TONE_UNIFIED: Record<SkinTone, string> = {\n 1: '',\n 2: '1F3FB',\n 3: '1F3FC',\n 4: '1F3FD',\n 5: '1F3FE',\n 6: '1F3FF',\n};\n\nexport function detectSkinToneFromUnified(unified: string): SkinTone | undefined {\n const normalizedUnified = unified.toLowerCase();\n for (const [modifier, tone] of Object.entries(SKIN_TONE_MODIFIERS)) {\n if (normalizedUnified.includes(modifier)) {\n return tone;\n }\n }\n return undefined;\n}\n\nexport function resolveSkin(\n emoji: EmojiEntry,\n explicitSkin: SkinTone | undefined,\n defaultSkin: SkinTone | undefined,\n): { native: string; skin: SkinTone | undefined } {\n const tone = explicitSkin ?? defaultSkin;\n\n if (!tone || tone === 1 || emoji.skins.length <= 1) {\n return {\n native: emoji.skins[0]?.native ?? '',\n skin: explicitSkin,\n };\n }\n\n const skinIndex = tone - 1;\n const skinEntry = emoji.skins[skinIndex] ?? emoji.skins[0];\n\n return {\n native: skinEntry?.native ?? emoji.skins[0]?.native ?? '',\n skin: tone,\n };\n}\n\nexport function skinToneShortcodeToTone(shortcode: string): SkinTone | undefined {\n const toneMatch = /^skin-tone-([1-6])$/.test(shortcode)\n ? shortcode.charAt(shortcode.length - 1)\n : undefined;\n if (toneMatch) {\n return Number.parseInt(toneMatch, 10) as SkinTone;\n }\n return undefined;\n}\n\nexport { SKIN_TONE_UNIFIED };\n","import { matchAscii } from './ascii';\nimport { type EmojiIndexes, buildIndexes } from './indexes';\nimport { detectSkinToneFromUnified, resolveSkin, skinToneShortcodeToTone } from './skin';\nimport type { SkinTone, Token, TokenizeOptions } from './types';\n\nconst SHORTCODE_RE = /^:([a-zA-Z0-9_+-]+):/;\nconst SKIN_TONE_SHORTCODE_RE = /^:skin-tone-([1-6]):/;\n\nconst indexCache = new WeakMap<\n TokenizeOptions['data'],\n Array<{\n customEmojis: TokenizeOptions['customEmojis'];\n extraAliases: TokenizeOptions['extraAliases'];\n indexes: EmojiIndexes;\n }>\n>();\n\ntype TokenizeRuntimeOptions = TokenizeOptions & { indexes?: EmojiIndexes };\n\nfunction getIndexes(options: TokenizeRuntimeOptions): EmojiIndexes {\n if (options.indexes) {\n return options.indexes;\n }\n\n const cachedEntries = indexCache.get(options.data);\n const cachedEntry = cachedEntries?.find(\n (entry) =>\n entry.customEmojis === options.customEmojis && entry.extraAliases === options.extraAliases,\n );\n\n if (cachedEntry) {\n return cachedEntry.indexes;\n }\n\n const indexes = buildIndexes(options.data, options.customEmojis, options.extraAliases);\n\n const nextEntry = {\n customEmojis: options.customEmojis,\n extraAliases: options.extraAliases,\n indexes,\n };\n\n if (cachedEntries) {\n cachedEntries.push(nextEntry);\n } else {\n indexCache.set(options.data, [nextEntry]);\n }\n\n return indexes;\n}\n\nfunction tryMatchUnicode(\n input: string,\n position: number,\n indexes: EmojiIndexes,\n): { native: string; emojiId: string; unified?: string } | undefined {\n indexes.unicodeRegex.lastIndex = position;\n const regexResult = indexes.unicodeRegex.exec(input);\n if (regexResult) {\n const native = regexResult[0];\n const emojiId = indexes.unicodeMap.get(native);\n if (emojiId) {\n const emoji = indexes.emojiMap.get(emojiId);\n const skin = emoji?.skins.find((skinEntry) => skinEntry.native === native);\n return { native, emojiId, unified: skin?.unified };\n }\n }\n return;\n}\n\nfunction tryMatchShortcode(\n input: string,\n position: number,\n indexes: EmojiIndexes,\n):\n | {\n shortcode: string;\n emojiId: string;\n fullMatch: string;\n isCustom?: boolean;\n }\n | undefined {\n const remaining = input.slice(position);\n const regexResult = SHORTCODE_RE.exec(remaining);\n if (regexResult?.[1]) {\n const shortcode = regexResult[1];\n const entry = indexes.shortcodeIndex.get(shortcode);\n if (entry) {\n return {\n shortcode,\n emojiId: entry.emojiId,\n fullMatch: regexResult[0],\n isCustom: entry.isCustom,\n };\n }\n }\n return;\n}\n\nfunction tryMatchUnknownShortcode(\n input: string,\n position: number,\n): { shortcode: string; fullMatch: string } | undefined {\n const remaining = input.slice(position);\n const regexResult = SHORTCODE_RE.exec(remaining);\n if (regexResult?.[1]) {\n return { shortcode: regexResult[1], fullMatch: regexResult[0] };\n }\n return;\n}\n\nexport function tokenize(input: string, options: TokenizeOptions): Token[] {\n return tokenizeWithIndexes(input, options);\n}\n\nexport function tokenizeWithIndexes(input: string, options: TokenizeRuntimeOptions): Token[] {\n const indexes = getIndexes(options);\n const tokens: Token[] = [];\n const ascii = options.ascii ?? true;\n let position = 0;\n let textBuffer = '';\n\n function flushText() {\n if (textBuffer.length > 0) {\n tokens.push({ type: 'text', value: textBuffer });\n textBuffer = '';\n }\n }\n\n while (position < input.length) {\n let matched = false;\n\n const unicodeResult = tryMatchUnicode(input, position, indexes);\n if (unicodeResult) {\n flushText();\n const detectedSkin = detectSkinToneFromUnified(unicodeResult.unified ?? '');\n const emoji = indexes.emojiMap.get(unicodeResult.emojiId);\n if (emoji) {\n const resolved = resolveSkin(emoji, detectedSkin, options.defaultSkin);\n tokens.push({\n type: 'emoji',\n emoji,\n native: resolved.native || unicodeResult.native,\n skin: resolved.skin,\n match: unicodeResult.native,\n source: 'unicode',\n });\n }\n position += unicodeResult.native.length;\n matched = true;\n }\n\n if (!matched) {\n const shortcodeResult = tryMatchShortcode(input, position, indexes);\n if (shortcodeResult) {\n flushText();\n let skinTone: SkinTone | undefined;\n let totalLength = shortcodeResult.fullMatch.length;\n\n const afterShortcode = input.slice(position + totalLength);\n const skinRegexResult = SKIN_TONE_SHORTCODE_RE.exec(afterShortcode);\n if (skinRegexResult?.[1]) {\n skinTone = skinToneShortcodeToTone(`skin-tone-${skinRegexResult[1]}`);\n totalLength += skinRegexResult[0].length;\n }\n\n const emoji = indexes.emojiMap.get(shortcodeResult.emojiId);\n if (emoji) {\n const isCustom = shortcodeResult.isCustom;\n const resolved = resolveSkin(emoji, skinTone, options.defaultSkin);\n tokens.push({\n type: 'emoji',\n emoji,\n native: resolved.native,\n skin: resolved.skin,\n shortcode: shortcodeResult.shortcode,\n match: input.slice(position, position + totalLength),\n source: isCustom ? 'custom' : 'shortcode',\n });\n }\n position += totalLength;\n matched = true;\n }\n }\n\n if (!matched) {\n const unknownResult = tryMatchUnknownShortcode(input, position);\n if (unknownResult) {\n flushText();\n tokens.push({\n type: 'unknown',\n shortcode: unknownResult.shortcode,\n match: unknownResult.fullMatch,\n });\n position += unknownResult.fullMatch.length;\n matched = true;\n }\n }\n\n if (!matched && ascii) {\n const asciiResult = matchAscii(input, position, indexes.asciiIndex, indexes.asciiCandidates);\n if (asciiResult) {\n flushText();\n const emoji = indexes.emojiMap.get(asciiResult.emojiId);\n if (emoji) {\n const resolved = resolveSkin(emoji, undefined, options.defaultSkin);\n tokens.push({\n type: 'emoji',\n emoji,\n native: resolved.native,\n match: asciiResult.ascii,\n source: 'ascii',\n });\n }\n position += asciiResult.ascii.length;\n matched = true;\n }\n }\n\n if (!matched) {\n textBuffer += input[position];\n position += 1;\n }\n }\n\n flushText();\n return tokens;\n}\n"],"mappings":"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"}
|