Implement the script to generate emojis

This commit is contained in:
Hakan Shehu
2024-11-08 11:12:13 +01:00
parent 7bc91a2d8d
commit ca45b87bcb
5 changed files with 472 additions and 22 deletions

Binary file not shown.

254
pnpm-lock.yaml generated
View File

@@ -521,6 +521,28 @@ importers:
specifier: ^1.6.0
version: 1.6.0(@types/node@22.9.0)
scripts:
dependencies:
'@emoji-mart/data':
specifier: ^1.2.1
version: 1.2.1
archiver:
specifier: ^7.0.1
version: 7.0.1
ulid:
specifier: ^2.3.0
version: 2.3.0
devDependencies:
'@types/archiver':
specifier: ^6.0.3
version: 6.0.3
ts-node:
specifier: ^10.9.2
version: 10.9.2(@types/node@22.9.0)(typescript@5.6.3)
typescript:
specifier: ^5.6.3
version: 5.6.3
packages:
7zip-bin@5.2.0:
@@ -861,6 +883,9 @@ packages:
'@emnapi/runtime@1.3.1':
resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==}
'@emoji-mart/data@1.2.1':
resolution: {integrity: sha512-no2pQMWiBy6gpBEiqGeU77/bFejDqUTRY7KX+0+iur13op3bqUsXdnwoZs6Xb1zbv0gAj5VvS1PWoUUckSr5Dw==}
'@esbuild/aix-ppc64@0.21.5':
resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
engines: {node: '>=12'}
@@ -2417,6 +2442,9 @@ packages:
'@tsconfig/node16@1.0.4':
resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
'@types/archiver@6.0.3':
resolution: {integrity: sha512-a6wUll6k3zX6qs5KlxIggs1P1JcYJaTCx2gnlr+f0S1yd2DoaEwoIK10HmBaLnZwWneBz+JBm0dwcZu0zECBcQ==}
'@types/babel__core@7.20.5':
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
@@ -2543,6 +2571,9 @@ packages:
'@types/react@18.3.12':
resolution: {integrity: sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==}
'@types/readdir-glob@1.1.5':
resolution: {integrity: sha512-raiuEPUYqXu+nvtY2Pe8s8FEmZ3x5yAH4VkLdihcPdalvsHltomrRC9BzuStrJ9yk06470hS0Crw0f1pXqD+Hg==}
'@types/responselike@1.0.3':
resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==}
@@ -2717,6 +2748,10 @@ packages:
abbrev@1.1.1:
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
abort-controller@3.0.0:
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
engines: {node: '>=6.5'}
accepts@1.3.8:
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
engines: {node: '>= 0.6'}
@@ -2798,10 +2833,18 @@ packages:
resolution: {integrity: sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==}
engines: {node: '>= 10'}
archiver-utils@5.0.2:
resolution: {integrity: sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==}
engines: {node: '>= 14'}
archiver@5.3.2:
resolution: {integrity: sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==}
engines: {node: '>= 10'}
archiver@7.0.1:
resolution: {integrity: sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==}
engines: {node: '>= 14'}
are-we-there-yet@2.0.0:
resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==}
engines: {node: '>=10'}
@@ -2898,9 +2941,15 @@ packages:
axios@1.7.7:
resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==}
b4a@1.6.7:
resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==}
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
bare-events@2.5.0:
resolution: {integrity: sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==}
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
@@ -2956,6 +3005,10 @@ packages:
buffer-crc32@0.2.13:
resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
buffer-crc32@1.0.0:
resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==}
engines: {node: '>=8.0.0'}
buffer-equal@1.0.1:
resolution: {integrity: sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==}
engines: {node: '>=0.4'}
@@ -2966,6 +3019,9 @@ packages:
buffer@5.7.1:
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
buffer@6.0.3:
resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
builder-util-runtime@9.2.10:
resolution: {integrity: sha512-6p/gfG1RJSQeIbz8TK5aPNkoztgY1q5TgmGFMAXcY8itsGW6Y2ld1ALsZ5UJn8rog7hKF3zHx5iQbNQ8uLcRlw==}
engines: {node: '>=12.0.0'}
@@ -3124,6 +3180,10 @@ packages:
resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==}
engines: {node: '>= 10'}
compress-commons@6.0.2:
resolution: {integrity: sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==}
engines: {node: '>= 14'}
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
@@ -3181,6 +3241,10 @@ packages:
resolution: {integrity: sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==}
engines: {node: '>= 10'}
crc32-stream@6.0.0:
resolution: {integrity: sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==}
engines: {node: '>= 14'}
crc@3.8.0:
resolution: {integrity: sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==}
@@ -3604,6 +3668,14 @@ packages:
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
engines: {node: '>= 0.6'}
event-target-shim@5.0.1:
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
engines: {node: '>=6'}
events@3.3.0:
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
engines: {node: '>=0.8.x'}
execa@8.0.1:
resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
engines: {node: '>=16.17'}
@@ -3631,6 +3703,9 @@ packages:
fast-diff@1.3.0:
resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
fast-fifo@1.3.2:
resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==}
fast-glob@3.3.2:
resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
engines: {node: '>=8.6.0'}
@@ -4074,6 +4149,10 @@ packages:
resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==}
engines: {node: '>= 0.4'}
is-stream@2.0.1:
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
engines: {node: '>=8'}
is-stream@3.0.0:
resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -4909,6 +4988,10 @@ packages:
process-nextick-args@2.0.1:
resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
process@0.11.10:
resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
engines: {node: '>= 0.6.0'}
progress@2.0.3:
resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
engines: {node: '>=0.4.0'}
@@ -5006,6 +5089,9 @@ packages:
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
queue-tick@1.0.1:
resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==}
quick-lru@5.1.1:
resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
engines: {node: '>=10'}
@@ -5156,6 +5242,10 @@ packages:
resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
engines: {node: '>= 6'}
readable-stream@4.5.2:
resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
readdir-glob@1.1.3:
resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==}
@@ -5404,6 +5494,9 @@ packages:
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
engines: {node: '>=10.0.0'}
streamx@2.20.1:
resolution: {integrity: sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA==}
string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
@@ -5511,6 +5604,9 @@ packages:
resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
engines: {node: '>=6'}
tar-stream@3.1.7:
resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==}
tar@6.2.1:
resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
engines: {node: '>=10'}
@@ -5518,6 +5614,9 @@ packages:
temp-file@3.4.0:
resolution: {integrity: sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==}
text-decoder@1.2.1:
resolution: {integrity: sha512-x9v3H/lTKIJKQQe7RPQkLfKAnc9lUTkWDypIQgTzPJAq+5/GCDHonmshfvlsNSj58yyshbIJJDLmU15qNERrXQ==}
text-table@0.2.0:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
@@ -6006,6 +6105,10 @@ packages:
resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==}
engines: {node: '>= 10'}
zip-stream@6.0.1:
resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==}
engines: {node: '>= 14'}
zod@3.23.8:
resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==}
@@ -6665,7 +6768,6 @@ snapshots:
'@cspotcode/source-map-support@0.8.1':
dependencies:
'@jridgewell/trace-mapping': 0.3.9
optional: true
'@develar/schema-utils@2.6.5':
dependencies:
@@ -6765,6 +6867,8 @@ snapshots:
tslib: 2.8.1
optional: true
'@emoji-mart/data@1.2.1': {}
'@esbuild/aix-ppc64@0.21.5':
optional: true
@@ -7073,7 +7177,6 @@ snapshots:
dependencies:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.0
optional: true
'@malept/cross-spawn-promise@1.1.1':
dependencies:
@@ -8231,17 +8334,17 @@ snapshots:
'@tootallnate/once@2.0.0': {}
'@tsconfig/node10@1.0.11':
optional: true
'@tsconfig/node10@1.0.11': {}
'@tsconfig/node12@1.0.11':
optional: true
'@tsconfig/node12@1.0.11': {}
'@tsconfig/node14@1.0.3':
optional: true
'@tsconfig/node14@1.0.3': {}
'@tsconfig/node16@1.0.4':
optional: true
'@tsconfig/node16@1.0.4': {}
'@types/archiver@6.0.3':
dependencies:
'@types/readdir-glob': 1.1.5
'@types/babel__core@7.20.5':
dependencies:
@@ -8400,6 +8503,10 @@ snapshots:
'@types/prop-types': 15.7.13
csstype: 3.1.3
'@types/readdir-glob@1.1.5':
dependencies:
'@types/node': 22.9.0
'@types/responselike@1.0.3':
dependencies:
'@types/node': 22.9.0
@@ -8644,6 +8751,10 @@ snapshots:
abbrev@1.1.1: {}
abort-controller@3.0.0:
dependencies:
event-target-shim: 5.0.1
accepts@1.3.8:
dependencies:
mime-types: 2.1.35
@@ -8761,6 +8872,16 @@ snapshots:
normalize-path: 3.0.0
readable-stream: 3.6.2
archiver-utils@5.0.2:
dependencies:
glob: 10.4.5
graceful-fs: 4.2.11
is-stream: 2.0.1
lazystream: 1.0.1
lodash: 4.17.21
normalize-path: 3.0.0
readable-stream: 4.5.2
archiver@5.3.2:
dependencies:
archiver-utils: 2.1.0
@@ -8771,13 +8892,22 @@ snapshots:
tar-stream: 2.2.0
zip-stream: 4.1.1
archiver@7.0.1:
dependencies:
archiver-utils: 5.0.2
async: 3.2.6
buffer-crc32: 1.0.0
readable-stream: 4.5.2
readdir-glob: 1.1.3
tar-stream: 3.1.7
zip-stream: 6.0.1
are-we-there-yet@2.0.0:
dependencies:
delegates: 1.0.0
readable-stream: 3.6.2
arg@4.1.3:
optional: true
arg@4.1.3: {}
arg@5.0.2: {}
@@ -8894,8 +9024,13 @@ snapshots:
transitivePeerDependencies:
- debug
b4a@1.6.7: {}
balanced-match@1.0.2: {}
bare-events@2.5.0:
optional: true
base64-js@1.5.1: {}
bcrypt@5.1.1(encoding@0.1.13):
@@ -8973,6 +9108,8 @@ snapshots:
buffer-crc32@0.2.13: {}
buffer-crc32@1.0.0: {}
buffer-equal@1.0.1: {}
buffer-from@1.1.2: {}
@@ -8982,6 +9119,11 @@ snapshots:
base64-js: 1.5.1
ieee754: 1.2.1
buffer@6.0.3:
dependencies:
base64-js: 1.5.1
ieee754: 1.2.1
builder-util-runtime@9.2.10:
dependencies:
debug: 4.3.7
@@ -9184,6 +9326,14 @@ snapshots:
normalize-path: 3.0.0
readable-stream: 3.6.2
compress-commons@6.0.2:
dependencies:
crc-32: 1.2.2
crc32-stream: 6.0.0
is-stream: 2.0.1
normalize-path: 3.0.0
readable-stream: 4.5.2
concat-map@0.0.1: {}
concat-stream@1.6.2:
@@ -9233,13 +9383,17 @@ snapshots:
crc-32: 1.2.2
readable-stream: 3.6.2
crc32-stream@6.0.0:
dependencies:
crc-32: 1.2.2
readable-stream: 4.5.2
crc@3.8.0:
dependencies:
buffer: 5.7.1
optional: true
create-require@1.1.1:
optional: true
create-require@1.1.1: {}
crelt@1.0.6: {}
@@ -9348,8 +9502,7 @@ snapshots:
diff-sequences@29.6.3: {}
diff@4.0.2:
optional: true
diff@4.0.2: {}
diff@7.0.0: {}
@@ -9833,6 +9986,10 @@ snapshots:
etag@1.8.1: {}
event-target-shim@5.0.1: {}
events@3.3.0: {}
execa@8.0.1:
dependencies:
cross-spawn: 7.0.3
@@ -9900,6 +10057,8 @@ snapshots:
fast-diff@1.3.0: {}
fast-fifo@1.3.2: {}
fast-glob@3.3.2:
dependencies:
'@nodelib/fs.stat': 2.0.5
@@ -10372,6 +10531,8 @@ snapshots:
dependencies:
call-bind: 1.0.7
is-stream@2.0.1: {}
is-stream@3.0.0: {}
is-string@1.0.7:
@@ -10590,8 +10751,7 @@ snapshots:
dependencies:
semver: 6.3.1
make-error@1.3.6:
optional: true
make-error@1.3.6: {}
markdown-it@14.1.0:
dependencies:
@@ -11076,6 +11236,8 @@ snapshots:
process-nextick-args@2.0.1: {}
process@0.11.10: {}
progress@2.0.3: {}
promise-retry@2.0.1:
@@ -11216,6 +11378,8 @@ snapshots:
queue-microtask@1.2.3: {}
queue-tick@1.0.1: {}
quick-lru@5.1.1: {}
range-parser@1.2.1: {}
@@ -11367,6 +11531,14 @@ snapshots:
string_decoder: 1.3.0
util-deprecate: 1.0.2
readable-stream@4.5.2:
dependencies:
abort-controller: 3.0.0
buffer: 6.0.3
events: 3.3.0
process: 0.11.10
string_decoder: 1.3.0
readdir-glob@1.1.3:
dependencies:
minimatch: 5.1.6
@@ -11678,6 +11850,14 @@ snapshots:
streamsearch@1.1.0: {}
streamx@2.20.1:
dependencies:
fast-fifo: 1.3.2
queue-tick: 1.0.1
text-decoder: 1.2.1
optionalDependencies:
bare-events: 2.5.0
string-width@4.2.3:
dependencies:
emoji-regex: 8.0.0
@@ -11838,6 +12018,12 @@ snapshots:
inherits: 2.0.4
readable-stream: 3.6.2
tar-stream@3.1.7:
dependencies:
b4a: 1.6.7
fast-fifo: 1.3.2
streamx: 2.20.1
tar@6.2.1:
dependencies:
chownr: 2.0.0
@@ -11852,6 +12038,8 @@ snapshots:
async-exit-hook: 2.0.1
fs-extra: 10.1.0
text-decoder@1.2.1: {}
text-table@0.2.0: {}
thenify-all@1.6.0:
@@ -11932,6 +12120,24 @@ snapshots:
yn: 3.1.1
optional: true
ts-node@10.9.2(@types/node@22.9.0)(typescript@5.6.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@tsconfig/node10': 1.0.11
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.4
'@types/node': 22.9.0
acorn: 8.14.0
acorn-walk: 8.3.4
arg: 4.1.3
create-require: 1.1.1
diff: 4.0.2
make-error: 1.3.6
typescript: 5.6.3
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
ts-pattern@5.5.0: {}
tsconfig-paths@3.15.0:
@@ -12120,8 +12326,7 @@ snapshots:
uuid@9.0.1: {}
v8-compile-cache-lib@3.0.1:
optional: true
v8-compile-cache-lib@3.0.1: {}
vary@1.1.2: {}
@@ -12329,8 +12534,7 @@ snapshots:
dependencies:
lib0: 0.2.98
yn@3.1.1:
optional: true
yn@3.1.1: {}
yocto-queue@0.1.0: {}
@@ -12342,4 +12546,10 @@ snapshots:
compress-commons: 4.1.2
readable-stream: 3.6.2
zip-stream@6.0.1:
dependencies:
archiver-utils: 5.0.2
compress-commons: 6.0.2
readable-stream: 4.5.2
zod@3.23.8: {}

19
scripts/package.json Normal file
View File

@@ -0,0 +1,19 @@
{
"name": "@colanode/scripts",
"version": "1.0.0",
"private": true,
"type": "module",
"scripts": {
"generate:emojis": "node --loader ts-node/esm src/generate-emojis.ts"
},
"devDependencies": {
"@types/archiver": "^6.0.3",
"ts-node": "^10.9.2",
"typescript": "^5.6.3"
},
"dependencies": {
"@emoji-mart/data": "^1.2.1",
"archiver": "^7.0.1",
"ulid": "^2.3.0"
}
}

View File

@@ -0,0 +1,213 @@
import fs from 'fs';
import path from 'path';
import { EmojiMartData } from '@emoji-mart/data';
import { monotonicFactory } from 'ulid';
import archiver from 'archiver';
const ulid = monotonicFactory();
type EmojiMartI18n = {
categories: Record<string, string>;
};
const emojiMartDataPath = 'node_modules/@emoji-mart/data/sets/15/twitter.json';
const emojiMartData = JSON.parse(
fs.readFileSync(emojiMartDataPath, 'utf-8')
) as EmojiMartData;
const i18nPath = 'node_modules/@emoji-mart/data/i18n/en.json';
const i18nData = JSON.parse(
fs.readFileSync(i18nPath, 'utf-8')
) as EmojiMartI18n;
const EMOJIS_DIR_PATH = 'emojis';
const EMOJIS_METADATA_FILE_PATH = 'emojis/emojis.json';
const ZIP_FILE_PATH = 'emojis.zip';
type EmojiMetadata = {
categories: EmojiCategory[];
emojis: Record<string, Emoji>;
};
type Emoji = {
id: string;
code: string;
name: string;
tags: string[];
emoticons: string[] | undefined;
skins: EmojiSkin[];
};
type EmojiCategory = {
id: string;
name: string;
emojis: string[];
};
type EmojiSkin = {
id: string;
unified: string;
};
const generateEmojiId = () => {
return ulid().toLowerCase() + 'em';
};
const generateEmojiSkinId = () => {
return ulid().toLowerCase() + 'es';
};
const getEmojiUrl = (unified: string) => {
let file = unified;
// Fix for "copyright" and "trademark" emojis
if (file.substring(0, 2) == '00') {
file = file.substring(2);
// Fix for keycap emojis
const regex = /-fe0f/i;
file = file.replace(regex, '');
}
if (file.startsWith('1f441')) {
const regex = /-fe0f/gi;
file = file.replace(regex, '');
}
if (file.endsWith('-fe0f')) {
const parts = file.split('-');
if (parts.length === 2 && parts[0]) {
file = parts[0];
}
}
return `https://cdn.jsdelivr.net/gh/jdecked/twemoji@15.1.0/assets/svg/${file}.svg`;
};
const generateMetadata = () => {
const existingEmojis: EmojiMetadata = fs.existsSync(EMOJIS_METADATA_FILE_PATH)
? (JSON.parse(
fs.readFileSync(EMOJIS_METADATA_FILE_PATH, 'utf-8')
) as EmojiMetadata)
: { emojis: {}, categories: [] };
const result: EmojiMetadata = {
categories: [],
emojis: {},
};
const idMap: Record<string, string> = {};
for (const emojiMartItem of Object.values(emojiMartData.emojis)) {
const existingEmoji = Object.values(existingEmojis.emojis).find(
(emoji) => emoji.code === emojiMartItem.id
);
const emojiId = existingEmoji ? existingEmoji.id : generateEmojiId();
const emoji: Emoji = {
id: emojiId,
code: emojiMartItem.id,
name: emojiMartItem.name,
tags: emojiMartItem.keywords,
emoticons: emojiMartItem.emoticons,
skins: emojiMartItem.skins.map((skin) => ({
id:
existingEmoji?.skins.find((s) => s.unified === skin.unified)?.id ??
generateEmojiSkinId(),
unified: skin.unified,
})),
};
idMap[emoji.code] = emoji.id;
result.emojis[emojiId] = emoji;
}
for (const emojiMartCategory of Object.values(emojiMartData.categories)) {
const i18nCategory = i18nData.categories[emojiMartCategory.id];
if (!i18nCategory) {
throw new Error(
`Category ${emojiMartCategory.id} not found in i18n data`
);
}
const categoryEmojis: string[] = [];
for (const emoji of emojiMartCategory.emojis) {
if (!idMap[emoji]) {
throw new Error(`Emoji ${emoji} not found in idMap`);
}
categoryEmojis.push(idMap[emoji]);
}
const category: EmojiCategory = {
id: emojiMartCategory.id,
name: i18nCategory,
emojis: categoryEmojis,
};
result.categories.push(category);
}
fs.writeFileSync(EMOJIS_METADATA_FILE_PATH, JSON.stringify(result, null, 2));
};
const generateImages = async () => {
if (!fs.existsSync(EMOJIS_DIR_PATH)) {
fs.mkdirSync(EMOJIS_DIR_PATH);
}
const emojis = JSON.parse(
fs.readFileSync(EMOJIS_METADATA_FILE_PATH, 'utf-8')
) as EmojiMetadata;
for (const emoji of Object.values(emojis.emojis)) {
for (const skin of emoji.skins) {
const fileName = `${skin.id}.svg`;
const filePath = path.join(EMOJIS_DIR_PATH, fileName);
if (fs.existsSync(filePath)) {
continue;
}
const url = getEmojiUrl(skin.unified);
console.log(`Downloading ${url} to ${filePath}`);
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to download ${url}`);
}
const svg = await response.text();
fs.writeFileSync(filePath, svg);
// Rate limit
await new Promise((resolve) => setTimeout(resolve, 10));
}
}
};
const zipEmojis = async () => {
await new Promise((resolve, reject) => {
const output = fs.createWriteStream(ZIP_FILE_PATH);
const archive = archiver('zip', { zlib: { level: 9 } });
output.on('close', () => {
console.log(`Zipped ${archive.pointer()} total bytes`);
resolve(void 0);
});
archive.on('error', (err) => reject(err));
archive.pipe(output);
archive.directory(EMOJIS_DIR_PATH, false);
archive.finalize();
});
};
const generateEmojis = async () => {
generateMetadata();
await generateImages();
await zipEmojis();
};
generateEmojis();

8
scripts/tsconfig.json Normal file
View File

@@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Scripts",
"extends": "../tsconfig.base.json",
"compilerOptions": {
"resolveJsonModule": true
}
}