ChatGPT Code Interpreterに簡単なSPA作ってもらった

## はじめに
ChatGPT，使ってますか？Webフロント初心者未満の私は主にブログの改修で絶賛お世話になっています．今回は最近使えるようになったCode Interpreterで簡単なSPAを作ってもらった話の紹介です．

## 困りごと
私のブログはGitHub Pagesを使って制作されており，記事をmarkdown形式で書いて`git push`するとよしなに静的サイトが生成されるシステムです．

ページこちら：https://kim-xps12.github.io/b-sky-lab/

markdownへ画像を載せるためにhtmlコードをベタ書きして，`<a>`タグや`<img>`タグにちまちまとGooglePhotoで公開設定した画像のURLを設定していたんですが，これが地味だけどかなり面倒です．~~ブログ更新をサボりがちだったのはこれが面倒すぎてストレスだったからだと半分くらい本気で思っています~~．URLを指定したらタグの全文がクリップボードへ格納されて，あとは貼り付けるだけだったら便利になるのになーとずっと思っていました．

## 欲しかったもの
そんなに手をかける元気もなかったので，以下の条件で考えました．

- 単一のhtmlファイルで完結している
  - javascriptのコードはhtmlに埋め込んでおく
- 入力：画像のURLをテキストボックスに入れる
- 加工：以下のhtmlコード中`piyo-url`に入力で受け取ったURLを設定する
    ```html
    <a href="piyo-url" target="_blank">
      <img src="piyo-url" width="75%" style="display: block; margin: auto;">
    </a>
    ```
- 出力：上記で加工された文字列がクリップボードへ格納される

慣れている人ならサクッと書けそうな内容ですね．

## 出来上がったもの

ChatGPTくんと何往復か問答して，最終的に以下のコードで完成としました．

```html
<!DOCTYPE html>
<html>
<head>
    <title>URL Appender</title>
</head>
<body>
    <input type="text" id="urlInput" placeholder="Enter your URL here" onkeydown="handleKeyDown(event)">
    <button onclick="appendToURL()">Append and Copy to Clipboard</button>
    <div id="result"></div>

    <script>
        function appendToURL() {
            var url = document.getElementById('urlInput').value;
            var appendedURL = `<a href="${url}" target="_blank">\n` +
                              `    <img src="${url}" width="75%" style="display: block; margin: auto;">\n` +
                              `</a>`;

            navigator.clipboard.writeText(appendedURL).then(function() {
                console.log('Appending and copying to clipboard was successful!');
                document.getElementById('result').innerHTML = appendedURL;
            }, function(err) {
                console.error('Could not copy text: ', err);
            });
        }

        function handleKeyDown(event) {
            if (event.keyCode === 13) {
                appendToURL();
            }
        }
    </script>
</body>
</html>
```

これをhtmlファイルとして保存して，Google Chromeで開くと以下のような画面が表示されます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1490597/4fa187b1-8c28-ccd6-e3ba-7109f1dded13.png)

[Enter your URL here]とある箇所に画像のURLを貼り付けて，右の[Append and Copy to Clipboard]ボタンを押下するとよしなに加工したURLがクリップボードへ格納されます．ボタンを押すのが面倒な場合も考えられたので，キーボードのEnterキー押下でも同様の処理が走るようにしました．とても便利です．

## 作り方

せっかくなのでプロンプトとその応答も載せておきます．


1. とりあえず簡単な例で頼む
    ```
    以下の条件を満たすwebアプリケーションのhtmlを作成してください．
    - 単一のhtmlファイルであること．
    - java scriptをhtmlファイル内に埋め込んで利用すること
    - URLを文字列として受け取って，任意の文字列と結合し，クリップボードへ保存する機能を実現すること
      - URLの受け取りはテキストボックスを読み取ることで実現すること
      - 結合対象の文字列はhtmlファイル内にハードコーディングでよい
      - 結合対象の文字列は暫定的に"hello-"とする
    ```
