ts-visio 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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +343 -0
  3. package/dist/Layer.d.ts +12 -0
  4. package/dist/Layer.js +35 -0
  5. package/dist/Page.d.ts +30 -0
  6. package/dist/Page.js +169 -0
  7. package/dist/PageManager.d.ts +8 -0
  8. package/dist/PageManager.js +35 -0
  9. package/dist/SchemaDiagram.d.ts +22 -0
  10. package/dist/SchemaDiagram.js +36 -0
  11. package/dist/Shape.d.ts +68 -0
  12. package/dist/Shape.js +203 -0
  13. package/dist/ShapeModifier.d.ts +66 -0
  14. package/dist/ShapeModifier.js +889 -0
  15. package/dist/ShapeReader.d.ts +9 -0
  16. package/dist/ShapeReader.js +51 -0
  17. package/dist/VisioDocument.d.ts +21 -0
  18. package/dist/VisioDocument.js +119 -0
  19. package/dist/VisioPackage.d.ts +10 -0
  20. package/dist/VisioPackage.js +112 -0
  21. package/dist/core/MasterManager.d.ts +15 -0
  22. package/dist/core/MasterManager.js +43 -0
  23. package/dist/core/MediaConstants.d.ts +5 -0
  24. package/dist/core/MediaConstants.js +16 -0
  25. package/dist/core/MediaManager.d.ts +13 -0
  26. package/dist/core/MediaManager.js +88 -0
  27. package/dist/core/PageManager.d.ts +28 -0
  28. package/dist/core/PageManager.js +244 -0
  29. package/dist/core/RelsManager.d.ts +11 -0
  30. package/dist/core/RelsManager.js +81 -0
  31. package/dist/core/VisioConstants.d.ts +38 -0
  32. package/dist/core/VisioConstants.js +41 -0
  33. package/dist/core/VisioValidator.d.ts +27 -0
  34. package/dist/core/VisioValidator.js +362 -0
  35. package/dist/index.d.ts +8 -0
  36. package/dist/index.js +32 -0
  37. package/dist/shapes/ConnectorBuilder.d.ts +37 -0
  38. package/dist/shapes/ConnectorBuilder.js +173 -0
  39. package/dist/shapes/ContainerBuilder.d.ts +6 -0
  40. package/dist/shapes/ContainerBuilder.js +103 -0
  41. package/dist/shapes/ForeignShapeBuilder.d.ts +4 -0
  42. package/dist/shapes/ForeignShapeBuilder.js +47 -0
  43. package/dist/shapes/ShapeBuilder.d.ts +4 -0
  44. package/dist/shapes/ShapeBuilder.js +68 -0
  45. package/dist/templates/MinimalVsdx.d.ts +10 -0
  46. package/dist/templates/MinimalVsdx.js +66 -0
  47. package/dist/types/VisioTypes.d.ts +85 -0
  48. package/dist/types/VisioTypes.js +14 -0
  49. package/dist/utils/StubHelpers.d.ts +7 -0
  50. package/dist/utils/StubHelpers.js +16 -0
  51. package/dist/utils/StyleHelpers.d.ts +30 -0
  52. package/dist/utils/StyleHelpers.js +95 -0
  53. package/dist/utils/VisioParsers.d.ts +6 -0
  54. package/dist/utils/VisioParsers.js +45 -0
  55. package/package.json +27 -0
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SchemaDiagram = void 0;
4
+ class SchemaDiagram {
5
+ constructor(page) {
6
+ this.page = page;
7
+ }
8
+ /**
9
+ * Adds a table entity to the diagram.
10
+ * @param tableName Name of the table
11
+ * @param columns List of column names (e.g., "id: int")
12
+ * @param x X coordinate
13
+ * @param y Y coordinate
14
+ */
15
+ async addTable(tableName, columns, x = 0, y = 0) {
16
+ return this.page.addTable(x, y, tableName, columns);
17
+ }
18
+ /**
19
+ * Connects two tables with a specific relationship type.
20
+ * @param fromTable Source table shape
21
+ * @param toTable Target table shape
22
+ * @param type Relationship type ('1:1' or '1:N')
23
+ */
24
+ async addRelation(fromTable, toTable, type) {
25
+ let beginArrow = '0'; // No arrow at start
26
+ let endArrow = '1'; // Default standard arrow
27
+ if (type === '1:1') {
28
+ endArrow = '1'; // Standard Arrow
29
+ }
30
+ else if (type === '1:N') {
31
+ endArrow = '29'; // Crow's Foot
32
+ }
33
+ await this.page.connectShapes(fromTable, toTable, beginArrow, endArrow);
34
+ }
35
+ }
36
+ exports.SchemaDiagram = SchemaDiagram;
@@ -0,0 +1,68 @@
1
+ import { VisioShape } from './types/VisioTypes';
2
+ import { VisioPackage } from './VisioPackage';
3
+ import { ShapeStyle } from './ShapeModifier';
4
+ import { VisioPropType } from './types/VisioTypes';
5
+ import { Layer } from './Layer';
6
+ export interface ShapeData {
7
+ value: string | number | boolean | Date;
8
+ label?: string;
9
+ hidden?: boolean;
10
+ type?: VisioPropType;
11
+ }
12
+ export declare class Shape {
13
+ private internalShape;
14
+ private pageId;
15
+ private pkg;
16
+ constructor(internalShape: VisioShape, pageId: string, pkg: VisioPackage);
17
+ get id(): string;
18
+ get name(): string;
19
+ get text(): string;
20
+ setText(newText: string): Promise<void>;
21
+ get width(): number;
22
+ get height(): number;
23
+ get x(): number;
24
+ get y(): number;
25
+ connectTo(targetShape: Shape, beginArrow?: string, endArrow?: string): Promise<this>;
26
+ setStyle(style: ShapeStyle): Promise<this>;
27
+ placeRightOf(targetShape: Shape, options?: {
28
+ gap: number;
29
+ }): Promise<this>;
30
+ placeBelow(targetShape: Shape, options?: {
31
+ gap: number;
32
+ }): Promise<this>;
33
+ addPropertyDefinition(name: string, type: number, options?: {
34
+ label?: string;
35
+ invisible?: boolean;
36
+ }): this;
37
+ setPropertyValue(name: string, value: string | number | boolean | Date): this;
38
+ addData(key: string, data: ShapeData): this;
39
+ addMember(memberShape: Shape): Promise<this>;
40
+ addListItem(item: Shape): Promise<this>;
41
+ resizeToFit(padding?: number): Promise<this>;
42
+ private refreshLocalState;
43
+ addHyperlink(address: string, description?: string): Promise<this>;
44
+ linkToPage(targetPage: {
45
+ name: string;
46
+ }, description?: string): Promise<this>;
47
+ /**
48
+ * Adds an external hyperlink to the shape.
49
+ * Shows up in the right-click menu in Visio.
50
+ * @param url External URL (e.g. https://google.com)
51
+ * @param description Text to show in the menu
52
+ */
53
+ toUrl(url: string, description?: string): Promise<this>;
54
+ /**
55
+ * Adds an internal link to another page.
56
+ * Shows up in the right-click menu in Visio.
57
+ * @param targetPage The Page object to link to
58
+ * @param description Text to show in the menu
59
+ */
60
+ toPage(targetPage: {
61
+ name: string;
62
+ }, description?: string): Promise<this>;
63
+ assignLayer(layer: Layer | number): Promise<this>;
64
+ /**
65
+ * Alias for assignLayer. Adds this shape to a layer.
66
+ */
67
+ addToLayer(layer: Layer | number): Promise<this>;
68
+ }
package/dist/Shape.js ADDED
@@ -0,0 +1,203 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Shape = void 0;
4
+ const ShapeModifier_1 = require("./ShapeModifier");
5
+ const VisioTypes_1 = require("./types/VisioTypes");
6
+ class Shape {
7
+ constructor(internalShape, pageId, pkg) {
8
+ this.internalShape = internalShape;
9
+ this.pageId = pageId;
10
+ this.pkg = pkg;
11
+ }
12
+ get id() {
13
+ return this.internalShape.ID;
14
+ }
15
+ get name() {
16
+ return this.internalShape.Name;
17
+ }
18
+ get text() {
19
+ return this.internalShape.Text || '';
20
+ }
21
+ async setText(newText) {
22
+ const modifier = new ShapeModifier_1.ShapeModifier(this.pkg);
23
+ await modifier.updateShapeText(this.pageId, this.id, newText);
24
+ // Update local state to reflect change
25
+ this.internalShape.Text = newText;
26
+ }
27
+ get width() {
28
+ return this.internalShape.Cells['Width'] ? Number(this.internalShape.Cells['Width'].V) : 0;
29
+ }
30
+ get height() {
31
+ return this.internalShape.Cells['Height'] ? Number(this.internalShape.Cells['Height'].V) : 0;
32
+ }
33
+ get x() {
34
+ return this.internalShape.Cells['PinX'] ? Number(this.internalShape.Cells['PinX'].V) : 0;
35
+ }
36
+ get y() {
37
+ return this.internalShape.Cells['PinY'] ? Number(this.internalShape.Cells['PinY'].V) : 0;
38
+ }
39
+ async connectTo(targetShape, beginArrow, endArrow) {
40
+ const modifier = new ShapeModifier_1.ShapeModifier(this.pkg);
41
+ await modifier.addConnector(this.pageId, this.id, targetShape.id, beginArrow, endArrow);
42
+ return this;
43
+ }
44
+ async setStyle(style) {
45
+ const modifier = new ShapeModifier_1.ShapeModifier(this.pkg);
46
+ await modifier.updateShapeStyle(this.pageId, this.id, style);
47
+ // Minimal local state update to reflect changes if necessary
48
+ // For now, valid XML is the priority.
49
+ return this;
50
+ }
51
+ async placeRightOf(targetShape, options = { gap: 1 }) {
52
+ const newX = targetShape.x + targetShape.width + options.gap;
53
+ const newY = targetShape.y; // Keep same Y (per instructions, aligns center-to-center if PinY is center)
54
+ const modifier = new ShapeModifier_1.ShapeModifier(this.pkg);
55
+ await modifier.updateShapePosition(this.pageId, this.id, newX, newY);
56
+ // Update local state is crucial for chaining successive placements
57
+ if (this.internalShape.Cells['PinX'])
58
+ this.internalShape.Cells['PinX'].V = newX.toString();
59
+ else
60
+ this.internalShape.Cells['PinX'] = { V: newX.toString(), N: 'PinX' };
61
+ if (this.internalShape.Cells['PinY'])
62
+ this.internalShape.Cells['PinY'].V = newY.toString();
63
+ else
64
+ this.internalShape.Cells['PinY'] = { V: newY.toString(), N: 'PinY' };
65
+ return this;
66
+ }
67
+ async placeBelow(targetShape, options = { gap: 1 }) {
68
+ const newX = targetShape.x; // Align Centers
69
+ // Target Bottom = target.y - target.height / 2
70
+ // My Top = Target Bottom - gap
71
+ // My Center = My Top - my.height / 2
72
+ // My Center = target.y - target.height/2 - gap - my.height/2
73
+ const newY = targetShape.y - (targetShape.height + this.height) / 2 - options.gap;
74
+ const modifier = new ShapeModifier_1.ShapeModifier(this.pkg);
75
+ await modifier.updateShapePosition(this.pageId, this.id, newX, newY);
76
+ if (this.internalShape.Cells['PinX'])
77
+ this.internalShape.Cells['PinX'].V = newX.toString();
78
+ else
79
+ this.internalShape.Cells['PinX'] = { V: newX.toString(), N: 'PinX' };
80
+ if (this.internalShape.Cells['PinY'])
81
+ this.internalShape.Cells['PinY'].V = newY.toString();
82
+ else
83
+ this.internalShape.Cells['PinY'] = { V: newY.toString(), N: 'PinY' };
84
+ return this;
85
+ }
86
+ addPropertyDefinition(name, type, options = {}) {
87
+ const modifier = new ShapeModifier_1.ShapeModifier(this.pkg);
88
+ modifier.addPropertyDefinition(this.pageId, this.id, name, type, options);
89
+ return this;
90
+ }
91
+ setPropertyValue(name, value) {
92
+ const modifier = new ShapeModifier_1.ShapeModifier(this.pkg);
93
+ modifier.setPropertyValue(this.pageId, this.id, name, value);
94
+ return this;
95
+ }
96
+ addData(key, data) {
97
+ // Auto-detect type if not provided
98
+ let type = data.type;
99
+ if (type === undefined) {
100
+ if (data.value instanceof Date) {
101
+ type = VisioTypes_1.VisioPropType.Date;
102
+ }
103
+ else if (typeof data.value === 'number') {
104
+ type = VisioTypes_1.VisioPropType.Number;
105
+ }
106
+ else if (typeof data.value === 'boolean') {
107
+ type = VisioTypes_1.VisioPropType.Boolean;
108
+ }
109
+ else {
110
+ type = VisioTypes_1.VisioPropType.String;
111
+ }
112
+ }
113
+ // 1. Define Property
114
+ this.addPropertyDefinition(key, type, {
115
+ label: data.label,
116
+ invisible: data.hidden
117
+ });
118
+ // 2. Set Value
119
+ this.setPropertyValue(key, data.value);
120
+ return this;
121
+ }
122
+ async addMember(memberShape) {
123
+ const modifier = new ShapeModifier_1.ShapeModifier(this.pkg);
124
+ // Type="Container" is the standard for Container relationships
125
+ await modifier.addRelationship(this.pageId, this.id, memberShape.id, 'Container');
126
+ return this;
127
+ }
128
+ async addListItem(item) {
129
+ const modifier = new ShapeModifier_1.ShapeModifier(this.pkg);
130
+ await modifier.addListItem(this.pageId, this.id, item.id);
131
+ // Refresh local state after modifer updates (resizeToFit called internally)
132
+ await this.refreshLocalState();
133
+ return this;
134
+ }
135
+ async resizeToFit(padding = 0.25) {
136
+ const modifier = new ShapeModifier_1.ShapeModifier(this.pkg);
137
+ await modifier.resizeContainerToFit(this.pageId, this.id, padding);
138
+ await this.refreshLocalState();
139
+ return this;
140
+ }
141
+ async refreshLocalState() {
142
+ // Reloads internal Cells from modifier's fresh XML
143
+ // This is a bit expensive but ensures consistency
144
+ const modifier = new ShapeModifier_1.ShapeModifier(this.pkg);
145
+ const geo = modifier.getShapeGeometry(this.pageId, this.id);
146
+ const update = (n, v) => {
147
+ if (this.internalShape.Cells[n])
148
+ this.internalShape.Cells[n].V = v;
149
+ else
150
+ this.internalShape.Cells[n] = { V: v, N: n };
151
+ };
152
+ update('PinX', geo.x.toString());
153
+ update('PinY', geo.y.toString());
154
+ update('Width', geo.width.toString());
155
+ update('Height', geo.height.toString());
156
+ }
157
+ async addHyperlink(address, description) {
158
+ const modifier = new ShapeModifier_1.ShapeModifier(this.pkg);
159
+ await modifier.addHyperlink(this.pageId, this.id, { address, description });
160
+ return this;
161
+ }
162
+ async linkToPage(targetPage, description) {
163
+ const modifier = new ShapeModifier_1.ShapeModifier(this.pkg);
164
+ // Internal links use SubAddress='PageName' and empty Address
165
+ await modifier.addHyperlink(this.pageId, this.id, {
166
+ address: '',
167
+ subAddress: targetPage.name,
168
+ description
169
+ });
170
+ return this;
171
+ }
172
+ /**
173
+ * Adds an external hyperlink to the shape.
174
+ * Shows up in the right-click menu in Visio.
175
+ * @param url External URL (e.g. https://google.com)
176
+ * @param description Text to show in the menu
177
+ */
178
+ async toUrl(url, description) {
179
+ return this.addHyperlink(url, description);
180
+ }
181
+ /**
182
+ * Adds an internal link to another page.
183
+ * Shows up in the right-click menu in Visio.
184
+ * @param targetPage The Page object to link to
185
+ * @param description Text to show in the menu
186
+ */
187
+ async toPage(targetPage, description) {
188
+ return this.linkToPage(targetPage, description);
189
+ }
190
+ async assignLayer(layer) {
191
+ const index = typeof layer === 'number' ? layer : layer.index;
192
+ const modifier = new ShapeModifier_1.ShapeModifier(this.pkg);
193
+ await modifier.assignLayer(this.pageId, this.id, index);
194
+ return this;
195
+ }
196
+ /**
197
+ * Alias for assignLayer. Adds this shape to a layer.
198
+ */
199
+ async addToLayer(layer) {
200
+ return this.assignLayer(layer);
201
+ }
202
+ }
203
+ exports.Shape = Shape;
@@ -0,0 +1,66 @@
1
+ import { VisioPackage } from './VisioPackage';
2
+ import { NewShapeProps } from './types/VisioTypes';
3
+ export declare class ShapeModifier {
4
+ private pkg;
5
+ addContainer(pageId: string, props: NewShapeProps): Promise<string>;
6
+ addList(pageId: string, props: NewShapeProps, direction?: 'vertical' | 'horizontal'): Promise<string>;
7
+ private parser;
8
+ private builder;
9
+ private relsManager;
10
+ private pageCache;
11
+ private dirtyPages;
12
+ autoSave: boolean;
13
+ constructor(pkg: VisioPackage);
14
+ private getPagePath;
15
+ private getAllShapes;
16
+ private getNextId;
17
+ private ensurePageSheet;
18
+ private updateNextShapeId;
19
+ private getParsed;
20
+ private saveParsed;
21
+ private performSave;
22
+ flush(): void;
23
+ addConnector(pageId: string, fromShapeId: string, toShapeId: string, beginArrow?: string, endArrow?: string): Promise<string>;
24
+ addShape(pageId: string, props: NewShapeProps, parentId?: string): Promise<string>;
25
+ updateShapeText(pageId: string, shapeId: string, newText: string): Promise<void>;
26
+ updateShapeStyle(pageId: string, shapeId: string, style: ShapeStyle): Promise<void>;
27
+ updateShapeDimensions(pageId: string, shapeId: string, w: number, h: number): Promise<void>;
28
+ updateShapePosition(pageId: string, shapeId: string, x: number, y: number): Promise<void>;
29
+ addPropertyDefinition(pageId: string, shapeId: string, name: string, type: number, options?: {
30
+ label?: string;
31
+ invisible?: boolean;
32
+ }): void;
33
+ private dateToVisioString;
34
+ setPropertyValue(pageId: string, shapeId: string, name: string, value: string | number | boolean | Date): void;
35
+ getShapeGeometry(pageId: string, shapeId: string): {
36
+ x: number;
37
+ y: number;
38
+ width: number;
39
+ height: number;
40
+ };
41
+ addRelationship(pageId: string, shapeId: string, relatedShapeId: string, type: string): Promise<void>;
42
+ getContainerMembers(pageId: string, containerId: string): string[];
43
+ reorderShape(pageId: string, shapeId: string, position: 'front' | 'back'): Promise<void>;
44
+ addListItem(pageId: string, listId: string, itemId: string): Promise<void>;
45
+ resizeContainerToFit(pageId: string, containerId: string, padding?: number): Promise<void>;
46
+ addHyperlink(pageId: string, shapeId: string, details: {
47
+ address?: string;
48
+ subAddress?: string;
49
+ description?: string;
50
+ }): Promise<void>;
51
+ addLayer(pageId: string, name: string, options?: {
52
+ visible?: boolean;
53
+ lock?: boolean;
54
+ print?: boolean;
55
+ }): Promise<{
56
+ name: string;
57
+ index: number;
58
+ }>;
59
+ assignLayer(pageId: string, shapeId: string, layerIndex: number): Promise<void>;
60
+ updateLayerProperty(pageId: string, layerIndex: number, propName: string, value: string): Promise<void>;
61
+ }
62
+ export interface ShapeStyle {
63
+ fillColor?: string;
64
+ fontColor?: string;
65
+ bold?: boolean;
66
+ }