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

coreuml-core

v1.0.1

Published

Framework-agnostic UML diagram engine for parsing, layout, and serialization

Readme

CoreUML

npm version npm downloads Test Suite Coverage License Node.js Visitors Buy Me a Coffee

A framework-agnostic UML diagram engine for parsing, layout, and serialization. CoreUML provides a simple DSL for creating UML class diagrams with automatic layout, manual positioning, and SVG export capabilities.

Features

Core Functionality

  • 📝 Simple DSL: Intuitive syntax for defining UML class diagrams
  • 🎨 Multiple Diagram Types: Classes, interfaces, enumerations, and packages
  • 🔗 Rich Relationships: Association, inheritance, composition, aggregation, dependency, realization
  • 🎯 Association Classes: Full support for UML association classes (many-to-many patterns)
  • 📐 Dynamic Sizing: Content-aware width and height for all UML elements
  • 🗺️ Automatic Layout: Hierarchical layout using Dagre algorithm
  • 📍 Manual Positioning: Fine-grained control with @position annotations
  • 🎨 Customization: Colors, stereotypes, and custom styling
  • 💾 Import/Export: JSON serialization and SVG generation
  • 🔄 Round-trip: Parse → serialize → parse with full fidelity
  • ✅ Type-Safe: Written in TypeScript with complete type definitions
  • 🧪 Well-Tested: 87% test coverage with 164+ tests

