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

@cardenelabs/dragon

v0.12.0

Published

Dragon — Mermaid 感覚で animated SVG を生成する Text DSL。 cdl engine を内部利用。

Readme

@cardenelabs/dragon

Dragon は @cardenelabs/cdl engine の上に乗る、 Mermaid 感覚の Text DSL。 箇条書きで書ける宣言的 syntax から animated SVG diagram を生成する。

Why Dragon

Mermaid は静的、 cdl 直書きは TypeScript builder が必要。 Dragon は両者の中間 ... Mermaid に似た短文 syntax で書きつつ、 cdl の animation engine 上で動く。

  • Mermaid 風 syntax (1 行 = 1 step、 A -> B 矢印、 box-drawing 不要)
  • Mermaid にない animation (state tween / phase highlight / badge)
  • 出力は cdl の CdlDiagram、 そのまま CdlDiagramView 等に渡せる
  • engine 部 (layout / render / animation) は cdl に委譲、 dragon は parser + compiler に専念

Quickstart

npm install @cardenelabs/dragon @cardenelabs/cdl
import { textDslToDiagram } from "@cardenelabs/dragon";
import { CdlDiagramView } from "@cardenelabs/cdl/react";

const diagram = textDslToDiagram(`
title: "送金フロー"
type: sequence

actors:
  - Alice
  - Vault: storage
  - Bob

flow:
  - Alice -> Vault: "deposit"
  - Vault -> Bob: "send" (success)
`);

// React で render
<CdlDiagramView diagram={diagram} />

記法に書ける欄

この節の一覧は検査が実装と突き合わせる (test/readme-notation-keys.test.ts)。 実装に欄が増えてここを直さないと落ちる。

最上位のブロック

| 欄 | 何を書くか | |---|---| | title | 図の題 | | type | 図種 (sequence / flow / swimlane / er / state / topology / gantt / class / mind / tree / c4 / solidity / 図表各種) | | actors | 箱 | | flow | 矢印 | | states | 状態の初期値 | | values | 他の状態から決まる値 (式) | | animation | 段 | | viewport | 図全体の大きさと間隔 | | lanes | 縦列の見出しと幅 | | groups | 縦列を束ねる枠 | | eyebrow | 図全体を 1 箱にする図種で、その箱の上に出す小見出し | | axes | 2 軸で仕分ける図の軸の名前 |

箱に書ける欄

- 名前: { 欄: 値, ... } の形で書く。

| 欄 | 何を書くか | |---|---| | kind | 見た目の種別 (card / storage / service / person 等、種類 とも書ける) | | subtitle | 題の下の補足 (補足 とも書ける) | | eyebrow | 題の上の小見出し | | value | 箱に出す値 ( とも書ける) | | rows | 箱の中に並べる行 ( とも書ける) | | lane | どの縦列に置くか | | stack | 縦列の中の何段目に置くか | | initial | 状態遷移図で始まりの状態か | | final | 状態遷移図で終わりの状態か | | tone | 色 | | nodes | 見本 (parts) の中の箱を差し替える | | touchpoint | 体験の道筋で、利用者が触れる場所 | | opportunity | 体験の道筋で、改善の余地 | | owner | 工程の並びで、担当 | | end | 工程の並びで、終わりの位置 | | posX | 置く場所の横位置 | | posY | 置く場所の縦位置 | | posW | 箱の幅 | | posH | 箱の高さ | | scale | 見本 (parts) の倍率 (倍率 とも書ける) |

矢印に書ける欄

- A -> B: "説明" (色, 線種) { 欄: 値, ... } の形で書く。

| 欄 | 何を書くか | |---|---| | sub | 説明の下の補足 | | guard | 状態遷移の条件 | | cardinality | 関係の多重度 (1:N 等) | | labelOffsetX | 説明文の位置を横にずらす | | labelOffsetY | 説明文の位置を縦にずらす | | overlay | true で説明文を線の上に重ねる (分岐図の条件ラベル用) |

記法の癖

箱の lane: が効く図種は限られる

縦列を並べるために使う図種 (flow / topology / swimlane) では効く。 縦列が骨格その ものになる図種 (sequence は縦列がそのまま時間軸の線) では効かず、知らせが出る。

効く図種でも 全ての箱に書いた時だけ 効く。 一部だけ書くと、書かなかった箱をどこに 置くか決められないため知らせが出る。

type: flow

lanes:
  left: { width: 320 }
  right: { width: 320 }

actors:
  - A: { kind: card, lane: left }
  - B: { kind: card, lane: right }

lanes: の id は組み立て側が作る形に合わせて、字 / 数 / 下線 / hyphen を受ける (lane-idle のような自動で作られた縦列の幅も書き直せる)。

静止した type: flow は書いた矢印の端を使わない

この図種は 登場人物を書いた順に鎖状に繋ぐ。 矢印の説明文は「その箱を to に持つ行」 から拾い、書いた側の端は使わない。

type: flow

actors: [A, B, C]

flow:
  - A -> C: "x"    # 出来るのは A -> B
  - C -> B: "y"    # 出来るのは B -> C

書いた端どおりに繋ぎたい時は箱に lane: を書く。 縦列を書いた形は別の組み立てを通り、 書いた端がそのまま矢印になる。 端が使われなかった行には知らせが出る。

API

