convert.mjs 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import { minUTF32, startUTF32Pair1, startUTF32Pair2, endUTF32Pair } from './data.mjs';
  2. function getEmojiCodePoint(code) {
  3. return parseInt(code, 16);
  4. }
  5. function utf32FirstNum(code) {
  6. return (code - minUTF32 >> 10 | 0) + startUTF32Pair1;
  7. }
  8. function utf32SecondNum(code) {
  9. return (code - minUTF32 & 1023) + startUTF32Pair2;
  10. }
  11. function splitUTF32Number(code) {
  12. if (code >= minUTF32) {
  13. return [utf32FirstNum(code), utf32SecondNum(code)];
  14. }
  15. }
  16. function isUTF32SplitNumber(value) {
  17. if (value >= startUTF32Pair1) {
  18. if (value < startUTF32Pair2) {
  19. return 1;
  20. }
  21. if (value < endUTF32Pair) {
  22. return 2;
  23. }
  24. }
  25. return false;
  26. }
  27. function mergeUTF32Numbers(part1, part2) {
  28. if (part1 < startUTF32Pair1 || part1 >= startUTF32Pair2 || part2 < startUTF32Pair2 || part2 >= endUTF32Pair) {
  29. return;
  30. }
  31. return (part1 - startUTF32Pair1 << 10) + (part2 - startUTF32Pair2) + minUTF32;
  32. }
  33. function getEmojiUnicode(code) {
  34. return String.fromCodePoint(
  35. typeof code === "number" ? code : getEmojiCodePoint(code)
  36. );
  37. }
  38. function convertEmojiSequenceToUTF16(numbers) {
  39. const results = [];
  40. for (let i = 0; i < numbers.length; i++) {
  41. const code = numbers[i];
  42. if (code >= minUTF32) {
  43. results.push(utf32FirstNum(code));
  44. results.push(utf32SecondNum(code));
  45. } else {
  46. results.push(code);
  47. }
  48. }
  49. return results;
  50. }
  51. function convertEmojiSequenceToUTF32(numbers, throwOnError = true) {
  52. const results = [];
  53. for (let i = 0; i < numbers.length; i++) {
  54. const code = numbers[i];
  55. if (code >= minUTF32) {
  56. results.push(code);
  57. continue;
  58. }
  59. const part = isUTF32SplitNumber(code);
  60. if (!part) {
  61. results.push(code);
  62. continue;
  63. }
  64. if (part === 1 && numbers.length > i + 1) {
  65. const merged = mergeUTF32Numbers(code, numbers[i + 1]);
  66. if (merged) {
  67. i++;
  68. results.push(merged);
  69. continue;
  70. }
  71. }
  72. if (throwOnError) {
  73. const nextCode = numbers[i + 1];
  74. throw new Error(
  75. `Invalid UTF-16 sequence: ${code.toString(16)}-${nextCode ? nextCode.toString(16) : "undefined"}`
  76. );
  77. }
  78. results.push(code);
  79. }
  80. return results;
  81. }
  82. export { convertEmojiSequenceToUTF16, convertEmojiSequenceToUTF32, getEmojiCodePoint, getEmojiUnicode, isUTF32SplitNumber, mergeUTF32Numbers, splitUTF32Number };