1. 良い感じのものが出てきた
    > 以下に、指定の条件を満たすHTMLコードを示します。HTMLファイル内にJavaScriptを埋め込み、テキストボックスで入力したURLを"hello-"という文字列と結合し、その結果をクリップボードに保存するように設定しています。
    ```html
    <!DOCTYPE html>
    <html>
    <head>
        <title>URL Appender</title>
    </head>
    <body>
        <input type="text" id="urlInput" placeholder="Enter your URL here">
        <button onclick="appendToURL()">Append and Copy to Clipboard</button>

        <script>
            function appendToURL() {
                var url = document.getElementById('urlInput').value;
                var appendedURL = "hello-" + url;

                navigator.clipboard.writeText(appendedURL).then(function() {
                    console.log('Appending and copying to clipboard was successful!');
                }, function(err) {
                    console.error('Could not copy text: ', err);
                });
            }
        </script>
    </body>
    </html>
    ```
    > 上記のコードでは、ユーザーがテキストボックスにURLを入力し、"Append and Copy to Clipboard"ボタンをクリックすると、そのURLに"hello-"が付加され、その結果がクリップボードにコピーされます。成功した場合、ブラウザのコンソールにメッセージが表示されます。
ただし、一部のブラウザではセキュリティの観点から、クリップボードへのアクセスを制限しているため、navigator.clipboard.writeText()関数が必ずしもすべての環境で動作するわけではないことに注意してください。

1. 褒めつつ，結合対象を適当な文字列から本命のhtmlタグに変更してもらう．valの箇所に～と書いていますが，コード例のURLをvalに置換するのを忘れています…
    ```
    ありがとうございます．要求を完璧に満たした素晴らしいコードです．このコードにおいて，「URLと任意の文字列と結合する」機能を以下のように変更してください．
    - 以下の文字列において，"val"の箇所に受け取ったURLを代入する

   \```
   <a href="https://www.pcbway.com/" target="_blank">
     <img src="https://lh3.googleusercontent.com/pw/AIL4fc8Y-5DuPTnE3TedC3e_nca1cqsRDBjK2vYiZSVxdn43k2GcDJb8VDV8-wWdl7YSXeOk8qgCawWcfoaiFgCJ9qnNb37NbIEaEEbSrzVHyW-GnTaFKR8emjXSvjAgoxjqR_kjjhXbRssYyPGhAMrseXb4Gg=w1602-h747-s-no?authuser=0" width="75%" style="display: block; margin: auto;">
   </a>
   \```

    ```

1. valへの置換忘れもよしなに意図を組んで作ってくれた．
    > 要求に従って、受け取ったURLをHTMLリンク内に代入するようにコードを変更しました。ここでは、受け取ったURLがリンクのhref属性と画像のsrc属性に設定されます。

    ```html
    <!DOCTYPE html>
    <html>
    <head>
        <title>URL Appender</title>
    </head>
    <body>
        <input type="text" id="urlInput" placeholder="Enter your URL here">
        <button onclick="appendToURL()">Append and Copy to Clipboard</button>
        <div id="result"></div>

        <script>
            function appendToURL() {
                var url = document.getElementById('urlInput').value;
                var appendedURL = `<a href="${url}" target="_blank">
                                    <img src="${url}" width="75%" style="display: block; margin: auto;">
                                   </a>`;

                navigator.clipboard.writeText(appendedURL).then(function() {
                    console.log('Appending and copying to clipboard was successful!');
                    document.getElementById('result').innerHTML = appendedURL;
                }, function(err) {
                    console.error('Could not copy text: ', err);
                });
            }
        </script>
    </body>
    </html>
    ```
    > このコードは、ユーザーがテキストボックスにURLを入力し、"Append and Copy to Clipboard"ボタンをクリックすると、そのURLを含む新しいリンクと画像タグが生成され、それがクリップボードにコピーされます。また、生成されたリンクと画像タグは画面上の"result"というIDを持つdivタグ内に表示されます。成功した場合、ブラウザのコンソールにメッセージが表示されます。
ただし、ブラウザのセキュリティポリシーにより、navigator.clipboard.writeText()関数がすべての環境で動作するわけではないことに注意してください。


1. クリップボードへ入る文字列のインデントが壊れてるので直してもらう
    ```
    ありがとうございます．要求を完璧に満たした素晴らしいコードです．このコードでクリップボードへ保存された文字列は以下のようにインデントが不適切です．この問題を解消したバージョンを作成してください．

    \```
    <a href="hoge-url" target="_blank">
                                    <img src="hoge-url" width="75%" style="display: block; margin: auto;">
                                   </a>
    \```
    ```

