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

ts-visio

v1.0.2

Published

A npm package for creating Visio files (vsdx) using TypeScript.

Readme

ts-visio

[!WARNING] Under Construction This library is currently being developed with heavy assistance from AI and is primarily an experimental project. Use with caution.

A Node.js library to strict-type interact with Visio (.vsdx) files. Built using specific schema-level abstractions to handle the complex internal structure of Visio documents (ShapeSheets, Pages, Masters).

Status: Work In Progress (TDD).

Features

  • Read VSDX: Open and parse .vsdx files (zippped XML).
  • Strict Typing: Interact with VisioPage, VisioShape, and VisioConnect objects.
  • ShapeSheet Access: Read Cells, Rows, and Sections directly.
  • Connections: Analyze connectivity between shapes.
  • Modular Architecture: Use specialized components for loading, page management, shape reading, and modification.
  • Modify Content: Update text content of shapes.
  • Create Shapes: Add new rectangular shapes with text to pages.
  • Connect Shapes: Create dynamic connectors between shapes.

Installation

npm install ts-visio

Usage

1. Create or Load a Document

The VisioDocument class is the main entry point.

import { VisioDocument } from 'ts-visio';

// Create a new blank document
const doc = await VisioDocument.create();

// OR Load an existing file
// const doc = await VisioDocument.load('diagram.vsdx');

2. Access Pages

Access pages through the pages property.

const page = doc.pages[0];
console.log(`Editing Page: ${page.name}`);

3. Add & Modify Shapes

Add new shapes or modify existing ones without dealing with XML.

// Add a new rectangle shape
const shape = await page.addShape({
    text: "Hello World",
    x: 1,
    y: 1,
    width: 3,
    height: 1,
    fillColor: "#ff0000", // Option hexadecimal fill color
    fontColor: "#ffffff",
    bold: true
});

// Modify text
await shape.setText("Updated Text");

console.log(`Shape ID: ${shape.id}`);

4. Groups & Nesting

Create Group shapes and add children to them.

// 1. Create a Group container
const group = await page.addShape({
    text: "Group",
    x: 5,
    y: 5,
    width: 4,
    height: 4,
    type: 'Group'
});

// 2. Add child shape directly to the group
// Coordinates are relative to the Group's bottom-left corner
await page.addShape({
    text: "Child",
    x: 1, // Relative X
    y: 1, // Relative Y
    width: 1,
    height: 1
}, group.id);

6. Automatic Layout

Easily position shapes relative to each other.

const shape1 = await page.addShape({ text: "Step 1", x: 2, y: 5, width: 2, height: 1 });
const shape2 = await page.addShape({ text: "Step 2", x: 0, y: 0, width: 2, height: 1 }); // X,Y ignored if we place it next

// Place Shape 2 to the right of Shape 1 with a 1-inch gap
await shape2.placeRightOf(shape1, { gap: 1 });

// Chain placement
const shape3 = await page.addShape({ text: "Step 3", x: 0, y: 0, width: 2, height: 1 });
await shape3.placeRightOf(shape2);

// Vertical stacking
const shape4 = await page.addShape({ text: "Below", x: 0, y: 0, width: 2, height: 1 });
await shape4.placeBelow(shape1, { gap: 0.5 });

7. Fluent API & Chaining

Combine creation, styling, and connection in a clean syntax.

const shape1 = await page.addShape({ text: "Start", x: 2, y: 4, width: 2, height: 1 });
const shape2 = await page.addShape({ text: "End", x: 6, y: 4, width: 2, height: 1 });

// Fluent Connection
await shape1.connectTo(shape2);

// Chaining Styles & Connections
await shape1.setStyle({ fillColor: '#00FF00' })
            .connectTo(shape2);

5. Advanced Connections

