メインコンテンツまでスキップ

インストール

npm install @dineug/erd-editor

このパッケージは ESM 専用("type": "module")で、dist フォルダのみを配布します。 CommonJS ビルドはないため、require('@dineug/erd-editor') は動作しません。

使い方

import '@dineug/erd-editor';

const editor = document.createElement('erd-editor');
editor.style.cssText = 'display: block; width: 100%; height: 100vh;';
document.body.appendChild(editor);

// load a document without adding an undo entry, then keep it in sync
editor.setInitialValue(localStorage.getItem('my-diagram') ?? '');
editor.addEventListener('change', () => {
localStorage.setItem('my-diagram', editor.value);
});

<erd-editor> は固有のサイズを持ちません。要素またはコンテナに width と height を明示的に指定してください。

setInitialValue('') は空のドキュメントから始めます。value への代入は読み込みを編集として扱うため、履歴に記録されます。 残りの API については ErdEditorElement を参照してください。

CDN

<script type="module">
import 'https://esm.run/@dineug/erd-editor';

const editor = document.createElement('erd-editor');
editor.style.cssText = 'display: block; width: 100%; height: 100vh;';
document.body.appendChild(editor);
</script>
<!-- or -->
<script type="module" src="https://esm.run/@dineug/erd-editor"></script>

バージョンを指定しない URL は常に最新のリリースを配信します。メジャーアップグレードが予告なくページに反映されるのを避けたい場合は、https://esm.run/@dineug/[email protected] のようにバージョンを固定します。

HTML

<erd-editor system-dark-mode enable-theme-builder></erd-editor>
<script type="module">
import 'https://esm.run/@dineug/erd-editor';

const editor = document.querySelector('erd-editor');
</script>
erd-editor {
display: block;
width: 100%;
height: 100vh;
}

ここで readonly を付けると編集できなくなります。value への代入、clear() の呼び出し、すべての setSchema*() は無視され、change イベントも発行されません。editor.value の読み取りは引き続き動作します。読み込みには代わりに setInitialValue() を使用します。

サーバーサイドレンダリング

パッケージを読み込むとモジュールスコープでカスタム要素を登録するため、DOM が必要であり、Node では例外が発生します。 Next.js、Nuxt、SvelteKit、Astro では、クライアント側でのみ実行される経路から読み込みます。

useEffect(() => {
import('@dineug/erd-editor');
}, []);

TypeScript

パッケージを読み込むと erd-editorHTMLElementTagNameMap に統合されるため、キャストなしで型が付きます。

import '@dineug/erd-editor';
import type { ErdEditorElement } from '@dineug/erd-editor';

const editor = document.createElement('erd-editor'); // ErdEditorElement
const found = document.querySelector('erd-editor'); // ErdEditorElement | null

ErdEditorElement は、独自の変数や props に型を付けるためにエクスポートしています。

構文ハイライト

Schema SQL と Code Generator のパネルは、ハイライターを渡さない限りプレーンテキストとして表示されます。 @dineug/erd-editor-shiki-worker は、それを Shared Worker で実行します。 Shiki と文法定義は 1 メガバイトを大きく超えるため、別のパッケージとして提供しています。

npm install @dineug/erd-editor-shiki-worker
import { setGetShikiServiceCallback } from '@dineug/erd-editor';

// deferred, so the highlighter never lands in your main chunk
import('@dineug/erd-editor-shiki-worker').then(({ getShikiService }) => {
setGetShikiServiceCallback(getShikiService);
});

CDN から読み込む場合は次のとおりです。

<script type="module">
import { setGetShikiServiceCallback } from 'https://esm.run/@dineug/erd-editor';
import { getShikiService } from 'https://esm.run/@dineug/erd-editor-shiki-worker';

setGetShikiServiceCallback(getShikiService);
</script>

