npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@yanqirenshi/d3.classes

v0.13.0

Published

UML Class Diagram visualization library using d3.js

Readme

CLASS.js

d3.jsを使用してUMLクラス図を描画するTypeScriptライブラリです。

インストール

npm install

使い方

基本的な使い方

import { ClassDiagram } from 'class.js';

const diagram = new ClassDiagram('#container', {
  width: 800,
  height: 600
});

// クラスを追加
const userClass = diagram.addClass({
  name: 'User',
  attributes: [
    { name: 'id', type: 'number', visibility: 'private' },
    { name: 'name', type: 'string', visibility: 'public' }
  ],
  methods: [
    { name: 'getName', returnType: 'string', visibility: 'public' }
  ],
  x: 100,
  y: 100
});

// 関係を追加
diagram.addRelationship({
  type: 'inheritance',  // association, inheritance, aggregation, composition, dependency
  from: { x: 200, y: 200 },
  to: { x: 200, y: 100 }
});

diagram.render();

JSONデータから読み込み

import { ClassDiagram, DiagramInput } from 'class.js';

const data: DiagramInput = {
  classes: [
    {
      name: 'Animal',
      stereotype: 'abstract',
      attributes: [{ name: 'name', type: 'string', visibility: 'protected' }],
      methods: [{ name: 'speak', returnType: 'void', visibility: 'public' }],
      x: 300,
      y: 50
    },
    {
      name: 'Dog',
      attributes: [{ name: 'breed', type: 'string', visibility: 'private' }],
      methods: [{ name: 'speak', returnType: 'void', visibility: 'public' }],
      x: 300,
      y: 200
    }
  ],
  relationships: [
    {
      type: 'inheritance',
      from: { x: 400, y: 200 },
      to: { x: 400, y: 130 }
    }
  ]
};

const diagram = new ClassDiagram('#container');
diagram.loadFromData(data).render();

識別子と接続先変更(v0.6.0+)

クラス・関係線とも任意の id を指定できます(省略時は追加順に class-N / rel-N が振られる)。識別子はレンダリングされる g.class-box / g.relationship の data-id 属性にも反映されるため、 ホスト側で「クリックされた要素がどれか」を DOM から特定できます。

diagram.addClass({ id: 'SessionLine', name: ..., position: { x: 0, y: 0 } });
diagram.addClass({ id: 'UserLine',    name: ..., position: { x: 300, y: 0 } });

diagram.addRelationship({
  id: 'rel-1',
  type: 'association',
  from: { classId: 'SessionLine', point: 'right' },
  to:   { classId: 'UserLine',    point: 'left' },
});
diagram.render();

// id で取得して接続先(クラス・接続辺)を付け替える(即再描画)
const rel = diagram.getRelationship('rel-1');
rel?.setConnection(
  { classId: 'SessionLine', point: 'right' },
  { classId: 'UserLine',    point: 'top' },
);
  • ClassDiagram.getClass(id) / ClassDiagram.getRelationship(id) で取得
  • Relationship.setConnection(from, to) は座標指定({ x, y })も可
  • Relationship.id / .from / .to で現在の状態を参照できる
  • 重複 id はエラー(黙って上書きしない)。自動採番は明示 id と衝突する番号をスキップする

属性の型表示とラベル属性(v0.7.0+)

  • 属性の型が未指定(文字列指定・type 省略)なら「: 型」は表示されません (以前のように : any へ補完しません)。"user" → + user
  • kind: 'label' を指定すると可視性記号・型とも表示せず名前だけを描画します (enum のバリアント列挙などのラベル用途)。
{
  name: name('SessionLine'),
  stereotype: 'enumeration',
  attributes: [
    'user',                                   // → 「+ user」
    { name: name('assistant'), kind: 'label' }, // → 「assistant」
  ],
  position: { x: 0, y: 0 },
}

角丸とヘッダの配色(v0.10.0+)

クラス box は既定で角丸(半径 4px)になります。radius: 0 を指定すると 従来どおりの直角に戻せます。

ヘッダ(クラス名の行)には背景色と文字色を指定できます。 background / font は @yanqirenshi/types の共有型(Background / Font)です。

{
  name: name('ユーザー'),
  stereotype: 'entity',
  position: { x: 100, y: 100 },
  radius: 8,                          // 角丸半径(px)。既定 4、0 で直角
  header: {
    background: { color: '#89c3eb' },  // 既定は塗りなし(本体と同色)
    font: { color: '#ffffff' },        // 既定は黒
  },
}

