emojistry 1.0.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.
@@ -0,0 +1,35 @@
1
+ {
2
+ "generatedAt": "2026-06-15T00:00:00.000Z",
3
+ "source": "sample",
4
+ "count": 2,
5
+ "emojis": [
6
+ {
7
+ "emoji": "😀",
8
+ "codepoints": ["U+1F600"],
9
+ "qualification": "fully-qualified",
10
+ "emojiVersion": "1.0",
11
+ "name": "grinning face",
12
+ "group": "Smileys & Emotion",
13
+ "subgroup": "face-smiling",
14
+ "slug": "grinning-face",
15
+ "category": "faces",
16
+ "keywords": ["grinning", "face"],
17
+ "hasSkinTone": false,
18
+ "isSequence": false
19
+ },
20
+ {
21
+ "emoji": "❤️",
22
+ "codepoints": ["U+2764", "U+FE0F"],
23
+ "qualification": "fully-qualified",
24
+ "emojiVersion": "0.6",
25
+ "name": "red heart",
26
+ "group": "Smileys & Emotion",
27
+ "subgroup": "emotion",
28
+ "slug": "red-heart",
29
+ "category": "faces",
30
+ "keywords": ["red", "heart"],
31
+ "hasSkinTone": false,
32
+ "isSequence": true
33
+ }
34
+ ]
35
+ }
@@ -0,0 +1,4 @@
1
+ import type { EmojiCategory } from "./types.js";
2
+ export declare function categoryForUnicodeGroup(group: string): EmojiCategory;
3
+ export declare function listCategories(): EmojiCategory[];
4
+ //# sourceMappingURL=categories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"categories.d.ts","sourceRoot":"","sources":["../src/categories.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAehD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAEpE;AAED,wBAAgB,cAAc,IAAI,aAAa,EAAE,CAchD"}
@@ -0,0 +1,30 @@
1
+ const GROUP_TO_CATEGORY = {
2
+ "Smileys & Emotion": "faces",
3
+ "People & Body": "people",
4
+ "Animals & Nature": "animals-nature",
5
+ "Food & Drink": "food-drink",
6
+ "Travel & Places": "travel-places",
7
+ Activities: "activities",
8
+ Objects: "objects",
9
+ Symbols: "symbols",
10
+ Flags: "flags",
11
+ Component: "components",
12
+ };
13
+ export function categoryForUnicodeGroup(group) {
14
+ return GROUP_TO_CATEGORY[group] ?? "other";
15
+ }
16
+ export function listCategories() {
17
+ return [
18
+ "faces",
19
+ "people",
20
+ "animals-nature",
21
+ "food-drink",
22
+ "travel-places",
23
+ "activities",
24
+ "objects",
25
+ "symbols",
26
+ "flags",
27
+ "components",
28
+ "other",
29
+ ];
30
+ }
@@ -0,0 +1,6 @@
1
+ export { categoryForUnicodeGroup, listCategories } from "./categories.js";
2
+ export { fetchEmojiTest, parseEmojiTest } from "./ingest/unicode.js";
3
+ export { normalizeEmojiEntries, normalizeEmojiEntry, slugify } from "./normalize/emoji.js";
4
+ export { findEmoji, groupByCategory, searchEmojis } from "./search.js";
5
+ export type { EmojiCategory, EmojiQualification, EmojiRecord, EmojiRegistrySnapshot, UnicodeEmojiEntry, } from "./types.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC3F,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACvE,YAAY,EACX,aAAa,EACb,kBAAkB,EAClB,WAAW,EACX,qBAAqB,EACrB,iBAAiB,GACjB,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { categoryForUnicodeGroup, listCategories } from "./categories.js";
2
+ export { fetchEmojiTest, parseEmojiTest } from "./ingest/unicode.js";
3
+ export { normalizeEmojiEntries, normalizeEmojiEntry, slugify } from "./normalize/emoji.js";
4
+ export { findEmoji, groupByCategory, searchEmojis } from "./search.js";
@@ -0,0 +1,4 @@
1
+ import type { UnicodeEmojiEntry } from "../types.js";
2
+ export declare function parseEmojiTest(input: string): UnicodeEmojiEntry[];
3
+ export declare function fetchEmojiTest(url: string): Promise<string>;
4
+ //# sourceMappingURL=unicode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unicode.d.ts","sourceRoot":"","sources":["../../src/ingest/unicode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIzE,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,EAAE,CA0CjE;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAUjE"}
@@ -0,0 +1,45 @@
1
+ const EMOJI_LINE_PATTERN = /^([0-9A-F ]+)\s*;\s*([a-z-]+)\s*#\s*(\S+)\s+E([0-9.]+)\s+(.+)$/u;
2
+ export function parseEmojiTest(input) {
3
+ const entries = [];
4
+ let group = "Other";
5
+ let subgroup = "other";
6
+ for (const rawLine of input.split("\n")) {
7
+ const line = rawLine.trim();
8
+ if (line.startsWith("# group:")) {
9
+ group = line.replace("# group:", "").trim();
10
+ continue;
11
+ }
12
+ if (line.startsWith("# subgroup:")) {
13
+ subgroup = line.replace("# subgroup:", "").trim();
14
+ continue;
15
+ }
16
+ const match = line.match(EMOJI_LINE_PATTERN);
17
+ if (!match)
18
+ continue;
19
+ const codepointText = match[1];
20
+ const qualification = match[2];
21
+ const emoji = match[3];
22
+ const emojiVersion = match[4];
23
+ const name = match[5];
24
+ entries.push({
25
+ emoji,
26
+ codepoints: codepointText
27
+ .trim()
28
+ .split(/\s+/u)
29
+ .map((value) => `U+${value}`),
30
+ qualification: qualification,
31
+ emojiVersion,
32
+ name,
33
+ group,
34
+ subgroup,
35
+ });
36
+ }
37
+ return entries;
38
+ }
39
+ export async function fetchEmojiTest(url) {
40
+ const response = await fetch(url);
41
+ if (!response.ok) {
42
+ throw new Error(`Failed to fetch Unicode emoji data: ${response.status} ${response.statusText}`);
43
+ }
44
+ return response.text();
45
+ }
@@ -0,0 +1,5 @@
1
+ import type { EmojiRecord, UnicodeEmojiEntry } from "../types.js";
2
+ export declare function normalizeEmojiEntry(entry: UnicodeEmojiEntry): EmojiRecord;
3
+ export declare function normalizeEmojiEntries(entries: UnicodeEmojiEntry[]): EmojiRecord[];
4
+ export declare function slugify(value: string): string;
5
+ //# sourceMappingURL=emoji.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emoji.d.ts","sourceRoot":"","sources":["../../src/normalize/emoji.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIlE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,GAAG,WAAW,CASzE;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,WAAW,EAAE,CAEjF;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM7C"}
@@ -0,0 +1,30 @@
1
+ import { categoryForUnicodeGroup } from "../categories.js";
2
+ const SKIN_TONE_CODEPOINTS = new Set(["U+1F3FB", "U+1F3FC", "U+1F3FD", "U+1F3FE", "U+1F3FF"]);
3
+ export function normalizeEmojiEntry(entry) {
4
+ return {
5
+ ...entry,
6
+ slug: slugify(entry.name),
7
+ category: categoryForUnicodeGroup(entry.group),
8
+ keywords: keywordsForName(entry.name),
9
+ hasSkinTone: entry.codepoints.some((codepoint) => SKIN_TONE_CODEPOINTS.has(codepoint)),
10
+ isSequence: entry.codepoints.length > 1,
11
+ };
12
+ }
13
+ export function normalizeEmojiEntries(entries) {
14
+ return entries.map(normalizeEmojiEntry);
15
+ }
16
+ export function slugify(value) {
17
+ return value
18
+ .toLowerCase()
19
+ .replace(/&/gu, " and ")
20
+ .replace(/[^a-z0-9]+/gu, "-")
21
+ .replace(/^-|-$/gu, "");
22
+ }
23
+ function keywordsForName(name) {
24
+ return [
25
+ ...new Set(name
26
+ .toLowerCase()
27
+ .split(/[^a-z0-9]+/u)
28
+ .filter(Boolean)),
29
+ ];
30
+ }
@@ -0,0 +1,5 @@
1
+ import type { EmojiCategory, EmojiRecord } from "./types.js";
2
+ export declare function searchEmojis(emojis: readonly EmojiRecord[], query: string): EmojiRecord[];
3
+ export declare function groupByCategory(emojis: readonly EmojiRecord[]): Partial<Record<EmojiCategory, EmojiRecord[]>>;
4
+ export declare function findEmoji(emojis: readonly EmojiRecord[], value: string): EmojiRecord | undefined;
5
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE7D,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,CAazF;AAED,wBAAgB,eAAe,CAC9B,MAAM,EAAE,SAAS,WAAW,EAAE,GAC5B,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,WAAW,EAAE,CAAC,CAAC,CAM/C;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAWhG"}
package/dist/search.js ADDED
@@ -0,0 +1,28 @@
1
+ export function searchEmojis(emojis, query) {
2
+ const normalizedQuery = query.trim().toLowerCase();
3
+ if (!normalizedQuery)
4
+ return [...emojis];
5
+ return emojis.filter((emoji) => {
6
+ return (emoji.emoji === query ||
7
+ emoji.name.toLowerCase().includes(normalizedQuery) ||
8
+ emoji.slug.includes(normalizedQuery) ||
9
+ emoji.keywords.some((keyword) => keyword.includes(normalizedQuery)) ||
10
+ emoji.codepoints.some((codepoint) => codepoint.toLowerCase() === normalizedQuery));
11
+ });
12
+ }
13
+ export function groupByCategory(emojis) {
14
+ return emojis.reduce((groups, emoji) => {
15
+ groups[emoji.category] ??= [];
16
+ groups[emoji.category]?.push(emoji);
17
+ return groups;
18
+ }, {});
19
+ }
20
+ export function findEmoji(emojis, value) {
21
+ const normalizedValue = value.trim().toLowerCase();
22
+ return emojis.find((emoji) => {
23
+ return (emoji.emoji === value ||
24
+ emoji.slug === normalizedValue ||
25
+ emoji.name.toLowerCase() === normalizedValue ||
26
+ emoji.codepoints.some((codepoint) => codepoint.toLowerCase() === normalizedValue));
27
+ });
28
+ }
@@ -0,0 +1,25 @@
1
+ export type EmojiQualification = "fully-qualified" | "minimally-qualified" | "unqualified" | "component";
2
+ export type EmojiCategory = "faces" | "people" | "animals-nature" | "food-drink" | "travel-places" | "activities" | "objects" | "symbols" | "flags" | "components" | "other";
3
+ export interface UnicodeEmojiEntry {
4
+ emoji: string;
5
+ codepoints: string[];
6
+ qualification: EmojiQualification;
7
+ emojiVersion: string;
8
+ name: string;
9
+ group: string;
10
+ subgroup: string;
11
+ }
12
+ export interface EmojiRecord extends UnicodeEmojiEntry {
13
+ slug: string;
14
+ category: EmojiCategory;
15
+ keywords: string[];
16
+ hasSkinTone: boolean;
17
+ isSequence: boolean;
18
+ }
19
+ export interface EmojiRegistrySnapshot {
20
+ generatedAt: string;
21
+ source: string;
22
+ count: number;
23
+ emojis: EmojiRecord[];
24
+ }
25
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAC3B,iBAAiB,GACjB,qBAAqB,GACrB,aAAa,GACb,WAAW,CAAC;AAEf,MAAM,MAAM,aAAa,GACtB,OAAO,GACP,QAAQ,GACR,gBAAgB,GAChB,YAAY,GACZ,eAAe,GACf,YAAY,GACZ,SAAS,GACT,SAAS,GACT,OAAO,GACP,YAAY,GACZ,OAAO,CAAC;AAEX,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,aAAa,EAAE,kBAAkB,CAAC;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAY,SAAQ,iBAAiB;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,aAAa,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,EAAE,CAAC;CACtB"}
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "emojistry",
3
+ "version": "1.0.0",
4
+ "description": "Versioned emoji registry, Unicode ingestion, categorization, and search data for apps.",
5
+ "license": "MIT",
6
+ "module": "dist/index.js",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "type": "module",
10
+ "private": false,
11
+ "sideEffects": false,
12
+ "files": [
13
+ "dist",
14
+ "data/generated",
15
+ "README.md"
16
+ ],
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.js",
24
+ "default": "./dist/index.js"
25
+ },
26
+ "./data": "./data/generated/emojis.json",
27
+ "./data/emojis.json": "./data/generated/emojis.json",
28
+ "./package.json": "./package.json"
29
+ },
30
+ "scripts": {
31
+ "build": "rm -rf dist && tsc -p tsconfig.build.json",
32
+ "dev": "bun run src/cli.ts",
33
+ "generate": "bun run src/cli.ts generate",
34
+ "server": "bun run src/server.ts",
35
+ "start": "bun run src/server.ts",
36
+ "worker:dev": "bunx wrangler dev",
37
+ "worker:deploy": "bunx wrangler deploy",
38
+ "lint": "eslint .",
39
+ "lint:fix": "eslint . --fix",
40
+ "format": "prettier --write .",
41
+ "format:check": "prettier --check .",
42
+ "check": "bun run typecheck && bun run lint && bun run format:check && bun test",
43
+ "pack:dry": "npm pack --dry-run",
44
+ "prepack": "bun run check && bun run build",
45
+ "test": "bun test",
46
+ "typecheck": "bunx tsc --noEmit"
47
+ },
48
+ "devDependencies": {
49
+ "@eslint/js": "^10.0.1",
50
+ "@types/bun": "latest",
51
+ "eslint": "^10.5.0",
52
+ "prettier": "^3.8.4",
53
+ "typescript": "^6.0.3",
54
+ "typescript-eslint": "^8.61.0"
55
+ }
56
+ }