クジラとネコの親子プログラミング - Docker for Windowsを使ってScratch3.0のオリジナル拡張機能を試してみよう。

# 親子プログラミングはGitとNode.jsが使えることが前提になっている？

小学校でのプログラミング教育の必須化に伴って、子供たちがScratch 3.0に触れる機会も増えるかと思います。そんな中、ブロックをくっつけるだけのお遊びツールだとあなどっていると、次のような連載が始まりました。

>[「親子でできる！Scratch と AWS を使った "ものづくり" 体験 - 1. 準備 〜 疎通確認編」](https://aws.amazon.com/jp/builders-flash/202009/programming-with-kids/)
2020-09-01
How to be a Developer
金澤 圭

この連載の[「2. 作業の前提について」](https://aws.amazon.com/jp/builders-flash/202009/programming-with-kids/#02)で、衝撃的な次の一文があります。

> **PC に Git と Node.js がインストールされている必要があります。**

保護者の方も、GitやNode.jsを当たり前のようにインストールしなければいけない時代になりましたね。でも、安心してください。Dockerという便利なツールがありますので、簡単に開発環境を整えることができます。

本記事では、Webベースの統合開発環境である`code-server`とScratch 3.0 拡張機能の開発と実行に必要なソースコード(`scratch-vm/scratch-gui`)を詰め合わせたDockerコンテナ(`jprad/s3coder`)を使って、Windowsパソコン上で、`Scratch 3.0 GUI`サーバーを起動できるようにします。
後半では、[「Scratch 3.0の拡張機能を作ってみよう」](https://ja.scratch-wiki.info/wiki/Scratch_3.0%E3%81%AE%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86)を参考にして、拡張機能を追加します。

**拡張機能を追加して、Scratch 3.0 GUIでコーディング**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/b3d94dc1-1606-fd30-97af-964b330fc61f.png)


## 必要なもの

- Windows 10 パソコン
- [Docker Desktop on Windows](https://docs.docker.com/docker-for-windows/install/) または [Docker Desktop on Windows Home](https://docs.docker.com/docker-for-windows/install-windows-home/)

Windows 10 パソコンにDockerをインストールしてください。Dockerのインストール方法は、リンク先や各種記事を参照してください。

## セットアップと起動

Dockerイメージ(`jprad/s3coder`)を元にDockerコンテナを起動し、`Scratch 3.0 GUI`サーバーをWindowパソコンで実行できるようにします。


### 1. 共有フォルダの作成とDockerコンテナの初回起動

Windows 10 で、コマンドプロンプトを起動し、次の一連のコマンドを入力します。

```コマンドプロンプト.cmd
cd c:\
mkdir scratch-ws
docker run --name s3coder -d -p 8080:8080 -p 8601:8601 ^
-v C:/scratch-ws:/home/coder/s3/scratch-ws -e PASSWORD=password ^
jprad/s3coder /home/coder/s3

REM docker run ... のコマンドが長いので「^（キャレット）」で改行しています。
```

`C\scratch-ws`フォルダは、Dockerコンテナにマウントされる共有フォルダです(/home/coder/s3/scratch-ws)。
`docker run`コマンドを開始すると、必要なDockerイメージ（合計：844.17 MB）のダウンロードが始まり、Dockerコンテナが起動されます（コンテナ名:`s3coder`）。

**ダウンロード中のコマンドプロンプト**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/1e16510d-3576-e54b-f18f-db51a117ad3e.png)

**ダウンロード完了後、コンテナ起動済みのコマンドプロンプト**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/b07acd91-20ef-9ecd-40c3-d2db99c2f325.png)


Dockerコンテナの初回起動時に、共有フォルダへのアクセスを許可するかどうかの確認通知が表示されますので、`[Share it]`で許可します。

> **共有を許可（`Share it`）**
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/c9fa22ee-7332-3206-aaf6-a193f0d73a82.png)

### 2.code-severへのログインとScratch 3.0 GUIの起動