| オプション | 既定 | 内容 | |---|---|---| | radius | 4 | 角丸半径(px)。0 で直角 | | header.background.color | なし | ヘッダ背景色。未指定なら塗らない(本体の白のまま) | | header.background.opacity | なし | ヘッダ背景の不透明度 | | header.font.color | black | クラス名の文字色 | | header.font.size | 14px | 指定時のみ上書き | | header.font.weight | bold | 指定時のみ上書き |

header.font が効くのはクラス名だけです。 ステレオタイプは box の外に描かれるため対象外です(v0.11.0 で変更 — 下記)。

描画される要素は以下のとおりです。 ヘッダ背景は本体 rect の上・テキストの下に入ります。

  • rect.box-body — 本体(rx に radius)
  • rect.box-header-bg — ヘッダ背景(rx に radius。上2隅が角丸)
  • rect.box-header-bg-foot — 下2隅の丸みを直角で埋める帯(radius: 0 のときは描かれない)

なお radius がヘッダ高(常に 30px)の半分 = 15 を超えると、ヘッダ背景の丸みは SVG の仕様でその半分に頭打ちになり、本体の角丸のほうが大きくなります (角の 1px 程度で背景が枠線からわずかにはみ出します)。 ヘッダに背景色を敷く場合、radius は 15 までを推奨します。

ステレオタイプの表示位置(v0.11.0+)

stereotype は box の外・上辺より上 に、中央揃え・斜体・12px・黒で描かれます (v0.10.0 まではヘッダの1行目として box の中に描いていました)。

        «abstract»        ← box の外(ベースライン y: -6)
   ┌──────────────────┐
   │       動物        │  ← ヘッダ(クラス名の1行)
   ├──────────────────┤
   │ # 名前    string  │
   └──────────────────┘
  • ヘッダは常に1行になったため、ステレオタイプを持つクラスの box 高さが 従来より 20px 縮みます。ステレオタイプの有無で高さは変わりません。
  • position の意味は変わりません(これまでどおり box の左上)。 ステレオタイプは box の上にはみ出して描かれるだけなので、既存図のボックス位置と 接続点の幾何は一切変わりません。
  • 文字色は黒固定で、header.font は適用されません。box の外は背景がキャンバスなので、 ヘッダ用の白文字などをそのまま当てると読めなくなるためです。
  • 要素は text.box-stereotype で、g.class-box の中にあります (ドラッグすると box と一緒に動きます)。

注意: box の上辺に接続する関係線(point: 'top')は、真上から来るとステレオタイプの 文字と重なります。 幾何は変えていないので、重なる場合は接続辺を変えて回避してください (例: point: 'left' / point: 90 など)。

説明(description)の保持(v0.12.0+)

クラス・属性・メソッドに description(文字列の配列。1行1要素)を持たせられます。

d3.classes は description を描画しません。 データとして保持するだけで、 box の見た目もレイアウト(高さ)も一切変わりません。 インスペクタなどでの表示は利用側の責務です。

diagram.addClass({
  id: 'user',
  name: name('User'),
  description: ['利用者を表す。', '認証の主体。'],
  attributes: [
    { name: name('id'), type: 'number', description: ['主キー。', '発行後は不変。'] },
  ],
  methods: [
    { name: name('login'), returnType: 'boolean', description: ['認証する。'] },
  ],
  position: { x: 0, y: 0 },
});

ClassBox から属性・メソッドを辿って読めます。

const box = diagram.getClass('user');

box.description;                            // ['利用者を表す。', '認証の主体。']
box.attributes.map((a) => a.description);   // [['主キー。', '発行後は不変。']]
box.methods.map((m) => m.description);      // [['認証する。']]

未指定は空配列 [] に正規化されます(undefined にはなりません)。 属性・メソッドの文字列ショートハンド(attributes: ['foo'])も [] です。 利用側は常に配列として扱えます。

クリックコールバックは無いので、要素の特定は従来どおり DOM 側で行います (g.class-box の data-id を拾って getClass(id))。

name.description との違い(重要)

同じオブジェクトに description が2つ並びます。名前も似ていますが別物です。

| 場所 | 型 | 位置づけ | |---|---|---| | name.description | string | 共有型 Name(@yanqirenshi/types)のフィールド。名前についての補足。d3.classes では参照していません(描画も API も無し) | | description | string[] | v0.12.0 で追加。要素そのものの説明。上記のとおり getter から読めます |

Name は全パッケージが使う共有型なので変更できません。 説明を持たせたいときはトップレベルの description を使ってください。

開発

# 開発サーバー起動
npm run dev

# ビルド
npm run build

# テスト
npm test

# 型チェック
npm run typecheck