Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Kreshnik committed Jan 17, 2023
0 parents commit d0cb3a8
Show file tree
Hide file tree
Showing 24 changed files with 744 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.idea
.vscode
.DS_Store
node_modules
77 changes: 77 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# d2lang-js

![Banner](docs/assets/img/banner.png)

An unofficial interface for building [D2](https://github.com/terrastruct/d2) diagram files in javascript.

## Installation

```
npm install d2lang-js
```
## Usage
```javascript
import d2 from "d2lang-js";

const umbrella = new d2.D2Shape(
"alphabet",
"Alphabet Inc",
d2.Shape.rectangle
)
const company = new d2.D2Shape(
"google",
"Google",
d2.Shape.rectangle
)
company.addShape(new d2.D2Shape("gmail", "Gmail", d2.Shape.rectangle));
company.addShape(new d2.D2Shape("meet", "Meet", d2.Shape.rectangle));
company.addShape(new d2.D2Shape("deepmind", "DeepMind", d2.Shape.rectangle));

const connection = new d2.D2Connection(company.name, umbrella.name, "BELONGS_TO", d2.Direction.TO);

const diagram = new d2.D2Diagram([umbrella, company],[connection]);
console.log(diagram.toString());
```

### D2 Output
```
alphabet: Alphabet Inc {
shape: rectangle
}
google: Google {
gmail: Gmail {
shape: rectangle
}
meet: Meet {
shape: rectangle
}
deepmind: Deepmind {
shape: rectangle
}
shape: rectangle
}
alphabet -> google
```

#### Online compiler
[D2 Playground](https://play.d2lang.com/)

#### Result of output above
![Demo](docs/assets/img/demo.png)

## Supported

- [x] Shapes (nodes)
- [x] Connections (links)
- [x] Styles
- [x] Containers (nodes/links in nodes)
- [x] Shapes in shapes
- [x] Arrow directions
- [ ] Markdown / block strings / code in shapes
- [ ] Icons in shapes
- [ ] SQL table shapes
- [ ] Class shapes
- [ ] Comments

## Inspiration
[py-d2](https://github.com/MrBlenny/py-d2)
16 changes: 16 additions & 0 deletions dist/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.D2Connection = exports.D2Shape = exports.D2Diagram = exports.Direction = exports.Shape = void 0;
const Shape_1 = __importDefault(require("./src/Enum/Shape"));
exports.Shape = Shape_1.default;
const Direction_1 = __importDefault(require("./src/Enum/Direction"));
exports.Direction = Direction_1.default;
const D2Diagram_1 = __importDefault(require("./src/D2Diagram"));
exports.D2Diagram = D2Diagram_1.default;
const D2Shape_1 = __importDefault(require("./src/D2Shape"));
exports.D2Shape = D2Shape_1.default;
const D2Connection_1 = __importDefault(require("./src/D2Connection"));
exports.D2Connection = D2Connection_1.default;
25 changes: 25 additions & 0 deletions dist/src/D2Connection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const Direction_1 = __importDefault(require("./Enum/Direction"));
class D2Connection {
constructor(firstShape, secondShape, label, direction = Direction_1.default.TO) {
this.firstShape = firstShape;
this.secondShape = secondShape;
this.label = label;
this.direction = direction;
}
lines() {
let base = `${this.firstShape} ${this.direction} ${this.secondShape}`;
if (this.label) {
base += `: ${this.label}`;
}
return [base];
}
toString() {
return this.lines().join("\n");
}
}
exports.default = D2Connection;
20 changes: 20 additions & 0 deletions dist/src/D2Diagram.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class D2Diagram {
constructor(shapes, connections) {
this.shapes = shapes || [];
this.connections = connections || [];
}
addShape(shape) {
this.shapes.push(shape);
}
addConnection(connection) {
this.connections.push(connection);
}
toString() {
let shapes = this.shapes.map((shape) => shape.toString());
let connections = this.connections.map((connection) => connection.toString());
return [...shapes, ...connections].join("\n");
}
}
exports.default = D2Diagram;
44 changes: 44 additions & 0 deletions dist/src/D2Shape.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const helpers_1 = require("./helpers");
class D2Shape {
constructor(name, label, shape, style, near) {
this.name = name;
this.label = label;
this.shape = shape;
this.shapes = [];
this.connections = [];
this.style = style;
this.near = near;
}
addShape(shape) {
// @ts-ignore
this.shapes.push(shape);
}
addConnection(connection) {
// @ts-ignore
this.connections.push(connection);
}
lines() {
// @ts-ignore
let shapes = (0, helpers_1.flatten)(this.shapes.map(shape => shape.lines()));
// @ts-ignore
let connections = (0, helpers_1.flatten)(this.connections.map(connection => connection.lines()));
let properties = shapes.concat(connections);
if (this.shape) {
properties.push(`shape: ${this.shape}`);
}
if (this.near) {
properties.push(`near: ${this.near}`);
}
if (this.style) {
properties.push(...this.style.lines());
}
let lines = (0, helpers_1.addLabelAndProperties)(this.name, this.label, properties);
return lines;
}
toString() {
return this.lines().join("\n");
}
}
exports.default = D2Shape;
46 changes: 46 additions & 0 deletions dist/src/D2Style.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const helpers_1 = require("./helpers");
class D2Style {
constructor(stroke, strokeWidth, fill, shadow, opacity, strokeDash, three_d) {
this.stroke = stroke;
this.strokeWidth = strokeWidth;
this.fill = fill;
this.shadow = shadow;
this.opacity = opacity;
this.strokeDash = strokeDash;
this.threeD = three_d;
}
lines() {
let styles = [];
if (this.stroke) {
styles.push(`stroke: ${this.stroke}`);
}
if (this.strokeWidth) {
styles.push(`stroke-width: ${this.strokeWidth}`);
}
if (this.fill) {
styles.push(`fill: ${this.fill}`);
}
if (this.shadow !== undefined) {
styles.push(`shadow: ${(0, helpers_1.stringifyBoolean)(this.shadow)}`);
}
if (this.opacity !== undefined) {
styles.push(`opacity: ${this.opacity}`);
}
if (this.strokeDash !== undefined) {
styles.push(`stroke-dash: ${this.strokeDash}`);
}
if (this.threeD !== undefined) {
styles.push(`3d: ${(0, helpers_1.stringifyBoolean)(this.threeD)}`);
}
if (styles.length == 0) {
return [];
}
return (0, helpers_1.addLabelAndProperties)("style", null, styles);
}
toString() {
return this.lines().join("\n");
}
}
exports.default = D2Style;
17 changes: 17 additions & 0 deletions dist/src/D2Text.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class D2Text {
constructor(text, format, pipes = 1) {
this.text = text;
this.format = format;
this.pipes = pipes;
}
lines() {
let sep = "|".repeat(this.pipes);
return [`${sep}${this.format}`, ...this.text.split("\n"), sep];
}
toString() {
return this.lines().join("\n");
}
}
exports.default = D2Text;
10 changes: 10 additions & 0 deletions dist/src/Enum/Direction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var Direction;
(function (Direction) {
Direction["TO"] = "->";
Direction["FROM"] = "<-";
Direction["BOTH"] = "<->";
Direction["NONE"] = "--";
})(Direction || (Direction = {}));
exports.default = Direction;
29 changes: 29 additions & 0 deletions dist/src/Enum/Shape.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var Shape;
(function (Shape) {
Shape["rectangle"] = "rectangle";
Shape["square"] = "square";
Shape["page"] = "page";
Shape["parallelogram"] = "parallelogram";
Shape["document"] = "document";
Shape["cylinder"] = "cylinder";
Shape["queue"] = "queue";
Shape["package"] = "package";
Shape["step"] = "step";
Shape["callout"] = "callout";
Shape["stored_data"] = "stored_data";
Shape["person"] = "person";
Shape["diamond"] = "diamond";
Shape["oval"] = "oval";
Shape["circle"] = "circle";
Shape["hexagon"] = "hexagon";
Shape["cloud"] = "cloud";
Shape["text"] = "text";
Shape["code"] = "code";
Shape["sql_table"] = "sql_table";
Shape["image"] = "image";
Shape["class"] = "class";
Shape["sequence_diagram"] = "sequence_diagram";
})(Shape || (Shape = {}));
exports.default = Shape;
34 changes: 34 additions & 0 deletions dist/src/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.stringifyBoolean = exports.flatten = exports.addLabelAndProperties = exports.indent = void 0;
function indent(items, times = 2) {
return items.map((item) => `${" ".repeat(times)}${item}`);
}
exports.indent = indent;
function addLabelAndProperties(name, label, properties) {
let hasProperties = properties !== undefined && properties.length > 0;
let firstLine = name;
if (label || hasProperties) {
firstLine += ":";
}
if (label) {
firstLine += ` ${label}`;
}
if (hasProperties) {
firstLine += " {";
}
if (properties && hasProperties) {
return [firstLine, ...indent(properties), "}"];
}
return [firstLine];
}
exports.addLabelAndProperties = addLabelAndProperties;
function flatten(items) {
// @ts-ignore
return [].concat(...items);
}
exports.flatten = flatten;
function stringifyBoolean(value) {
return value ? "true" : "false";
}
exports.stringifyBoolean = stringifyBoolean;
Binary file added docs/assets/img/banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/img/demo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Shape from "./src/Enum/Shape";
import Direction from "./src/Enum/Direction";

import D2Diagram from "./src/D2Diagram";
import D2Shape from "./src/D2Shape";
import D2Connection from "./src/D2Connection";

export {Shape, Direction, D2Diagram, D2Shape, D2Connection};
28 changes: 28 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "d2lang-js",
"version": "0.1.0",
"description": "An unofficial interface for building diagram files in javascript",
"keywords": [
"d2lang",
"d2lang-js"
],
"author": "Kreshnik Hasanaj",
"repository": {
"type": "git",
"url": "git+https://github.com/Kreshnik/d2lang-js.git"
},
"bugs": {
"url": "https://github.com/Kreshnik/d2lang-js/issues"
},
"homepage": "https://github.com/Kreshnik/d2lang-js#readme",
"license": "MIT",
"scripts": {
"build": "npm run clean && tsc",
"clean": "tsc --build --clean"
},
"main": "./dist/index.js",
"devDependencies": {
"@types/node": "^18.11.18",
"typescript": "^4.9.4"
}
}
28 changes: 28 additions & 0 deletions src/D2Connection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Direction from "./Enum/Direction";

class D2Connection {
firstShape: string;
secondShape: string;
label?: string;
direction: Direction;

constructor(firstShape: string, secondShape: string, label?: string, direction: Direction = Direction.TO) {
this.firstShape = firstShape;
this.secondShape = secondShape;
this.label = label;
this.direction = direction;
}

lines(): string[] {
let base = `${this.firstShape} ${this.direction} ${this.secondShape}`;
if (this.label) {
base += `: ${this.label}`;
}
return [base];
}

toString(): string {
return this.lines().join("\n");
}
}
export default D2Connection;
Loading

0 comments on commit d0cb3a8

Please sign in to comment.