mirror of
https://github.com/notion-enhancer/notion-enhancer.git
synced 2025-04-06 21:49:03 +00:00
extension: emoji sets
This commit is contained in:
parent
1f9537b755
commit
a824ba8856
75
repo/emoji-sets/client.mjs
Normal file
75
repo/emoji-sets/client.mjs
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* notion-enhancer: emoji sets
|
||||
* (c) 2021 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
||||
* (https://notion-enhancer.github.io/) under the MIT license
|
||||
*/
|
||||
|
||||
export default async function ({ web, env }, db) {
|
||||
const style = await db.get(['style']),
|
||||
// real emojis are used on macos instead of the twitter set
|
||||
nativeEmojiSelector = `[style*='"Apple Color Emoji", "Segoe UI Emoji", NotoColorEmoji, "Noto Color Emoji", "Segoe UI Symbol", "Android Emoji", EmojiSymbols']:not(data-emoji-sets-unsupported)`,
|
||||
imgEmojiSelector = '.notion-emoji:not(data-emoji-sets-unsupported)',
|
||||
imgEmojiOverlaySelector = `${imgEmojiSelector} + [src*="notion-emojis"]`;
|
||||
|
||||
await web.whenReady();
|
||||
|
||||
const nativeEmojis = document.querySelectorAll(nativeEmojiSelector).length,
|
||||
imgEmojis = document.querySelectorAll(imgEmojiSelector).length;
|
||||
|
||||
const unsupportedEmojis = [],
|
||||
emojiReqs = new Map(),
|
||||
getEmoji = async (emoji) => {
|
||||
if (unsupportedEmojis.includes(emoji)) return undefined;
|
||||
try {
|
||||
if (!emojiReqs.get(emoji)) {
|
||||
emojiReqs.set(emoji, fetch(`https://emojicdn.elk.sh/${emoji}?style=${style}`));
|
||||
}
|
||||
const res = await emojiReqs.get(emoji);
|
||||
if (!res.ok) throw new Error();
|
||||
return `url("https://emojicdn.elk.sh/${emoji}?style=${style}") 100% 100% / 100%`;
|
||||
} catch {
|
||||
unsupportedEmojis.push(emoji);
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
if (nativeEmojis) {
|
||||
const updateEmojis = async () => {
|
||||
const $emojis = document.querySelectorAll(nativeEmojiSelector);
|
||||
for (const $emoji of $emojis) {
|
||||
const emojiBg = await getEmoji($emoji.ariaLabel);
|
||||
if (emojiBg) {
|
||||
$emoji.style.background = emojiBg;
|
||||
$emoji.style.width = '1em';
|
||||
$emoji.style.height = '1em';
|
||||
$emoji.style.display = 'inline-block';
|
||||
$emoji.innerText = '';
|
||||
await new Promise((res, rej) => requestAnimationFrame(res));
|
||||
} else {
|
||||
$emoji.dataset.emojiSetsUnsupported = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
web.addDocumentObserver(updateEmojis, [nativeEmojiSelector]);
|
||||
}
|
||||
|
||||
if (style !== 'twitter' && imgEmojis) {
|
||||
const updateEmojis = async () => {
|
||||
const $emojis = document.querySelectorAll(imgEmojiSelector);
|
||||
for (const $emoji of $emojis) {
|
||||
const emojiBg = await getEmoji($emoji.ariaLabel);
|
||||
if (emojiBg) {
|
||||
$emoji.style.background = emojiBg;
|
||||
$emoji.style.opacity = 1;
|
||||
if ($emoji.nextElementSibling?.matches?.(imgEmojiOverlaySelector)) {
|
||||
$emoji.nextElementSibling.style.opacity = 0;
|
||||
}
|
||||
} else {
|
||||
$emoji.dataset.emojiSetsUnsupported = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
updateEmojis();
|
||||
web.addDocumentObserver(updateEmojis, [imgEmojiSelector, imgEmojiOverlaySelector]);
|
||||
}
|
||||
}
|
42
repo/emoji-sets/mod.json
Normal file
42
repo/emoji-sets/mod.json
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "emoji sets",
|
||||
"id": "a2401ee1-93ba-4b8c-9781-7f570bf5d71e",
|
||||
"version": "0.4.0",
|
||||
"description": "pick from a variety of emoji styles to use.",
|
||||
"tags": ["extension", "customisation"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "dragonwocky",
|
||||
"email": "thedragonring.bod@gmail.com",
|
||||
"homepage": "https://dragonwocky.me/",
|
||||
"avatar": "https://dragonwocky.me/avatar.jpg"
|
||||
}
|
||||
],
|
||||
"js": {
|
||||
"client": ["client.mjs"]
|
||||
},
|
||||
"css": {},
|
||||
"options": [
|
||||
{
|
||||
"type": "select",
|
||||
"key": "style",
|
||||
"label": "emoji style",
|
||||
"values": [
|
||||
"twitter",
|
||||
"apple",
|
||||
"google",
|
||||
"microsoft",
|
||||
"samsung",
|
||||
"whatsapp",
|
||||
"facebook",
|
||||
"messenger",
|
||||
"joypixels",
|
||||
"openmoji",
|
||||
"emojidex",
|
||||
"lg",
|
||||
"htc",
|
||||
"mozilla"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -18,11 +18,12 @@
|
||||
"pinky-boom",
|
||||
|
||||
"bypass-preview",
|
||||
"calendar-scroll",
|
||||
"font-chooser",
|
||||
"collapse-properties",
|
||||
"scroll-to-top",
|
||||
"calendar-scroll",
|
||||
"collapse-properties",
|
||||
"indentation-lines",
|
||||
"focus-mode",
|
||||
"word-counter"
|
||||
"word-counter",
|
||||
"emoji-sets"
|
||||
]
|
||||
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* word counter
|
||||
* (c) 2020 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
||||
* under the MIT license
|
||||
*/
|
||||
|
||||
#word-counter-details {
|
||||
width: 100%;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
#word-counter-details > div {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: -0.5em;
|
||||
}
|
||||
#word-counter-details > div > p {
|
||||
margin: 0.5em;
|
||||
cursor: pointer;
|
||||
font-size: var(--theme--font_label-size);
|
||||
color: var(--theme--text);
|
||||
border-radius: 3px;
|
||||
padding: 0.25rem 0.5rem;
|
||||
background: var(--theme--interactive_hover);
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
#word-counter-details > div > p:hover {
|
||||
background: transparent;
|
||||
border: 1px solid var(--theme--interactive_hover);
|
||||
}
|
||||
|
||||
#word-counter-details > div > span {
|
||||
max-width: 10em;
|
||||
padding: 0.4rem 0.5rem 0.25rem 0.5rem;
|
||||
font-size: calc(var(--theme--font_label-size) * 0.8);
|
||||
color: var(--theme--text_ui_info);
|
||||
}
|
||||
|
||||
#word-counter-details > div > p > svg {
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
margin: 0 0 -2px 0.3em;
|
||||
color: var(--theme--text_ui_info);
|
||||
}
|
||||
|
||||
#word-counter-details-tooltip {
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
padding: 0.25em 0.5em;
|
||||
border-radius: 3px;
|
||||
box-shadow: var(--theme--box-shadow_strong);
|
||||
border-right-width: 1px;
|
||||
font-size: calc(var(--theme--font_label-size) * 0.8);
|
||||
background: var(--theme--interactive_hover);
|
||||
opacity: 0;
|
||||
transition: opacity 120ms ease-in;
|
||||
}
|
||||
#word-counter-details-tooltip.active {
|
||||
opacity: 1;
|
||||
}
|
@ -1,166 +0,0 @@
|
||||
/*
|
||||
* word counter
|
||||
* (c) 2020 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
||||
* (c) 2020 admiraldus (https://github.com/admiraldus)
|
||||
* under the MIT license
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const { createElement } = require('../../pkg/helpers.js');
|
||||
|
||||
module.exports = {
|
||||
id: 'b99deb52-6955-43d2-a53b-a31540cd19a5',
|
||||
tags: ['extension'],
|
||||
name: 'word counter',
|
||||
desc:
|
||||
'add page details: word/character/sentence/block count & speaking/reading times.',
|
||||
version: '0.2.0',
|
||||
author: 'dragonwocky',
|
||||
options: [
|
||||
{
|
||||
key: 'hide_page_details_text',
|
||||
label: 'hide "page details" text',
|
||||
type: 'toggle',
|
||||
value: false,
|
||||
},
|
||||
],
|
||||
hacks: {
|
||||
'renderer/preload.js'(store, __exports) {
|
||||
const copyToClipboard = (str) => {
|
||||
const el = document.createElement('textarea');
|
||||
el.value = str;
|
||||
el.setAttribute('readonly', '');
|
||||
el.style.position = 'absolute';
|
||||
el.style.left = '-9999px';
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(el);
|
||||
},
|
||||
humanTime = (mins) => {
|
||||
let readable = '';
|
||||
if (1 <= mins) {
|
||||
readable += `${Math.floor(mins)} min`;
|
||||
if (2 <= mins) readable += 's';
|
||||
}
|
||||
const secs = Math.round((mins % 1) * 60);
|
||||
if (1 <= secs) {
|
||||
if (1 <= mins) readable += ' ';
|
||||
readable += `${secs} sec`;
|
||||
if (2 <= secs) readable += 's';
|
||||
}
|
||||
return readable;
|
||||
};
|
||||
|
||||
document.addEventListener('readystatechange', (event) => {
|
||||
if (document.readyState !== 'complete') return false;
|
||||
let queue = [],
|
||||
$page = document.getElementsByClassName('notion-page-content')[0];
|
||||
const DOCUMENT_OBSERVER = new MutationObserver((list, observer) => {
|
||||
if (!queue.length) requestIdleCallback(() => handle(queue));
|
||||
queue.push(...list);
|
||||
}),
|
||||
PAGE_OBSERVER = new MutationObserver(showPageWordDetails);
|
||||
DOCUMENT_OBSERVER.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
});
|
||||
function handle(list) {
|
||||
queue = [];
|
||||
for (let { addedNodes } of list) {
|
||||
if (
|
||||
addedNodes[0] &&
|
||||
addedNodes[0].className === 'notion-page-content'
|
||||
) {
|
||||
$page = addedNodes[0];
|
||||
showPageWordDetails();
|
||||
|
||||
PAGE_OBSERVER.disconnect();
|
||||
PAGE_OBSERVER.observe($page, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
characterData: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
const $container = createElement(
|
||||
`<div id="word-counter-details"><div></div></div>`
|
||||
),
|
||||
$tooltip = createElement(
|
||||
`<span id="word-counter-details-tooltip"></span>`
|
||||
);
|
||||
function showPageWordDetails() {
|
||||
const details = {
|
||||
words: $page.innerText.replace(/\s+/g, ' ').split(' ').length,
|
||||
characters: $page.innerText.length,
|
||||
sentences: $page.innerText.split('.').length,
|
||||
blocks: $page.querySelectorAll('[data-block-id]').length,
|
||||
};
|
||||
details['reading time'] = [
|
||||
humanTime(details.words / 275),
|
||||
'~275 wpm',
|
||||
];
|
||||
details['speaking time'] = [
|
||||
humanTime(details.words / 180),
|
||||
'~180 wpm',
|
||||
];
|
||||
|
||||
$container.children[0].innerHTML = `
|
||||
${store().hide_page_details_text ? '' : '<span><b>page details<br></b> (click to copy)</span>'}
|
||||
${Object.keys(details).reduce(
|
||||
(prev, key) =>
|
||||
prev +
|
||||
(Array.isArray(details[key])
|
||||
? `<p>
|
||||
<b>${details[key][0]}</b> ${key}
|
||||
<!-- from https://fontawesome.com/icons/question-circle?style=regular -->
|
||||
<svg data-tooltip="${details[key][1]}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003
|
||||
248-248C504 119.083 392.957 8 256 8zm0 448c-110.532 0-200-89.431-200-200
|
||||
0-110.495 89.472-200 200-200 110.491 0 200 89.471 200 200 0 110.53-89.431 200-200
|
||||
200zm107.244-255.2c0 67.052-72.421 68.084-72.421 92.863V300c0 6.627-5.373 12-12 12h-45.647c-6.627
|
||||
0-12-5.373-12-12v-8.659c0-35.745 27.1-50.034 47.579-61.516 17.561-9.845 28.324-16.541 28.324-29.579
|
||||
0-17.246-21.999-28.693-39.784-28.693-23.189 0-33.894 10.977-48.942 29.969-4.057 5.12-11.46 6.071-16.666
|
||||
2.124l-27.824-21.098c-5.107-3.872-6.251-11.066-2.644-16.363C184.846 131.491 214.94 112
|
||||
261.794 112c49.071 0 101.45 38.304 101.45 88.8zM298 368c0 23.159-18.841
|
||||
42-42 42s-42-18.841-42-42 18.841-42 42-42 42 18.841 42 42z"
|
||||
></path>
|
||||
</svg>
|
||||
</p>`
|
||||
: `<p><b>${details[key]}</b> ${key}</p>`),
|
||||
''
|
||||
)}`;
|
||||
$page.previousElementSibling.children[0].appendChild($container);
|
||||
if (!$container.offsetParent) return;
|
||||
$container.offsetParent.appendChild($tooltip);
|
||||
$container
|
||||
.querySelectorAll('p')
|
||||
.forEach((p) =>
|
||||
p.addEventListener('click', (e) =>
|
||||
copyToClipboard(e.target.innerText)
|
||||
)
|
||||
);
|
||||
$container.querySelectorAll('[data-tooltip]').forEach((el) => {
|
||||
el.addEventListener('mouseenter', (e) => {
|
||||
$tooltip.innerText = el.getAttribute('data-tooltip');
|
||||
$tooltip.style.top = el.parentElement.offsetTop + 2.5 + 'px';
|
||||
$tooltip.style.left =
|
||||
el.parentElement.offsetLeft +
|
||||
el.parentElement.offsetWidth -
|
||||
5 +
|
||||
'px';
|
||||
$tooltip.classList.add('active');
|
||||
});
|
||||
el.addEventListener('mouseleave', (e) =>
|
||||
$tooltip.classList.remove('active')
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
Loading…
Reference in New Issue
Block a user