登録は一度だけで、エディタの設置前でも設置後でも構いません。すでに表示されているパネルは、ハイライターが届いた時点で再描画されます。 対応している言語は SQL、TypeScript、GraphQL、C#、Java、Kotlin、Scala、Go、Python です。コード生成AMLDBML はバンドルに文法定義がないため、これらのパネルはプレーンテキストのままです。

動作を妨げる要因が 2 つあります。ワーカーは data: URI としてインライン化しているため、CSP が厳しいページでは worker-src data: が必要です。 SharedWorker がない環境、つまり Android の Chrome や 16.4 より前の Safari では、ハイライターが返されず、パネルはプレーンテキストのままです。

エントリーポイント

@dineug/erd-editor を読み込むと、副作用として <erd-editor> を登録します。それ以外には、要素の型と 3 つのコールバック設定関数をエクスポートしています。

エクスポート説明
ErdEditorElement(型)要素のインターフェースです。ErdEditorElement を参照してください。
setGetShikiServiceCallback(cb)構文ハイライターを渡します。() => ShikiService | null です。
setExportFileCallback(cb)ブラウザのダウンロードを置き換えます。(blob, { fileName }) => void です。
setImportFileCallback(cb)ブラウザのファイル選択を置き換えます。({ type, op, accept }) => void です。

@dineug/erd-editor/engine.js は 2 つ目のエントリーポイントです。DOM なしでドキュメントの store を動かすため、Web Worker でも動作します。リモート保存を参照してください。

ファイルダイアログ

読み込みと書き出しは差し替え可能なコールバックを経由するため、ブラウザのファイルダイアログを持たないホスト、例えば IDE の Webview でも独自の実装を渡せます。 2 つは対称ではありません。書き出しは完成したファイルを渡しますが、読み込みはファイルを要求するだけで、内容は自分でエディタに渡します。

opset または diff です。diff の場合は type に関係なく setDiffValue() に渡します。それ以外では type がメソッドを決め、accept にはその型の拡張子が入っているため、そのままホストのファイルダイアログに渡せます。

typeacceptメソッド
json.jsoneditor.value = text
sql.sqleditor.setSchemaSQL(text)
graphql.graphql,.gql,.graphqlseditor.setSchemaGraphQL(text)
dbml.dbmleditor.setSchemaDBML(text)
aml.amleditor.setSchemaAML(text)
import { setExportFileCallback, setImportFileCallback } from '@dineug/erd-editor';

setExportFileCallback((blob, { fileName }) => host.writeFile(fileName, blob));

setImportFileCallback(async ({ type, op, accept }) => {
const text = await host.pickFile(accept);

if (op === 'diff') {
editor.setDiffValue(text);
} else if (type === 'json') {
editor.value = text;
} else if (type === 'sql') {
editor.setSchemaSQL(text);
} else if (type === 'graphql') {
editor.setSchemaGraphQL(text);
} else if (type === 'dbml') {
editor.setSchemaDBML(text);
} else if (type === 'aml') {
editor.setSchemaAML(text);
}
});

処理する type ごとに分岐し、それ以外は無視します。 value への代入はパースの前にドキュメントを消去します。そのため、.erd.json ドキュメントではないデータを、包括的な else や、後から追加された type が漏れたことによって value に渡すと、何も読み込まれずにダイアグラムが空になります。

エディタが生成する fileName<データベース名>-<時刻>.erd.json.sql.png のいずれかを付けたもので、時刻は yyyy-MM-dd'T'HH_mm_ss の形式です。データベース名が空の場合は unnamed になります。

設定しない場合、エディタはブラウザ自身のダウンロードとファイル選択の動作を使用します。null を渡すと元の動作に戻ります。

対応ブラウザ

Chrome 91+、Edge 94+、Firefox 93+、Safari 16.4+ に対応しています。公開しているバンドルのビルド対象である ES2022 を基準にしています。 ポリフィルは同梱していません。より古いブラウザに対応する必要がある場合は、自分で追加します。