fix emoji rendering (force font emoji for everything)

use hybrid emoji (different fonts for better UX)
add missing Twemoji.Mozilla license
This commit is contained in:
NightFox 2024-02-14 20:28:25 +03:00
parent 0f969b5adb
commit a09c4968c9
3 changed files with 138 additions and 13 deletions

View File

@ -33,9 +33,10 @@ h1,h2,h3,h4,h5 {
} }
.emoji { .emoji {
/*font-family: "Twemoji Mozilla Built", sans-serif;*/ font-family: "Noto Color Emoji", sans-serif;
/*font-family: "Noto Color Emoji", sans-serif;*/
font-family: "OpenMojiDemoFont", sans-serif; font-family: "OpenMojiDemoFont", sans-serif;
font-family: "Twemoji Mozilla Built", sans-serif;
font-size: 16px;
font-weight: 400; font-weight: 400;
font-style: normal; font-style: normal;
} }
@ -43,6 +44,28 @@ h1,h2,h3,h4,h5 {
font-variant-emoji: emoji; /* experimental and only in firefox :( */ font-variant-emoji: emoji; /* experimental and only in firefox :( */
content: '\FE0F'; /* fuck off, give me emoji // https://codepoints.net/U+FE0F */ content: '\FE0F'; /* fuck off, give me emoji // https://codepoints.net/U+FE0F */
} }
.emoji.Twemoji {
font-family: "Twemoji Mozilla Built", sans-serif;
font-size: 16px;
}
.emoji.Noto {
font-family: "Noto Color Emoji", sans-serif;
font-size: 14px;
/*vertical-align: top;*/
}
.emoji.OpenMoji {
font-family: "OpenMojiDemoFont", sans-serif;
font-size: 17px;
position: relative;
left: -1px;
}
.emoji.OpenMoji + .text-left-margin {
margin-left: 0;
}
.emoji.Noto + .emoji.Noto {
margin-left: 4px;
}
footer { footer {
text-align: center; text-align: center;
@ -244,7 +267,8 @@ body.min { /* split feature */
position: absolute; position: absolute;
animation: flash var(--animation-duration) infinite; animation: flash var(--animation-duration) infinite;
} }
.block-gold.anim_off { .block-gold.anim_off,
.block-gold.anim_force_off {
animation: none; animation: none;
} }

View File

@ -0,0 +1,50 @@
## License for the Code
Copyright 2016-2018, Mozilla Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
## License for the Visual Design
The Emoji art in the twe-svg.zip archive comes from [Twemoji](https://twitter.github.io/twemoji),
and is used and redistributed under the CC-BY-4.0 [license terms](https://github.com/twitter/twemoji#license)
offered by the Twemoji project.
### Creative Commons Attribution 4.0 International (CC BY 4.0)
https://creativecommons.org/licenses/by/4.0/legalcode
or for the human readable summary: https://creativecommons.org/licenses/by/4.0/
#### You are free to:
**Share** — copy and redistribute the material in any medium or format
**Adapt** — remix, transform, and build upon the material for any purpose, even commercially.
The licensor cannot revoke these freedoms as long as you follow the license terms.
#### Under the following terms:
**Attribution** — You must give appropriate credit, provide a link to the license,
and indicate if changes were made.
You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
**No additional restrictions** — You may not apply legal terms or **technological measures**
that legally restrict others from doing anything the license permits.
#### Notices:
You do not have to comply with the license for elements of the material in the public domain
or where your use is permitted by an applicable exception or limitation. No warranties are given.
The license may not give you all of the permissions necessary for your intended use.
For example, other rights such as publicity, privacy, or moral rights may limit how you use the material.

View File

@ -19,6 +19,51 @@ function sectionLink(value, d) {
return [a]; return [a];
} }
// fonts: Twemoji, Noto, OpenMoji
const emojiFontReplacementTable = {
"🌑":"Twemoji",
"☀":"Noto",
"🧲":"Noto",
"☢":"Noto",
"🔦":"OpenMoji",
"🎆":"Noto",
"💎":"Noto",
"🏀":"Noto",
"🖌":"Noto",
}
function emojiFont(emoji) {
let emojiFontReplacement = emojiFontReplacementTable[emoji];
emojiFontReplacement = emojiFontReplacement ? " " + emojiFontReplacement : "";
return emojiFontReplacement;
}
function emojiDetect(string) {
const regex_emoji = /\p{Extended_Pictographic}/gu; // it's not complete but it's enough for case
const matches = [...string.matchAll(regex_emoji)];
return matches;
}
function emojiToTag(string) {
const results = emojiDetect(string);
let lastIndex = 0;
const tagArray = [];
for (let result of results) {
let emoji = result[0];
if (result.index > lastIndex) {
tagArray.push(Text(string.slice(lastIndex, result.index)));
}
tagArray.push(Tag('span', {"class": "emoji" + emojiFont(emoji)}, emoji));
lastIndex = result.index + emoji.length;
}
if (lastIndex < string.length) {
tagArray.push(Text(string.slice(lastIndex)));
}
return tagArray;
}
function channelWithEmoji(value) { function channelWithEmoji(value) {
const replacements = { const replacements = {
"full": "🖼", "full": "🖼",
@ -33,14 +78,14 @@ function channelWithEmoji(value) {
"diffuse": "🎆", "diffuse": "🎆",
"specular": "💎", "specular": "💎",
"material": "🖌", "material": "🖌",
"indirect": "🥏",//🏀🏓🥏 "indirect": "🏀",//🏀🏓🥏
"indirect_specular": "🥏💎", "indirect_specular": "🏀💎",
"indirect_diffuse": "🥏🎆" "indirect_diffuse": "🏀🎆"
} }
const emoji = replacements[value]; const emoji = replacements[value];
if (emoji) { if (emoji) {
return [ return [
Tag('span', {"class": "emoji"}, emoji), ...emojiToTag(emoji),
Tag("span", {"class": "text-left-margin"}, value) Tag("span", {"class": "text-left-margin"}, value)
]; ];
} else { } else {
@ -61,7 +106,12 @@ function colorPct(value) {
} }
function isPassed(value) { function isPassed(value) {
return [Tag("span", {"class": "emoji"}, value ? "❌" : "✔")]; //✔✅ const font = value ? emojiFont("❌") : emojiFont("✔");
return [
Tag("span", {"class": "emoji" + font},
value ? "❌" : "✅" // ✔✅
)
];
} }
function makeTable(fields, data, attrs_func) { function makeTable(fields, data, attrs_func) {
@ -166,7 +216,7 @@ function buildData(table, images, data, sort) {
let diffElement = this.querySelector(".block-diff"); let diffElement = this.querySelector(".block-diff");
let goldElement = this.querySelector(".block-gold"); let goldElement = this.querySelector(".block-gold");
diffElement.classList.toggle("show_diff"); diffElement.classList.toggle("show_diff");
goldElement.classList.toggle("anim_off"); goldElement.classList.toggle("anim_force_off");
}); });
}; };
@ -217,6 +267,7 @@ window.onload = () => {
let themes = []; let themes = [];
for (const linkElement of linkElements) { for (const linkElement of linkElements) {
const themeName = linkElement.getAttribute("data-theme"); const themeName = linkElement.getAttribute("data-theme");
const emojiTags = emojiToTag(linkElement.title);
const checked = !linkElement.rel.includes("alternate") ? {"checked": "checked"} : {}; const checked = !linkElement.rel.includes("alternate") ? {"checked": "checked"} : {};
themes.push( themes.push(
Tag("label", null, null, [ Tag("label", null, null, [
@ -224,7 +275,7 @@ window.onload = () => {
"click", (e) => { "click", (e) => {
updateLinkRel(linkElements, e.target.id); updateLinkRel(linkElements, e.target.id);
}), }),
Text(linkElement.title) ...emojiTags
]) ])
) )
}; };
@ -336,7 +387,7 @@ window.onload = () => {
]), ]),
Tag("ul", {"class": "list"}, null, [ Tag("ul", {"class": "list"}, null, [
Tag("li", null, null, [ Tag("li", null, null, [
Tag("span", {"class": "emoji"}, "🧲"), Tag("span", {"class": "emoji Noto"}, "🧲"),
Text(" position"), Text(" position"),
Tag("label", null, null, [ Tag("label", null, null, [
Tag("input", {"type": "radio", "name": "sidebar_pos", "value": "left", ...uglyChecked(sidebarPos == "left")}, null, null, "input", (e) => { Tag("input", {"type": "radio", "name": "sidebar_pos", "value": "left", ...uglyChecked(sidebarPos == "left")}, null, null, "input", (e) => {
@ -385,7 +436,7 @@ window.onload = () => {
Text(" center ") Text(" center ")
]), ]),
Tag("b", null, null, [ Tag("b", null, null, [
Tag("span", {"class": "emoji"}, "🖼"), Tag("span", {"class": "emoji Noto"}, "🖼"),
Tag("label", null, null, [ Tag("label", null, null, [
Text(" vertical padding"), Text(" vertical padding"),
Tag("input", {"type": "checkbox", "name": "all_diff", "checked": "checked"}, null, null, "input", (e) => { Tag("input", {"type": "checkbox", "name": "all_diff", "checked": "checked"}, null, null, "input", (e) => {
@ -446,7 +497,7 @@ window.onload = () => {
// stop animation when not in viewport // stop animation when not in the viewport
function handleIntersection(entries, observer) { function handleIntersection(entries, observer) {
for (let entry of entries) { for (let entry of entries) {
if (!entry.isIntersecting) { if (!entry.isIntersecting) {