diff --git a/package.json b/package.json index a9fe69b9..47f34c59 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "homepage": "https://github.com/webosbrew/youtube-webos#readme", "dependencies": { "@babel/runtime-corejs3": "^7.29.2", + "@twemoji/api": "^17.0.2", "core-js-pure": "^3.49.0", "regenerator-runtime": "^0.14.1", "tiny-sha256": "^1.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 282f00a6..117e831d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: '@babel/runtime-corejs3': specifier: ^7.29.2 version: 7.29.2 + '@twemoji/api': + specifier: ^17.0.2 + version: 17.0.2 core-js-pure: specifier: ^3.49.0 version: 3.49.0 @@ -1202,6 +1205,12 @@ packages: peerDependencies: eslint: ^9.0.0 || ^10.0.0 + '@twemoji/api@17.0.2': + resolution: {integrity: sha512-5xIdBcFLpRW4goXNdNNz497TzMHF2a76yElEaqISxVPj+KpJB82KuXHczfjhhTCsPaP1lAhM3qPtvAhMG7e71A==} + + '@twemoji/parser@17.0.1': + resolution: {integrity: sha512-Uiq5sq1Wx91Y6C0DczMlu4Gj4nC/0z8UIhT7S53hi/JATaS1oLM5jXygjot7STtyVoIagfnpsBCWaNy3ayfyFw==} + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -2489,6 +2498,9 @@ packages: jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + jsonfile@5.0.0: + resolution: {integrity: sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w==} + jsonschema@1.5.0: resolution: {integrity: sha512-K+A9hhqbn0f3pJX17Q/7H6yQfD/5OXgdrR5UE12gMXCiN9D5Xq2o5mddV2QEcX/bjla99ASsAAQUyMCCRWAEhw==} @@ -4923,6 +4935,15 @@ snapshots: estraverse: 5.3.0 picomatch: 4.0.3 + '@twemoji/api@17.0.2': + dependencies: + '@twemoji/parser': 17.0.1 + fs-extra: 8.1.0 + jsonfile: 5.0.0 + universalify: 0.1.2 + + '@twemoji/parser@17.0.1': {} + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.29.0 @@ -6276,6 +6297,12 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 + jsonfile@5.0.0: + dependencies: + universalify: 0.1.2 + optionalDependencies: + graceful-fs: 4.2.11 + jsonschema@1.5.0: {} jsprim@1.4.2: diff --git a/src/emoji-font.css b/src/emoji-font.css new file mode 100644 index 00000000..5bc44f4d --- /dev/null +++ b/src/emoji-font.css @@ -0,0 +1,6 @@ +img.emoji { + height: 1em; + width: 1em; + margin: 0 0.05em 0 0.1em; + vertical-align: -0.1em; +} diff --git a/src/emoji-font.ts b/src/emoji-font.ts new file mode 100644 index 00000000..90590c93 --- /dev/null +++ b/src/emoji-font.ts @@ -0,0 +1,24 @@ +import twemoji from '@twemoji/api'; + +import './emoji-font.css'; + +const YT_FORMATTED_STR_TAG = 'yt-formatted-string'; + +const emojiObs = new MutationObserver((mutations) => { + mutations + .flatMap((mut) => Array.from(mut.addedNodes)) + .filter((node) => node instanceof HTMLElement) + .flatMap((elem) => + Array.from( + elem.querySelectorAll(YT_FORMATTED_STR_TAG) as NodeListOf + ) + ) + .forEach((elem) => void twemoji.parse(elem, { size: '72x72' })); +}); + +// twemoji expects the charset to be UTF-8 +if (document.characterSet === 'UTF-8') { + emojiObs.observe(document.body, { childList: true, subtree: true }); +} else { + console.warn('document charset not utf-8. Emoji replacement disabled.'); +} diff --git a/src/userScript.ts b/src/userScript.ts index 1edea6b7..bc26dfb0 100644 --- a/src/userScript.ts +++ b/src/userScript.ts @@ -29,3 +29,4 @@ import './remove-endscreen'; import './hooks'; import './block-webos-cast'; import './auto-account-select'; +import './emoji-font';