Open Site Navigation

React のコンポーネントのソースコードをプログラムで変更する

前の記事でHTMLElementからFiberを取得する方法がわかったのでFiberから取得できる _debugSource というプロパティには下記のような情報が入っています。

{
    "fileName": "/Users/kyohei/Develop/labelmake.jp/src/components/Page.tsx",
    "lineNumber": 74,
    "columnNumber": 17
}

今回作成するものはこの情報を使ってコンポーネントのclassNameを変更するというプログラムです。



 


この情報のlineNumber, colmunNumberはコンポーネントの始まりなのでそこと同じ行にclassNameがあるとは限らない。


なので一度ソースコードをパースする必要がある。


参考になったのは下記のアプリ


https://astexplorer.net/


このアプリはカーソルがある要素のに対応したASTのNodeに対してハイライトできているので、FIberの_debugSourceの情報を使えばコンポーネントのASTのNodeを特定できると思った。


いろいろと調べていくとソースコードをパースして変更して、変更したソースコードを返却するには下記のBabelのモジュールを使うことで実現できるということがわかった。


  • Parsing

  • @babel/parser を用いて、ソースコードをASTに変換

  • Transformation


  • @babel/traverseを用いて、ASTを変換する、

  • Code Generat

  • @babel/generator を用いて
ASTをソースコードに変換する


 

今回作成したのはあくまで動作確認程度のスクリプトですが、下記のレポジトリにコードがあります。


https://github.com/visual-editor-for-x/visual-editor-for-tailwind/tree/main/packages/component-modifier


内容はこんな感じ。

inputとしてFiberのソースコードの情報から取れるfileNameとコンポーネントの開始行としてlineNumberをcomponentStartLineに名前変更しています。


あとはそのコンポーネントのattribute(classNameやidなどを変更できます。)、変更前の文字列と新しい値。


やっていることは簡単で、parseしてtraverseしてgenerateすれば実現できました。

traverseの部分でパースしたコンポーネントの木構造をもれなく検索していき、条件に合ったNodeに対してなにかしらの処理を追加することができます。


条件についてですが、下記のような条件で合致したNodeの値を書き換えています。

path.parent.loc?.start.line===componentStartLine&&
path.node.name.name===attribute&&(path.node.valueasStringLiteral).value===oldValue
  1. 親要素(コンポーネント自体)の開始行がFiberのlineNumberと一致しているか

  2. input.attributeとNodeのnameが一致しているか

  3. Nodeの値がoldValueと一致しているか

という条件です。

一致していれば値をnewValueと変更します。


このようにbabelを使えばfiberの情報からReact のコンポーネントのソースコードをプログラムで変更することができました。

 

次はVSCodeのExtensionの作り方を見ていきます。

最初に言い忘れましたが、これまで技術検証してきたコードを使ってVSCodeのExtentionを作るつもりです。

具体的にはビジュアルエディターでtailwindのclass名を変更し、ソースコードにも反映できるというものをプロトタイプとして作成します。

最終的にはFIgmaを触る感覚でReactのコンポーネントを作成していくことのできるビジュアルエディターを作ることを目標にしています。

head1

id

Table of contents