Use specific arrowheads (Crow's Foot, etc.)

import { ArrowHeads } from 'ts-visio/utils/StyleHelpers';

await page.connectShapes(shape1, shape2, ArrowHeads.One, ArrowHeads.CrowsFoot);
// OR
await shape1.connectTo(shape2, ArrowHeads.One, ArrowHeads.CrowsFoot);

6. Database Tables

Create a compound stacked shape for database tables.

const tableShape = await page.addTable(
    5,
    5,
    "Users",
    ["ID: int", "Name: varchar", "Email: varchar"]
);
console.log(tableShape.id); // Access ID

8. Typed Schema Builder (Facade)

For ER diagrams, use the SchemaDiagram wrapper for simplified semantics.

import { VisioDocument, SchemaDiagram } from 'ts-visio';

const doc = await VisioDocument.create();
const page = doc.pages[0];
const schema = new SchemaDiagram(page);

// Add Tables
const users = await schema.addTable('Users', ['id', 'email'], 0, 0);
const posts = await schema.addTable('Posts', ['id', 'user_id'], 5, 0);

// Add Relations (1:N maps to Crow's Foot arrow)
await schema.addRelation(users, posts, '1:N');

9. Save the Document

Save the modified document back to disk.

await doc.save('updated_diagram.vsdx');

10. Using Stencils (Masters)

Load a template that already contains stencils (like "Network" or "Flowchart") and drop shapes by their Master ID.

// 1. Load a template with stencils
const doc = await VisioDocument.load('template_with_masters.vsdx');
const page = doc.pages[0];

// 2. Drop a shape using a Master ID
// (You can find IDs in visio/masters/masters.xml of the template)
await page.addShape({
    text: "Router 1",
    x: 2,
    y: 2,
    width: 1,
    height: 1,
    masterId: "5" // ID of the 'Router' master in the template
});

// The library automatically handles the relationships so the file stays valid.

11. Multi-Page Documents

Create multiple pages and organize your diagram across them.

const doc = await VisioDocument.create();

// Page 1 (Default)
const page1 = doc.pages[0];
await page1.addShape({ text: "Home", x: 1, y: 1 });

// Page 2 (New)
const page2 = await doc.addPage("Architecture Diagram");
await page2.addShape({ text: "Server", x: 4, y: 4 });

await doc.save("multipage.vsdx");

12. Shape Data (Custom Properties)

Add metadata to shapes, which is crucial for "Smart" diagrams like visual databases or inventories.

const shape = await page.addShape({ text: "Server DB-01", x: 2, y: 2 });

// Synchronous Fluent API
shape.addData("IP", { value: "192.168.1.10", label: "IP Address" })
     .addData("Status", { value: "Active" })
     .addData("LastRefreshed", { value: new Date() }) // Auto-serialized as Visio Date
     .addData("ConfigID", { value: 1024, hidden: true }); // Invisible to user

13. Image Embedding

Embed PNG or JPEG images directly into the diagram.

import * as fs from 'fs';

const buffer = fs.readFileSync('logo.png');
const page = doc.pages[0];

// Add image at (x=2, y=5) with width=3, height=2
await page.addImage(buffer, 'logo.png', 2, 5, 3, 2);

14. Containers

Create visual grouping containers (Classic Visio style).

// Create a Container
const container = await page.addContainer({
    text: "Network Zone",
    x: 1, y: 1,
    width: 6, height: 4
});

// Add shapes "inside" the container area
// (Visio treats them as members if they are spatially within)
const shape = await page.addShape({ text: "Server A", x: 2, y: 2, width: 1, height: 1 });

// Explicitly link the shape to the container (so they move together)
await container.addMember(shape);

15. Lists (Stacking Containers)

Create ordered lists that automatically stack items either vertically (Tables) or horizontally (Timelines).

// Vertical List (e.g. Database Table)
const list = await page.addList({
    text: "Users",
    x: 1, y: 10,
    width: 3, height: 1
}, 'vertical'); // 'vertical' or 'horizontal'

// Items stack automatically
await list.addListItem(item1);
await list.addListItem(item2);

16. Interactivity & Navigation (Hyperlinks)

Add internal links (drill-downs) or external links (web references). These appear in the right-click menu in Visio.

// 1. External URL
await shape.toUrl('https://jira.com/123', 'Open Ticket');

// 2. Internal Page Link
const detailPage = await doc.addPage('Details');
await shape.toPage(detailPage, 'Go to Details');

// 3. Chainable
await shape.toUrl('https://google.com')
           .toPage(detailPage);

17. Layers

Organize complex diagrams with layers. Control visibility and locking programmatically.

// 1. Define Layers
const wireframe = await page.addLayer('Wireframe');
const annotations = await page.addLayer('Annotations');

// 2. Assign Shapes to Layers
await shape.addToLayer(wireframe);
await noteBox.addToLayer(annotations);

// 3. Toggle Visibility
await annotations.hide();  // Hide for presentation
await annotations.show();  // Show again

// 4. Lock Layer
await wireframe.setLocked(true);

18. Cross-Functional Flowcharts (Swimlanes)

Create structured Swimlane diagrams involving Pools and Lanes.

// 1. Create a Pool (Vertical List)
const pool = await page.addSwimlanePool({
    text: "User Registration",
    x: 5, y: 5, width: 10, height: 6
});

// 2. Create Lanes (Containers)
const lane1 = await page.addSwimlaneLane({ text: "Client", width: 10, height: 2 });
const lane2 = await page.addSwimlaneLane({ text: "Server", width: 10, height: 2 });

// 3. Add Lanes to Pool (Order matters)
await pool.addListItem(lane1);
await pool.addListItem(lane2);

// 4. Group Shapes into Lanes
// This binds their movement so they stay inside the lane
await lane1.addMember(startShape);
await lane2.addMember(serverShape);

Examples

Check out the examples directory for complete scripts.

  • Simple Schema: Generates a database schema ERD with tables, styling, and Crow's Foot connectors.
  • Network Topology: Demonstrates the Fluent Shape Data API to build a network map with hidden metadata, typed properties, and connections.
  • Containers Demo: Shows how to create Classic Visio containers and place shapes within them.
  • Lists Demo: Demonstrates Vertical and Horizontal List stacks.
  • Hyperlinks Demo: Demonstrates Internal and External navigation.
  • Layers Demo: Shows how to create layers and toggle visibility.
  • Image Embedding Demo: Demonstrates how to embed PNG or JPEG images into a diagram.
  • Swimlane Demo: Demonstrates creating Cross-Functional Flowcharts with Pools and Lanes.

Development

This project uses Vitest for testing.

npm install
npm test