From 4934feb33e2d0423fb50876062669e0f6efe6857 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Tue, 2 Jun 2026 16:30:38 +0300 Subject: [PATCH] =?UTF-8?q?=E8=B8=8A=E3=81=A3=E3=81=A6=E3=81=AA=E3=81=84?= =?UTF-8?q?=E5=A4=9C=E3=82=92=E7=9F=A5=E3=82=89=E3=81=AA=E3=81=84=20?= =?UTF-8?q?=E8=B8=8A=E3=81=A3=E3=81=A6=E3=81=AA=E3=81=84=E5=A4=9C=E3=81=8C?= =?UTF-8?q?=E6=B0=97=E3=81=AB=E5=85=A5=E3=82=89=E3=81=AA=E3=81=84=20https:?= =?UTF-8?q?//shigusegubu.club/notice/B6Y2J5biTNp1VtN0pE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/rich_content/rich_content.jsx | 81 ++++++++++++++----- src/components/rich_content/rich_content.scss | 11 ++- 2 files changed, 72 insertions(+), 20 deletions(-) diff --git a/src/components/rich_content/rich_content.jsx b/src/components/rich_content/rich_content.jsx index 60b546a83..1625f4a51 100644 --- a/src/components/rich_content/rich_content.jsx +++ b/src/components/rich_content/rich_content.jsx @@ -324,18 +324,18 @@ export default { newAttrs['data-mfm-operator'] = mfmOperator switch(mfmOperator) { case 'position': { - const x = fullAttrs['data-mfm-x'] || 0 - const y = fullAttrs['data-mfm-y'] || 0 + const x = fullAttrs['data-mfm-x'].replace(/\.+$/,'') || 0 + const y = fullAttrs['data-mfm-y'].replace(/\.+$/,'') || 0 newAttrs.style = [ 'transform:', - `translateX(calc(${x} * (var(--emoji-size) / 2)))`, - `translateY(calc(${y} * (var(--emoji-size) / 2)))`, + `translate(calc(${x} * (var(--emoji-size) / 2)), `, + `calc(${y} * (var(--emoji-size) / 2)))`, ].join(' ') break } case 'scale': { - const x = fullAttrs['data-mfm-x'] || 1 - const y = fullAttrs['data-mfm-y'] || 1 + const x = fullAttrs['data-mfm-x'].replace(/\.+$/,'') || 1 + const y = fullAttrs['data-mfm-y'].replace(/\.+$/,'') || 1 newAttrs.style = [ 'transform:', `scale(${x}, ${y})`, @@ -345,11 +345,9 @@ export default { case 'rotate': { const deg = fullAttrs['data-mfm-deg'] || 0 newAttrs.style = [ - 'transform:', - `rotate(${deg}deg);`, - 'transform-origin:', - 'center', - ].join(' ') + `transform: rotate(${deg}deg)`, + 'transform-origin: center', + ].join(';') break } case 'bg': { @@ -363,32 +361,79 @@ export default { const color = fullAttrs['data-mfm-color'] || 0 newAttrs.style = [ `color: #${color}`, - ].join(' ') + ].join(';') break } case 'spin': { - const speed = fullAttrs['data-mfm-speed'] = '1s' - const delay = fullAttrs['data-mfm-delay'] = 0 + const speed = fullAttrs['data-mfm-speed'] || '1s' + const delay = fullAttrs['data-mfm-delay'] || 0 + const left = fullAttrs['data-mfm-left'] != null + const alternate = fullAttrs['data-mfm-alternate'] != null const y = fullAttrs['data-mfm-y'] != null const x = fullAttrs['data-mfm-x'] != null + const anim = [ x ? 'mfm-spinX' : null, y ? 'mfm-spinY' : null, 'mfm-spin' ].filter(a => a)[0] - newAttrs.style = `animation: ${speed} linear ${delay} infinite normal none running ${anim}` + + const direction = [ + alternate ? 'alternate' : null, + left ? 'reverse' : null, + 'normal', + ].filter(a => a)[0] + + newAttrs.style = [ + `animation-name: ${anim}`, + `animation-duration: ${speed}`, + 'animation-iteration-count: infinite', + `animation-delay: ${delay}`, + `animation-direction: ${direction}`, + 'animation-fill-mode: none', + 'animation-timing-function: linear', + ].join(';') break } case 'flip': { newAttrs.style = 'transform: scaleX(-1)' break } - case 'jump': + case 'border': { + const width = fullAttrs['data-mfm-width'] || '0' + const style = fullAttrs['data-mfm-style'] || 'solid' + const color = fullAttrs['data-mfm-color'] || 'transparent' + const radius = fullAttrs['data-mfm-radius'] || '0' + const noclip = fullAttrs['data-mfm-noclip'] || false + + newAttrs.style = [ + `border: ${width} ${style} ${color}`, + `border-radius: ${radius}`, + `overflow: ${noclip ? 'visible' : 'clip'}` + ].join(';') + break + } + case 'tada': + case 'jelly': case 'twitch': case 'shake': - case 'bounce': - newAttrs.style = `animation: 0.75s linear 0s infinite normal none running mfm-${mfmOperator}` + case 'jump': + case 'bounce': { + const speed = fullAttrs['data-mfm-speed'] || '1s' + const delay = fullAttrs['data-mfm-delay'] || 0 + + const rules = [ + `animation-name: mfm-${mfmOperator}`, + `animation-duration: ${speed}`, + 'animation-iteration-count: infinite', + `animation-delay: ${delay}`, + 'animation-direction: normal', + 'animation-fill-mode: none', + 'animation-timing-function: linear', + ].join(';') + newAttrs.style = rules break + } default: console.log(mfmOperator, opener) console.log(mfmOperator) diff --git a/src/components/rich_content/rich_content.scss b/src/components/rich_content/rich_content.scss index 230ea8be5..4aad49477 100644 --- a/src/components/rich_content/rich_content.scss +++ b/src/components/rich_content/rich_content.scss @@ -1,9 +1,16 @@ .RichContent { font-family: var(--font); + text-align: center; .mfm { display: inline-block; font-size: calc(var(--emoji-size) / 2); + + .emoji { + /* Misskey's emoji width knows no bounds */ + /* stylelint-disable-next-line declaration-no-important */ + max-width: unset !important; + } } &.-faint { @@ -148,7 +155,7 @@ a .RichContent { } 25% { - transform: translateY(-16px) + transform: translateY(-1em) } 50% { @@ -156,7 +163,7 @@ a .RichContent { } 75% { - transform: translateY(-8px) + transform: translateY(-0.5em) } 100% {