fix(emojos): fix emojos on Ubuntu and Chrome on Windows (#661)
* fix(emojos): fix emojos on Ubuntu and Chrome on Windows * fixup * start working on unit tests * fixup * add more tests and fix emoji
This commit is contained in:
parent
4e35c82f94
commit
4124da2439
|
@ -56,6 +56,7 @@ matrix:
|
||||||
include:
|
include:
|
||||||
- env: BROWSER=chrome:headless COMMAND=test-browser-suite0
|
- env: BROWSER=chrome:headless COMMAND=test-browser-suite0
|
||||||
- env: BROWSER=chrome:headless COMMAND=test-browser-suite1
|
- env: BROWSER=chrome:headless COMMAND=test-browser-suite1
|
||||||
|
- env: COMMAND=test-unit
|
||||||
- env: COMMAND=deploy-all-travis
|
- env: COMMAND=deploy-all-travis
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- env: COMMAND=deploy-all-travis
|
- env: COMMAND=deploy-all-travis
|
||||||
|
|
|
@ -102,3 +102,8 @@ This is also available locally after `npm run build` at `.sapper/client/report.h
|
||||||
7. Run `rm -fr mastodon/` and `npm run run-mastodon` to confirm everything's working
|
7. Run `rm -fr mastodon/` and `npm run run-mastodon` to confirm everything's working
|
||||||
|
|
||||||
Check `mastodon.log` if you have any issues.
|
Check `mastodon.log` if you have any issues.
|
||||||
|
|
||||||
|
## Unit tests
|
||||||
|
|
||||||
|
There are also some unit tests that run in Node using Mocha. You can find them in `tests/unit` and
|
||||||
|
run them using `npm run test-unit`.
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
if [[ "$COMMAND" = deploy-all-travis ]]; then
|
if [[ "$COMMAND" = deploy-all-travis || "$COMMAND" = test-unit ]]; then
|
||||||
exit 0 # no need to setup mastodon in this case
|
exit 0 # no need to setup mastodon in this case
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
79
package-lock.json
generated
79
package-lock.json
generated
|
@ -508,7 +508,7 @@
|
||||||
},
|
},
|
||||||
"util": {
|
"util": {
|
||||||
"version": "0.10.3",
|
"version": "0.10.3",
|
||||||
"resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
|
"resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz",
|
||||||
"integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
|
"integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"inherits": "2.0.1"
|
"inherits": "2.0.1"
|
||||||
|
@ -1621,6 +1621,12 @@
|
||||||
"base64-js": "^1.1.2"
|
"base64-js": "^1.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"browser-stdout": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"browserify-aes": {
|
"browserify-aes": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
|
||||||
|
@ -3444,6 +3450,12 @@
|
||||||
"repeating": "^2.0.0"
|
"repeating": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"diff": {
|
||||||
|
"version": "3.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
|
||||||
|
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"diffie-hellman": {
|
"diffie-hellman": {
|
||||||
"version": "5.0.3",
|
"version": "5.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
|
||||||
|
@ -4991,6 +5003,12 @@
|
||||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
||||||
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
|
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
|
||||||
},
|
},
|
||||||
|
"growl": {
|
||||||
|
"version": "1.10.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
|
||||||
|
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"gulp-clone": {
|
"gulp-clone": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/gulp-clone/-/gulp-clone-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/gulp-clone/-/gulp-clone-2.0.1.tgz",
|
||||||
|
@ -5161,6 +5179,12 @@
|
||||||
"minimalistic-assert": "^1.0.1"
|
"minimalistic-assert": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"he": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
|
||||||
|
"integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"helmet": {
|
"helmet": {
|
||||||
"version": "3.14.0",
|
"version": "3.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/helmet/-/helmet-3.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/helmet/-/helmet-3.14.0.tgz",
|
||||||
|
@ -6447,6 +6471,59 @@
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mocha": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"browser-stdout": "1.3.1",
|
||||||
|
"commander": "2.15.1",
|
||||||
|
"debug": "3.1.0",
|
||||||
|
"diff": "3.5.0",
|
||||||
|
"escape-string-regexp": "1.0.5",
|
||||||
|
"glob": "7.1.2",
|
||||||
|
"growl": "1.10.5",
|
||||||
|
"he": "1.1.1",
|
||||||
|
"minimatch": "3.0.4",
|
||||||
|
"mkdirp": "0.5.1",
|
||||||
|
"supports-color": "5.4.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"glob": {
|
||||||
|
"version": "7.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
||||||
|
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fs.realpath": "^1.0.0",
|
||||||
|
"inflight": "^1.0.4",
|
||||||
|
"inherits": "2",
|
||||||
|
"minimatch": "^3.0.4",
|
||||||
|
"once": "^1.3.0",
|
||||||
|
"path-is-absolute": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"supports-color": {
|
||||||
|
"version": "5.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
|
||||||
|
"integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"has-flag": "^3.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"moment": {
|
"moment": {
|
||||||
"version": "2.22.2",
|
"version": "2.22.2",
|
||||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz",
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz",
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
"testcafe": "run-s testcafe-suite0 testcafe-suite1",
|
"testcafe": "run-s testcafe-suite0 testcafe-suite1",
|
||||||
"testcafe-suite0": "cross-env-shell testcafe --hostname localhost --skip-js-errors -c 4 $BROWSER tests/spec/0*",
|
"testcafe-suite0": "cross-env-shell testcafe --hostname localhost --skip-js-errors -c 4 $BROWSER tests/spec/0*",
|
||||||
"testcafe-suite1": "cross-env-shell testcafe --hostname localhost --skip-js-errors $BROWSER tests/spec/1*",
|
"testcafe-suite1": "cross-env-shell testcafe --hostname localhost --skip-js-errors $BROWSER tests/spec/1*",
|
||||||
|
"test-unit": "mocha -r esm tests/unit/",
|
||||||
"wait-for-mastodon-to-start": "node -r esm bin/wait-for-mastodon-to-start.js",
|
"wait-for-mastodon-to-start": "node -r esm bin/wait-for-mastodon-to-start.js",
|
||||||
"wait-for-mastodon-data": "node -r esm bin/wait-for-mastodon-data.js",
|
"wait-for-mastodon-data": "node -r esm bin/wait-for-mastodon-data.js",
|
||||||
"globalize-css": "node ./bin/globalize-css.js",
|
"globalize-css": "node ./bin/globalize-css.js",
|
||||||
|
@ -104,7 +105,9 @@
|
||||||
"webpack-bundle-analyzer": "^3.0.3"
|
"webpack-bundle-analyzer": "^3.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"assert": "^1.4.1",
|
||||||
"eslint-plugin-html": "^5.0.0",
|
"eslint-plugin-html": "^5.0.0",
|
||||||
|
"mocha": "^5.2.0",
|
||||||
"now": "^12.0.0",
|
"now": "^12.0.0",
|
||||||
"standard": "^12.0.1",
|
"standard": "^12.0.1",
|
||||||
"testcafe": "^0.23.0"
|
"testcafe": "^0.23.0"
|
||||||
|
|
8
routes/_utils/emojiRegex.js
Normal file
8
routes/_utils/emojiRegex.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import emojiRegex from 'emoji-regex/es2015/text'
|
||||||
|
|
||||||
|
let theEmojiRegex
|
||||||
|
|
||||||
|
export function getEmojiRegex () {
|
||||||
|
theEmojiRegex = theEmojiRegex || emojiRegex() // only init when needed, then cache
|
||||||
|
return theEmojiRegex
|
||||||
|
}
|
|
@ -1,6 +1,11 @@
|
||||||
import { replaceAll } from './strings'
|
import { replaceAll } from './strings'
|
||||||
|
import { replaceEmoji } from './replaceEmoji'
|
||||||
|
|
||||||
export function emojifyText (text, emojis, autoplayGifs) {
|
export function emojifyText (text, emojis, autoplayGifs) {
|
||||||
|
// replace native emoji with wrapped spans so we can give them the proper font-family
|
||||||
|
text = replaceEmoji(text, substring => `<span class="inline-emoji">${substring}</span>`)
|
||||||
|
|
||||||
|
// replace custom emoji
|
||||||
if (emojis) {
|
if (emojis) {
|
||||||
for (let emoji of emojis) {
|
for (let emoji of emojis) {
|
||||||
let urlToUse = autoplayGifs ? emoji.url : emoji.static_url
|
let urlToUse = autoplayGifs ? emoji.url : emoji.static_url
|
||||||
|
@ -13,5 +18,6 @@ export function emojifyText (text, emojis, autoplayGifs) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import { replaceAll } from './strings'
|
import { replaceAll } from './strings'
|
||||||
import emojiRegex from 'emoji-regex/es2015/text.js'
|
import { replaceEmoji } from './replaceEmoji'
|
||||||
|
|
||||||
let theEmojiRegex
|
|
||||||
|
|
||||||
export function removeEmoji (text, emojis) {
|
export function removeEmoji (text, emojis) {
|
||||||
// remove custom emoji
|
// remove custom emoji
|
||||||
|
@ -11,7 +9,6 @@ export function removeEmoji (text, emojis) {
|
||||||
text = replaceAll(text, shortcodeWithColons, '')
|
text = replaceAll(text, shortcodeWithColons, '')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// remove regular emoji
|
// remove native emoji
|
||||||
theEmojiRegex = theEmojiRegex || emojiRegex() // only init when needed, then cache
|
return replaceEmoji(text, () => '').trim()
|
||||||
return text.replace(theEmojiRegex, '').trim()
|
|
||||||
}
|
}
|
||||||
|
|
35
routes/_utils/replaceEmoji.js
Normal file
35
routes/_utils/replaceEmoji.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import { getEmojiRegex } from './emojiRegex'
|
||||||
|
|
||||||
|
// replace emoji in HTML with something else, safely skipping HTML tags
|
||||||
|
export function replaceEmoji (string, replacer) {
|
||||||
|
let output = ''
|
||||||
|
let leftAngleBracketIdx = string.indexOf('<')
|
||||||
|
let currentIdx = 0
|
||||||
|
let emojiRegex = getEmojiRegex()
|
||||||
|
|
||||||
|
function safeReplacer (substring) {
|
||||||
|
if (substring.match(/^[0-9]+$/)) { // for some reason, emoji-regex matches digits
|
||||||
|
return substring
|
||||||
|
}
|
||||||
|
return replacer(substring)
|
||||||
|
}
|
||||||
|
|
||||||
|
while (leftAngleBracketIdx !== -1) {
|
||||||
|
let substring = string.substring(currentIdx, leftAngleBracketIdx)
|
||||||
|
|
||||||
|
output += substring.replace(emojiRegex, safeReplacer)
|
||||||
|
|
||||||
|
let rightAngleBracketIdx = string.indexOf('>', leftAngleBracketIdx + 1)
|
||||||
|
if (rightAngleBracketIdx === -1) { // broken HTML, abort
|
||||||
|
output += string.substring(leftAngleBracketIdx, string.length)
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
output += string.substring(leftAngleBracketIdx, rightAngleBracketIdx) + '>'
|
||||||
|
currentIdx = rightAngleBracketIdx + 1
|
||||||
|
leftAngleBracketIdx = string.indexOf('<', currentIdx)
|
||||||
|
}
|
||||||
|
|
||||||
|
output += string.substring(currentIdx, string.length).replace(emojiRegex, safeReplacer)
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
|
@ -1,14 +1,11 @@
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
color: var(--body-text-color);
|
color: var(--body-text-color);
|
||||||
background: var(--body-bg);
|
background: var(--body-bg);
|
||||||
-webkit-tap-highlight-color: transparent; /* fix for blue background on spoiler tap on Chrome for Android */
|
-webkit-tap-highlight-color: transparent; /* fix for blue background on spoiler tap on Chrome for Android */
|
||||||
//-webkit-overflow-scrolling: touch;
|
|
||||||
//overflow-y: auto;
|
|
||||||
//overflow-x: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-content {
|
.main-content {
|
||||||
|
@ -214,3 +211,7 @@ textarea {
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inline-emoji {
|
||||||
|
font-family: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Twemoji Mozilla", "Noto Color Emoji", "EmojiOne Color", "Android Emoji", sans-serif;
|
||||||
|
}
|
|
@ -17,7 +17,7 @@
|
||||||
<style>
|
<style>
|
||||||
/* auto-generated w/ build-sass.js */
|
/* auto-generated w/ build-sass.js */
|
||||||
body{--button-primary-bg: #6081e6;--button-primary-text: #fff;--button-primary-border: #132c76;--button-primary-bg-active: #456ce2;--button-primary-bg-hover: #6988e7;--button-bg: #e6e6e6;--button-text: #333;--button-border: #a7a7a7;--button-bg-active: #bfbfbf;--button-bg-hover: #f2f2f2;--input-border: #dadada;--anchor-text: #4169e1;--main-bg: #fff;--body-bg: #e8edfb;--body-text-color: #333;--main-border: #dadada;--svg-fill: #4169e1;--form-bg: #f7f7f7;--form-border: #c1c1c1;--nav-bg: #4169e1;--nav-border: #214cce;--nav-a-border: #4169e1;--nav-a-selected-border: #fff;--nav-a-selected-bg: #6d8ce8;--nav-svg-fill: #fff;--nav-text-color: #fff;--nav-a-selected-border-hover: #fff;--nav-a-selected-bg-hover: #839deb;--nav-a-bg-hover: #577ae4;--nav-a-border-hover: #4169e1;--nav-svg-fill-hover: #fff;--nav-text-color-hover: #fff;--action-button-fill-color: #90a8ee;--action-button-fill-color-hover: #a2b6f0;--action-button-fill-color-active: #577ae4;--action-button-fill-color-pressed: #2351dc;--action-button-fill-color-pressed-hover: #3862e0;--action-button-fill-color-pressed-active: #1d44b8;--action-button-deemphasized-fill-color: #666;--action-button-deemphasized-fill-color-hover: #9e9e9e;--action-button-deemphasized-fill-color-active: #737373;--action-button-deemphasized-fill-color-pressed: #545454;--action-button-deemphasized-fill-color-pressed-hover: #616161;--action-button-deemphasized-fill-color-pressed-active: #404040;--settings-list-item-bg: #fff;--settings-list-item-text: #4169e1;--settings-list-item-text-hover: #4169e1;--settings-list-item-border: #dadada;--settings-list-item-bg-active: #e6e6e6;--settings-list-item-bg-hover: #fafafa;--toast-bg: #333;--toast-border: #fafafa;--toast-text: #fff;--mask-bg: #333;--mask-svg-fill: #fff;--mask-opaque-bg: rgba(51,51,51,0.8);--loading-bg: #ededed;--account-profile-bg-backdrop-filter: rgba(255,255,255,0.7);--account-profile-bg: rgba(255,255,255,0.9);--deemphasized-text-color: #666;--focus-outline: #c5d1f6;--very-deemphasized-link-color: rgba(65,105,225,0.6);--very-deemphasized-text-color: rgba(102,102,102,0.6);--status-direct-background: #d2dcf8;--main-theme-color: #4169e1;--warning-color: #e01f19;--alt-input-bg: rgba(255,255,255,0.7);--muted-modal-bg: transparent;--muted-modal-focus: #999;--muted-modal-hover: rgba(255,255,255,0.2);--compose-autosuggest-item-hover: #ced8f7;--compose-autosuggest-item-active: #b8c7f4;--compose-autosuggest-outline: #dbe3f9;--compose-button-halo: rgba(255,255,255,0.1)}
|
body{--button-primary-bg: #6081e6;--button-primary-text: #fff;--button-primary-border: #132c76;--button-primary-bg-active: #456ce2;--button-primary-bg-hover: #6988e7;--button-bg: #e6e6e6;--button-text: #333;--button-border: #a7a7a7;--button-bg-active: #bfbfbf;--button-bg-hover: #f2f2f2;--input-border: #dadada;--anchor-text: #4169e1;--main-bg: #fff;--body-bg: #e8edfb;--body-text-color: #333;--main-border: #dadada;--svg-fill: #4169e1;--form-bg: #f7f7f7;--form-border: #c1c1c1;--nav-bg: #4169e1;--nav-border: #214cce;--nav-a-border: #4169e1;--nav-a-selected-border: #fff;--nav-a-selected-bg: #6d8ce8;--nav-svg-fill: #fff;--nav-text-color: #fff;--nav-a-selected-border-hover: #fff;--nav-a-selected-bg-hover: #839deb;--nav-a-bg-hover: #577ae4;--nav-a-border-hover: #4169e1;--nav-svg-fill-hover: #fff;--nav-text-color-hover: #fff;--action-button-fill-color: #90a8ee;--action-button-fill-color-hover: #a2b6f0;--action-button-fill-color-active: #577ae4;--action-button-fill-color-pressed: #2351dc;--action-button-fill-color-pressed-hover: #3862e0;--action-button-fill-color-pressed-active: #1d44b8;--action-button-deemphasized-fill-color: #666;--action-button-deemphasized-fill-color-hover: #9e9e9e;--action-button-deemphasized-fill-color-active: #737373;--action-button-deemphasized-fill-color-pressed: #545454;--action-button-deemphasized-fill-color-pressed-hover: #616161;--action-button-deemphasized-fill-color-pressed-active: #404040;--settings-list-item-bg: #fff;--settings-list-item-text: #4169e1;--settings-list-item-text-hover: #4169e1;--settings-list-item-border: #dadada;--settings-list-item-bg-active: #e6e6e6;--settings-list-item-bg-hover: #fafafa;--toast-bg: #333;--toast-border: #fafafa;--toast-text: #fff;--mask-bg: #333;--mask-svg-fill: #fff;--mask-opaque-bg: rgba(51,51,51,0.8);--loading-bg: #ededed;--account-profile-bg-backdrop-filter: rgba(255,255,255,0.7);--account-profile-bg: rgba(255,255,255,0.9);--deemphasized-text-color: #666;--focus-outline: #c5d1f6;--very-deemphasized-link-color: rgba(65,105,225,0.6);--very-deemphasized-text-color: rgba(102,102,102,0.6);--status-direct-background: #d2dcf8;--main-theme-color: #4169e1;--warning-color: #e01f19;--alt-input-bg: rgba(255,255,255,0.7);--muted-modal-bg: transparent;--muted-modal-focus: #999;--muted-modal-hover: rgba(255,255,255,0.2);--compose-autosuggest-item-hover: #ced8f7;--compose-autosuggest-item-active: #b8c7f4;--compose-autosuggest-outline: #dbe3f9;--compose-button-halo: rgba(255,255,255,0.1)}
|
||||||
body{margin:0;font-family:system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;font-size:14px;line-height:1.4;color:var(--body-text-color);background:var(--body-bg);-webkit-tap-highlight-color:transparent}.main-content{padding-top:42px;contain:content}@media (max-width: 991px){.main-content{padding-top:52px}}@media (max-width: 767px){.main-content{padding-top:62px}}main{position:relative;width:602px;max-width:100vw;padding:0;box-sizing:border-box;margin:30px auto 15px;background:var(--main-bg);border:1px solid var(--main-border);border-radius:1px;min-height:70vh}@media (max-width: 767px){main{margin:5px auto 15px}}footer{width:602px;max-width:100vw;box-sizing:border-box;margin:15px auto;border-radius:1px;background:var(--main-bg);font-size:0.9em;padding:20px;border:1px solid var(--main-border)}h1,h2,h3,h4,h5,h6{margin:0 0 0.5em 0;font-weight:400;line-height:1.2}h1{font-size:2em}a{color:var(--anchor-text);text-decoration:none}a:visited{color:var(--anchor-text)}a:hover{text-decoration:underline}input{border:1px solid var(--input-border);padding:5px;box-sizing:border-box}input[type=search]{-webkit-appearance:none}input,textarea{background:inherit;color:inherit}button,.button{font-size:1.2em;background:var(--button-bg);border-radius:2px;padding:10px 15px;border:1px solid var(--button-border);cursor:pointer;color:var(--button-text)}button:hover,.button:hover{background:var(--button-bg-hover);text-decoration:none}button:active,.button:active{background:var(--button-bg-active)}button[disabled],.button[disabled]{opacity:0.35;pointer-events:none;cursor:not-allowed}button.primary,.button.primary{border:1px solid var(--button-primary-border);background:var(--button-primary-bg);color:var(--button-primary-text)}button.primary:hover,.button.primary:hover{background:var(--button-primary-bg-hover)}button.primary:active,.button.primary:active{background:var(--button-primary-bg-active)}p,label,input{font-size:1.3em}ul,li,p{padding:0;margin:0}.hidden{opacity:0}*:focus{outline:2px solid var(--focus-outline)}.container:focus{outline:none}button::-moz-focus-inner{border:0}input:required,input:invalid{box-shadow:none}textarea{font-family:inherit;font-size:inherit;box-sizing:border-box}@keyframes spin{0%{transform:rotate(0deg)}25%{transform:rotate(90deg)}50%{transform:rotate(180deg)}75%{transform:rotate(270deg)}100%{transform:rotate(360deg)}}.spin{animation:spin 1.5s infinite linear}.ellipsis::after{content:"\2026"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.inline-custom-emoji{width:1.4em;height:1.4em;margin:-0.1em 0;object-fit:contain;vertical-align:middle}
|
body{margin:0;font-family:system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;font-size:14px;line-height:1.4;color:var(--body-text-color);background:var(--body-bg);-webkit-tap-highlight-color:transparent}.main-content{padding-top:42px;contain:content}@media (max-width: 991px){.main-content{padding-top:52px}}@media (max-width: 767px){.main-content{padding-top:62px}}main{position:relative;width:602px;max-width:100vw;padding:0;box-sizing:border-box;margin:30px auto 15px;background:var(--main-bg);border:1px solid var(--main-border);border-radius:1px;min-height:70vh}@media (max-width: 767px){main{margin:5px auto 15px}}footer{width:602px;max-width:100vw;box-sizing:border-box;margin:15px auto;border-radius:1px;background:var(--main-bg);font-size:0.9em;padding:20px;border:1px solid var(--main-border)}h1,h2,h3,h4,h5,h6{margin:0 0 0.5em 0;font-weight:400;line-height:1.2}h1{font-size:2em}a{color:var(--anchor-text);text-decoration:none}a:visited{color:var(--anchor-text)}a:hover{text-decoration:underline}input{border:1px solid var(--input-border);padding:5px;box-sizing:border-box}input[type=search]{-webkit-appearance:none}input,textarea{background:inherit;color:inherit}button,.button{font-size:1.2em;background:var(--button-bg);border-radius:2px;padding:10px 15px;border:1px solid var(--button-border);cursor:pointer;color:var(--button-text)}button:hover,.button:hover{background:var(--button-bg-hover);text-decoration:none}button:active,.button:active{background:var(--button-bg-active)}button[disabled],.button[disabled]{opacity:0.35;pointer-events:none;cursor:not-allowed}button.primary,.button.primary{border:1px solid var(--button-primary-border);background:var(--button-primary-bg);color:var(--button-primary-text)}button.primary:hover,.button.primary:hover{background:var(--button-primary-bg-hover)}button.primary:active,.button.primary:active{background:var(--button-primary-bg-active)}p,label,input{font-size:1.3em}ul,li,p{padding:0;margin:0}.hidden{opacity:0}*:focus{outline:2px solid var(--focus-outline)}.container:focus{outline:none}button::-moz-focus-inner{border:0}input:required,input:invalid{box-shadow:none}textarea{font-family:inherit;font-size:inherit;box-sizing:border-box}@keyframes spin{0%{transform:rotate(0deg)}25%{transform:rotate(90deg)}50%{transform:rotate(180deg)}75%{transform:rotate(270deg)}100%{transform:rotate(360deg)}}.spin{animation:spin 1.5s infinite linear}.ellipsis::after{content:"\2026"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.inline-custom-emoji{width:1.4em;height:1.4em;margin:-0.1em 0;object-fit:contain;vertical-align:middle}.inline-emoji{font-family:"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Twemoji Mozilla", "Noto Color Emoji", "EmojiOne Color", "Android Emoji", sans-serif}
|
||||||
body.the-body.offline{--button-primary-bg: #ababab;--button-primary-text: #fff;--button-primary-border: #4d4d4d;--button-primary-bg-active: #9c9c9c;--button-primary-bg-hover: #b0b0b0;--button-bg: #e6e6e6;--button-text: #333;--button-border: #a7a7a7;--button-bg-active: #bfbfbf;--button-bg-hover: #f2f2f2;--input-border: #dadada;--anchor-text: #999;--main-bg: #fff;--body-bg: #fafafa;--body-text-color: #333;--main-border: #dadada;--svg-fill: #999;--form-bg: #f7f7f7;--form-border: #c1c1c1;--nav-bg: #999;--nav-border: gray;--nav-a-border: #999;--nav-a-selected-border: #fff;--nav-a-selected-bg: #b3b3b3;--nav-svg-fill: #fff;--nav-text-color: #fff;--nav-a-selected-border-hover: #fff;--nav-a-selected-bg-hover: #bfbfbf;--nav-a-bg-hover: #a6a6a6;--nav-a-border-hover: #999;--nav-svg-fill-hover: #fff;--nav-text-color-hover: #fff;--action-button-fill-color: #c7c7c7;--action-button-fill-color-hover: #d1d1d1;--action-button-fill-color-active: #a6a6a6;--action-button-fill-color-pressed: #878787;--action-button-fill-color-pressed-hover: #949494;--action-button-fill-color-pressed-active: #737373;--action-button-deemphasized-fill-color: #666;--action-button-deemphasized-fill-color-hover: #9e9e9e;--action-button-deemphasized-fill-color-active: #737373;--action-button-deemphasized-fill-color-pressed: #545454;--action-button-deemphasized-fill-color-pressed-hover: #616161;--action-button-deemphasized-fill-color-pressed-active: #404040;--settings-list-item-bg: #fff;--settings-list-item-text: #999;--settings-list-item-text-hover: #999;--settings-list-item-border: #dadada;--settings-list-item-bg-active: #e6e6e6;--settings-list-item-bg-hover: #fafafa;--toast-bg: #333;--toast-border: #fafafa;--toast-text: #fff;--mask-bg: #333;--mask-svg-fill: #fff;--mask-opaque-bg: rgba(51,51,51,0.8);--loading-bg: #ededed;--account-profile-bg-backdrop-filter: rgba(255,255,255,0.7);--account-profile-bg: rgba(255,255,255,0.9);--deemphasized-text-color: #666;--focus-outline: #bfbfbf;--very-deemphasized-link-color: rgba(153,153,153,0.6);--very-deemphasized-text-color: rgba(102,102,102,0.6);--status-direct-background: #ededed;--main-theme-color: #999;--warning-color: #e01f19;--alt-input-bg: rgba(255,255,255,0.7);--muted-modal-bg: transparent;--muted-modal-focus: #999;--muted-modal-hover: rgba(255,255,255,0.2);--compose-autosuggest-item-hover: #c4c4c4;--compose-autosuggest-item-active: #b8b8b8;--compose-autosuggest-outline: #ccc;--compose-button-halo: rgba(255,255,255,0.1)}
|
body.the-body.offline{--button-primary-bg: #ababab;--button-primary-text: #fff;--button-primary-border: #4d4d4d;--button-primary-bg-active: #9c9c9c;--button-primary-bg-hover: #b0b0b0;--button-bg: #e6e6e6;--button-text: #333;--button-border: #a7a7a7;--button-bg-active: #bfbfbf;--button-bg-hover: #f2f2f2;--input-border: #dadada;--anchor-text: #999;--main-bg: #fff;--body-bg: #fafafa;--body-text-color: #333;--main-border: #dadada;--svg-fill: #999;--form-bg: #f7f7f7;--form-border: #c1c1c1;--nav-bg: #999;--nav-border: gray;--nav-a-border: #999;--nav-a-selected-border: #fff;--nav-a-selected-bg: #b3b3b3;--nav-svg-fill: #fff;--nav-text-color: #fff;--nav-a-selected-border-hover: #fff;--nav-a-selected-bg-hover: #bfbfbf;--nav-a-bg-hover: #a6a6a6;--nav-a-border-hover: #999;--nav-svg-fill-hover: #fff;--nav-text-color-hover: #fff;--action-button-fill-color: #c7c7c7;--action-button-fill-color-hover: #d1d1d1;--action-button-fill-color-active: #a6a6a6;--action-button-fill-color-pressed: #878787;--action-button-fill-color-pressed-hover: #949494;--action-button-fill-color-pressed-active: #737373;--action-button-deemphasized-fill-color: #666;--action-button-deemphasized-fill-color-hover: #9e9e9e;--action-button-deemphasized-fill-color-active: #737373;--action-button-deemphasized-fill-color-pressed: #545454;--action-button-deemphasized-fill-color-pressed-hover: #616161;--action-button-deemphasized-fill-color-pressed-active: #404040;--settings-list-item-bg: #fff;--settings-list-item-text: #999;--settings-list-item-text-hover: #999;--settings-list-item-border: #dadada;--settings-list-item-bg-active: #e6e6e6;--settings-list-item-bg-hover: #fafafa;--toast-bg: #333;--toast-border: #fafafa;--toast-text: #fff;--mask-bg: #333;--mask-svg-fill: #fff;--mask-opaque-bg: rgba(51,51,51,0.8);--loading-bg: #ededed;--account-profile-bg-backdrop-filter: rgba(255,255,255,0.7);--account-profile-bg: rgba(255,255,255,0.9);--deemphasized-text-color: #666;--focus-outline: #bfbfbf;--very-deemphasized-link-color: rgba(153,153,153,0.6);--very-deemphasized-text-color: rgba(102,102,102,0.6);--status-direct-background: #ededed;--main-theme-color: #999;--warning-color: #e01f19;--alt-input-bg: rgba(255,255,255,0.7);--muted-modal-bg: transparent;--muted-modal-focus: #999;--muted-modal-hover: rgba(255,255,255,0.2);--compose-autosuggest-item-hover: #c4c4c4;--compose-autosuggest-item-active: #b8b8b8;--compose-autosuggest-outline: #ccc;--compose-button-halo: rgba(255,255,255,0.1)}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
137
tests/unit/test-emoji.js
Normal file
137
tests/unit/test-emoji.js
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
/* global describe, it */
|
||||||
|
|
||||||
|
import { replaceEmoji } from '../../routes/_utils/replaceEmoji'
|
||||||
|
import assert from 'assert'
|
||||||
|
|
||||||
|
const mindBlown = String.fromCodePoint(0x1F92F)
|
||||||
|
const elephant = String.fromCodePoint(0x1F418)
|
||||||
|
const womanBowing = [0x1f647, 0x200d, 0x2640, 0xfe0f].map(_ => String.fromCodePoint(_)).join('')
|
||||||
|
|
||||||
|
describe('test-emoji.js', function () {
|
||||||
|
it('does emoji replacement correctly', function () {
|
||||||
|
let replacer = _ => `<div>${_}</div>`
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji('hello world', replacer),
|
||||||
|
'hello world'
|
||||||
|
)
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(`${mindBlown}`, replacer),
|
||||||
|
`<div>${mindBlown}</div>`
|
||||||
|
)
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(`${mindBlown} ${elephant}`, replacer),
|
||||||
|
`<div>${mindBlown}</div> <div>${elephant}</div>`
|
||||||
|
)
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(`${elephant} woot ${mindBlown}`, replacer),
|
||||||
|
`<div>${elephant}</div> woot <div>${mindBlown}</div>`
|
||||||
|
)
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(`woot ${mindBlown}`, replacer),
|
||||||
|
`woot <div>${mindBlown}</div>`
|
||||||
|
)
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(`${mindBlown} woot`, replacer),
|
||||||
|
`<div>${mindBlown}</div> woot`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('handles multi-code emoji', function () {
|
||||||
|
let replacer = _ => `<div>${_}</div>`
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(`hello ${womanBowing}`, replacer),
|
||||||
|
`hello <div>${womanBowing}</div>`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('handles emoji mixed with custom emoji', function () {
|
||||||
|
let replacer = _ => `<div>${_}</div>`
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(`hello ${womanBowing} and :blobpats: and ${elephant}`, replacer),
|
||||||
|
`hello <div>${womanBowing}</div> and :blobpats: and <div>${elephant}</div>`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('handles sequential emoji', function () {
|
||||||
|
let replacer = _ => `<div>${_}</div>`
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(`${elephant}${elephant}${womanBowing}${mindBlown}`, replacer),
|
||||||
|
`<div>${elephant}</div><div>${elephant}</div><div>${womanBowing}</div><div>${mindBlown}</div>`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not replace digits', function () {
|
||||||
|
let replacer = _ => `<div>${_}</div>`
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(`it's over 9000`, replacer),
|
||||||
|
`it's over 9000`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not replace emoji inside HTML tags', function () {
|
||||||
|
let replacer = _ => `<div>${_}</div>`
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(`check this cool link: <a href='http://example.com?q=${mindBlown}'>link</a>`, replacer),
|
||||||
|
`check this cool link: <a href='http://example.com?q=${mindBlown}'>link</a>`
|
||||||
|
)
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(
|
||||||
|
`<a href='http://foo.com?q=${mindBlown}'>link</a> and <a href='http://foo.com?q=${mindBlown}'>link</a>`,
|
||||||
|
replacer
|
||||||
|
),
|
||||||
|
`<a href='http://foo.com?q=${mindBlown}'>link</a> and <a href='http://foo.com?q=${mindBlown}'>link</a>`
|
||||||
|
)
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(
|
||||||
|
`<a href='http://foo.com?q=${mindBlown}'>link</a> and ${mindBlown}`,
|
||||||
|
replacer
|
||||||
|
),
|
||||||
|
`<a href='http://foo.com?q=${mindBlown}'>link</a> and <div>${mindBlown}</div>`
|
||||||
|
)
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(
|
||||||
|
`<a href='http://foo.com?q=${mindBlown}'>link</a> and ${mindBlown} and ` +
|
||||||
|
`<a href='http://foo.com?q=${mindBlown}'>link</a>`,
|
||||||
|
replacer
|
||||||
|
),
|
||||||
|
`<a href='http://foo.com?q=${mindBlown}'>link</a> and <div>${mindBlown}</div> and ` +
|
||||||
|
`<a href='http://foo.com?q=${mindBlown}'>link</a>`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('removes emoji', function () {
|
||||||
|
let replacer = _ => ''
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(`woot ${mindBlown}`, replacer),
|
||||||
|
`woot `
|
||||||
|
)
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(`woot ${mindBlown} woot`, replacer),
|
||||||
|
`woot woot`
|
||||||
|
)
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(`woot ${mindBlown}${elephant}`, replacer),
|
||||||
|
`woot `
|
||||||
|
)
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(`woot ${mindBlown}${elephant} woot`, replacer),
|
||||||
|
`woot woot`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can handle a dangling left angle bracket for some reason', function () {
|
||||||
|
let replacer = _ => `<div>${_}</div>`
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(`woot ${mindBlown} <`, replacer),
|
||||||
|
`woot <div>${mindBlown}</div> <`
|
||||||
|
)
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(`woot ${mindBlown} <hahahahaha`, replacer),
|
||||||
|
`woot <div>${mindBlown}</div> <hahahahaha`
|
||||||
|
)
|
||||||
|
assert.strictEqual(
|
||||||
|
replaceEmoji(`<woot ${mindBlown} <hahahahaha`, replacer),
|
||||||
|
`<woot ${mindBlown} <hahahahaha`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in a new issue