Dockerコンテナの起動完了後、[`code-server` ( http://localhost:8080 )](http://localhost:8080) へアクセスし、ログインします（パスワードは、`password`です）。統合開発環境が開きますので、Dockerイメージに同梱されている `scratch-gui`を起動します。起動方法が構成ファイル（./s3/.vscode/launch.json）に設定されていますので、クリック操作のみで起動できます。`scratch-gui`の起動完了後、[`Scratch 3.0 GUI` ( http://localhost:8601 )](http://localhost:8601) へアクセスすると、公式ページとは少しばかり異なっていますが、使い慣れた`Scratch 3.0`でのコーディングが行えます。

**手順**
1. [`code-server` ( http://localhost:8080 )](http://localhost:8080) へアクセスする。
2. パスワードに`password`と入力し、`[SUBMIT]`ボタンをクリックし、ログインする。
3. `[Run (Ctrl + Shift + D)]`アイコンをクリックする。
4. ドロップダウンリストで`'Run Scratch 3.0 GUI'`(既定)を選択する。
5. `[Start Debuging]`アイコンをクリックする。
6. `[TERMINAL]`タブをクリックし、ビルド完了後の`'Compiled successfully'` が表示されるのを待つ。
7. [`Scratch 3.0 GUI` ( http://localhost:8601 )](http://localhost:8601) へアクセスする。

**scratch-guiの起動**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/cceb8672-dbad-bc47-54bf-9c8f2812b203.png)

**Scratch 3.0 GUI**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/d0a6e594-1fb4-1440-ce57-42ecc4a27656.png)


### 3.停止・再開

**scratch-guiの再開・停止**
scratch-guiを停止せずに再開するには、coder-serverの`[Restart (Ctrl+Shift+F5)]`アイコンをクリックします。
scratch-guiを停止するには、code-serverの`[Stop (Shift+F5)]`アイコンをクリックします。

**scratch-guiの開始**

1. `[Run (Ctrl + Shift + D)]`アイコンをクリックする。
2. ドロップダウンリストで`'Run Scratch 3.0 GUI'`(既定)を選択する。
3. `[Start Debuging]`アイコンをクリックする。
4. `[TERMINAL]`タブをクリックし、ビルド完了後の`'Compiled successfully'` が表示されるのを待つ。

**Dockerコンテナの停止**
コマンドプロンプトで次のコマンドを実行するとDockerコンテナ（コンテナ名:`s3coder`）が停止します。

```コマンドプロンプト.cmd
docker stop s3coder
```

**Dockerコンテナの再開**
コマンドプロンプトで次のコマンドを実行するとDockerコンテナ（コンテナ名:`s3coder`）が再開します。

```コマンドプロンプト.cmd
docker start s3coder
```

## 拡張機能の開発

Scratch 3.0 Extensions の開発に関する情報には、次のようなものがあります。

- [「子供の科学 2020年9月号, p.p.66-69, ジャバスクリプトでスクラッチを拡張しよう」](https://amzn.to/35hAzDc)<br>子供向けの月刊誌の記事です。
- [「Scratch を改造しよう」](https://otona-scratch.champierre.com/books/1/posts)<br>[Strecth3](https://stretch3.github.io/)として、Scratch3.0で機械学習をプログラミングできる開発環境を提供する石原 淳也（いしはら じゅんや）氏の有償コンテンツです（一部無料公開あり）。
- [「Scratch 3.0 Extensions」](https://github.com/LLK/scratch-vm/blob/develop/docs/extensions.md)<br>LLK公式の拡張機能に関するページです。
- [「Scratch 3.0の拡張機能を作ってみよう」](https://ja.scratch-wiki.info/wiki/Scratch_3.0%E3%81%AE%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86)<br>Scratch 3.0の拡張機能の作り方をその下準備から説明しています。

ここでは、[「Scratch 3.0の拡張機能を作ってみよう」](https://ja.scratch-wiki.info/wiki/Scratch_3.0%E3%81%AE%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86)を参考にログを出力する拡張機能（ブロック）を実装(コピペ)してみます。

### 拡張機能に必要なファイル

拡張機能(`s3coder_newblocks`)を実装するには、次のファイルを追加・編集します。


**scratch-vm**

| # | フォルダ | ファイル | 追加 | 編集 | 説明 |
|:-:|---------|---------|:----:|:---:|------|
| 1 |scratch-vm/src/extensions/s3coder_newblocks | index.js | 〇 |  | 拡張機能(`newblocks`)の本体です。 |
| 2 | scratch-vm/src/extension-support | extension-manager.js |  | 〇 | 追加した拡張機能(`s3coder_newblocks`)を`builtinExtensions`に追加登録します。 |


**scratch-gui**

| # | フォルダ | ファイル | 追加 | 編集 | 説明 |
|:-:|---------|---------|:----:|:---:|------|
| 1 | scratch-gui/src/lib/libraries/extensions/s3coder_newblocks| newblocks.png | 〇 |  | 600x372ピクセルのPNG形式ファイルです。拡張機能の選択時にバナーとして表示されます。|
| 2 | scratch-gui/src/lib/libraries/extensions/s3coder_newblocks | newblocks-small.png | 〇 |  | 80x80ピクセルのPNG形式ファイルです。ブロックのアイコンとして表示されます。|
| 3 | scratch-gui/src/lib/libraries/extensions | index.js |  | 〇 | PNG形式ファイルの読込定義と拡張ブロックの定義を設定します。 |

### scratch-vm での実装

scratch-vmで、拡張機能そのものを実装します。

**フォルダ作成**

拡張機能用のフォルダを次の手順で作成します。

1. `code-server`のEXPLORERで、`s3/scratch-vm/src/extensions`フォルダを選択します。
2. 右クリックで、コンテキストメニューから`New Folder`を選択し、`'s3coder_newblocks'`フォルダを作成します。

**index.jsファイルの実装**

次の手順で、`index.js`ファイルを実装します。

1. 作成した`'s3coder_newblocks'`フォルダで右クリックし、`New File`を選択し、ファイル名を`index.js`とします。
2. [「Scratch 3.0の拡張機能を作ってみよう/基本の書式 - 拡張機能の追加」](https://ja.scratch-wiki.info/wiki/Scratch_3.0%E3%81%AE%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86/%E5%9F%BA%E6%9C%AC%E3%81%AE%E6%9B%B8%E5%BC%8F#.E6.8B.A1.E5.BC.B5.E6.A9.9F.E8.83.BD.E3.81.AE.E8.BF.BD.E5.8A.A0)から`index.js`のソースコードをコピー＆ペーストします。

<details><summary>index.js</summary><div>

```index.js
const ArgumentType = require('../../extension-support/argument-type');
const BlockType = require('../../extension-support/block-type');
const Cast = require('../../util/cast');
const log = require('../../util/log');

/**
 * Icon svg to be displayed at the left edge of each extension block, encoded as a data URI.
 * @type {string}
 */
// eslint-disable-next-line max-len
const blockIconURI = 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgdmlld0JveD0iMCAwIDQwIDQwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48ZyBpZD0iSUQwLjA4NjgyNDQzOTAwMDMzODMyIiB0cmFuc2Zvcm09Im1hdHJpeCgwLjQ5MTU0NjY2MDY2MTY5NzQsIDAsIDAsIDAuNDkxNTQ2NjYwNjYxNjk3NCwgLTY0LjUsIC03Ny4yNSkiPjxwYXRoIGlkPSJJRDAuNTcyMTQ2MjMwMzc3MjU2OSIgZmlsbD0iI0ZGOTQwMCIgc3Ryb2tlPSJub25lIiBkPSJNIDE4OCAxNDEgTCAyNTAgMTQxIEwgMjUwIDIwMyBMIDE4OCAyMDMgTCAxODggMTQxIFogIiB0cmFuc2Zvcm09Im1hdHJpeCgxLjI4NzkwMzMwODg2ODQwODIsIDAsIDAsIDEuMjg3OTAzMzA4ODY4NDA4MiwgLTExMC45LCAtMjQuNCkiLz48cGF0aCBpZD0iSUQwLjYzODMzNjEzNTA3NDQ5NjMiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIGQ9Ik0gMTk2IDIwNCBDIDE5NiAyMDQgMTkyLjcwNiAxOTAuMDU4IDE5MyAxODMgQyAxOTMuMDc0IDE4MS4yMzYgMTk1Ljg4NiAxNzguNDU4IDE5NyAxODAgQyAyMDEuNDU1IDE4Ni4xNjggMjAzLjQ0MyAyMDMuNzU0IDIwNiAyMDEgQyAyMDkuMjExIDE5Ny41NDIgMjEwIDE2NiAyMTAgMTY2ICIgdHJhbnNmb3JtPSJtYXRyaXgoMSwgMCwgMCwgMSwgLTU3LCAxNS44KSIvPjxwYXRoIGlkPSJJRDAuNzU4NzMwMzU2NTgxNTA5MSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgZD0iTSAyMTUgMTY5IEMgMjE1IDE2OSAyMTguMzY3IDE2OS41MzQgMjIwIDE3MCBDIDIyMC43MTYgMTcwLjIwNSAyMjEuMjc4IDE3MC44MTkgMjIyIDE3MSBDIDIyMi42NDYgMTcxLjE2MiAyMjMuMzY4IDE3MC43ODkgMjI0IDE3MSBDIDIyNC40NDcgMTcxLjE0OSAyMjUgMTcyIDIyNSAxNzIgIiB0cmFuc2Zvcm09Im1hdHJpeCgxLCAwLCAwLCAxLCAtNTcsIDE1LjgpIi8+PHBhdGggaWQ9IklEMC4yNDM2NzMwNzMxMjc4NjU4IiBmaWxsPSJub25lIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBkPSJNIDIyNyAxNTQgQyAyMjcgMTU0IDIxOC41NTUgMTQ3Ljg5MCAyMTcgMTUxIEMgMjEyLjM0NSAxNjAuMzEwIDIxMS4yODkgMTcxLjczMyAyMTMgMTgyIEMgMjEzLjYxMiAxODUuNjcyIDIyMyAxODcgMjIzIDE4NyAiIHRyYW5zZm9ybT0ibWF0cml4KDEsIDAsIDAsIDEsIC01NywgMTUuOCkiLz48cGF0aCBpZD0iSUQwLjc5MzkzOTQ4MTk1NTAyMTYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIGQ9Ik0gMTc1IDIwMC41MDAgQyAxNzUgMjAwLjUwMCAxNjkuODA1IDIyMS45MTMgMTcxIDIyMi43NTAgQyAxNzIuMTk1IDIyMy41ODcgMTc4Ljc5NSAyMDUuMjk1IDE4Mi41MDAgMjA1Ljc1MCBDIDE4NS45MjAgMjA2LjE3MCAxODEuODU5IDIyNC41MDAgMTg1LjI1MCAyMjQuNTAwIEMgMTg5LjIxMyAyMjQuNTAwIDE5Ny4yNTAgMjA1Ljc1MCAxOTcuMjUwIDIwNS43NTAgIi8+PC9nPjwvc3ZnPg==';

/**
 * Icon svg to be displayed in the category menu, encoded as a data URI.
 * @type {string}
 */
// eslint-disable-next-line max-len
const menuIconURI = 'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgdmlld0JveD0iMCAwIDQwIDQwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48ZyBpZD0iSUQwLjA4NjgyNDQzOTAwMDMzODMyIiB0cmFuc2Zvcm09Im1hdHJpeCgwLjQ5MTU0NjY2MDY2MTY5NzQsIDAsIDAsIDAuNDkxNTQ2NjYwNjYxNjk3NCwgLTY0LjUsIC03Ny4yNSkiPjxwYXRoIGlkPSJJRDAuNTcyMTQ2MjMwMzc3MjU2OSIgZmlsbD0iI0ZGOTQwMCIgc3Ryb2tlPSJub25lIiBkPSJNIDE4OCAxNDEgTCAyNTAgMTQxIEwgMjUwIDIwMyBMIDE4OCAyMDMgTCAxODggMTQxIFogIiB0cmFuc2Zvcm09Im1hdHJpeCgxLjI4NzkwMzMwODg2ODQwODIsIDAsIDAsIDEuMjg3OTAzMzA4ODY4NDA4MiwgLTExMC45LCAtMjQuNCkiLz48cGF0aCBpZD0iSUQwLjYzODMzNjEzNTA3NDQ5NjMiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIGQ9Ik0gMTk2IDIwNCBDIDE5NiAyMDQgMTkyLjcwNiAxOTAuMDU4IDE5MyAxODMgQyAxOTMuMDc0IDE4MS4yMzYgMTk1Ljg4NiAxNzguNDU4IDE5NyAxODAgQyAyMDEuNDU1IDE4Ni4xNjggMjAzLjQ0MyAyMDMuNzU0IDIwNiAyMDEgQyAyMDkuMjExIDE5Ny41NDIgMjEwIDE2NiAyMTAgMTY2ICIgdHJhbnNmb3JtPSJtYXRyaXgoMSwgMCwgMCwgMSwgLTU3LCAxNS44KSIvPjxwYXRoIGlkPSJJRDAuNzU4NzMwMzU2NTgxNTA5MSIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjRkZGRkZGIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgZD0iTSAyMTUgMTY5IEMgMjE1IDE2OSAyMTguMzY3IDE2OS41MzQgMjIwIDE3MCBDIDIyMC43MTYgMTcwLjIwNSAyMjEuMjc4IDE3MC44MTkgMjIyIDE3MSBDIDIyMi42NDYgMTcxLjE2MiAyMjMuMzY4IDE3MC43ODkgMjI0IDE3MSBDIDIyNC40NDcgMTcxLjE0OSAyMjUgMTcyIDIyNSAxNzIgIiB0cmFuc2Zvcm09Im1hdHJpeCgxLCAwLCAwLCAxLCAtNTcsIDE1LjgpIi8+PHBhdGggaWQ9IklEMC4yNDM2NzMwNzMxMjc4NjU4IiBmaWxsPSJub25lIiBzdHJva2U9IiNGRkZGRkYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBkPSJNIDIyNyAxNTQgQyAyMjcgMTU0IDIxOC41NTUgMTQ3Ljg5MCAyMTcgMTUxIEMgMjEyLjM0NSAxNjAuMzEwIDIxMS4yODkgMTcxLjczMyAyMTMgMTgyIEMgMjEzLjYxMiAxODUuNjcyIDIyMyAxODcgMjIzIDE4NyAiIHRyYW5zZm9ybT0ibWF0cml4KDEsIDAsIDAsIDEsIC01NywgMTUuOCkiLz48cGF0aCBpZD0iSUQwLjc5MzkzOTQ4MTk1NTAyMTYiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIGQ9Ik0gMTc1IDIwMC41MDAgQyAxNzUgMjAwLjUwMCAxNjkuODA1IDIyMS45MTMgMTcxIDIyMi43NTAgQyAxNzIuMTk1IDIyMy41ODcgMTc4Ljc5NSAyMDUuMjk1IDE4Mi41MDAgMjA1Ljc1MCBDIDE4NS45MjAgMjA2LjE3MCAxODEuODU5IDIyNC41MDAgMTg1LjI1MCAyMjQuNTAwIEMgMTg5LjIxMyAyMjQuNTAwIDE5Ny4yNTAgMjA1Ljc1MCAxOTcuMjUwIDIwNS43NTAgIi8+PC9nPjwvc3ZnPg==';


/**
 * Class for the new blocks in Scratch 3.0
 * @param {Runtime} runtime - the runtime instantiating this block package.
 * @constructor
 */
class Scratch3NewBlocks {
    constructor (runtime) {
        /**
         * The runtime instantiating this block package.
         * @type {Runtime}
         */
        this.runtime = runtime;

        //this._onTargetCreated = this._onTargetCreated.bind(this);
        //this.runtime.on('targetWasCreated', this._onTargetCreated);
    }


    /**
     * @returns {object} metadata for this extension and its blocks.
     */
    getInfo () {
        return {
            id: 'newblocks',
            name: 'New Blocks',
            menuIconURI: menuIconURI,
            blockIconURI: blockIconURI,
            blocks: [
                {
                    opcode: 'writeLog',
                    blockType: BlockType.COMMAND,
                    text: 'log [TEXT]',
                    arguments: {
                        TEXT: {
                            type: ArgumentType.STRING,
                            defaultValue: "hello"
                        }
                    }
                },
                {
                    opcode: 'getBrowser',
                    text: 'browser',
                    blockType: BlockType.REPORTER
                }
            ],
            menus: {
            }
        };
    }

    /**
     * Write log.
     * @param {object} args - the block arguments.
     * @property {number} TEXT - the text.
     */
    writeLog (args) {
        const text = Cast.toString(args.TEXT);
        log.log(text);
    }

    /**
     * Get the browser.
     * @return {number} - the user agent.
     */
    getBrowser () {
        return navigator.userAgent;
    }
}

module.exports = Scratch3NewBlocks;
```
</div></details>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/b083038a-7355-fe96-12da-b1a1e8b95437.png)

**extension-manager.jsファイルの変更**

`scratch-vm/src/extension-support`フォルダの`extension-manager.js`ファイルを開き、`builtinExtensions`に、次のように拡張機能(`s3coder_newblocks`)を追加登録します。
※カンマで区切ることを忘れないでください。

```extension-manager.js
const builtinExtensions = {
    ...
    gdxfor: () => require('../extensions/scratch3_gdx_for'),
    newblocks: () => require('../extensions/s3coder_newblocks'),
};
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/fa4cc1e7-0eed-f768-9a04-79521802a7fd.png)


### scratch-gui での設定

scratch-guiで、拡張機能を選択できるように設定します。

**フォルダ作成**

画像保存用のフォルダを次の手順で作成します。

1. `code-server`のEXPLORERで、`s3/scratch-gui/src/lib/libraries/extensions`フォルダを選択します。
2. 右クリックで、コンテキストメニューから`New Folder`を選択し、`'s3coder_newblocks'`フォルダを作成します。

**画像ファイル**

画像ファイルをダウンロードし、作成したフォルダへ保存します。

<details><summary>２つの画像ファイル(クリックして展開)</summary><div>

**newblocks.png**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/908c0bf0-b743-8e06-91e0-057c4f461c03.png)

**newblocks-small.png**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/5248f30c-a222-e0d4-8156-945405c7d4f1.png)

</div></details>


1. ２つの画像ファイルをダウンロードし、`C:\scratch-ws`フォルダへ保存します。
2. `code-server`のEXPLORERで、`s3/scratch-ws`フォルダを開き、２つの画像ファイルを選択し、右クリックでコンテキストメニューから`Copy`します。
3. `s3/scratch-gui/src/lib/libraries/extensions/s3coder_newblocks`フォルダを選択し、右クリックでコンテキストメニューから`Paste`します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/98326605-3eb1-59de-379a-d91c84cad734.png)

**index.jsファイルの設定**

`s3/scratch-gui/src/lib/libraries/extensions`フォルダの`index.js`ファイルを開き、次のように拡張機能の設定を行います。これにより、`Scratch 3.0 GUI`の拡張機能の追加で、拡張機能を選択できるようになります。

```index.js
...
import gdxforConnectionSmallIconURL from './gdxfor/gdxfor-small.svg';

import newblocksImage from './s3coder_newblocks/newblocks.png';
import newblocksInsetImage from './s3coder_newblocks/newblocks-small.png';

export default [
...
        ),
        helpLink: 'https://scratch.mit.edu/vernier'
    },
    {
        name: (
            <FormattedMessage
                defaultMessage="New Blocks"
                description="Name for the 'New Blocks' extension"
                id="gui.extension.newblocks.name"
            />
        ),
        extensionId: 'newblocks',
        iconURL: newblocksImage,
        insetIconURL: newblocksInsetImage,
        description: (
            <FormattedMessage
                defaultMessage="New extension"
                description="Description for the 'New Blocks' extension"
                id="gui.extension.newblocks.description"
            />
        ),
        featured: true
    },
];
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/075cd3d8-595c-5ce5-cf62-e8496370d6a9.png)

### 動作確認

`scratch-gui`を開始し、`Scratch 3.0 GUI`を開きなおすと、「拡張機能を追加」で、新しい拡張機能を選択できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/0c5fee1a-ccb0-d624-cb04-2c28449c0de4.png)

`logブロック`を実行すると、ブラウザのConsoleに`hello`と出力されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/81387b57-6e85-5c00-f8f5-eb8b4146de7c.png)


# おわりに

- Dockerイメージ([jprad/s3coder](https://hub.docker.com/r/jprad/s3coder))を使って、Scratch 3.0 Extentionsの開発環境と動作環境を構築しました。
- [「Scratch 3.0の拡張機能を作ってみよう」](https://ja.scratch-wiki.info/wiki/Scratch_3.0%E3%81%AE%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86)を参考にして、拡張機能を追加しました。

**2020.11.03 追記**
[親子でできる！Scratch と AWS を使った “ものづくり” 体験 - 2. 簡単なクイズを作って if-else を学ぶ！編
https://aws.amazon.com/jp/builders-flash/202011/programming-with-kids-2/](https://aws.amazon.com/jp/builders-flash/202011/programming-with-kids-2/)

<details><summary>**【メモ】Dockerイメージの作成**</summary><div>

```dos.cmd
cd c:\
mkdir scratch-ws
docker run -it -p 8080:8080 -p 8601:8601 -v C:/scratch-ws:/home/coder/s3/scratch-ws -e PASSWORD=password codercom/code-server /home/coder/s3

```

http://localhost:8080/ へアクセス

```bash
sudo apt-get update -y
sudo apt-get install -y nodejs npm
sudo npm install -g npm
```

```bash
sudo chown -R coder:coder /home/coder/s3
git clone --depth 1 https://github.com/llk/scratch-vm.git
git clone --depth 1 https://github.com/llk/scratch-gui.git

cd scratch-vm
npm ci
sudo npm link

cd ../scratch-gui
npm ci
sudo npm link scratch-vm

```

```
npm start
--->> [Ctrl]+[C]で中断
```
http://localhost:8601/ へアクセス

* scratch-guiのポート
<br>ENV環境変数で設定可能


**Dockerfile** の記述

```
docker build -t test-image .

docker run --name test-container -it -p 8080:8080 -p 8601:8601 -v C:/scratch-ws:/home/coder/s3/scratch-ws -e PASSWORD=password test-image /home/coder/s3

```
</div></details>