Skip to content

Commit 218b0a8

Browse files
committed
feat(exporter): init basic shapes for excalidraw
1 parent a4ed31d commit 218b0a8

File tree

9 files changed

+288
-21
lines changed

9 files changed

+288
-21
lines changed
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
{
2+
"type": "excalidraw",
3+
"version": 2,
4+
"source": "https://excalidraw-anddd7.vercel.app",
5+
"elements": [
6+
{
7+
"type": "rectangle",
8+
"version": 185,
9+
"versionNonce": 454457666,
10+
"isDeleted": false,
11+
"id": "KUrWOmNsdwZrvoFhH8Jn0",
12+
"fillStyle": "hachure",
13+
"strokeWidth": 1,
14+
"strokeStyle": "solid",
15+
"roughness": 2,
16+
"opacity": 100,
17+
"angle": 0,
18+
"x": 880,
19+
"y": 214,
20+
"strokeColor": "#000000",
21+
"backgroundColor": "transparent",
22+
"width": 281,
23+
"height": 99,
24+
"seed": 1313707755,
25+
"groupIds": [],
26+
"strokeSharpness": "sharp",
27+
"boundElements": [
28+
{
29+
"id": "F04x3rJdXT2KyCiWWUU5z",
30+
"type": "arrow"
31+
}
32+
],
33+
"updated": 1660984302780,
34+
"link": null,
35+
"locked": false
36+
},
37+
{
38+
"type": "rectangle",
39+
"version": 96,
40+
"versionNonce": 1366276354,
41+
"isDeleted": false,
42+
"id": "BzGBNMtEi5oz75TTTyG1K",
43+
"fillStyle": "hachure",
44+
"strokeWidth": 1,
45+
"strokeStyle": "solid",
46+
"roughness": 2,
47+
"opacity": 100,
48+
"angle": 0,
49+
"x": 873.5,
50+
"y": 444.5,
51+
"strokeColor": "#000000",
52+
"backgroundColor": "transparent",
53+
"width": 281,
54+
"height": 99,
55+
"seed": 1720794910,
56+
"groupIds": [],
57+
"strokeSharpness": "sharp",
58+
"boundElements": [
59+
{
60+
"id": "F04x3rJdXT2KyCiWWUU5z",
61+
"type": "arrow"
62+
}
63+
],
64+
"updated": 1660984294419,
65+
"link": null,
66+
"locked": false
67+
},
68+
{
69+
"id": "F04x3rJdXT2KyCiWWUU5z",
70+
"type": "arrow",
71+
"x": 1013.2674452163553,
72+
"y": 314,
73+
"width": 5.872538676542717,
74+
"height": 127.00000000000006,
75+
"angle": 0,
76+
"strokeColor": "#000000",
77+
"backgroundColor": "transparent",
78+
"fillStyle": "hachure",
79+
"strokeWidth": 1,
80+
"strokeStyle": "solid",
81+
"roughness": 2,
82+
"opacity": 100,
83+
"groupIds": [],
84+
"strokeSharpness": "round",
85+
"seed": 1389974238,
86+
"version": 390,
87+
"versionNonce": 857116866,
88+
"isDeleted": false,
89+
"boundElements": null,
90+
"updated": 1660984302797,
91+
"link": null,
92+
"locked": false,
93+
"points": [
94+
[
95+
0,
96+
0
97+
],
98+
[
99+
5.872538676542717,
100+
127.00000000000006
101+
]
102+
],
103+
"lastCommittedPoint": null,
104+
"startBinding": {
105+
"elementId": "KUrWOmNsdwZrvoFhH8Jn0",
106+
"focus": 0.06705081194342587,
107+
"gap": 1
108+
},
109+
"endBinding": {
110+
"elementId": "BzGBNMtEi5oz75TTTyG1K",
111+
"focus": 0.05316049235892252,
112+
"gap": 3.5
113+
},
114+
"startArrowhead": null,
115+
"endArrowhead": "arrow"
116+
},
117+
{
118+
"id": "rXcc6rzZXrsJ7yW09Kb1v",
119+
"type": "text",
120+
"x": 947,
121+
"y": 248,
122+
"width": 125,
123+
"height": 26,
124+
"angle": 0,
125+
"strokeColor": "#000000",
126+
"backgroundColor": "transparent",
127+
"fillStyle": "hachure",
128+
"strokeWidth": 1,
129+
"strokeStyle": "solid",
130+
"roughness": 2,
131+
"opacity": 100,
132+
"groupIds": [],
133+
"strokeSharpness": "sharp",
134+
"seed": 203889822,
135+
"version": 71,
136+
"versionNonce": 1729880770,
137+
"isDeleted": false,
138+
"boundElements": null,
139+
"updated": 1660984381357,
140+
"link": null,
141+
"locked": false,
142+
"text": "Sample Text",
143+
"fontSize": 20,
144+
"fontFamily": 3,
145+
"textAlign": "left",
146+
"verticalAlign": "top",
147+
"baseline": 18,
148+
"containerId": null,
149+
"originalText": "Sample Text"
150+
}
151+
],
152+
"appState": {
153+
"gridSize": null,
154+
"viewBackgroundColor": "#ffffff"
155+
},
156+
"files": {}
157+
}

packages/exporter/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export * from './source/mermaid-flow';
5151
export * from './source/mermaid-flowdb';
5252

5353
export * from './target/drawio';
54-
export * from './target/excalidraw';
54+
export * from './target/excalidraw-exporter';
5555
export * from './target/exporter';
5656
export * from './target/mxgraph/drawio-wrapper';
5757
export * from './target/mxgraph/drawio-encode';

