0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GASとD2.jsとCodeMirrorで実現する簡易ダイアグラムエディタ

Last updated at Posted at 2025-05-10

はじめに

前回の記事では Google Apps Script (GAS) と D2.js で実現するダイアグラムビューアを作成しました。

今回はその発展として、ウェブブラウザ上で D2コード を書いた瞬間に SVG が更新される 簡易 D2 エディタ を実装します。

エディタはすべて ウェブブラウザ と GAS だけで完結するため、その他のサーバーは不要です。

ゴール

d2js_editor.gif

左にコード、右に即時レンダリング結果が表示されるシンプルな構成です。

技術スタックの役割

技術 レイヤー 主な役割
D2.js クライアント(描画エンジン) D2 言語の記述をリアルタイムで SVG ダイアグラムに変換
CodeMirror 6 クライアント(UI・エディタ) D2 スクリプトを記述・編集・リアルタイムプレビューのトリガー
GAS サーバー(HTML 配信) Web UI を提供し、必要に応じて Google ドキュメントなどから D2 コードを取得

プロジェクト作成手順

  1. GAS プロジェクトを新規作成
    • Apps Script エディタで「新しいプロジェクト」を選択
  2. Code.gs を追加
    Code.gs
    function doGet() {
      return HtmlService.createHtmlOutputFromFile('index');
    }
    
  3. index.html を追加(次章参照)
  4. [デプロイ] → [ウェブアプリ]
    • 「新しいデプロイ」「アクセスを全員」に設定し URL を取得
    • これでブラウザからアクセス可能

作成した index.html ファイル

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <title>D2.js エディタ</title>
  <style>
    /* 全体のフォントと余白設定 */
    body {
      font-family: sans-serif;
      padding: 1em;
    }

    /* エディタと描画結果を左右に並べる */
    .container {
      display: flex;
      gap: 1em;
      align-items: flex-start;
    }

    /* 左側:CodeMirror エディタ */
    #editor {
      width: 50%;
      border: 1px solid #ccc;
    }

    /* 右側:SVG描画エリア */
    #diagram {
      width: 50%;
      overflow: hidden;
    }

    /* SVGにボーダーを付けて見やすく、サイズをウィンドウに対して自動調整 */
    #diagram svg {
      box-sizing: border-box;
      width: 100%;
      height: 80vh;
      display: block;
      border: 1px solid #ccc;
    }
  </style>

  <!-- CodeMirror の状態管理モジュールをインポート -->
  <script type="importmap">
  {
    "imports": {
      "@codemirror/state": "https://esm.sh/@codemirror/state@6.4.1"
    }
  }
  </script>
</head>
<body>
  <h2>D2.js 簡易エディタ</h2>
  <div class="container">
    <div id="editor"></div>
    <div id="diagram"></div>
  </div>

  <script type="module">
    // CodeMirror 用のモジュールを読み込み
    import { EditorView, basicSetup } from "https://esm.sh/@codemirror/basic-setup@0.20.0?external=@codemirror/state";
    import { EditorState } from "https://esm.sh/@codemirror/state@6.4.1";

    // D2.js 本体を読み込み(WASMベースの図表エンジン)
    import { D2 } from "https://esm.sh/@terrastruct/d2@0.1.23";

    const diagramDiv = document.getElementById("diagram");

    // 初期図表コード:x → y → z の簡単なフロー
    const initialCode = `x -> y
y -> z
x: 開始
y: 処理
z: 終了`;

    // エディタ内容が変更されたら再描画
    const updateListener = EditorView.updateListener.of((update) => {
      if (update.docChanged) {
        renderDiagram(update.state.doc.toString());
      }
    });

    // CodeMirror エディタを初期化
    const editor = new EditorView({
      state: EditorState.create({
        doc: initialCode,
        extensions: [basicSetup, updateListener],
      }),
      parent: document.getElementById("editor"),
    });

    const d2 = new D2(); // D2.js インスタンス生成

    // SVG描画を行う関数
    async function renderDiagram(code) {
      try {
        const result = await d2.compile(code); // D2コードをコンパイル
        const svg = await d2.render(result.diagram, result.renderOptions); // SVG出力
        diagramDiv.innerHTML = svg; // HTMLに表示
      } catch (err) {
        diagramDiv.innerHTML = `<pre style="color:red;">${err.message}</pre>`; // エラー表示
      }
    }

    // 初回描画
    renderDiagram(initialCode);
  </script>
</body>
</html>

ポイント

  • importmap を使うことでモジュール同士の依存解決が簡潔
  • エディタ更新を updateListener でフックし renderDiagram() を呼ぶだけ
  • 失敗時はエラーメッセージを SVG 領域に赤字表示

サンプル D2 コードと結果

以下のコードをエディタに貼ると即座にフロー図が再描画されます。

サンプル
Start: 開始
Input: 入力確認
Decision: 正常?
ProcessA: データ登録
ProcessB: エラー処理
End: 終了

Start -> Input -> Decision
Decision -> ProcessA: はい
Decision -> ProcessB: いいえ
ProcessA -> End
ProcessB -> End

image.png

まとめ

これで、GAS とブラウザだけで完結する リアルタイム D2 ダイアグラムエディタ が完成しました

次のステップとして編集したダイアグラムをロード・セーブする機能を追加します

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?