Text DSL (人向け YAML)

  • textDslToDiagram(src: string): CdlDiagram ... 一発変換 (v0.4 / v0.5 auto-detect、 recommended entry)
  • parseTextDslV05(src: string): V05ParseResult ... v0.5 parser を直接呼出 (error 詳細取得)
  • compileToCdl(doc: DslDocument): CdlDiagram ... AST → CdlDiagram

JSON DSL (LLM 向け)

  • jsonToDiagram(json: unknown): CdlDiagram ... JSON DSL → CdlDiagram、 validation error は throw
  • validateDragonJson(json: unknown): { ok, data | errors } ... compile なしで validation のみ
  • diagramJsonSchema ... JSON Schema (Draft 7)、 LLM の tool schema にそのまま注入可能

Deprecated (2026-12-31 削除予定)

  • parseTextDsl(src: string): ParseResult ... v0.4 parser、 textDslToDiagram に移行推奨

LLM 向け JSON DSL

LLM (Anthropic Claude / OpenAI GPT) が structured output で確実に diagram を生成できるよう、 YAML DSL と 1:1 対応する JSON 記法を提供する。

最小 example

import { jsonToDiagram } from "@cardenelabs/dragon";
import { CdlDiagramView } from "@cardenelabs/cdl/react";

const diagram = jsonToDiagram({
  title: "ログインAPI",
  type: "sequence",
  actors: ["ユーザー", "API", "DB"],
  flow: [
    { from: "ユーザー", to: "API", label: "ログイン要求" },
    { from: "API", to: "DB", label: "ユーザー検索" },
    { from: "DB", to: "API", label: "結果", tone: "success" },
    { from: "API", to: "ユーザー", label: "認証成功", tone: "success" },
  ],
  animation: [
    { step: "call", duration: 1.4, focus: ["ユーザー", "API"] },
    { step: "query", duration: 1.4, focus: ["API", "DB"] },
    { step: "return", duration: 1.4, focus: ["DB", "API"] },
    { step: "ok", duration: 1.4, focus: ["API", "ユーザー"] },
  ],
});
// <CdlDiagramView diagram={diagram} />

Anthropic Claude で LLM に書かせる example

import Anthropic from "@anthropic-ai/sdk";
import { jsonToDiagram, diagramJsonSchema, validateDragonJson } from "@cardenelabs/dragon";

const client = new Anthropic();

async function generateDiagramFromLLM(userRequest: string, maxRetry = 3) {
  const messages: Anthropic.MessageParam[] = [{ role: "user", content: userRequest }];
  for (let attempt = 0; attempt < maxRetry; attempt++) {
    const res = await client.messages.create({
      model: "claude-sonnet-5",
      max_tokens: 4096,
      tools: [{
        name: "create_diagram",
        description: "Create an animated diagram from user's request using Dragon DSL.",
        input_schema: diagramJsonSchema,
      }],
      tool_choice: { type: "tool", name: "create_diagram" },
      messages,
    });
    const toolUse = res.content.find((c) => c.type === "tool_use");
    if (!toolUse || toolUse.type !== "tool_use") throw new Error("no tool_use in LLM response");
    const validation = validateDragonJson(toolUse.input);
    if (validation.ok) {
      return jsonToDiagram(validation.data);
    }
    // retry loop = error path を prompt に注入して LLM に修正させる
    const errorSummary = validation.errors.map((e) => `  ${e.path}: ${e.message}`).join("\n");
    messages.push({ role: "assistant", content: res.content });
    messages.push({
      role: "user",
      content: `The diagram JSON has validation errors:\n${errorSummary}\nPlease fix and retry.`,
    });
  }
  throw new Error(`LLM failed to generate valid diagram after ${maxRetry} attempts`);
}

// 使用例
const diagram = await generateDiagramFromLLM(
  "ユーザーが API 経由で DB に検索をかけて結果を受け取るシーケンス図を作って"
);

OpenAI GPT で structured output に使う場合

import OpenAI from "openai";
import { jsonToDiagram, diagramJsonSchema } from "@cardenelabs/dragon";

const client = new OpenAI();
const res = await client.chat.completions.create({
  model: "gpt-4o-2024-08-06",
  messages: [{ role: "user", content: "..." }],
  response_format: {
    type: "json_schema",
    json_schema: { name: "diagram", strict: true, schema: diagramJsonSchema },
  },
});
const json = JSON.parse(res.choices[0].message.content!);
const diagram = jsonToDiagram(json);

JSON Schema の場所

  • SSOT = packages/dragon/src/schemas/diagram.json
  • npm 経由取得 = @cardenelabs/dragon/schemas/diagram.json (package.json exports)
  • TypeScript import = import { diagramJsonSchema } from "@cardenelabs/dragon"

YAML と JSON の 1:1 対応

同じ図を両方の記法で書ける。 人 → YAML、 LLM → JSON が推奨だが、 混在可能。

| YAML | JSON | |---|---| | title: "..." | {title: "..."} | | actors: [A, B: kind] | {actors: [{name: "A"}, {name: "B", kind: "storage"}]} | | - A -> B: "label" | {from: "A", to: "B", label: "label"} | | step: "..." 1.4s | {step: "...", duration: 1.4} | | focus: [A, B] | {focus: ["A", "B"]} |

箱に書ける項目 (tone / owner / posX 等) は両方の記法で同じ。 一覧は実装 (INLINE_ACTOR_KEYS) が持ち、packages/dragon/test/json-actor-fields.test.ts が 両入口の一致を確かめる。 ここに一覧を写すと項目が増えた時に取り残されるため書かない。

License

MIT