📅

Slack のタイムスタンプを絶対時間表記にする

2022/09/28に公開

ほんとそれです。
https://twitter.com/esumii/status/1572797419343196160

普段使っているアプリのうち、GitLab は、こんな具合に設定で相対表記か絶対表記か選べるのでいいんですが、

Slack が設定できなくて困るので、むりやり変更してみました。

Slack のタイムスタンプ表示部分の DOM 構造

このテーマと無関係と思われる属性は除いて、さらに見やすいように整形してあります。

<a
  aria-label="Sep 26th at 15:48:00"
  data-ts="1664174880.411349"
  class="c-link c-timestamp"
  href="https://******.slack.com/archives/***********/p1234567890123456"
>
    <span class="c-timestamp__label">7 minutes ago</span>
</a>

aria-label に、マウスカーソルをホバーしたときにポップアップする絶対時間表記の文字列が入っています。これが使えそうです。
(data-ts に epoch が入ってるようなので、これを使った方がより柔軟な表示をできそうですが、たった今気づいたのでやってません(爆)。)

方法1: CSS

Stylus で、こんなカスタムCSSを入れてみました。

a.c-timestamp::after {
    content: " (" attr(aria-label) ")";
}

試行錯誤した経緯はばっさり割愛しますが、.c-timestamp__labelspan の中身を書き換えることはできず諦めて、::after で併記してます。

なかなかいい感じです。なんですが、疑似要素で追加した文字列はコピーできないってことをすっかり忘れていました。それでは御利益半減なので、次の方法に行きます。

方法2: Mutaion Observer

Tampermonkeyで、こんなカスタムスクリプトを入れてみました。
なお、@run-atdocument-start にしてあります。

(function() {
    'use strict';

    const callback = (mutations, observer) => {
        for (const mutation of mutations) {
            //console.log("mutation: ", mutation);
            if (mutation.type == 'childList' && mutation.addedNodes.length > 0) {
                const elements = mutation.target.getElementsByClassName('c-timestamp');
                for (const element of elements) {
                    if (element.parentNode.className == 'c-message_kit__gutter__right') {
                        const timestamp = element.getElementsByClassName('c-timestamp__label')[0];
                        const absolute = element.getAttribute('aria-label');
                        if (timestamp.innerText != absolute) {
                            timestamp.innerText = absolute;
                        }
                    }
                }
            }
            else if (mutation.type == 'characterData' && mutation.target.parentNode.className == 'c-timestamp__label') {
                const timestamp = mutation.target.parentNode;
                const element = timestamp.parentNode;
                const absolute = element.getAttribute('aria-label');
                if (timestamp.innerText != absolute) {
                    timestamp.innerText = absolute;
                }
            }
        }
    }
    const observer = new MutationObserver(callback);
    observer.observe(document.body,{
        subtree: true,
        childList: true,
        attributes: false,
        characterData: true,
        attributeOldValue: false,
        characterDataOldValue: false
    });
})();

ここでも試行錯誤しまくった経緯はばっさり省きますが、Mutation Observer で、子孫に .c-timestamp な要素を持ったノードが生成されたのを捕まえて、.c-timestamp__labelspan の中身を aria-label の値で上書きしてます。
2022-09-29追記: .c-timestamp__labelspan の text に直接 mutation が上がってくるケースもありました。対応するようにコードを改訂しました。
2022-10-31追記: 余分に書き換わって表示が乱れるケースがあったので、コードを改訂しました。

こんな感じになりました。コピペもちゃんとできます。

Discussion