Advanced Features

  • Generic Types: Support for type parameters (class Box<T>)
  • Abstract Classes: Abstract classes and methods with italic rendering
  • Static Members: Static attributes and methods with underline styling
  • Visibility Modifiers: Public (+), private (-), protected (#), package (~)
  • Multiplicity: Relationship cardinality (1, 0.., 1..)
  • Label Positioning: Start, middle, or end label placement
  • Connection Points: Custom attachment points (top, bottom, left, right)
  • Bidirectional Relationships: Double-headed arrows
  • Notes: Attached or standalone documentation notes
  • Packages: Logical grouping of classes

Installation

npm install CoreUML-core

Quick Start

import { createDiagramEngine, exportToSVG, layoutDiagram } from 'CoreUML-core';

const engine = createDiagramEngine();

// Define your UML diagram
const diagram = engine.parse(`
  class User {
    + id: number
    + name: string
    + email: string
    + login(): void
  }

  class Order {
    + id: number
    + total: number
    + items: OrderItem[]
  }

  User "1" --> "0..*" Order : "places"
`);

// Auto-layout
const layout = layoutDiagram(diagram);

// Export to SVG
const svg = exportToSVG(diagram, layout, {
  autoSize: true,
  padding: 40
});

console.log(svg); // SVG markup ready for use

Syntax Guide

Classes

// Basic class
class User {
  + name: string
  + email: string
  + login(): void
}

// Abstract class
abstract class Entity {
  + id: number
  + abstract validate(): boolean
}

// Class with generics
class Repository<T> {
  + items: T[]
  + add(item: T): void
}

// Static members
class Config {
  + static instance: Config
  + static getInstance(): Config
}

// Default values
class Counter {
  + count: number = 0
}

Interfaces

interface Drawable {
  + draw(): void
  + clear(): void
}

// Interface with generics
interface Repository<T> {
  + find(id: number): T
  + save(entity: T): void
}

Enumerations

enum Status { PENDING, ACTIVE, COMPLETED, CANCELLED }
enum Color { RED, GREEN, BLUE }

Relationships

// Association (simple arrow)
User --> Order

// Association with multiplicity
Customer "1" --> "0..*" Order

// Association with label
User --> Order : "places"

// Inheritance (empty triangle)
User <|-- Entity

// Composition (filled diamond)
House -|> Room

// Aggregation (empty diamond)
Team o-- Player

// Dependency (dashed arrow)
Service ..> Logger

// Realization (dashed arrow with triangle)
Circle ..|> Drawable

// Bidirectional
A <--> B

Association Classes

Association classes represent relationships that have their own attributes:

class Student {
  + studentId: number
  + name: string
}

class Course {
  + courseId: number
  + title: string
}

class Enrollment {
  + grade: float
  + enrollmentDate: Date
  + status: string
}

// Many-to-many association
Student "0..*" -- "0..*" Course : "enrolls in"

// Link the association class
@associationClass Enrollment student-course

Annotations

// Position (manual layout)
@position User (100, 200)

// Stereotype
@stereotype UserService "service"

// Color
@color Important red
@color package-domain "#e3f2fd"

// Relationship color
@color user-order blue

// Label position
User --> Order @middle : "places"

// Connection points
User[right] --> Order[left]

Packages

package domain {
  class User {
    + name: string
  }

  class Order {
    + id: number
  }
}

@position package-domain (50, 50)
@color package-domain lightblue

Notes

// Attached note
note for User "This represents a user in the system"

// Standalone note
note at (200, 300) "Important: Always validate input"

API Reference

createDiagramEngine()

Creates a new diagram engine instance.

const engine = createDiagramEngine();

parse(code: string): Diagram

Parses UML code and returns a diagram object.

const diagram = engine.parse(`
  class User {
    + name: string
  }
`);

serialize(diagram: Diagram): string

Serializes a diagram back to UML code.

const code = engine.serialize(diagram);

layoutDiagram(diagram: Diagram, options?: LayoutOptions): LayoutResult

Computes automatic layout for a diagram.

const layout = layoutDiagram(diagram, {
  direction: 'TB',  // TB, LR, BT, RL
  nodeSep: 80,      // Horizontal spacing
  rankSep: 100      // Vertical spacing
});

applyLayout(diagram: Diagram, layout: LayoutResult): Diagram

Applies computed layout to a diagram.

const positionedDiagram = applyLayout(diagram, layout);

exportToSVG(diagram: Diagram, layout: LayoutResult, options?: SVGOptions): string

Exports diagram to SVG.

const svg = exportToSVG(diagram, layout, {
  autoSize: true,     // Auto-calculate viewBox
  padding: 40,        // Padding around diagram
  nodeWidth: 200,     // Default node width (overridden by dynamic sizing)
  nodeHeight: 150     // Default node height (overridden by dynamic sizing)
});

exportDiagram(diagram: Diagram, metadata?: Metadata): string

Exports diagram to JSON.

const json = exportDiagram(diagram, {
  author: 'John Doe',
  description: 'E-commerce domain model'
});

importDiagram(json: string): Diagram

Imports diagram from JSON.

const diagram = importDiagram(json);

Dynamic Sizing

CoreUML automatically calculates optimal dimensions for all UML elements based on their content:

Width Calculation

  • Minimum: 120px
  • Maximum: 400px
  • Algorithm: Text width estimation based on character count and font size
  • Factors: Class name, attributes, methods, stereotypes, type parameters

Height Calculation

  • Dynamic: Based on number of attributes and methods
  • Components:
    • Header: 30px (40px with stereotype)
    • Attributes: 16px per line + 8px padding
    • Methods: 16px per line + 8px padding
    • Separators: 4px between sections

Example:

// This class will have optimal width based on longest text
class VeryLongClassNameWithManyAttributes {
  + veryLongAttributeName: VeryLongTypeName
  + anotherLongAttribute: AnotherType
  + methodWithLongName(param1: Type, param2: Type): ReturnType
}

Examples

Basic E-commerce Domain

const diagram = engine.parse(`
  abstract class Entity {
    + id: number
    + createdAt: Date
    + abstract validate(): boolean
  }

  class Customer {
    + name: string
    + email: string
    + register(): void
  }

  class Order {
    + orderNumber: string
    + total: number
    + status: OrderStatus
    + submit(): void
  }

  class Product {
    + sku: string
    + name: string
    + price: number
  }

  enum OrderStatus { PENDING, CONFIRMED, SHIPPED, DELIVERED }

  Customer <|-- Entity
  Order <|-- Entity
  Product <|-- Entity

  Customer "1" --> "0..*" Order : "places"
  Order "1" --> "1..*" Product : "contains"

  @position Entity (300, 50)
  @position Customer (100, 200)
  @position Order (300, 200)
  @position Product (500, 200)
  @position OrderStatus (500, 350)
`);

Layered Architecture

const diagram = engine.parse(`
  package presentation {
    class UserController {
      + getUser(id: number): User
      + createUser(data: UserDTO): User
    }
  }

  package domain {
    class User {
      + id: number
      + name: string
      + email: string
      + validate(): boolean
    }

    interface IUserRepository {
      + find(id: number): User
      + save(user: User): void
    }
  }

  package infrastructure {
    class UserRepository {
      + find(id: number): User
      + save(user: User): void
    }
  }

  UserController --> User
  UserController --> IUserRepository
  UserRepository ..|> IUserRepository

  @position package-presentation (50, 50)
  @position package-domain (50, 200)
  @position package-infrastructure (50, 400)
`);

Association Class Pattern

const diagram = engine.parse(`
  class Employee {
    + employeeId: number
    + name: string
    + department: string
  }

  class Project {
    + projectId: number
    + name: string
    + budget: number
  }

  class Assignment {
    + role: string
    + hoursPerWeek: number
    + startDate: Date
    + endDate: Date
    + updateHours(hours: number): void
  }

  Employee "0..*" -- "0..*" Project : "assigned to"
  @associationClass Assignment employee-project

  @position Employee (100, 200)
  @position Project (500, 200)
  @position Assignment (300, 50)
`);

Testing

Run the test suite:

# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests with coverage
npm run test:coverage

Test Coverage

Overall:       87.27% lines, 86.64% statements, 74.74% branches
Parser:        97.66% statements
Validation:    98.30% statements
Layout:        90.00% statements
SVG Rendering: 78.93% statements
Serialization: 76.92% statements

Framework Integration

CoreUML is framework-agnostic and works with any JavaScript/TypeScript framework:

React

import { useEffect, useState } from 'react';
import { createDiagramEngine, exportToSVG, layoutDiagram } from 'CoreUML-core';

function DiagramViewer({ code }) {
  const [svg, setSvg] = useState('');

  useEffect(() => {
    const engine = createDiagramEngine();
    const diagram = engine.parse(code);
    const layout = layoutDiagram(diagram);
    const svgOutput = exportToSVG(diagram, layout, { autoSize: true });
    setSvg(svgOutput);
  }, [code]);

  return <div dangerouslySetInnerHTML={{ __html: svg }} />;
}

Vue

<template>
  <div v-html="svg"></div>
</template>

<script>
import { createDiagramEngine, exportToSVG, layoutDiagram } from 'CoreUML-core';

export default {
  props: ['code'],
  data() {
    return { svg: '' };
  },
  watch: {
    code: {
      immediate: true,
      handler(newCode) {
        const engine = createDiagramEngine();
        const diagram = engine.parse(newCode);
        const layout = layoutDiagram(diagram);
        this.svg = exportToSVG(diagram, layout, { autoSize: true });
      }
    }
  }
};
</script>

Node.js (Server-side)

import { createDiagramEngine, exportToSVG, layoutDiagram } from 'CoreUML-core';
import { writeFileSync } from 'fs';

const engine = createDiagramEngine();
const diagram = engine.parse(code);
const layout = layoutDiagram(diagram);
const svg = exportToSVG(diagram, layout, { autoSize: true });

writeFileSync('output.svg', svg);

UML Compliance

CoreUML implements a significant subset of UML 2.5 class diagram specification:

Supported (~70%)

  • ✅ Classes with attributes and methods
  • ✅ Interfaces
  • ✅ Enumerations
  • ✅ Abstract classes and methods
  • ✅ Visibility modifiers
  • ✅ Static members
  • ✅ Generic types
  • ✅ Association relationships
  • ✅ Association classes
  • ✅ Inheritance
  • ✅ Composition
  • ✅ Aggregation
  • ✅ Dependency
  • ✅ Realization
  • ✅ Multiplicity
  • ✅ Stereotypes
  • ✅ Notes
  • ✅ Packages

Planned

  • ⏳ Qualified associations
  • ⏳ N-ary associations
  • ⏳ Constraints (OCL)
  • ⏳ Templates
  • ⏳ Nested classes
  • ⏳ Signals
  • ⏳ Data types

Performance

CoreUML is designed for performance:

  • Parsing: ~1ms for typical diagrams (10-20 classes)
  • Layout: ~50ms for complex diagrams (50+ classes)
  • SVG Generation: ~10ms
  • Memory: Minimal overhead with immutable data structures

Limitations

  • Max Input Size: 5MB (configurable via parser)
  • Recommended: < 100 classes per diagram for optimal performance

Architecture

CoreUML-core/
├── src/
│   ├── engine/          # Core parsing and validation
│   │   ├── parser.ts
│   │   ├── validation.ts
│   │   └── DiagramEngine.ts
│   ├── layout/          # Automatic layout using Dagre
│   │   └── layoutEngine.ts
│   ├── io/              # Import/export functionality
│   │   ├── svg.ts
│   │   └── serialization.ts
│   ├── types/           # TypeScript type definitions
│   │   └── diagram.ts
│   └── index.ts         # Public API
├── tests/               # Comprehensive test suite
├── examples/            # Example diagrams
└── dist/                # Compiled output

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Development Setup

# Clone repository
git clone https://github.com/fabiooraziomirto/CoreUML.git
cd CoreUML

# Install dependencies
npm install

# Build
npm run build

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

Guidelines

  1. Code Style: Follow existing TypeScript conventions
  2. Tests: Add tests for new features (maintain 80%+ coverage)
  3. Documentation: Update README and JSDoc comments
  4. Commits: Use conventional commit messages

License & Usage

Apache License 2.0 - see LICENSE file for details.

Note: This software may be used freely for any purpose. However, publications, articles, or papers describing or analyzing this architecture require prior written permission from the author.

Acknowledgments

  • Layout engine powered by Dagre
  • Inspired by PlantUML and Mermaid
  • Built with TypeScript and tested with Jest

Support


Made with ❤️ by FoM Dev