🧑‍💻

#130 AIチャットサイト用の汎用改行設定ツールを作る1

に公開

はじめに

最近、AIチャットサイトが次々と登場しています。しかし、多くのサイトでは改行設定が用意されておらず、Enterキーで送信されてしまう仕様が主流です。このため、意図せずメッセージを送信してしまうことがあり、使い勝手が悪いと感じる場面が多々あります。

以前、Google Chatの改行設定をカスタマイズするブラウザ拡張機能を作ったことがありました(リンク)。このときの拡張機能を流用して、AIチャットサイトでも汎用的に改行設定を変更できる拡張機能を作れないかと考えました。今回は、その実現可能性を検証してみます。

やりたいこと

以下の3点を目指します。

  1. 改行設定の変更
    Enterで改行し、Ctrl + Enterで送信するように設定を切り替えたい。

  2. 対象ページの柔軟な追加
    対象となるページを、ソースコードを書き換えずに拡張機能のUIから簡単に追加できるようにしたい。

  3. 入力欄の指定
    Enterキーの動作を常に変更してしまうと意図せぬ動作が発生しそうなので、各ページのチャット欄入力中以外は処理が走らないようにしたい。
    入力欄の検知は、拡張機能のUIからHTMLセレクタを手動入力する形にする。入力欄にIDが振られていないことも多いため自動検知は難しそう。

このうち1番については拡張機能ではなく各ページの実装に依存するため、可能かどうか不安があります。
そのため、今回は1番の実現可能性について検証を行います。

検証

Google Chat用の拡張機能を作った際は、Enterキーのkeydownイベントをキャンセルし、execCommand("insertLineBreak")を実行することで改行を実現しました。この方法がAIチャットサイトでも有効か試してみます。

検証対象サイト

検証コード(Google Chatの拡張機能のJavaScriptをほぼそのまま流用)
// (サイトごとに変更)入力欄のセレクタ
let selector = 'div[contenteditable="true"]';
// 投稿キー
let postKey = 'ctrlKey';

let isComposing = false;

// IME開始時
window.addEventListener('compositionstart', () => {
  isComposing = true;
});

// IME終了時(変換確定時)
window.addEventListener('compositionend', () => {
  isComposing = false;
});

window.addEventListener("keydown", handler, true);

function handler(event) {
  if (isComposing) {
    // 変換の最中なら何もしない
    return;
  }
  if (!postKey || postKey == 'enter') {
    // 改行設定がデフォルト通りなら何もしない
    return;
  }
  if (event.key !== "Enter") {
    // Enterキー以外は何もしない
    return;
  }
  if (event.isModified) {
    // 無限ループ防止
    return;
  }
  if (!event.target.matches(selector)) {
    // 入力エリア以外のときは何もしない
    return;
  }

  if (event[postKey]) {
    // 投稿キー + Enter の場合
    // Enter 単体イベントを発火させて投稿を実行
    const properties = [];
    for (const key in event) {
      properties[key] = event[key];
    }
    properties.shiftKey = false;
    const modifiedEvent = new KeyboardEvent("keydown", properties);
    modifiedEvent.isModified = true;
    event.target.dispatchEvent(modifiedEvent);
  } else {
    // Enter 単体の場合
    // 改行実行
    document.execCommand("insertLineBreak");
  }

  event.preventDefault();
  event.stopImmediatePropagation();
}

検証したところ、Ctrl + Enter での送信はすべてのサイトで動作したのですが、Enterでの改行が、一部のサイトではスペースが入るのみとなってしまいました。
そこで、改行の実行として別の処理方法を試してみました。
上記の検証コードで、document.execCommand("insertLineBreak");の代わりに下記のようにShift + Enterのキーイベントを発火してみます。

代替コード
let lineBreakEvent = new KeyboardEvent("keydown", {
  key: "Enter",
  shiftKey: true,
  bubbles: true,
  cancelable: true
});
lineBreakEvent.isModified = true;
event.target.dispatchEvent(lineBreakEvent);

こちらで検証したところ、execCommand("insertLineBreak")が効かなかったサイトはこの方法で改行できましたが、execCommand("insertLineBreak")で改行できたサイトはこちらの方法では改行できませんでした。

検証結果まとめ

サイト execCommand("insertLineBreak")で改行 dispatchEventで改行 Ctrl + Enter で送信
ChatGPT 空白が入るだけ 改行できた 送信できた
Claude 空白が入るだけ 改行できた 送信できた
Felo 改行できた 何も起こらない 送信できた
Perplexity 改行できた 何も起こらない 送信できた

上表より、execCommand("insertLineBreak")dispatchEventの2つの方法を組み合わせれば、今回検証した限りでは全てのサイトに対応できそうです。

まとめ

今回は、改行設定を変更する拡張機能の実現可能性を検証しました。その結果、2つの改行処理を組み合わせることで、主要なAIチャットサイトで動作する見込みが得られました。

次回は、対象ページの登録やセレクタの設定を行えるUIを拡張機能に実装し、実際に使用できる形に進めていきます。また、受け付ける改行処理がサイトによって異なる理由についても可能であれば調査してみたいと思います。

最後まで読んでいただきありがとうございました。

Discussion