ちょっとjsかじったデザイナーがFigmaのプラグイン作ったったwwww

## 🙇ご挨拶
どうも、[株式会社HRBrain](https://www.hrbrain.co.jp/)でプロダクトデザイナーをやっています。打田です。
みなさんFigmaのプラグインって作ったことありますか❓👀
以前Figmaの公式イベントにお邪魔した際、AtlassianのDesign Opsチームがデザインシステムの浸透のためにカラースタイルやコンポーネントの入れ替えプラグインを作成したという話を聞きました。
デザイナー周りの仕事の人でも、そのくらいはハンドメイドできた方がいいかもなと感心しました。

ということで思い立ったが吉日、もうちょっとここに手が届いたら嬉しいなという機能を自分で作ってみました。

## ❓具体的な背景
デザイナーやフロントのみなさん、以下のようなことって結構ありませんか？
- ほとんど同じ形なのにちょっとだけ文言が違うインスタンスをたくさん作る状況があった
    - 具体例：エラーのタイトルと文言が違うものが５パターンくらい必要になった
      - それらを全部一つずつデザインに起こすのは管理が大変
      - デザイナーが作ったステータスのバリエーションを探すのが大変

↓↓↓こんな感じ↓↓↓
![エラー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2334232/a9a4e3d1-dd2a-f693-3a71-2ce29cd387e5.png)


デザイナー的にも実はこの状況をうまく落とすのは結構面倒で、あるデザインデータではバリエーションを網羅していたけど、プロトタイプでは更新が漏れているなんてことも結構あったりします。
この問題をなんとかクリアするものの作成に挑戦してみます。

## 🤖作ったもの
https://github.com/MasaUchida/json_propaty_mapper

ということで、コンポーネントで設定したプロパティに、入力したjsonを反映するプラグインを作りました🎉🎉🎉
これによりjsonの値が入ったinstanceを作ってくれます💪💪💪

**↓↓↓実際の動き↓↓↓**
![plugin_movie.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2334232/cb98c702-ceac-e040-42cf-b994ba5e8f8f.gif)


**↓↓↓今回入力したjson↓↓↓**
※なおnameはレイヤー名に反映されます
```json
{
  "instances": [
    { "name": "name1", "title": "title1", "content": "value1" },
    { "name": "name2", "title": "title2", "content": "value2" }
  ]
}
```


## 🛠️どうやって作るの？

### Figma APIの仕組み

Figmaは直接Figma上のデータを提供はしておらず、UI⇆codeをmessageイベントでやりとりします。
オフィシャルが言うのには以下のような仕組みだそうです。

> The main thread can access the Figma "scene" (the hierarchy of layers that make up a Figma document) but not the browser APIs. Conversely, the iframe can access the browser APIs, but not the Figma scene. The main thread and the iframe can communicate with each other through **message passing**.
> 
**訳**
メインスレッドは「シーン」（Figmaドキュメントを形成するレイヤーの階層）にアクセスできますが、ブラウザAPIにはアクセスできません。
それに対し、iframeはブラウザAPIにアクセスできますが、Figmaシーンにはアクセスできません。
メインスレッドとiframeはメッセージパッシングを通じて互いに通信できます。

つまり以下の役割で動いています

- iframe（プラグインのUI部分）はブラウザAPI → プラグインの画面担当
- メインスレッドはFigmaシーン → Figma内の内容取得担当
- 上記2人はメッセージイベント`（document.eventListener(”message”,()⇒{}))`でやりとりをする

実際に以下のファイルがそれぞれを担当しています

- ui.html（ブラウザAPI）
- code.ts（シーン）


### プラグインのざっくりした流れ

**プラグインのタイプを決める**
プラグインは概ね以下の3つに別れます
- プラグインの操作UIがありインプットもある
- プラグインの操作UIがありインプットはない（選択中のものの特定の値を見せるだけなど）
- プラグインの操作UIはなくプラグイン実行時に即時効果を発揮して終わる

上記を踏まえてのプログラムの流れは概ね以下になります
```mermaid
flowchart LR
%%変数
has_UI?{"UIある？"}
has_input?{"inputある？"}

get_UI_input["UIのinputを取得"]
get_node_list["選択中のnodeの</br>配列を取得"]
main_thread["メインスレッド側で</br>データ加工（※）"]
create_or_set_data["createやsetの</br>メソッドでnodeを作る"]

%%フロー
has_UI?--はい-->has_input?
	has_input?--はい-->get_UI_input-->get_node_list
	has_input?--いいえ-->get_node_list
has_UI?--いいえ-->get_node_list

get_node_list-->main_thread
main_thread-->create_or_set_data
```
（※）ここを色々いっぱい書けば複雑なプラグインになっていく

### Hello World

あとは習うより慣れろということで、Hello Worldをやっていきましょう‼️
Figmaでは「Hello World!」ならぬ「5連オレンジ正方形」という一通りの環境が立ち上がった画面が存在するので、まずはこの5連オレンジ正方形を見に行きましょう

1　FigmaのツールバーのPlugin>Development>New pluginから新しいプラグインを作成します
![スクリーンショット 2023-06-25 15.25.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2334232/c5554368-c073-c447-9937-d936ec759f62.png)


2　プラグインはFigma+FigJam両用のものかFigmaオンリーのものかを選択します
![スクリーンショット 2023-06-25 15.26.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2334232/ef0ebdab-887b-e1c3-46d1-23b75e3df92d.png)

3　さらに以下のプラグインのどれかを選択します
![スクリーンショット 2023-06-25 15.27.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2334232/72bfe5c6-81d1-0678-65b5-badb9d9e109e.png)
- 空っぽプラグイン
- UIを提供せず即時実行系のプラグイン
- UIを提供するプラグイン


4　ここまで行くとFigmaプラグイン開発用のフォルダを任意のディレクトリに作成できます
![スクリーンショット 2023-06-26 18.50.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2334232/d9b07dee-a18c-7b72-69d3-b4163d26b933.png)

5　開発ディレクトリに入って現代開発のお約束を行います

```sh
cd 開発中のプラグインのディレクトリ

npm install
```

ここまでやるととりあえずコードは書けそうな雰囲気がするんですが**この後忘れがち**なのできちんとやっておきましょう

6　コードをbuildする

```sh
npm build
```

Figmaは基本メインスレッド部分はtsファイルなので、buildしないと動きません。
打田はこれを忘れてずっと動かないなぁと立ち往生していました。
結局解決せずFigma advocateのタニさん[(twitter)](https://twitter.com/hiloki)に相談して助けていただきました。

7　Figmaの画面に移動して、できたプラグインを動かす
![スクリーンショット 2023-06-26 18.52.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2334232/abe07771-5a3b-0076-4bfe-b8ddd8434648.png)
![スクリーンショット 2023-06-26 18.52.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2334232/375a90b1-d9bb-a726-3070-de6817bff554.png)
![スクリーンショット 2023-06-26 18.58.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2334232/3452001f-9751-d5da-ed57-4a702f7d6a3e.png)
動きました　とりあえずこの状態になれば開発環境立ち上げは完了です

### おまけ

```sh
npm watch
```

毎回buildするのも大変なので公式がwatchコマンドを提供してくれています。
基本コードをセーブすると画面に変更がかかります。

Figmaオフィシャルの大イベントConfig 2023での大型アップデート以降、コードをセーブして自動buildされた後にプラグインの再起動はしなくて良くなったようです。


## 🎓学んだこと
ここからはデザイナーなりにプラグイン開発で学んだことと、これ作っとけばとりあえずプラグインのど真ん中は抑えられるよというtipsを記録していきます。

### 超基本の構文tips

プラグイン開発をただの努力ゲーにできる超頻発パターンを一つ作ってみました。
これさえ作っておければひとまず画面上の要素にどんなプロパティとメソッドが入っているのかは確かめられます。
情報さえ取得してしまえば、それをどう引っ張ってきてどうやって値を変更するかの手がかりがつかめますよね。

```ts
//1. 今選択している画面上のノード（四角とか丸とかフレームとか）の取得
const nodes = figma.currentPage.selection

//2. 取得したノードに繰り返し処理
nodes.forEach((node)=>{

//3. ノードが特定のノードかどうかを判定
	if (node.type === "任意のnodeの型"){
		処理//（console.log（node）で）何が返ってくるか調べることをおすすめします
	}

})
```
**一応順番に説明**
1. 選択する時は複数選択もあり得るので`figma.currentPage.selection`はSeanNode型の配列で返ってきます。
2. 配列で返ってくるのでforEachにかけます。
3. いろんなものを取得してきていると思うので、その中でも特定のnodeのものだけに処理を行います

ちなみにFigmaの画面上に写っているものたち = 「node」にはそれぞれいろんな型があります。
これらはTypeScriptの型ガードのために「type」と言うプロパティを提供しており、そこでnodeの種類を判断して処理対象にする型を任意に選択できます。

https://www.figma.com/plugin-docs/api/nodes/


### Figma APIページ英語で読みにくくない？

ドキュメントを読む・探すに困ったらconsole.logでとりあえず掴んだもんの中身見たらいいんちゃう？派の打田です、ちょろっと前述しましたがlogで返ってくるものを見ちゃいましょう。
実際に返ってくるもの以上に正確なもんはないですし。
    
```ts
//今選択している画面上のノード（四角とか丸とかフレームとか）の取得
const nodes = figma.currentPage.selection
    
//取得したノード繰り返し処理
nodes.forEach((node)=>{
 	console.log(node)//ここでプロパティを見れるので、どの型のnodeに何が入ってるのか調べよう
})
```
    

## 🔥後は努力

後はひたすら画面上のデータを拾っては、そのデータに加工をかけて画面上に返すというコードを書いていくだけです💪
データの加工部分がメインのコードとなりますので、そこをひたすらやるのみです。

## ⭐️今後の展望
Figmaはきちんと作っていれば下図のようなコンポーネント設計になることが多く、componentにinstanceが入れ子になっていきます。
この状況でネストされた先のプロパティも入力できるように進化させていきたいです。
![スクリーンショット 2023-06-25 16.32.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2334232/e2a0f20f-9687-8b68-3d80-94ed3cef3038.png)

あと、まだプロトタイプでFigmaのコミュニティに公開していないので、作りきって公開したいです。

## 📣宣伝コーナー
ここまで読んでいただきありがとうございます❗️ここからは宣伝コーナーです。
弊社、HRBrainは現在中途だけでなく新卒の方も鋭意採用中です🔥
Web技術を背景にしたデザインの設計や、合理的でシンプルなデザインシステムの構築など、表現の側面とはまた違う「設計」文脈のプロダクトデザインに興味がある方などドシドシご応募ください💪

ここまで読んでいただけるような技術にも興味のあるデザイナーさんと一緒にお仕事できると嬉しいです！！よろしくお願いします🙇

https://www.hrbrain.co.jp/recruit/