1. 直ったものが出てきた（実際にはクリップボードへ文字列が入っていなかったのでもう1往復していますが割愛）．
    > クリップボードへの書き込みは、ユーザーのブラウザによっては制限されている可能性があります。具体的には、クリップボードへの書き込みはユーザーの操作（クリックなど）をトリガーにする必要がある場合が多いです。また、これらのAPIはHTTPS接続を通じた安全なコンテキストでのみ動作する場合があります。
さらに、HTML要素をクリップボードにコピーする際には、navigator.clipboard.writeText()ではなくnavigator.clipboard.write()を使用する必要があります。ただし、navigator.clipboard.write()はBlobを含むDataTransferオブジェクトを受け取ります。
しかし、現時点では（2023年7月）、多くのブラウザはクリップボードへのHTMLの書き込みを直接サポートしていません。そのため、HTMLをクリップボードにコピーする最も一般的な方法は、HTMLをテキストとしてコピーし、そのテキストを受け取った側で適切に解釈することです。この制限により、クリップボードにコピーしたHTMLがそのままの形で他のアプリケーションに貼り付けられるとは限りません。
したがって、現在の要件を満たすためには、HTMLをテキストとしてクリップボードにコピーするようにコードを修正します。その結果、クリップボードにコピーされたHTMLはテキストとして利用できます。
以下に、修正したコードを示します：
    ```html
    <!DOCTYPE html>
    <html>
    <head>
        <title>URL Appender</title>
    </head>
    <body>
        <input type="text" id="urlInput" placeholder="Enter your URL here">
        <button onclick="appendToURL()">Append and Copy to Clipboard</button>
        <div id="result"></div>

        <script>
            function appendToURL() {
                var url = document.getElementById('urlInput').value;
                var appendedURL = `<a href="${url}" target="_blank">\n` +
                                  `    <img src="${url}" width="75%" style="display: block; margin: auto;">\n` +
                                  `</a>`;

                navigator.clipboard.writeText(appendedURL).then(function() {
                    console.log('Appending and copying to clipboard was successful!');
                    document.getElementById('result').innerHTML = appendedURL;
                }, function(err) {
                    console.error('Could not copy text: ', err);
                });
            }
        </script>
    </body>
    </html>
    ```
    > このコードは、ユーザーがテキストボックスにURLを入力し、"Append and Copy to Clipboard"ボタンをクリックすると、そのURLを含む新しいリンクと画像タグが生成され、それがテキストとしてクリップボードにコピーされます。

1. ついでにEnterキー押下でも動くようにしてもらう．
    ```
    ありがとうございます．要求を完璧に満たした素晴らしいコードです．更に，クリップボードへのコピーが「テキストボックスがアクティブな状態でEnterキーを押下したとき」にも実行されるように改良してください．
    ```

1. 言った通りのものが出てきた．これで完成！ここまで約20分…
    > "Enter"キーの押下を検出するためには、テキストボックスに"keydown"イベントリスナーを追加します。このイベントリスナーは、ユーザーがキーを押下したときに発火します。その後、イベントのkeyCodeプロパティをチェックして、押下されたキーが"Enter"キー（keyCode 13）であるかどうかを確認します。もし"Enter"キーが押下されていたら、URLを処理してクリップボードにコピーする関数を呼び出します。
以下に、改良したコードを示します：

    ```html
    <!DOCTYPE html>
    <html>
    <head>
        <title>URL Appender</title>
    </head>
    <body>
        <input type="text" id="urlInput" placeholder="Enter your URL here" onkeydown="handleKeyDown(event)">
        <button onclick="appendToURL()">Append and Copy to Clipboard</button>
        <div id="result"></div>

        <script>
            function appendToURL() {
                var url = document.getElementById('urlInput').value;
                var appendedURL = `<a href="${url}" target="_blank">\n` +
                                  `    <img src="${url}" width="75%" style="display: block; margin: auto;">\n` +
                                  `</a>`;

                navigator.clipboard.writeText(appendedURL).then(function() {
                    console.log('Appending and copying to clipboard was successful!');
                    document.getElementById('result').innerHTML = appendedURL;
                }, function(err) {
                    console.error('Could not copy text: ', err);
                });
            }

            function handleKeyDown(event) {
                if (event.keyCode === 13) {
                    appendToURL();
                }
            }
        </script>
    </body>
    </html>
    ```
## おわりに
いかがでしたか？ChatGPT Code Interpreter，革命的に便利ですね…便利な活用ができたらまた記事更新したいと思います．それでは．