packages/exporter/src/target/converter.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { Graph, MxGraph } from "@feakin/exporter";
1+
import { MxGraph } from "./mxgraph/mxgraph";
2+
import { Graph } from "../model/graph";
23

34
export class Converter {
45
protected graph: MxGraph;

packages/exporter/src/target/drawio.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
import { FeakinExporter } from './exporter';
2+
import { Graph } from "../model/graph";
23

34
export class DrawioExporter implements FeakinExporter {
4-
export(_x: string): string {
5+
graph: Graph;
6+
7+
constructor(graph: Graph) {
8+
this.graph = graph;
9+
}
10+
11+
export(): any {
512
return '';
613
}
714

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import * as fs from "fs";
2+
import * as path from "path";
3+
import DrawioEncode from "./mxgraph/drawio-encode";
4+
import { Mxfile, MxGraph } from "./mxgraph/mxgraph";
5+
import { DrawioConverter } from "./mxgraph/drawio-converter";
6+
import { ExcalidrawExporter } from "./excalidraw-exporter";
7+
import { Graph } from "../model/graph";
8+
9+
const pwd = process.env["PWD"] || process.cwd();
10+
11+
describe('ExcalidrawExporter', () => {
12+
let mxGraph: MxGraph;
13+
14+
beforeAll(() => {
15+
const drawioFile = path.resolve(pwd, "./_fixtures/drawio/android-ag.drawio");
16+
const data = fs.readFileSync(drawioFile, { encoding: 'utf8', flag: 'r' });
17+
18+
const encoded: Mxfile | any = DrawioEncode.decodeXml(data);
19+
mxGraph = DrawioEncode.xml2obj(encoded) as MxGraph;
20+
});
21+
22+
it('exporter', () => {
23+
const drawioConverter = new DrawioConverter(mxGraph);
24+
const graph: Graph = drawioConverter.convert();
25+
26+
const exporter = new ExcalidrawExporter(graph).export();
27+
28+
fs.writeFileSync('./test/exporter.excalidraw', JSON.stringify(exporter, null, 2));
29+
});
30+
});
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { FeakinExporter } from './exporter';
2+
import { Graph, Node } from '../model/graph';
3+
import { randomInteger } from '../renderer/drawn-style/rough-seed';
4+
5+
export interface ExportedDataState {
6+
type: string;
7+
version: number;
8+
source: string;
9+
elements: any[];
10+
appState: any;
11+
files: any;
12+
}
13+
14+
export class ExcalidrawExporter implements FeakinExporter {
15+
graph: Graph;
16+
17+
constructor(graph: Graph) {
18+
this.graph = graph;
19+
}
20+
21+
export(): ExportedDataState {
22+
const root = this.createRoot();
23+
24+
this.graph.nodes.forEach(node => {
25+
root.elements.push(this.createNode(node));
26+
});
27+
28+
return root;
29+
}
30+
31+
footer(): string {
32+
return '';
33+
}
34+
35+
header(): string {
36+
return '';
37+
}
38+
39+
createRoot(): ExportedDataState {
40+
return {
41+
"type": "excalidraw",
42+
"version": 2,
43+
"source": "https://feakin.com",
44+
"elements": [],
45+
"appState": {
46+
"gridSize": null,
47+
"viewBackgroundColor": "#ffffff"
48+
},
49+
"files": {}
50+
}
51+
}
52+
53+
createNode(node: Node): object {
54+
return {
55+
id: randomInteger(),
56+
type: 'rectangle',
57+
x: node.x,
58+
y: node.y,
59+
width: node.width || 0,
60+
height: node.height || 0,
61+
angle: 0,
62+
strokeColor: '#000000',
63+
backgroundColor: 'transparent',
64+
fillStyle: 'solid',
65+
strokeWidth: 1,
66+
strokeStyle: 'solid',
67+
roughness: 1,
68+
opacity: 100,
69+
groupIds: [],
70+
strokeSharpness: "sharp",
71+
seed: randomInteger(),
72+
version: 11,
73+
versionNonce: 0,
74+
isDeleted: false,
75+
boundElements: [],
76+
updated: Date.now(),
77+
link: null,
78+
locked: false,
79+
};
80+
}
81+
}

packages/exporter/src/target/excalidraw.ts

Lines changed: 0 additions & 15 deletions
This file was deleted.

packages/exporter/src/target/exporter.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
import { Graph } from "../model/graph";
2+
13
export interface FeakinExporter {
2-
export(x: string): string;
4+
graph: Graph;
5+
6+
export(): any;
37

48
header(): string;
59

packages/exporter/src/target/mxgraph/drawio-converter.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class DrawioConverter extends Converter implements FeakinConverter {
2424

2525
this.mxCells.forEach((cell: MXCell) => {
2626
if (cell.attributes?.source && cell.attributes?.target) {
27-
filtered.edges.push(this.convertRelation(cell));
27+
filtered.edges.push(this.convertEdge(cell));
2828
} else if (cell.attributes?.value) {
2929
filtered.nodes.push(this.convertNode(cell));
3030
}
@@ -47,7 +47,7 @@ export class DrawioConverter extends Converter implements FeakinConverter {
4747
return parsed;
4848
}
4949

50-
private convertRelation(cell: MXCell): Edge {
50+
private convertEdge(cell: MXCell): Edge {
5151
const attrs = cell.attributes!;
5252

5353
return {
@@ -89,6 +89,8 @@ export class DrawioConverter extends Converter implements FeakinConverter {
8989
label: attrs.value,
9090
x: point.x,
9191
y: point.y,
92+
width: parseFloat(String(geoAttrs?.width || 0)),
93+
height: parseFloat(String(geoAttrs?.height || 0)),
9294
};
9395
}
9496
}

0 commit comments

Comments
 (0)