ts-visio 1.0.1 → 1.1.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/README.md +25 -0
- package/dist/Layer.d.ts +3 -1
- package/dist/Layer.js +6 -7
- package/dist/Page.d.ts +12 -0
- package/dist/Page.js +29 -11
- package/dist/Shape.d.ts +4 -2
- package/dist/Shape.js +44 -78
- package/dist/ShapeModifier.d.ts +9 -0
- package/dist/ShapeModifier.js +190 -271
- package/dist/VisioDocument.js +5 -1
- package/dist/core/MasterManager.js +1 -1
- package/dist/core/MediaConstants.js +11 -2
- package/dist/core/MediaManager.js +8 -16
- package/dist/core/PageManager.d.ts +1 -1
- package/dist/core/PageManager.js +12 -16
- package/dist/core/RelsManager.js +4 -11
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/shapes/ConnectorBuilder.js +8 -9
- package/dist/shapes/ContainerBuilder.js +8 -6
- package/dist/shapes/ForeignShapeBuilder.js +7 -4
- package/dist/shapes/ShapeBuilder.js +3 -3
- package/dist/types/VisioTypes.d.ts +4 -0
- package/dist/utils/StyleHelpers.d.ts +0 -4
- package/dist/utils/StyleHelpers.js +1 -13
- package/dist/utils/XmlHelper.d.ts +39 -0
- package/dist/utils/XmlHelper.js +56 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -321,6 +321,30 @@ await annotations.show(); // Show again
|
|
|
321
321
|
await wireframe.setLocked(true);
|
|
322
322
|
```
|
|
323
323
|
|
|
324
|
+
#### 18. Cross-Functional Flowcharts (Swimlanes)
|
|
325
|
+
Create structured Swimlane diagrams involving Pools and Lanes.
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
// 1. Create a Pool (Vertical List)
|
|
329
|
+
const pool = await page.addSwimlanePool({
|
|
330
|
+
text: "User Registration",
|
|
331
|
+
x: 5, y: 5, width: 10, height: 6
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// 2. Create Lanes (Containers)
|
|
335
|
+
const lane1 = await page.addSwimlaneLane({ text: "Client", width: 10, height: 2 });
|
|
336
|
+
const lane2 = await page.addSwimlaneLane({ text: "Server", width: 10, height: 2 });
|
|
337
|
+
|
|
338
|
+
// 3. Add Lanes to Pool (Order matters)
|
|
339
|
+
await pool.addListItem(lane1);
|
|
340
|
+
await pool.addListItem(lane2);
|
|
341
|
+
|
|
342
|
+
// 4. Group Shapes into Lanes
|
|
343
|
+
// This binds their movement so they stay inside the lane
|
|
344
|
+
await lane1.addMember(startShape);
|
|
345
|
+
await lane2.addMember(serverShape);
|
|
346
|
+
```
|
|
347
|
+
|
|
324
348
|
## Examples
|
|
325
349
|
|
|
326
350
|
Check out the [examples](./examples) directory for complete scripts.
|
|
@@ -332,6 +356,7 @@ Check out the [examples](./examples) directory for complete scripts.
|
|
|
332
356
|
- **[Hyperlinks Demo](./examples/hyperlinks_demo.ts)**: Demonstrates Internal and External navigation.
|
|
333
357
|
- **[Layers Demo](./examples/layers_demo.ts)**: Shows how to create layers and toggle visibility.
|
|
334
358
|
- **[Image Embedding Demo](./examples/images_demo.ts)**: Demonstrates how to embed PNG or JPEG images into a diagram.
|
|
359
|
+
- **[Swimlane Demo](./examples/swimlane_demo.ts)**: Demonstrates creating Cross-Functional Flowcharts with Pools and Lanes.
|
|
335
360
|
|
|
336
361
|
## Development
|
|
337
362
|
|
package/dist/Layer.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { VisioPackage } from './VisioPackage';
|
|
2
|
+
import { ShapeModifier } from './ShapeModifier';
|
|
2
3
|
export declare class Layer {
|
|
3
4
|
name: string;
|
|
4
5
|
index: number;
|
|
5
6
|
private pageId?;
|
|
6
7
|
private pkg?;
|
|
7
|
-
|
|
8
|
+
private modifier;
|
|
9
|
+
constructor(name: string, index: number, pageId?: string | undefined, pkg?: VisioPackage | undefined, modifier?: ShapeModifier);
|
|
8
10
|
setVisible(visible: boolean): Promise<this>;
|
|
9
11
|
setLocked(locked: boolean): Promise<this>;
|
|
10
12
|
hide(): Promise<this>;
|
package/dist/Layer.js
CHANGED
|
@@ -3,26 +3,25 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Layer = void 0;
|
|
4
4
|
const ShapeModifier_1 = require("./ShapeModifier");
|
|
5
5
|
class Layer {
|
|
6
|
-
constructor(name, index, pageId, pkg) {
|
|
6
|
+
constructor(name, index, pageId, pkg, modifier) {
|
|
7
7
|
this.name = name;
|
|
8
8
|
this.index = index;
|
|
9
9
|
this.pageId = pageId;
|
|
10
10
|
this.pkg = pkg;
|
|
11
|
+
this.modifier = modifier ?? (pkg ? new ShapeModifier_1.ShapeModifier(pkg) : null);
|
|
11
12
|
}
|
|
12
13
|
async setVisible(visible) {
|
|
13
|
-
if (!this.pageId || !this.
|
|
14
|
+
if (!this.pageId || !this.modifier) {
|
|
14
15
|
throw new Error('Layer was not created with page context. Cannot update properties.');
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
-
await modifier.updateLayerProperty(this.pageId, this.index, 'Visible', visible ? '1' : '0');
|
|
17
|
+
await this.modifier.updateLayerProperty(this.pageId, this.index, 'Visible', visible ? '1' : '0');
|
|
18
18
|
return this;
|
|
19
19
|
}
|
|
20
20
|
async setLocked(locked) {
|
|
21
|
-
if (!this.pageId || !this.
|
|
21
|
+
if (!this.pageId || !this.modifier) {
|
|
22
22
|
throw new Error('Layer was not created with page context. Cannot update properties.');
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
await modifier.updateLayerProperty(this.pageId, this.index, 'Lock', locked ? '1' : '0');
|
|
24
|
+
await this.modifier.updateLayerProperty(this.pageId, this.index, 'Lock', locked ? '1' : '0');
|
|
26
25
|
return this;
|
|
27
26
|
}
|
|
28
27
|
async hide() {
|
package/dist/Page.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export declare class Page {
|
|
|
12
12
|
private media;
|
|
13
13
|
private rels;
|
|
14
14
|
private modifier;
|
|
15
|
+
/** Resolved OPC part path for this page's XML file. */
|
|
16
|
+
private pagePath;
|
|
15
17
|
constructor(internalPage: VisioPage, pkg: VisioPackage, media?: MediaManager, rels?: RelsManager, modifier?: ShapeModifier);
|
|
16
18
|
get id(): string;
|
|
17
19
|
get name(): string;
|
|
@@ -21,6 +23,16 @@ export declare class Page {
|
|
|
21
23
|
addImage(data: Buffer, name: string, x: number, y: number, width: number, height: number): Promise<Shape>;
|
|
22
24
|
addContainer(props: NewShapeProps): Promise<Shape>;
|
|
23
25
|
addList(props: NewShapeProps, direction?: 'vertical' | 'horizontal'): Promise<Shape>;
|
|
26
|
+
/**
|
|
27
|
+
* Creates a Swimlane Pool (which is technically a Vertical List of Containers).
|
|
28
|
+
* @param props Visual properties
|
|
29
|
+
*/
|
|
30
|
+
addSwimlanePool(props: NewShapeProps): Promise<Shape>;
|
|
31
|
+
/**
|
|
32
|
+
* Creates a Swimlane Lane (which is technically a Container).
|
|
33
|
+
* @param props Visual properties
|
|
34
|
+
*/
|
|
35
|
+
addSwimlaneLane(props: NewShapeProps): Promise<Shape>;
|
|
24
36
|
addTable(x: number, y: number, title: string, columns: string[]): Promise<Shape>;
|
|
25
37
|
addLayer(name: string, options?: {
|
|
26
38
|
visible?: boolean;
|
package/dist/Page.js
CHANGED
|
@@ -12,9 +12,13 @@ class Page {
|
|
|
12
12
|
constructor(internalPage, pkg, media, rels, modifier) {
|
|
13
13
|
this.internalPage = internalPage;
|
|
14
14
|
this.pkg = pkg;
|
|
15
|
+
// Prefer the relationship-resolved path over the ID-derived fallback so
|
|
16
|
+
// that loaded files with non-sequential page filenames work correctly.
|
|
17
|
+
this.pagePath = internalPage.xmlPath ?? `visio/pages/page${internalPage.ID}.xml`;
|
|
15
18
|
this.media = media || new MediaManager_1.MediaManager(pkg);
|
|
16
19
|
this.rels = rels || new RelsManager_1.RelsManager(pkg);
|
|
17
20
|
this.modifier = modifier || new ShapeModifier_1.ShapeModifier(pkg);
|
|
21
|
+
this.modifier.registerPage(internalPage.ID, this.pagePath);
|
|
18
22
|
}
|
|
19
23
|
get id() {
|
|
20
24
|
return this.internalPage.ID;
|
|
@@ -24,11 +28,9 @@ class Page {
|
|
|
24
28
|
}
|
|
25
29
|
getShapes() {
|
|
26
30
|
const reader = new ShapeReader_1.ShapeReader(this.pkg);
|
|
27
|
-
// Assuming standard path mapping for now
|
|
28
|
-
const pagePath = `visio/pages/page${this.id}.xml`;
|
|
29
31
|
try {
|
|
30
|
-
const internalShapes = reader.readShapes(pagePath);
|
|
31
|
-
return internalShapes.map(s => new Shape_1.Shape(s, this.id, this.pkg));
|
|
32
|
+
const internalShapes = reader.readShapes(this.pagePath);
|
|
33
|
+
return internalShapes.map(s => new Shape_1.Shape(s, this.id, this.pkg, this.modifier));
|
|
32
34
|
}
|
|
33
35
|
catch (e) {
|
|
34
36
|
// If page file doesn't exist or is empty, return empty array
|
|
@@ -53,7 +55,7 @@ class Page {
|
|
|
53
55
|
'LocPinY': props.height / 2
|
|
54
56
|
}
|
|
55
57
|
});
|
|
56
|
-
return new Shape_1.Shape(internalStub, this.id, this.pkg);
|
|
58
|
+
return new Shape_1.Shape(internalStub, this.id, this.pkg, this.modifier);
|
|
57
59
|
}
|
|
58
60
|
async connectShapes(fromShape, toShape, beginArrow, endArrow) {
|
|
59
61
|
await this.modifier.addConnector(this.id, fromShape.id, toShape.id, beginArrow, endArrow);
|
|
@@ -61,8 +63,8 @@ class Page {
|
|
|
61
63
|
async addImage(data, name, x, y, width, height) {
|
|
62
64
|
// 1. Upload Media
|
|
63
65
|
const mediaPath = this.media.addMedia(name, data);
|
|
64
|
-
// 2. Link Page to Media
|
|
65
|
-
const rId = await this.rels.
|
|
66
|
+
// 2. Link Page to Media (use resolved path so loaded files work correctly)
|
|
67
|
+
const rId = await this.rels.addImageRelationship(this.pagePath, mediaPath);
|
|
66
68
|
// 3. Create Shape
|
|
67
69
|
const newId = await this.modifier.addShape(this.id, {
|
|
68
70
|
text: '',
|
|
@@ -80,7 +82,7 @@ class Page {
|
|
|
80
82
|
'PinY': y
|
|
81
83
|
}
|
|
82
84
|
});
|
|
83
|
-
return new Shape_1.Shape(internalStub, this.id, this.pkg);
|
|
85
|
+
return new Shape_1.Shape(internalStub, this.id, this.pkg, this.modifier);
|
|
84
86
|
}
|
|
85
87
|
async addContainer(props) {
|
|
86
88
|
const newId = await this.modifier.addContainer(this.id, props);
|
|
@@ -94,7 +96,7 @@ class Page {
|
|
|
94
96
|
'PinY': props.y
|
|
95
97
|
}
|
|
96
98
|
});
|
|
97
|
-
return new Shape_1.Shape(internalStub, this.id, this.pkg);
|
|
99
|
+
return new Shape_1.Shape(internalStub, this.id, this.pkg, this.modifier);
|
|
98
100
|
}
|
|
99
101
|
async addList(props, direction = 'vertical') {
|
|
100
102
|
const newId = await this.modifier.addList(this.id, props, direction);
|
|
@@ -108,7 +110,23 @@ class Page {
|
|
|
108
110
|
'PinY': props.y
|
|
109
111
|
}
|
|
110
112
|
});
|
|
111
|
-
return new Shape_1.Shape(internalStub, this.id, this.pkg);
|
|
113
|
+
return new Shape_1.Shape(internalStub, this.id, this.pkg, this.modifier);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Creates a Swimlane Pool (which is technically a Vertical List of Containers).
|
|
117
|
+
* @param props Visual properties
|
|
118
|
+
*/
|
|
119
|
+
async addSwimlanePool(props) {
|
|
120
|
+
// A Pool is just a vertical list
|
|
121
|
+
return this.addList(props, 'vertical');
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Creates a Swimlane Lane (which is technically a Container).
|
|
125
|
+
* @param props Visual properties
|
|
126
|
+
*/
|
|
127
|
+
async addSwimlaneLane(props) {
|
|
128
|
+
// A Lane is just a container
|
|
129
|
+
return this.addContainer(props);
|
|
112
130
|
}
|
|
113
131
|
async addTable(x, y, title, columns) {
|
|
114
132
|
// ... (previous implementation)
|
|
@@ -163,7 +181,7 @@ class Page {
|
|
|
163
181
|
}
|
|
164
182
|
async addLayer(name, options) {
|
|
165
183
|
const info = await this.modifier.addLayer(this.id, name, options);
|
|
166
|
-
return new Layer_1.Layer(info.name, info.index, this.id, this.pkg);
|
|
184
|
+
return new Layer_1.Layer(info.name, info.index, this.id, this.pkg, this.modifier);
|
|
167
185
|
}
|
|
168
186
|
}
|
|
169
187
|
exports.Page = Page;
|
package/dist/Shape.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { VisioShape } from './types/VisioTypes';
|
|
2
2
|
import { VisioPackage } from './VisioPackage';
|
|
3
|
-
import { ShapeStyle } from './ShapeModifier';
|
|
3
|
+
import { ShapeModifier, ShapeStyle } from './ShapeModifier';
|
|
4
4
|
import { VisioPropType } from './types/VisioTypes';
|
|
5
5
|
import { Layer } from './Layer';
|
|
6
6
|
export interface ShapeData {
|
|
@@ -13,7 +13,8 @@ export declare class Shape {
|
|
|
13
13
|
private internalShape;
|
|
14
14
|
private pageId;
|
|
15
15
|
private pkg;
|
|
16
|
-
|
|
16
|
+
private modifier;
|
|
17
|
+
constructor(internalShape: VisioShape, pageId: string, pkg: VisioPackage, modifier?: ShapeModifier);
|
|
17
18
|
get id(): string;
|
|
18
19
|
get name(): string;
|
|
19
20
|
get text(): string;
|
|
@@ -65,4 +66,5 @@ export declare class Shape {
|
|
|
65
66
|
* Alias for assignLayer. Adds this shape to a layer.
|
|
66
67
|
*/
|
|
67
68
|
addToLayer(layer: Layer | number): Promise<this>;
|
|
69
|
+
private setLocalCoord;
|
|
68
70
|
}
|
package/dist/Shape.js
CHANGED
|
@@ -3,11 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Shape = void 0;
|
|
4
4
|
const ShapeModifier_1 = require("./ShapeModifier");
|
|
5
5
|
const VisioTypes_1 = require("./types/VisioTypes");
|
|
6
|
+
/** Round a coordinate to 10 decimal places to prevent float-to-string-to-float precision drift. */
|
|
7
|
+
function fmtCoord(n) {
|
|
8
|
+
return parseFloat(n.toFixed(10)).toString();
|
|
9
|
+
}
|
|
6
10
|
class Shape {
|
|
7
|
-
constructor(internalShape, pageId, pkg) {
|
|
11
|
+
constructor(internalShape, pageId, pkg, modifier) {
|
|
8
12
|
this.internalShape = internalShape;
|
|
9
13
|
this.pageId = pageId;
|
|
10
14
|
this.pkg = pkg;
|
|
15
|
+
this.modifier = modifier ?? new ShapeModifier_1.ShapeModifier(pkg);
|
|
11
16
|
}
|
|
12
17
|
get id() {
|
|
13
18
|
return this.internalShape.ID;
|
|
@@ -19,9 +24,7 @@ class Shape {
|
|
|
19
24
|
return this.internalShape.Text || '';
|
|
20
25
|
}
|
|
21
26
|
async setText(newText) {
|
|
22
|
-
|
|
23
|
-
await modifier.updateShapeText(this.pageId, this.id, newText);
|
|
24
|
-
// Update local state to reflect change
|
|
27
|
+
await this.modifier.updateShapeText(this.pageId, this.id, newText);
|
|
25
28
|
this.internalShape.Text = newText;
|
|
26
29
|
}
|
|
27
30
|
get width() {
|
|
@@ -37,64 +40,43 @@ class Shape {
|
|
|
37
40
|
return this.internalShape.Cells['PinY'] ? Number(this.internalShape.Cells['PinY'].V) : 0;
|
|
38
41
|
}
|
|
39
42
|
async connectTo(targetShape, beginArrow, endArrow) {
|
|
40
|
-
|
|
41
|
-
await modifier.addConnector(this.pageId, this.id, targetShape.id, beginArrow, endArrow);
|
|
43
|
+
await this.modifier.addConnector(this.pageId, this.id, targetShape.id, beginArrow, endArrow);
|
|
42
44
|
return this;
|
|
43
45
|
}
|
|
44
46
|
async setStyle(style) {
|
|
45
|
-
|
|
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.
|
|
47
|
+
await this.modifier.updateShapeStyle(this.pageId, this.id, style);
|
|
49
48
|
return this;
|
|
50
49
|
}
|
|
51
50
|
async placeRightOf(targetShape, options = { gap: 1 }) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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' };
|
|
51
|
+
// PinX is the shape centre, so right edge of target = target.x + target.width/2;
|
|
52
|
+
// left edge of this = newX - this.width/2. Set left edge = right edge of target + gap.
|
|
53
|
+
const newX = targetShape.x + (targetShape.width / 2) + options.gap + (this.width / 2);
|
|
54
|
+
const newY = targetShape.y; // Align centres vertically
|
|
55
|
+
await this.modifier.updateShapePosition(this.pageId, this.id, newX, newY);
|
|
56
|
+
// Update local state — rounded to avoid float precision drift in chained placements
|
|
57
|
+
this.setLocalCoord('PinX', newX);
|
|
58
|
+
this.setLocalCoord('PinY', newY);
|
|
65
59
|
return this;
|
|
66
60
|
}
|
|
67
61
|
async placeBelow(targetShape, options = { gap: 1 }) {
|
|
68
|
-
const newX = targetShape.x; // Align
|
|
69
|
-
// Target
|
|
70
|
-
//
|
|
71
|
-
// My Center = My Top - my.height / 2
|
|
72
|
-
// My Center = target.y - target.height/2 - gap - my.height/2
|
|
62
|
+
const newX = targetShape.x; // Align centres horizontally
|
|
63
|
+
// Target bottom edge = target.y - target.height/2
|
|
64
|
+
// This centre = target bottom - gap - this.height/2
|
|
73
65
|
const newY = targetShape.y - (targetShape.height + this.height) / 2 - options.gap;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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' };
|
|
66
|
+
await this.modifier.updateShapePosition(this.pageId, this.id, newX, newY);
|
|
67
|
+
this.setLocalCoord('PinX', newX);
|
|
68
|
+
this.setLocalCoord('PinY', newY);
|
|
84
69
|
return this;
|
|
85
70
|
}
|
|
86
71
|
addPropertyDefinition(name, type, options = {}) {
|
|
87
|
-
|
|
88
|
-
modifier.addPropertyDefinition(this.pageId, this.id, name, type, options);
|
|
72
|
+
this.modifier.addPropertyDefinition(this.pageId, this.id, name, type, options);
|
|
89
73
|
return this;
|
|
90
74
|
}
|
|
91
75
|
setPropertyValue(name, value) {
|
|
92
|
-
|
|
93
|
-
modifier.setPropertyValue(this.pageId, this.id, name, value);
|
|
76
|
+
this.modifier.setPropertyValue(this.pageId, this.id, name, value);
|
|
94
77
|
return this;
|
|
95
78
|
}
|
|
96
79
|
addData(key, data) {
|
|
97
|
-
// Auto-detect type if not provided
|
|
98
80
|
let type = data.type;
|
|
99
81
|
if (type === undefined) {
|
|
100
82
|
if (data.value instanceof Date) {
|
|
@@ -110,59 +92,37 @@ class Shape {
|
|
|
110
92
|
type = VisioTypes_1.VisioPropType.String;
|
|
111
93
|
}
|
|
112
94
|
}
|
|
113
|
-
|
|
114
|
-
this.addPropertyDefinition(key, type, {
|
|
115
|
-
label: data.label,
|
|
116
|
-
invisible: data.hidden
|
|
117
|
-
});
|
|
118
|
-
// 2. Set Value
|
|
95
|
+
this.addPropertyDefinition(key, type, { label: data.label, invisible: data.hidden });
|
|
119
96
|
this.setPropertyValue(key, data.value);
|
|
120
97
|
return this;
|
|
121
98
|
}
|
|
122
99
|
async addMember(memberShape) {
|
|
123
|
-
|
|
124
|
-
// Type="Container" is the standard for Container relationships
|
|
125
|
-
await modifier.addRelationship(this.pageId, this.id, memberShape.id, 'Container');
|
|
100
|
+
await this.modifier.addRelationship(this.pageId, this.id, memberShape.id, 'Container');
|
|
126
101
|
return this;
|
|
127
102
|
}
|
|
128
103
|
async addListItem(item) {
|
|
129
|
-
|
|
130
|
-
await modifier.addListItem(this.pageId, this.id, item.id);
|
|
131
|
-
// Refresh local state after modifer updates (resizeToFit called internally)
|
|
104
|
+
await this.modifier.addListItem(this.pageId, this.id, item.id);
|
|
132
105
|
await this.refreshLocalState();
|
|
133
106
|
return this;
|
|
134
107
|
}
|
|
135
108
|
async resizeToFit(padding = 0.25) {
|
|
136
|
-
|
|
137
|
-
await modifier.resizeContainerToFit(this.pageId, this.id, padding);
|
|
109
|
+
await this.modifier.resizeContainerToFit(this.pageId, this.id, padding);
|
|
138
110
|
await this.refreshLocalState();
|
|
139
111
|
return this;
|
|
140
112
|
}
|
|
141
113
|
async refreshLocalState() {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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());
|
|
114
|
+
const geo = this.modifier.getShapeGeometry(this.pageId, this.id);
|
|
115
|
+
this.setLocalCoord('PinX', geo.x);
|
|
116
|
+
this.setLocalCoord('PinY', geo.y);
|
|
117
|
+
this.setLocalCoord('Width', geo.width);
|
|
118
|
+
this.setLocalCoord('Height', geo.height);
|
|
156
119
|
}
|
|
157
120
|
async addHyperlink(address, description) {
|
|
158
|
-
|
|
159
|
-
await modifier.addHyperlink(this.pageId, this.id, { address, description });
|
|
121
|
+
await this.modifier.addHyperlink(this.pageId, this.id, { address, description });
|
|
160
122
|
return this;
|
|
161
123
|
}
|
|
162
124
|
async linkToPage(targetPage, description) {
|
|
163
|
-
|
|
164
|
-
// Internal links use SubAddress='PageName' and empty Address
|
|
165
|
-
await modifier.addHyperlink(this.pageId, this.id, {
|
|
125
|
+
await this.modifier.addHyperlink(this.pageId, this.id, {
|
|
166
126
|
address: '',
|
|
167
127
|
subAddress: targetPage.name,
|
|
168
128
|
description
|
|
@@ -189,8 +149,7 @@ class Shape {
|
|
|
189
149
|
}
|
|
190
150
|
async assignLayer(layer) {
|
|
191
151
|
const index = typeof layer === 'number' ? layer : layer.index;
|
|
192
|
-
|
|
193
|
-
await modifier.assignLayer(this.pageId, this.id, index);
|
|
152
|
+
await this.modifier.assignLayer(this.pageId, this.id, index);
|
|
194
153
|
return this;
|
|
195
154
|
}
|
|
196
155
|
/**
|
|
@@ -199,5 +158,12 @@ class Shape {
|
|
|
199
158
|
async addToLayer(layer) {
|
|
200
159
|
return this.assignLayer(layer);
|
|
201
160
|
}
|
|
161
|
+
setLocalCoord(name, value) {
|
|
162
|
+
const v = fmtCoord(value);
|
|
163
|
+
if (this.internalShape.Cells[name])
|
|
164
|
+
this.internalShape.Cells[name].V = v;
|
|
165
|
+
else
|
|
166
|
+
this.internalShape.Cells[name] = { V: v, N: name };
|
|
167
|
+
}
|
|
202
168
|
}
|
|
203
169
|
exports.Shape = Shape;
|
package/dist/ShapeModifier.d.ts
CHANGED
|
@@ -9,9 +9,18 @@ export declare class ShapeModifier {
|
|
|
9
9
|
private relsManager;
|
|
10
10
|
private pageCache;
|
|
11
11
|
private dirtyPages;
|
|
12
|
+
private shapeCache;
|
|
13
|
+
private pagePathRegistry;
|
|
12
14
|
autoSave: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Register the resolved OPC part path for a page ID.
|
|
17
|
+
* Must be called before any operation on a loaded file to ensure the
|
|
18
|
+
* correct file is targeted rather than the ID-derived fallback name.
|
|
19
|
+
*/
|
|
20
|
+
registerPage(pageId: string, xmlPath: string): void;
|
|
13
21
|
constructor(pkg: VisioPackage);
|
|
14
22
|
private getPagePath;
|
|
23
|
+
private getShapeMap;
|
|
15
24
|
private getAllShapes;
|
|
16
25
|
private getNextId;
|
|
17
26
|
private ensurePageSheet;
|