@swiftlysingh/excalidraw-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +159 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +152 -0
- package/dist/cli.js.map +1 -0
- package/dist/factory/connection-factory.d.ts +16 -0
- package/dist/factory/connection-factory.d.ts.map +1 -0
- package/dist/factory/connection-factory.js +91 -0
- package/dist/factory/connection-factory.js.map +1 -0
- package/dist/factory/element-factory.d.ts +16 -0
- package/dist/factory/element-factory.d.ts.map +1 -0
- package/dist/factory/element-factory.js +78 -0
- package/dist/factory/element-factory.js.map +1 -0
- package/dist/factory/index.d.ts +8 -0
- package/dist/factory/index.d.ts.map +1 -0
- package/dist/factory/index.js +8 -0
- package/dist/factory/index.js.map +1 -0
- package/dist/factory/node-factory.d.ts +24 -0
- package/dist/factory/node-factory.d.ts.map +1 -0
- package/dist/factory/node-factory.js +85 -0
- package/dist/factory/node-factory.js.map +1 -0
- package/dist/factory/text-factory.d.ts +42 -0
- package/dist/factory/text-factory.d.ts.map +1 -0
- package/dist/factory/text-factory.js +148 -0
- package/dist/factory/text-factory.js.map +1 -0
- package/dist/generator/excalidraw-generator.d.ts +17 -0
- package/dist/generator/excalidraw-generator.d.ts.map +1 -0
- package/dist/generator/excalidraw-generator.js +91 -0
- package/dist/generator/excalidraw-generator.js.map +1 -0
- package/dist/generator/index.d.ts +5 -0
- package/dist/generator/index.d.ts.map +1 -0
- package/dist/generator/index.js +5 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/layout/arrow-router.d.ts +48 -0
- package/dist/layout/arrow-router.d.ts.map +1 -0
- package/dist/layout/arrow-router.js +103 -0
- package/dist/layout/arrow-router.js.map +1 -0
- package/dist/layout/elk-layout.d.ts +11 -0
- package/dist/layout/elk-layout.d.ts.map +1 -0
- package/dist/layout/elk-layout.js +179 -0
- package/dist/layout/elk-layout.js.map +1 -0
- package/dist/layout/index.d.ts +6 -0
- package/dist/layout/index.d.ts.map +1 -0
- package/dist/layout/index.js +6 -0
- package/dist/layout/index.js.map +1 -0
- package/dist/parser/dsl-parser.d.ts +21 -0
- package/dist/parser/dsl-parser.d.ts.map +1 -0
- package/dist/parser/dsl-parser.js +249 -0
- package/dist/parser/dsl-parser.js.map +1 -0
- package/dist/parser/index.d.ts +6 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +6 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/json-parser.d.ts +16 -0
- package/dist/parser/json-parser.d.ts.map +1 -0
- package/dist/parser/json-parser.js +76 -0
- package/dist/parser/json-parser.js.map +1 -0
- package/dist/types/dsl.d.ts +127 -0
- package/dist/types/dsl.d.ts.map +1 -0
- package/dist/types/dsl.js +14 -0
- package/dist/types/dsl.js.map +1 -0
- package/dist/types/excalidraw.d.ts +171 -0
- package/dist/types/excalidraw.d.ts.map +1 -0
- package/dist/types/excalidraw.js +36 -0
- package/dist/types/excalidraw.js.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# excalidraw-cli
|
|
2
|
+
|
|
3
|
+
Create Excalidraw flowcharts and diagrams from text-based DSL or JSON.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Text-based DSL** for quick flowchart creation
|
|
8
|
+
- **JSON API** for programmatic use
|
|
9
|
+
- **Auto-layout** using ELK.js (Eclipse Layout Kernel)
|
|
10
|
+
- **Multiple flow directions**: TB (top-bottom), BT, LR, RL
|
|
11
|
+
- **Programmable API** for integration into other tools
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
### From Source (Local Development)
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
git clone https://github.com/swiftlysingh/excalidraw-cli.git
|
|
19
|
+
cd excalidraw-cli
|
|
20
|
+
npm install
|
|
21
|
+
npm run build
|
|
22
|
+
npm link # Makes 'excalidraw-cli' available globally
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Direct Usage (No Install)
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Run directly with node
|
|
29
|
+
node dist/cli.js create --inline "[A] -> [B]" -o diagram.excalidraw
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
### Create from DSL
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Inline DSL
|
|
38
|
+
excalidraw-cli create --inline "(Start) -> [Process] -> {Decision?}" -o flow.excalidraw
|
|
39
|
+
|
|
40
|
+
# From file
|
|
41
|
+
excalidraw-cli create flowchart.dsl -o diagram.excalidraw
|
|
42
|
+
|
|
43
|
+
# From stdin
|
|
44
|
+
echo "[A] -> [B] -> [C]" | excalidraw-cli create --stdin -o diagram.excalidraw
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### DSL Syntax
|
|
48
|
+
|
|
49
|
+
| Syntax | Element | Description |
|
|
50
|
+
|--------|---------|-------------|
|
|
51
|
+
| `[Label]` | Rectangle | Process steps, actions |
|
|
52
|
+
| `{Label}` | Diamond | Decisions, conditionals |
|
|
53
|
+
| `(Label)` | Ellipse | Start/End points |
|
|
54
|
+
| `[[Label]]` | Database | Data storage |
|
|
55
|
+
| `->` | Arrow | Connection |
|
|
56
|
+
| `-->` | Dashed Arrow | Dashed connection |
|
|
57
|
+
| `-> "text" ->` | Labeled Arrow | Connection with label |
|
|
58
|
+
|
|
59
|
+
### Example DSL
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
(Start) -> [Enter Credentials] -> {Valid?}
|
|
63
|
+
{Valid?} -> "yes" -> [Dashboard] -> (End)
|
|
64
|
+
{Valid?} -> "no" -> [Show Error] -> [Enter Credentials]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Directives
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
@direction LR # Left to Right (default: TB)
|
|
71
|
+
@spacing 60 # Node spacing in pixels
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## CLI Reference
|
|
75
|
+
|
|
76
|
+
### Commands
|
|
77
|
+
|
|
78
|
+
#### `create`
|
|
79
|
+
|
|
80
|
+
Create an Excalidraw flowchart.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
excalidraw-cli create [input] [options]
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Options:**
|
|
87
|
+
- `-o, --output <file>` - Output file path (default: flowchart.excalidraw)
|
|
88
|
+
- `-f, --format <type>` - Input format: dsl, json (default: dsl)
|
|
89
|
+
- `--inline <dsl>` - Inline DSL string
|
|
90
|
+
- `--stdin` - Read from stdin
|
|
91
|
+
- `-d, --direction <dir>` - Flow direction: TB, BT, LR, RL
|
|
92
|
+
- `-s, --spacing <n>` - Node spacing in pixels
|
|
93
|
+
- `--verbose` - Verbose output
|
|
94
|
+
|
|
95
|
+
#### `parse`
|
|
96
|
+
|
|
97
|
+
Parse and validate input without generating output.
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
excalidraw-cli parse <input> [options]
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## JSON API
|
|
104
|
+
|
|
105
|
+
For programmatic flowchart creation:
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"nodes": [
|
|
110
|
+
{ "id": "start", "type": "ellipse", "label": "Start" },
|
|
111
|
+
{ "id": "process", "type": "rectangle", "label": "Process" },
|
|
112
|
+
{ "id": "end", "type": "ellipse", "label": "End" }
|
|
113
|
+
],
|
|
114
|
+
"edges": [
|
|
115
|
+
{ "from": "start", "to": "process" },
|
|
116
|
+
{ "from": "process", "to": "end" }
|
|
117
|
+
],
|
|
118
|
+
"options": {
|
|
119
|
+
"direction": "TB",
|
|
120
|
+
"nodeSpacing": 50
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
excalidraw-cli create flowchart.json -o diagram.excalidraw
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Programmatic Usage
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import { createFlowchartFromDSL, createFlowchartFromJSON } from 'excalidraw-cli';
|
|
133
|
+
|
|
134
|
+
// From DSL
|
|
135
|
+
const dsl = '(Start) -> [Process] -> (End)';
|
|
136
|
+
const json = await createFlowchartFromDSL(dsl);
|
|
137
|
+
|
|
138
|
+
// From JSON input
|
|
139
|
+
const input = {
|
|
140
|
+
nodes: [
|
|
141
|
+
{ id: 'a', type: 'rectangle', label: 'Hello' },
|
|
142
|
+
{ id: 'b', type: 'rectangle', label: 'World' }
|
|
143
|
+
],
|
|
144
|
+
edges: [{ from: 'a', to: 'b' }]
|
|
145
|
+
};
|
|
146
|
+
const json2 = await createFlowchartFromJSON(input);
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Output
|
|
150
|
+
|
|
151
|
+
The generated `.excalidraw` files can be:
|
|
152
|
+
|
|
153
|
+
1. Opened directly in [Excalidraw](https://excalidraw.com) (File > Open)
|
|
154
|
+
2. Imported into Obsidian with the Excalidraw plugin
|
|
155
|
+
3. Used with any tool that supports the Excalidraw format
|
|
156
|
+
|
|
157
|
+
## License
|
|
158
|
+
|
|
159
|
+
MIT
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;GAIG"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Excalidraw CLI
|
|
4
|
+
*
|
|
5
|
+
* Create Excalidraw flowcharts from DSL or JSON input.
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
9
|
+
import { parseDSL } from './parser/dsl-parser.js';
|
|
10
|
+
import { parseJSONString } from './parser/json-parser.js';
|
|
11
|
+
import { layoutGraph } from './layout/elk-layout.js';
|
|
12
|
+
import { generateExcalidraw, serializeExcalidraw } from './generator/excalidraw-generator.js';
|
|
13
|
+
const program = new Command();
|
|
14
|
+
program
|
|
15
|
+
.name('excalidraw-cli')
|
|
16
|
+
.description('Create Excalidraw flowcharts from DSL or JSON')
|
|
17
|
+
.version('1.0.0');
|
|
18
|
+
/**
|
|
19
|
+
* Create command - main flowchart creation
|
|
20
|
+
*/
|
|
21
|
+
program
|
|
22
|
+
.command('create')
|
|
23
|
+
.description('Create an Excalidraw flowchart')
|
|
24
|
+
.argument('[input]', 'Input file path (DSL or JSON)')
|
|
25
|
+
.option('-o, --output <file>', 'Output file path', 'flowchart.excalidraw')
|
|
26
|
+
.option('-f, --format <type>', 'Input format: dsl, json (default: dsl)', 'dsl')
|
|
27
|
+
.option('--inline <dsl>', 'Inline DSL string')
|
|
28
|
+
.option('--stdin', 'Read input from stdin')
|
|
29
|
+
.option('-d, --direction <dir>', 'Flow direction: TB, BT, LR, RL (default: TB)')
|
|
30
|
+
.option('-s, --spacing <n>', 'Node spacing in pixels', '50')
|
|
31
|
+
.option('--verbose', 'Verbose output')
|
|
32
|
+
.action(async (inputFile, options) => {
|
|
33
|
+
try {
|
|
34
|
+
let input;
|
|
35
|
+
let format = options.format;
|
|
36
|
+
// Get input from various sources
|
|
37
|
+
if (options.inline) {
|
|
38
|
+
input = options.inline;
|
|
39
|
+
}
|
|
40
|
+
else if (options.stdin) {
|
|
41
|
+
input = readFileSync(0, 'utf-8'); // Read from stdin
|
|
42
|
+
}
|
|
43
|
+
else if (inputFile) {
|
|
44
|
+
input = readFileSync(inputFile, 'utf-8');
|
|
45
|
+
// Auto-detect format from file extension
|
|
46
|
+
if (inputFile.endsWith('.json')) {
|
|
47
|
+
format = 'json';
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.error('Error: No input provided. Use --inline, --stdin, or provide an input file.');
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
if (options.verbose) {
|
|
55
|
+
console.log(`Input format: ${format}`);
|
|
56
|
+
console.log(`Input length: ${input.length} characters`);
|
|
57
|
+
}
|
|
58
|
+
// Parse input
|
|
59
|
+
let graph;
|
|
60
|
+
if (format === 'json') {
|
|
61
|
+
graph = parseJSONString(input);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
graph = parseDSL(input);
|
|
65
|
+
}
|
|
66
|
+
// Apply CLI options
|
|
67
|
+
if (options.direction) {
|
|
68
|
+
const dir = options.direction.toUpperCase();
|
|
69
|
+
if (['TB', 'BT', 'LR', 'RL'].includes(dir)) {
|
|
70
|
+
graph.options.direction = dir;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (options.spacing) {
|
|
74
|
+
const spacing = parseInt(options.spacing, 10);
|
|
75
|
+
if (!isNaN(spacing)) {
|
|
76
|
+
graph.options.nodeSpacing = spacing;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (options.verbose) {
|
|
80
|
+
console.log(`Parsed ${graph.nodes.length} nodes and ${graph.edges.length} edges`);
|
|
81
|
+
console.log(`Layout direction: ${graph.options.direction}`);
|
|
82
|
+
}
|
|
83
|
+
// Layout the graph
|
|
84
|
+
const layoutedGraph = await layoutGraph(graph);
|
|
85
|
+
if (options.verbose) {
|
|
86
|
+
console.log(`Layout complete. Canvas size: ${layoutedGraph.width}x${layoutedGraph.height}`);
|
|
87
|
+
}
|
|
88
|
+
// Generate Excalidraw file
|
|
89
|
+
const excalidrawFile = generateExcalidraw(layoutedGraph);
|
|
90
|
+
const output = serializeExcalidraw(excalidrawFile);
|
|
91
|
+
// Write output
|
|
92
|
+
if (options.output === '-') {
|
|
93
|
+
process.stdout.write(output);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
writeFileSync(options.output, output, 'utf-8');
|
|
97
|
+
console.log(`Created: ${options.output}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.error('Error:', error instanceof Error ? error.message : error);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
/**
|
|
106
|
+
* Parse command - parse and validate input without generating
|
|
107
|
+
*/
|
|
108
|
+
program
|
|
109
|
+
.command('parse')
|
|
110
|
+
.description('Parse and validate input without generating output')
|
|
111
|
+
.argument('<input>', 'Input file path')
|
|
112
|
+
.option('-f, --format <type>', 'Input format: dsl, json (default: dsl)', 'dsl')
|
|
113
|
+
.action((inputFile, options) => {
|
|
114
|
+
try {
|
|
115
|
+
const input = readFileSync(inputFile, 'utf-8');
|
|
116
|
+
let format = options.format;
|
|
117
|
+
// Auto-detect format from file extension
|
|
118
|
+
if (inputFile.endsWith('.json')) {
|
|
119
|
+
format = 'json';
|
|
120
|
+
}
|
|
121
|
+
// Parse input
|
|
122
|
+
let graph;
|
|
123
|
+
if (format === 'json') {
|
|
124
|
+
graph = parseJSONString(input);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
graph = parseDSL(input);
|
|
128
|
+
}
|
|
129
|
+
console.log('Parse successful!');
|
|
130
|
+
console.log(` Nodes: ${graph.nodes.length}`);
|
|
131
|
+
console.log(` Edges: ${graph.edges.length}`);
|
|
132
|
+
console.log(` Direction: ${graph.options.direction}`);
|
|
133
|
+
console.log('\nNodes:');
|
|
134
|
+
for (const node of graph.nodes) {
|
|
135
|
+
console.log(` - [${node.type}] ${node.label}`);
|
|
136
|
+
}
|
|
137
|
+
console.log('\nEdges:');
|
|
138
|
+
for (const edge of graph.edges) {
|
|
139
|
+
const sourceNode = graph.nodes.find((n) => n.id === edge.source);
|
|
140
|
+
const targetNode = graph.nodes.find((n) => n.id === edge.target);
|
|
141
|
+
const label = edge.label ? ` "${edge.label}"` : '';
|
|
142
|
+
console.log(` - ${sourceNode?.label} ->${label} ${targetNode?.label}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
console.error('Parse error:', error instanceof Error ? error.message : error);
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
// Parse arguments and run
|
|
151
|
+
program.parse();
|
|
152
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates Excalidraw arrow elements for connections between nodes.
|
|
5
|
+
*/
|
|
6
|
+
import type { ExcalidrawArrow, ExcalidrawArrowBinding, ExcalidrawBoundElement } from '../types/excalidraw.js';
|
|
7
|
+
import type { LayoutedEdge, LayoutedNode, EdgeStyle } from '../types/dsl.js';
|
|
8
|
+
/**
|
|
9
|
+
* Create an arrow element
|
|
10
|
+
*/
|
|
11
|
+
export declare function createArrow(edge: LayoutedEdge, sourceNode: LayoutedNode, targetNode: LayoutedNode, boundElements?: ExcalidrawBoundElement[]): ExcalidrawArrow;
|
|
12
|
+
/**
|
|
13
|
+
* Create arrow with explicit bindings
|
|
14
|
+
*/
|
|
15
|
+
export declare function createArrowWithBindings(id: string, x: number, y: number, points: Array<[number, number]>, startBinding: ExcalidrawArrowBinding | null, endBinding: ExcalidrawArrowBinding | null, boundElements?: ExcalidrawBoundElement[], style?: EdgeStyle): ExcalidrawArrow;
|
|
16
|
+
//# sourceMappingURL=connection-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection-factory.d.ts","sourceRoot":"","sources":["../../src/factory/connection-factory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EACV,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAkB7E;;GAEG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,YAAY,EAClB,UAAU,EAAE,YAAY,EACxB,UAAU,EAAE,YAAY,EACxB,aAAa,CAAC,EAAE,sBAAsB,EAAE,GACvC,eAAe,CA0CjB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,EAAE,EAAE,MAAM,EACV,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,MAAM,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAC/B,YAAY,EAAE,sBAAsB,GAAG,IAAI,EAC3C,UAAU,EAAE,sBAAsB,GAAG,IAAI,EACzC,aAAa,CAAC,EAAE,sBAAsB,EAAE,EACxC,KAAK,CAAC,EAAE,SAAS,GAChB,eAAe,CA+BjB"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates Excalidraw arrow elements for connections between nodes.
|
|
5
|
+
*/
|
|
6
|
+
import { createBaseElement } from './element-factory.js';
|
|
7
|
+
import { calculateStartBinding, calculateEndBinding } from '../layout/arrow-router.js';
|
|
8
|
+
/**
|
|
9
|
+
* Map DSL edge style to Excalidraw properties
|
|
10
|
+
*/
|
|
11
|
+
function mapEdgeStyle(style) {
|
|
12
|
+
if (!style)
|
|
13
|
+
return {};
|
|
14
|
+
return {
|
|
15
|
+
strokeColor: style.strokeColor,
|
|
16
|
+
strokeWidth: style.strokeWidth,
|
|
17
|
+
strokeStyle: style.strokeStyle,
|
|
18
|
+
roughness: style.roughness,
|
|
19
|
+
startArrowhead: style.startArrowhead ?? null,
|
|
20
|
+
endArrowhead: style.endArrowhead ?? 'arrow',
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Create an arrow element
|
|
25
|
+
*/
|
|
26
|
+
export function createArrow(edge, sourceNode, targetNode, boundElements) {
|
|
27
|
+
const styleProps = mapEdgeStyle(edge.style);
|
|
28
|
+
// Calculate bindings
|
|
29
|
+
const startBindingInfo = calculateStartBinding(sourceNode, targetNode);
|
|
30
|
+
const endBindingInfo = calculateEndBinding(sourceNode, targetNode);
|
|
31
|
+
// Use the source point as arrow position
|
|
32
|
+
const x = edge.sourcePoint.x;
|
|
33
|
+
const y = edge.sourcePoint.y;
|
|
34
|
+
// Calculate bounding box for width/height
|
|
35
|
+
let minX = 0, maxX = 0, minY = 0, maxY = 0;
|
|
36
|
+
for (const [px, py] of edge.points) {
|
|
37
|
+
minX = Math.min(minX, px);
|
|
38
|
+
maxX = Math.max(maxX, px);
|
|
39
|
+
minY = Math.min(minY, py);
|
|
40
|
+
maxY = Math.max(maxY, py);
|
|
41
|
+
}
|
|
42
|
+
const width = maxX - minX;
|
|
43
|
+
const height = maxY - minY;
|
|
44
|
+
return {
|
|
45
|
+
...createBaseElement('arrow', x, y, width, height, {
|
|
46
|
+
id: edge.id,
|
|
47
|
+
roundness: { type: 2 }, // Proportional roundness for smooth curves
|
|
48
|
+
boundElements: boundElements || null,
|
|
49
|
+
...styleProps,
|
|
50
|
+
}),
|
|
51
|
+
type: 'arrow',
|
|
52
|
+
points: edge.points,
|
|
53
|
+
lastCommittedPoint: null,
|
|
54
|
+
startBinding: startBindingInfo.binding,
|
|
55
|
+
endBinding: endBindingInfo.binding,
|
|
56
|
+
startArrowhead: styleProps.startArrowhead ?? null,
|
|
57
|
+
endArrowhead: styleProps.endArrowhead ?? 'arrow',
|
|
58
|
+
elbowed: false,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create arrow with explicit bindings
|
|
63
|
+
*/
|
|
64
|
+
export function createArrowWithBindings(id, x, y, points, startBinding, endBinding, boundElements, style) {
|
|
65
|
+
const styleProps = mapEdgeStyle(style);
|
|
66
|
+
// Calculate bounding box
|
|
67
|
+
let minX = 0, maxX = 0, minY = 0, maxY = 0;
|
|
68
|
+
for (const [px, py] of points) {
|
|
69
|
+
minX = Math.min(minX, px);
|
|
70
|
+
maxX = Math.max(maxX, px);
|
|
71
|
+
minY = Math.min(minY, py);
|
|
72
|
+
maxY = Math.max(maxY, py);
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
...createBaseElement('arrow', x, y, maxX - minX, maxY - minY, {
|
|
76
|
+
id,
|
|
77
|
+
roundness: { type: 2 },
|
|
78
|
+
boundElements: boundElements || null,
|
|
79
|
+
...styleProps,
|
|
80
|
+
}),
|
|
81
|
+
type: 'arrow',
|
|
82
|
+
points,
|
|
83
|
+
lastCommittedPoint: null,
|
|
84
|
+
startBinding,
|
|
85
|
+
endBinding,
|
|
86
|
+
startArrowhead: styleProps.startArrowhead ?? null,
|
|
87
|
+
endArrowhead: styleProps.endArrowhead ?? 'arrow',
|
|
88
|
+
elbowed: false,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=connection-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection-factory.js","sourceRoot":"","sources":["../../src/factory/connection-factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Element Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates base Excalidraw element properties shared by all elements.
|
|
5
|
+
*/
|
|
6
|
+
import type { ExcalidrawElementBase } from '../types/excalidraw.js';
|
|
7
|
+
/**
|
|
8
|
+
* Create base element properties
|
|
9
|
+
*/
|
|
10
|
+
export declare function createBaseElement(type: ExcalidrawElementBase['type'], x: number, y: number, width: number, height: number, options?: Partial<ExcalidrawElementBase>): ExcalidrawElementBase;
|
|
11
|
+
/**
|
|
12
|
+
* Reset the index counter (useful for testing)
|
|
13
|
+
*/
|
|
14
|
+
export declare function resetIndexCounter(): void;
|
|
15
|
+
export { DEFAULT_ELEMENT_STYLE } from '../types/excalidraw.js';
|
|
16
|
+
//# sourceMappingURL=element-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element-factory.d.ts","sourceRoot":"","sources":["../../src/factory/element-factory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAoCpE;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,qBAAqB,CAAC,MAAM,CAAC,EACnC,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,GACvC,qBAAqB,CA6BvB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAGD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Element Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates base Excalidraw element properties shared by all elements.
|
|
5
|
+
*/
|
|
6
|
+
import { nanoid } from 'nanoid';
|
|
7
|
+
import { DEFAULT_ELEMENT_STYLE } from '../types/excalidraw.js';
|
|
8
|
+
// Index counter for z-ordering
|
|
9
|
+
let indexCounter = 0;
|
|
10
|
+
/**
|
|
11
|
+
* Generate a unique index string for element ordering
|
|
12
|
+
*/
|
|
13
|
+
function generateIndex() {
|
|
14
|
+
indexCounter++;
|
|
15
|
+
// Convert to base-26 alphabetic index (a, b, c, ..., aa, ab, ...)
|
|
16
|
+
let idx = indexCounter;
|
|
17
|
+
let result = '';
|
|
18
|
+
while (idx > 0) {
|
|
19
|
+
idx--;
|
|
20
|
+
result = String.fromCharCode(97 + (idx % 26)) + result;
|
|
21
|
+
idx = Math.floor(idx / 26);
|
|
22
|
+
}
|
|
23
|
+
return 'a' + result;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Generate a random seed for roughness rendering
|
|
27
|
+
*/
|
|
28
|
+
function generateSeed() {
|
|
29
|
+
return Math.floor(Math.random() * 2147483647);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Generate version nonce
|
|
33
|
+
*/
|
|
34
|
+
function generateVersionNonce() {
|
|
35
|
+
return Math.floor(Math.random() * 2147483647);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Create base element properties
|
|
39
|
+
*/
|
|
40
|
+
export function createBaseElement(type, x, y, width, height, options) {
|
|
41
|
+
return {
|
|
42
|
+
id: options?.id || nanoid(21),
|
|
43
|
+
type,
|
|
44
|
+
x,
|
|
45
|
+
y,
|
|
46
|
+
width,
|
|
47
|
+
height,
|
|
48
|
+
angle: options?.angle ?? 0,
|
|
49
|
+
strokeColor: options?.strokeColor ?? DEFAULT_ELEMENT_STYLE.strokeColor,
|
|
50
|
+
backgroundColor: options?.backgroundColor ?? DEFAULT_ELEMENT_STYLE.backgroundColor,
|
|
51
|
+
fillStyle: options?.fillStyle ?? DEFAULT_ELEMENT_STYLE.fillStyle,
|
|
52
|
+
strokeWidth: options?.strokeWidth ?? DEFAULT_ELEMENT_STYLE.strokeWidth,
|
|
53
|
+
strokeStyle: options?.strokeStyle ?? DEFAULT_ELEMENT_STYLE.strokeStyle,
|
|
54
|
+
roughness: options?.roughness ?? DEFAULT_ELEMENT_STYLE.roughness,
|
|
55
|
+
opacity: options?.opacity ?? DEFAULT_ELEMENT_STYLE.opacity,
|
|
56
|
+
groupIds: options?.groupIds ?? [],
|
|
57
|
+
frameId: options?.frameId ?? null,
|
|
58
|
+
index: options?.index ?? generateIndex(),
|
|
59
|
+
roundness: options?.roundness ?? null,
|
|
60
|
+
seed: options?.seed ?? generateSeed(),
|
|
61
|
+
version: options?.version ?? 1,
|
|
62
|
+
versionNonce: options?.versionNonce ?? generateVersionNonce(),
|
|
63
|
+
isDeleted: options?.isDeleted ?? false,
|
|
64
|
+
boundElements: options?.boundElements ?? null,
|
|
65
|
+
updated: options?.updated ?? Date.now(),
|
|
66
|
+
link: options?.link ?? null,
|
|
67
|
+
locked: options?.locked ?? false,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Reset the index counter (useful for testing)
|
|
72
|
+
*/
|
|
73
|
+
export function resetIndexCounter() {
|
|
74
|
+
indexCounter = 0;
|
|
75
|
+
}
|
|
76
|
+
// Re-export defaults
|
|
77
|
+
export { DEFAULT_ELEMENT_STYLE } from '../types/excalidraw.js';
|
|
78
|
+
//# sourceMappingURL=element-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element-factory.js","sourceRoot":"","sources":["../../src/factory/element-factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory module exports
|
|
3
|
+
*/
|
|
4
|
+
export { createBaseElement, resetIndexCounter, DEFAULT_ELEMENT_STYLE } from './element-factory.js';
|
|
5
|
+
export { createNode, createRectangle, createDiamond, createEllipse } from './node-factory.js';
|
|
6
|
+
export { createArrow, createArrowWithBindings } from './connection-factory.js';
|
|
7
|
+
export { createText, createBoundText, createNodeLabel, createEdgeLabel } from './text-factory.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/factory/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACnG,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory module exports
|
|
3
|
+
*/
|
|
4
|
+
export { createBaseElement, resetIndexCounter, DEFAULT_ELEMENT_STYLE } from './element-factory.js';
|
|
5
|
+
export { createNode, createRectangle, createDiamond, createEllipse } from './node-factory.js';
|
|
6
|
+
export { createArrow, createArrowWithBindings } from './connection-factory.js';
|
|
7
|
+
export { createText, createBoundText, createNodeLabel, createEdgeLabel } from './text-factory.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/factory/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACnG,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates Excalidraw shape elements (rectangle, diamond, ellipse).
|
|
5
|
+
*/
|
|
6
|
+
import type { ExcalidrawRectangle, ExcalidrawDiamond, ExcalidrawEllipse, ExcalidrawBoundElement } from '../types/excalidraw.js';
|
|
7
|
+
import type { LayoutedNode } from '../types/dsl.js';
|
|
8
|
+
/**
|
|
9
|
+
* Create a rectangle element
|
|
10
|
+
*/
|
|
11
|
+
export declare function createRectangle(node: LayoutedNode, boundElements?: ExcalidrawBoundElement[]): ExcalidrawRectangle;
|
|
12
|
+
/**
|
|
13
|
+
* Create a diamond element
|
|
14
|
+
*/
|
|
15
|
+
export declare function createDiamond(node: LayoutedNode, boundElements?: ExcalidrawBoundElement[]): ExcalidrawDiamond;
|
|
16
|
+
/**
|
|
17
|
+
* Create an ellipse element
|
|
18
|
+
*/
|
|
19
|
+
export declare function createEllipse(node: LayoutedNode, boundElements?: ExcalidrawBoundElement[]): ExcalidrawEllipse;
|
|
20
|
+
/**
|
|
21
|
+
* Create a node element based on type
|
|
22
|
+
*/
|
|
23
|
+
export declare function createNode(node: LayoutedNode, boundElements?: ExcalidrawBoundElement[]): ExcalidrawRectangle | ExcalidrawDiamond | ExcalidrawEllipse;
|
|
24
|
+
//# sourceMappingURL=node-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-factory.d.ts","sourceRoot":"","sources":["../../src/factory/node-factory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EACV,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,YAAY,EAAa,MAAM,iBAAiB,CAAC;AAmB/D;;GAEG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,YAAY,EAClB,aAAa,CAAC,EAAE,sBAAsB,EAAE,GACvC,mBAAmB,CAYrB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,YAAY,EAClB,aAAa,CAAC,EAAE,sBAAsB,EAAE,GACvC,iBAAiB,CAYnB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,YAAY,EAClB,aAAa,CAAC,EAAE,sBAAsB,EAAE,GACvC,iBAAiB,CAYnB;AAED;;GAEG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,YAAY,EAClB,aAAa,CAAC,EAAE,sBAAsB,EAAE,GACvC,mBAAmB,GAAG,iBAAiB,GAAG,iBAAiB,CAa7D"}
|