Skip to content

Instantly share code, notes, and snippets.

@pacochi
Last active June 3, 2021 09:55
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pacochi/ae6714d1c71a8ef52a3d5a3407886e94 to your computer and use it in GitHub Desktop.
Save pacochi/ae6714d1c71a8ef52a3d5a3407886e94 to your computer and use it in GitHub Desktop.
Mastodon の発言入力欄で絵文字の後ろについているスペースをゼロ幅スペースに変換するボタンを追加します。
// ==UserScript==
// @name [Mastodon] add "space → zero width space" button
// @namespace hen.acho.co
// @include https://*/web/*
// @version 2.210603
// @description make custom emoji fit snugly
// @downloadURL https://gist.github.com/pacochi/ae6714d1c71a8ef52a3d5a3407886e94/raw/mastodon_spc2zwsp.user.js
// @run-at document-idle
// @grant none
// ==/UserScript==
(() => {
const root = document.querySelector('#mastodon');
if (!root) return;
// ここ見つかるまで MutationObserver 挟もうかと思ったけどすぐ見つかるっぽい
const body = root.querySelector('.columns-area, .columns-area__panels__main');
if (!body) return;
const BR = s => s.replace(/[^\r\n]/g, '');
const addFitButton = (drawer = body.querySelector('.drawer')) => {
if (!drawer || drawer.querySelector('#zwspconv')) return;
const buttons = drawer.querySelector('.compose-form__buttons');
const tootTextarea = drawer.querySelector('.autosuggest-textarea__textarea');
if (!buttons || !tootTextarea) return;
const spButton = Object.assign(document.createElement('button'),
{ id: 'zwspconv', textContent: '詰', className: 'text-icon-button'}
);
spButton.addEventListener('click', e => {
// https://github.com/vitalyq/react-trigger-change/blob/v1.0.2/lib/change.js#L135-L140
// が動かなくなったから
// https://github.com/facebook/react/issues/11095
// にした
Object.getOwnPropertyDescriptor(Object.getPrototypeOf(tootTextarea), 'value').set
.call(tootTextarea, tootTextarea.value
// 詰めた後に絵文字いじったりするので割と多めにつけてる
// 必要最低限にしたい場合は https://gist.github.com/unarist/08f56c49986d3b1775fe88bc918cac50 を参照してね
.replace(/(\s*)(:[-\w]+:)(\s*)/g, (_, p, c, s) => `${BR(p)}\u200b${c}\u200b${BR(s)}`)
.replace(/\u200b+/g, '\u200b'));
tootTextarea.dispatchEvent(new Event('input', { bubbles: true }));
}, false);
buttons.append(spButton);
};
if (window.matchMedia('(max-width: 1280px)').matches) {
let columns = body.querySelector('.columns-area--mobile');
let drawer = null;
const observer = new MutationObserver((mutations, observer) => {
drawer = mutations.reduce(
(nodes, mutation) => nodes.concat(Array.from(mutation.addedNodes)), [])
.find(node => node.className == 'drawer');
columns = body.querySelector('.columns-area--mobile');
if (columns) observer.observe(columns, { childList: true });
if (location.pathname == '/web/statuses/new') addFitButton();
else if (body.className.trim() == 'columns-area' && drawer) addFitButton(drawer);
});
observer.observe(body, { childList: true });
if (columns) observer.observe(columns, { childList: true });
}
addFitButton();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment