ts-visio 1.13.0 → 1.16.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 +96 -15
- package/dist/Layer.d.ts +14 -0
- package/dist/Layer.js +14 -0
- package/dist/Page.d.ts +106 -9
- package/dist/Page.js +118 -64
- package/dist/Shape.d.ts +17 -2
- package/dist/Shape.js +15 -0
- package/dist/ShapeModifier.d.ts +82 -124
- package/dist/ShapeModifier.js +192 -821
- package/dist/ShapeReader.d.ts +0 -3
- package/dist/ShapeReader.js +6 -51
- package/dist/VisioDocument.d.ts +57 -1
- package/dist/VisioDocument.js +66 -0
- package/dist/core/ConnectorEditor.d.ts +12 -0
- package/dist/core/ConnectorEditor.js +45 -0
- package/dist/core/ContainerEditor.d.ts +16 -0
- package/dist/core/ContainerEditor.js +179 -0
- package/dist/core/LayerEditor.d.ts +36 -0
- package/dist/core/LayerEditor.js +209 -0
- package/dist/core/MasterManager.d.ts +64 -9
- package/dist/core/MasterManager.js +406 -23
- package/dist/core/PageManager.d.ts +2 -3
- package/dist/core/PageManager.js +18 -93
- package/dist/core/PageSheetEditor.d.ts +40 -0
- package/dist/core/PageSheetEditor.js +130 -0
- package/dist/core/PageXmlCache.d.ts +42 -0
- package/dist/core/PageXmlCache.js +194 -0
- package/dist/core/RelsManager.js +1 -6
- package/dist/core/VisioConstants.d.ts +10 -0
- package/dist/core/VisioConstants.js +29 -1
- package/dist/core/VisioValidator.js +2 -24
- package/dist/diagrams/SchemaDiagram.d.ts +22 -0
- package/dist/diagrams/SchemaDiagram.js +36 -0
- package/dist/diagrams/SwimlanePattern.d.ts +14 -0
- package/dist/diagrams/SwimlanePattern.js +19 -0
- package/dist/diagrams/TablePattern.d.ts +11 -0
- package/dist/diagrams/TablePattern.js +44 -0
- package/dist/index.d.ts +3 -7
- package/dist/index.js +6 -10
- package/dist/shapes/ContainerBuilder.js +0 -22
- package/dist/shapes/ShapeBuilder.js +7 -8
- package/dist/types/VisioTypes.d.ts +98 -4
- package/dist/utils/ShapeTreeUtils.d.ts +21 -0
- package/dist/utils/ShapeTreeUtils.js +77 -0
- package/dist/utils/StyleHelpers.d.ts +2 -14
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# ts-visio
|
|
2
2
|
|
|
3
|
+
[](https://zimmermanw84.github.io/ts-visio/)
|
|
4
|
+
|
|
3
5
|
> [!WARNING]
|
|
4
6
|
> **Under Construction**
|
|
5
7
|
> This library is currently being developed with heavy assistance from AI and is primarily an experimental project. Use with caution.
|
|
@@ -14,7 +16,7 @@ Built using specific schema-level abstractions to handle the complex internal st
|
|
|
14
16
|
- **Strict Typing**: Interact with `VisioPage`, `VisioShape`, and `VisioConnect` objects.
|
|
15
17
|
- **ShapeSheet Access**: Read `Cells`, `Rows`, and `Sections` directly.
|
|
16
18
|
- **Connections**: Analyze connectivity between shapes.
|
|
17
|
-
- **Modular Architecture**:
|
|
19
|
+
- **Modular Architecture**: Clean layered architecture — `VisioDocument` → `Page` → `Shape` is the full public surface; XML and OPC internals stay encapsulated.
|
|
18
20
|
- **Modify Content**: Update text content of shapes.
|
|
19
21
|
- **Create Shapes**: Rectangles, ellipses, diamonds, rounded rectangles, triangles, parallelograms.
|
|
20
22
|
- **Connect Shapes**: Dynamic connectors with arrow styles, line styling, and routing (straight / orthogonal / curved).
|
|
@@ -30,6 +32,7 @@ Built using specific schema-level abstractions to handle the complex internal st
|
|
|
30
32
|
- **Color Palette**: Register named colors in the document's color table via `doc.addColor()` and look them up by index or hex value with `doc.getColors()` / `doc.getColorIndex()`.
|
|
31
33
|
- **Read Layers Back**: Enumerate existing layers from loaded files via `page.getLayers()`; delete a layer with `layer.delete()`, rename with `layer.rename()`, and read `layer.visible` / `layer.locked` state.
|
|
32
34
|
- **Group Traversal**: Access nested child shapes via `shape.getChildren()`, check `shape.isGroup`, and read `shape.type`.
|
|
35
|
+
- **Drawing Scale**: Set a real-world unit mapping on any page (`page.setDrawingScale()`), read it back (`page.getDrawingScale()`), or reset to 1:1 (`page.clearDrawingScale()`). Supports all common imperial and metric units.
|
|
33
36
|
|
|
34
37
|
Feature gaps are being tracked in [FEATURES.md](./FEATURES.md).
|
|
35
38
|
|
|
@@ -201,26 +204,53 @@ Save the modified document back to disk.
|
|
|
201
204
|
await doc.save('updated_diagram.vsdx');
|
|
202
205
|
```
|
|
203
206
|
|
|
204
|
-
#### 10.
|
|
205
|
-
|
|
207
|
+
#### 10. Masters & Stencils
|
|
208
|
+
|
|
209
|
+
**Create a master from scratch** — define a reusable shape with a built-in geometry, then stamp instances onto any page:
|
|
206
210
|
|
|
207
211
|
```typescript
|
|
208
|
-
|
|
209
|
-
const doc = await VisioDocument.load('template_with_masters.vsdx');
|
|
212
|
+
const doc = await VisioDocument.create();
|
|
210
213
|
const page = doc.pages[0];
|
|
211
214
|
|
|
212
|
-
//
|
|
213
|
-
//
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
height: 1,
|
|
220
|
-
|
|
215
|
+
// Define masters (geometries: 'rectangle' | 'ellipse' | 'diamond' |
|
|
216
|
+
// 'rounded-rectangle' | 'triangle' | 'parallelogram')
|
|
217
|
+
const boxMaster = doc.createMaster('Box');
|
|
218
|
+
const processMaster = doc.createMaster('Process', 'ellipse');
|
|
219
|
+
const decisionMaster = doc.createMaster('Decision', 'diamond');
|
|
220
|
+
|
|
221
|
+
// Stamp instances — geometry + styling come from the master definition
|
|
222
|
+
await page.addShape({ text: 'Start', x: 1, y: 1, width: 2, height: 1, masterId: processMaster.id });
|
|
223
|
+
await page.addShape({ text: 'Step 1', x: 4, y: 1, width: 2, height: 1, masterId: boxMaster.id });
|
|
224
|
+
await page.addShape({ text: 'Branch?', x: 7, y: 1, width: 2, height: 1, masterId: decisionMaster.id });
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**Import masters from a `.vssx` stencil file** — bring in an entire stencil and use any of its masters:
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
const doc = await VisioDocument.create();
|
|
231
|
+
|
|
232
|
+
// Path to a .vssx file, or pass a Buffer / ArrayBuffer directly
|
|
233
|
+
const stencilMasters = await doc.importMastersFromStencil('./Network_Shapes.vssx');
|
|
234
|
+
const router = stencilMasters.find(m => m.name === 'Router')!;
|
|
235
|
+
|
|
236
|
+
await doc.pages[0].addShape({
|
|
237
|
+
text: 'Router 1', x: 2, y: 2, width: 1, height: 1,
|
|
238
|
+
masterId: router.id,
|
|
221
239
|
});
|
|
240
|
+
```
|
|
222
241
|
|
|
223
|
-
|
|
242
|
+
**List masters already in the document** — useful after loading a `.vsdx` that was created in Visio:
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
const doc = await VisioDocument.load('existing_diagram.vsdx');
|
|
246
|
+
const masters = doc.getMasters();
|
|
247
|
+
// [{ id: '1', name: 'Box', nameU: 'Box', xmlPath: 'visio/masters/master1.xml' }, ...]
|
|
248
|
+
|
|
249
|
+
// Find and reuse a master by name
|
|
250
|
+
const routerMaster = masters.find(m => m.name === 'Router');
|
|
251
|
+
if (routerMaster) {
|
|
252
|
+
await doc.pages[0].addShape({ text: 'Router 2', x: 5, y: 5, width: 1, height: 1, masterId: routerMaster.id });
|
|
253
|
+
}
|
|
224
254
|
```
|
|
225
255
|
|
|
226
256
|
#### 11. Multi-Page Documents
|
|
@@ -682,6 +712,16 @@ const styles = doc.getStyles();
|
|
|
682
712
|
`StyleProps` supports: `fillColor`, `lineColor`, `lineWeight` (pt), `linePattern`, `fontColor`, `fontSize` (pt), `bold`, `italic`, `underline`, `strikethrough`, `fontFamily`, `horzAlign`, `verticalAlign`, `spaceBefore`, `spaceAfter`, `lineSpacing`, `textMarginTop/Bottom/Left/Right` (in).
|
|
683
713
|
Local shape properties always override inherited stylesheet values.
|
|
684
714
|
|
|
715
|
+
The alignment and style types are exported for use in typed consumers:
|
|
716
|
+
|
|
717
|
+
```typescript
|
|
718
|
+
import type { HorzAlign, VertAlign, ShapeStyle } from 'ts-visio';
|
|
719
|
+
|
|
720
|
+
const style: ShapeStyle = { horzAlign: 'center', verticalAlign: 'middle', bold: true };
|
|
721
|
+
const align: HorzAlign = 'justify'; // 'left' | 'center' | 'right' | 'justify'
|
|
722
|
+
const valign: VertAlign = 'bottom'; // 'top' | 'middle' | 'bottom'
|
|
723
|
+
```
|
|
724
|
+
|
|
685
725
|
#### 30. Reading Connectors Back
|
|
686
726
|
Enumerate connectors on a page — including those loaded from an existing `.vsdx` file — and inspect or delete them.
|
|
687
727
|
|
|
@@ -789,6 +829,47 @@ for (const g of groups) {
|
|
|
789
829
|
|
|
790
830
|
`getChildren()` returns `[]` for non-group shapes. Children are full `Shape` instances — all existing methods (`setStyle()`, `getProperties()`, `delete()`, etc.) work on them.
|
|
791
831
|
|
|
832
|
+
#### 33. Drawing Scale
|
|
833
|
+
Map page coordinates to real-world units. One `pageScale` `pageUnit` on the paper equals `drawingScale` `drawingUnit` in reality. Visio uses this to display rulers, grids, and shape dimensions in real-world terms.
|
|
834
|
+
|
|
835
|
+
```typescript
|
|
836
|
+
import type { LengthUnit, DrawingScaleInfo } from 'ts-visio';
|
|
837
|
+
|
|
838
|
+
// 1 inch on paper = 10 feet in the real world (architectural)
|
|
839
|
+
page.setDrawingScale(1, 'in', 10, 'ft');
|
|
840
|
+
|
|
841
|
+
// 1:100 metric (1 cm on paper = 100 cm = 1 m in reality)
|
|
842
|
+
page.setDrawingScale(1, 'cm', 100, 'cm');
|
|
843
|
+
|
|
844
|
+
// Engineering: 1 inch = 20 feet
|
|
845
|
+
page.setDrawingScale(1, 'in', 20, 'ft');
|
|
846
|
+
|
|
847
|
+
// Read the current scale back
|
|
848
|
+
const scale: DrawingScaleInfo | null = page.getDrawingScale();
|
|
849
|
+
if (scale) {
|
|
850
|
+
console.log(`${scale.pageScale} ${scale.pageUnit} = ${scale.drawingScale} ${scale.drawingUnit}`);
|
|
851
|
+
// → "1 in = 10 ft"
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
// Returns null when no custom scale is set
|
|
855
|
+
const freshPage = doc.pages[0];
|
|
856
|
+
console.log(freshPage.getDrawingScale()); // null
|
|
857
|
+
|
|
858
|
+
// Reset to 1:1 (no scale)
|
|
859
|
+
page.clearDrawingScale();
|
|
860
|
+
console.log(page.getDrawingScale()); // null
|
|
861
|
+
|
|
862
|
+
// All methods are chainable
|
|
863
|
+
page.setDrawingScale(1, 'mm', 1000, 'mm')
|
|
864
|
+
.setNamedSize('A1'); // combine with page size changes
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
Supported `LengthUnit` values:
|
|
868
|
+
- Imperial: `'in'` (inches), `'ft'` (feet), `'yd'` (yards), `'mi'` (miles)
|
|
869
|
+
- Metric: `'mm'`, `'cm'`, `'m'`, `'km'`
|
|
870
|
+
|
|
871
|
+
The drawing scale does not affect the internal coordinate system — shape positions and sizes are still specified in page-inches. The scale is purely a display/annotation mapping applied by Visio's ruler and grid.
|
|
872
|
+
|
|
792
873
|
---
|
|
793
874
|
|
|
794
875
|
## Examples
|
package/dist/Layer.d.ts
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import { VisioPackage } from './VisioPackage';
|
|
2
2
|
import { ShapeModifier } from './ShapeModifier';
|
|
3
|
+
/**
|
|
4
|
+
* A named display layer on a Visio page.
|
|
5
|
+
*
|
|
6
|
+
* Layers control the visibility and printability of groups of shapes.
|
|
7
|
+
* Obtain instances via `page.getLayers()` or `page.addLayer()`.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const annotations = await page.addLayer('Annotations');
|
|
12
|
+
* ann.setVisible(false); // hide all shapes on this layer
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @category Layers
|
|
16
|
+
*/
|
|
3
17
|
export declare class Layer {
|
|
4
18
|
name: string;
|
|
5
19
|
index: number;
|
package/dist/Layer.js
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Layer = void 0;
|
|
4
4
|
const ShapeModifier_1 = require("./ShapeModifier");
|
|
5
|
+
/**
|
|
6
|
+
* A named display layer on a Visio page.
|
|
7
|
+
*
|
|
8
|
+
* Layers control the visibility and printability of groups of shapes.
|
|
9
|
+
* Obtain instances via `page.getLayers()` or `page.addLayer()`.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const annotations = await page.addLayer('Annotations');
|
|
14
|
+
* ann.setVisible(false); // hide all shapes on this layer
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @category Layers
|
|
18
|
+
*/
|
|
5
19
|
class Layer {
|
|
6
20
|
constructor(name, index, pageId, pkg, modifier, _visible = true, _locked = false) {
|
|
7
21
|
this.name = name;
|
package/dist/Page.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { VisioPage, ConnectorStyle, PageOrientation, PageSizeName, ConnectionTarget } from './types/VisioTypes';
|
|
1
|
+
import { VisioPage, ConnectorStyle, PageOrientation, PageSizeName, ConnectionTarget, DrawingScaleInfo, LengthUnit } from './types/VisioTypes';
|
|
2
2
|
import { Connector } from './Connector';
|
|
3
3
|
import { VisioPackage } from './VisioPackage';
|
|
4
4
|
import { ShapeModifier } from './ShapeModifier';
|
|
@@ -7,6 +7,21 @@ import { Shape } from './Shape';
|
|
|
7
7
|
import { MediaManager } from './core/MediaManager';
|
|
8
8
|
import { RelsManager } from './core/RelsManager';
|
|
9
9
|
import { Layer } from './Layer';
|
|
10
|
+
/**
|
|
11
|
+
* Represents a single page (tab) inside a Visio document.
|
|
12
|
+
*
|
|
13
|
+
* Obtain a `Page` instance from {@link VisioDocument.pages},
|
|
14
|
+
* {@link VisioDocument.addPage}, or {@link VisioDocument.getPage}.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const doc = await VisioDocument.create();
|
|
19
|
+
* const page = doc.pages[0];
|
|
20
|
+
* await page.addShape({ text: 'Hello', x: 1, y: 1, width: 2, height: 1 });
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @category Pages
|
|
24
|
+
*/
|
|
10
25
|
export declare class Page {
|
|
11
26
|
private internalPage;
|
|
12
27
|
private pkg;
|
|
@@ -39,6 +54,10 @@ export declare class Page {
|
|
|
39
54
|
* Swaps width and height when the current orientation does not match the requested one.
|
|
40
55
|
*/
|
|
41
56
|
setOrientation(orientation: PageOrientation): this;
|
|
57
|
+
/**
|
|
58
|
+
* Return all top-level shapes on the page.
|
|
59
|
+
* Group children are not included; use {@link findShapes} to search the entire shape tree.
|
|
60
|
+
*/
|
|
42
61
|
getShapes(): Shape[];
|
|
43
62
|
/**
|
|
44
63
|
* Find a shape by its ID anywhere on the page, including shapes nested inside groups.
|
|
@@ -50,6 +69,29 @@ export declare class Page {
|
|
|
50
69
|
* the predicate. Equivalent to getAllShapes().filter(predicate).
|
|
51
70
|
*/
|
|
52
71
|
findShapes(predicate: (shape: Shape) => boolean): Shape[];
|
|
72
|
+
/**
|
|
73
|
+
* Add a new shape to the page and return a {@link Shape} handle to it.
|
|
74
|
+
*
|
|
75
|
+
* @param props Visual and text properties for the new shape.
|
|
76
|
+
* All geometry fields (`x`, `y`, `width`, `height`) are in inches.
|
|
77
|
+
* @param parentId Optional ID of an existing group shape to nest the new shape inside.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* // Plain rectangle
|
|
82
|
+
* const box = await page.addShape({ text: 'Server', x: 2, y: 3, width: 2, height: 1 });
|
|
83
|
+
*
|
|
84
|
+
* // Ellipse with styling
|
|
85
|
+
* await page.addShape({
|
|
86
|
+
* text: 'Start', x: 1, y: 1, width: 1.5, height: 1.5,
|
|
87
|
+
* geometry: 'ellipse', fillColor: '#4472C4', fontColor: '#ffffff',
|
|
88
|
+
* });
|
|
89
|
+
*
|
|
90
|
+
* // Master instance (shape defined by a reusable master)
|
|
91
|
+
* const m = doc.createMaster('Router', 'ellipse');
|
|
92
|
+
* await page.addShape({ text: '', x: 4, y: 2, width: 1, height: 1, masterId: m.id });
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
53
95
|
addShape(props: NewShapeProps, parentId?: string): Promise<Shape>;
|
|
54
96
|
/**
|
|
55
97
|
* Return all connector shapes on the page.
|
|
@@ -57,19 +99,50 @@ export declare class Page {
|
|
|
57
99
|
* and a `delete()` method to remove the connector.
|
|
58
100
|
*/
|
|
59
101
|
getConnectors(): Connector[];
|
|
102
|
+
/**
|
|
103
|
+
* Draw a connector (line/arrow) between two shapes on this page.
|
|
104
|
+
*
|
|
105
|
+
* @param fromShape Source shape.
|
|
106
|
+
* @param toShape Target shape.
|
|
107
|
+
* @param beginArrow Arrow head at the source end (use {@link ArrowHeads} constants).
|
|
108
|
+
* @param endArrow Arrow head at the target end (use {@link ArrowHeads} constants).
|
|
109
|
+
* @param style Line color, weight, pattern, and routing style.
|
|
110
|
+
* @param fromPort Named connection point on the source shape (e.g. `'Right'`).
|
|
111
|
+
* @param toPort Named connection point on the target shape (e.g. `'Left'`).
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* import { ArrowHeads } from 'ts-visio';
|
|
116
|
+
* const a = await page.addShape({ text: 'A', x: 1, y: 1, width: 1, height: 1 });
|
|
117
|
+
* const b = await page.addShape({ text: 'B', x: 4, y: 1, width: 1, height: 1 });
|
|
118
|
+
* await page.connectShapes(a, b, ArrowHeads.None, ArrowHeads.OpenArrow,
|
|
119
|
+
* { lineColor: '#333333', routing: 'orthogonal' });
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
60
122
|
connectShapes(fromShape: Shape, toShape: Shape, beginArrow?: string, endArrow?: string, style?: ConnectorStyle, fromPort?: ConnectionTarget, toPort?: ConnectionTarget): Promise<void>;
|
|
123
|
+
/**
|
|
124
|
+
* Embed an image on the page and return the resulting Foreign shape.
|
|
125
|
+
*
|
|
126
|
+
* @param data Raw image bytes (PNG, JPEG, GIF, BMP, or TIFF).
|
|
127
|
+
* @param name Filename used to store the image inside the archive (e.g. `'logo.png'`).
|
|
128
|
+
* @param x Horizontal pin position in inches.
|
|
129
|
+
* @param y Vertical pin position in inches.
|
|
130
|
+
* @param width Display width in inches.
|
|
131
|
+
* @param height Display height in inches.
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* import fs from 'fs';
|
|
136
|
+
* const imgBuffer = fs.readFileSync('./logo.png');
|
|
137
|
+
* await page.addImage(imgBuffer, 'logo.png', 1, 1, 2, 1);
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
61
140
|
addImage(data: Buffer, name: string, x: number, y: number, width: number, height: number): Promise<Shape>;
|
|
62
141
|
addContainer(props: NewShapeProps): Promise<Shape>;
|
|
63
142
|
addList(props: NewShapeProps, direction?: 'vertical' | 'horizontal'): Promise<Shape>;
|
|
64
|
-
/**
|
|
65
|
-
* Creates a Swimlane Pool (which is technically a Vertical List of Containers).
|
|
66
|
-
* @param props Visual properties
|
|
67
|
-
*/
|
|
143
|
+
/** Creates a Swimlane Pool (a vertical List of Containers). */
|
|
68
144
|
addSwimlanePool(props: NewShapeProps): Promise<Shape>;
|
|
69
|
-
/**
|
|
70
|
-
* Creates a Swimlane Lane (which is technically a Container).
|
|
71
|
-
* @param props Visual properties
|
|
72
|
-
*/
|
|
145
|
+
/** Creates a Swimlane Lane (a Container inside a pool). */
|
|
73
146
|
addSwimlaneLane(props: NewShapeProps): Promise<Shape>;
|
|
74
147
|
addTable(x: number, y: number, title: string, columns: string[]): Promise<Shape>;
|
|
75
148
|
addLayer(name: string, options?: {
|
|
@@ -86,6 +159,30 @@ export declare class Page {
|
|
|
86
159
|
* // [{ name: 'Background', index: 0, visible: true, locked: false }, ...]
|
|
87
160
|
*/
|
|
88
161
|
getLayers(): Layer[];
|
|
162
|
+
/**
|
|
163
|
+
* Return the current drawing scale, or `null` if no custom scale is set (1:1).
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* const scale = page.getDrawingScale();
|
|
167
|
+
* // { pageScale: 1, pageUnit: 'in', drawingScale: 10, drawingUnit: 'ft' }
|
|
168
|
+
*/
|
|
169
|
+
getDrawingScale(): DrawingScaleInfo | null;
|
|
170
|
+
/**
|
|
171
|
+
* Set a custom drawing scale for the page.
|
|
172
|
+
* One `pageScale` `pageUnit` on paper equals `drawingScale` `drawingUnit` in the real world.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* // 1 inch on paper = 10 feet in the real world
|
|
176
|
+
* page.setDrawingScale(1, 'in', 10, 'ft');
|
|
177
|
+
*
|
|
178
|
+
* // 1:100 metric
|
|
179
|
+
* page.setDrawingScale(1, 'cm', 100, 'cm');
|
|
180
|
+
*/
|
|
181
|
+
setDrawingScale(pageScale: number, pageUnit: LengthUnit, drawingScale: number, drawingUnit: LengthUnit): this;
|
|
182
|
+
/**
|
|
183
|
+
* Remove any custom drawing scale, reverting the page to a 1:1 ratio.
|
|
184
|
+
*/
|
|
185
|
+
clearDrawingScale(): this;
|
|
89
186
|
/** @internal Used by VisioDocument.renamePage() to keep in-memory state in sync. */
|
|
90
187
|
_updateName(newName: string): void;
|
|
91
188
|
}
|
package/dist/Page.js
CHANGED
|
@@ -10,6 +10,23 @@ const MediaManager_1 = require("./core/MediaManager");
|
|
|
10
10
|
const RelsManager_1 = require("./core/RelsManager");
|
|
11
11
|
const StubHelpers_1 = require("./utils/StubHelpers");
|
|
12
12
|
const Layer_1 = require("./Layer");
|
|
13
|
+
const TablePattern_1 = require("./diagrams/TablePattern");
|
|
14
|
+
const SwimlanePattern_1 = require("./diagrams/SwimlanePattern");
|
|
15
|
+
/**
|
|
16
|
+
* Represents a single page (tab) inside a Visio document.
|
|
17
|
+
*
|
|
18
|
+
* Obtain a `Page` instance from {@link VisioDocument.pages},
|
|
19
|
+
* {@link VisioDocument.addPage}, or {@link VisioDocument.getPage}.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const doc = await VisioDocument.create();
|
|
24
|
+
* const page = doc.pages[0];
|
|
25
|
+
* await page.addShape({ text: 'Hello', x: 1, y: 1, width: 2, height: 1 });
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @category Pages
|
|
29
|
+
*/
|
|
13
30
|
class Page {
|
|
14
31
|
constructor(internalPage, pkg, media, rels, modifier) {
|
|
15
32
|
this.internalPage = internalPage;
|
|
@@ -73,6 +90,10 @@ class Page {
|
|
|
73
90
|
}
|
|
74
91
|
return this;
|
|
75
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Return all top-level shapes on the page.
|
|
95
|
+
* Group children are not included; use {@link findShapes} to search the entire shape tree.
|
|
96
|
+
*/
|
|
76
97
|
getShapes() {
|
|
77
98
|
const reader = new ShapeReader_1.ShapeReader(this.pkg);
|
|
78
99
|
try {
|
|
@@ -106,6 +127,29 @@ class Page {
|
|
|
106
127
|
.map(s => new Shape_1.Shape(s, this.id, this.pkg, this.modifier))
|
|
107
128
|
.filter(predicate);
|
|
108
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Add a new shape to the page and return a {@link Shape} handle to it.
|
|
132
|
+
*
|
|
133
|
+
* @param props Visual and text properties for the new shape.
|
|
134
|
+
* All geometry fields (`x`, `y`, `width`, `height`) are in inches.
|
|
135
|
+
* @param parentId Optional ID of an existing group shape to nest the new shape inside.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* // Plain rectangle
|
|
140
|
+
* const box = await page.addShape({ text: 'Server', x: 2, y: 3, width: 2, height: 1 });
|
|
141
|
+
*
|
|
142
|
+
* // Ellipse with styling
|
|
143
|
+
* await page.addShape({
|
|
144
|
+
* text: 'Start', x: 1, y: 1, width: 1.5, height: 1.5,
|
|
145
|
+
* geometry: 'ellipse', fillColor: '#4472C4', fontColor: '#ffffff',
|
|
146
|
+
* });
|
|
147
|
+
*
|
|
148
|
+
* // Master instance (shape defined by a reusable master)
|
|
149
|
+
* const m = doc.createMaster('Router', 'ellipse');
|
|
150
|
+
* await page.addShape({ text: '', x: 4, y: 2, width: 1, height: 1, masterId: m.id });
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
109
153
|
async addShape(props, parentId) {
|
|
110
154
|
const newId = await this.modifier.addShape(this.id, props, parentId);
|
|
111
155
|
// Return a fresh Shape object representing the new shape
|
|
@@ -142,15 +186,49 @@ class Page {
|
|
|
142
186
|
return [];
|
|
143
187
|
}
|
|
144
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Draw a connector (line/arrow) between two shapes on this page.
|
|
191
|
+
*
|
|
192
|
+
* @param fromShape Source shape.
|
|
193
|
+
* @param toShape Target shape.
|
|
194
|
+
* @param beginArrow Arrow head at the source end (use {@link ArrowHeads} constants).
|
|
195
|
+
* @param endArrow Arrow head at the target end (use {@link ArrowHeads} constants).
|
|
196
|
+
* @param style Line color, weight, pattern, and routing style.
|
|
197
|
+
* @param fromPort Named connection point on the source shape (e.g. `'Right'`).
|
|
198
|
+
* @param toPort Named connection point on the target shape (e.g. `'Left'`).
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```typescript
|
|
202
|
+
* import { ArrowHeads } from 'ts-visio';
|
|
203
|
+
* const a = await page.addShape({ text: 'A', x: 1, y: 1, width: 1, height: 1 });
|
|
204
|
+
* const b = await page.addShape({ text: 'B', x: 4, y: 1, width: 1, height: 1 });
|
|
205
|
+
* await page.connectShapes(a, b, ArrowHeads.None, ArrowHeads.OpenArrow,
|
|
206
|
+
* { lineColor: '#333333', routing: 'orthogonal' });
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
145
209
|
async connectShapes(fromShape, toShape, beginArrow, endArrow, style, fromPort, toPort) {
|
|
146
210
|
await this.modifier.addConnector(this.id, fromShape.id, toShape.id, beginArrow, endArrow, style, fromPort, toPort);
|
|
147
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Embed an image on the page and return the resulting Foreign shape.
|
|
214
|
+
*
|
|
215
|
+
* @param data Raw image bytes (PNG, JPEG, GIF, BMP, or TIFF).
|
|
216
|
+
* @param name Filename used to store the image inside the archive (e.g. `'logo.png'`).
|
|
217
|
+
* @param x Horizontal pin position in inches.
|
|
218
|
+
* @param y Vertical pin position in inches.
|
|
219
|
+
* @param width Display width in inches.
|
|
220
|
+
* @param height Display height in inches.
|
|
221
|
+
*
|
|
222
|
+
* @example
|
|
223
|
+
* ```typescript
|
|
224
|
+
* import fs from 'fs';
|
|
225
|
+
* const imgBuffer = fs.readFileSync('./logo.png');
|
|
226
|
+
* await page.addImage(imgBuffer, 'logo.png', 1, 1, 2, 1);
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
148
229
|
async addImage(data, name, x, y, width, height) {
|
|
149
|
-
// 1. Upload Media
|
|
150
230
|
const mediaPath = this.media.addMedia(name, data);
|
|
151
|
-
// 2. Link Page to Media (use resolved path so loaded files work correctly)
|
|
152
231
|
const rId = await this.rels.addImageRelationship(this.pagePath, mediaPath);
|
|
153
|
-
// 3. Create Shape
|
|
154
232
|
const newId = await this.modifier.addShape(this.id, {
|
|
155
233
|
text: '',
|
|
156
234
|
x, y, width, height,
|
|
@@ -197,72 +275,16 @@ class Page {
|
|
|
197
275
|
});
|
|
198
276
|
return new Shape_1.Shape(internalStub, this.id, this.pkg, this.modifier);
|
|
199
277
|
}
|
|
200
|
-
/**
|
|
201
|
-
* Creates a Swimlane Pool (which is technically a Vertical List of Containers).
|
|
202
|
-
* @param props Visual properties
|
|
203
|
-
*/
|
|
278
|
+
/** Creates a Swimlane Pool (a vertical List of Containers). */
|
|
204
279
|
async addSwimlanePool(props) {
|
|
205
|
-
|
|
206
|
-
return this.addList(props, 'vertical');
|
|
280
|
+
return SwimlanePattern_1.SwimlanePattern.addPool(this, props);
|
|
207
281
|
}
|
|
208
|
-
/**
|
|
209
|
-
* Creates a Swimlane Lane (which is technically a Container).
|
|
210
|
-
* @param props Visual properties
|
|
211
|
-
*/
|
|
282
|
+
/** Creates a Swimlane Lane (a Container inside a pool). */
|
|
212
283
|
async addSwimlaneLane(props) {
|
|
213
|
-
|
|
214
|
-
return this.addContainer(props);
|
|
284
|
+
return SwimlanePattern_1.SwimlanePattern.addLane(this, props);
|
|
215
285
|
}
|
|
216
286
|
async addTable(x, y, title, columns) {
|
|
217
|
-
|
|
218
|
-
// Dimensions
|
|
219
|
-
const width = 3;
|
|
220
|
-
const headerHeight = 0.5;
|
|
221
|
-
const lineItemHeight = 0.25;
|
|
222
|
-
const bodyHeight = Math.max(0.5, columns.length * lineItemHeight + 0.1); // Min height
|
|
223
|
-
const totalHeight = headerHeight + bodyHeight;
|
|
224
|
-
// 1. Create Main Group Shape (Transparent container)
|
|
225
|
-
// Group Logic:
|
|
226
|
-
// Positioned at (x, y) on the Page.
|
|
227
|
-
// Size encapsulates both header and body.
|
|
228
|
-
const groupShape = await this.addShape({
|
|
229
|
-
text: '', // No text on container
|
|
230
|
-
x: x,
|
|
231
|
-
y: y,
|
|
232
|
-
width: width,
|
|
233
|
-
height: totalHeight,
|
|
234
|
-
type: 'Group'
|
|
235
|
-
});
|
|
236
|
-
// 2. Header Shape (Inside Group)
|
|
237
|
-
// Coords relative to Group (Bottom-Left is 0,0)
|
|
238
|
-
// Header is at top. Center X is Width/2.
|
|
239
|
-
// Center Y = BodyHeight + (HeaderHeight/2)
|
|
240
|
-
const headerCenterY = bodyHeight + (headerHeight / 2);
|
|
241
|
-
await this.addShape({
|
|
242
|
-
text: title,
|
|
243
|
-
x: width / 2, // Relative PinX
|
|
244
|
-
y: headerCenterY, // Relative PinY
|
|
245
|
-
width: width,
|
|
246
|
-
height: headerHeight,
|
|
247
|
-
fillColor: '#DDDDDD',
|
|
248
|
-
bold: true
|
|
249
|
-
}, groupShape.id);
|
|
250
|
-
// 3. Body Shape (Inside Group)
|
|
251
|
-
// Bottom part. Center X is Width/2.
|
|
252
|
-
// Center Y = BodyHeight/2
|
|
253
|
-
const bodyCenterY = bodyHeight / 2;
|
|
254
|
-
const bodyText = columns.join('\n');
|
|
255
|
-
await this.addShape({
|
|
256
|
-
text: bodyText,
|
|
257
|
-
x: width / 2, // Relative PinX
|
|
258
|
-
y: bodyCenterY, // Relative PinY
|
|
259
|
-
width: width,
|
|
260
|
-
height: bodyHeight,
|
|
261
|
-
fillColor: '#FFFFFF',
|
|
262
|
-
fontColor: '#000000'
|
|
263
|
-
}, groupShape.id);
|
|
264
|
-
// Return the Group Shape
|
|
265
|
-
return groupShape;
|
|
287
|
+
return TablePattern_1.TablePattern.add(this, x, y, title, columns);
|
|
266
288
|
}
|
|
267
289
|
async addLayer(name, options) {
|
|
268
290
|
const info = await this.modifier.addLayer(this.id, name, options);
|
|
@@ -280,6 +302,38 @@ class Page {
|
|
|
280
302
|
const infos = this.modifier.getPageLayers(this.id);
|
|
281
303
|
return infos.map(l => new Layer_1.Layer(l.name, l.index, this.id, this.pkg, this.modifier, l.visible, l.locked));
|
|
282
304
|
}
|
|
305
|
+
/**
|
|
306
|
+
* Return the current drawing scale, or `null` if no custom scale is set (1:1).
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* const scale = page.getDrawingScale();
|
|
310
|
+
* // { pageScale: 1, pageUnit: 'in', drawingScale: 10, drawingUnit: 'ft' }
|
|
311
|
+
*/
|
|
312
|
+
getDrawingScale() {
|
|
313
|
+
return this.modifier.getDrawingScale(this.id);
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Set a custom drawing scale for the page.
|
|
317
|
+
* One `pageScale` `pageUnit` on paper equals `drawingScale` `drawingUnit` in the real world.
|
|
318
|
+
*
|
|
319
|
+
* @example
|
|
320
|
+
* // 1 inch on paper = 10 feet in the real world
|
|
321
|
+
* page.setDrawingScale(1, 'in', 10, 'ft');
|
|
322
|
+
*
|
|
323
|
+
* // 1:100 metric
|
|
324
|
+
* page.setDrawingScale(1, 'cm', 100, 'cm');
|
|
325
|
+
*/
|
|
326
|
+
setDrawingScale(pageScale, pageUnit, drawingScale, drawingUnit) {
|
|
327
|
+
this.modifier.setDrawingScale(this.id, pageScale, pageUnit, drawingScale, drawingUnit);
|
|
328
|
+
return this;
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Remove any custom drawing scale, reverting the page to a 1:1 ratio.
|
|
332
|
+
*/
|
|
333
|
+
clearDrawingScale() {
|
|
334
|
+
this.modifier.clearDrawingScale(this.id);
|
|
335
|
+
return this;
|
|
336
|
+
}
|
|
283
337
|
/** @internal Used by VisioDocument.renamePage() to keep in-memory state in sync. */
|
|
284
338
|
_updateName(newName) {
|
|
285
339
|
this.internalPage.Name = newName;
|
package/dist/Shape.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { VisioShape, ConnectorStyle, ConnectionTarget, ConnectionPointDef } from './types/VisioTypes';
|
|
1
|
+
import { VisioShape, ConnectorStyle, ConnectionTarget, ConnectionPointDef, ShapeStyle } from './types/VisioTypes';
|
|
2
2
|
import { VisioPackage } from './VisioPackage';
|
|
3
|
-
import { ShapeModifier
|
|
3
|
+
import { ShapeModifier } from './ShapeModifier';
|
|
4
4
|
import { VisioPropType } from './types/VisioTypes';
|
|
5
5
|
import { Layer } from './Layer';
|
|
6
6
|
export interface ShapeData {
|
|
@@ -15,6 +15,21 @@ export interface ShapeHyperlink {
|
|
|
15
15
|
description?: string;
|
|
16
16
|
newWindow: boolean;
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* A handle to a single shape on a Visio page.
|
|
20
|
+
*
|
|
21
|
+
* Obtain instances via {@link Page.addShape}, {@link Page.getShapes},
|
|
22
|
+
* {@link Page.getShapeById}, or {@link Page.findShapes}.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const shape = await page.addShape({ text: 'Box', x: 1, y: 1, width: 2, height: 1 });
|
|
27
|
+
* await shape.setStyle({ fillColor: '#4472C4', fontColor: '#ffffff', bold: true });
|
|
28
|
+
* console.log(shape.id, shape.x, shape.y);
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @category Shapes
|
|
32
|
+
*/
|
|
18
33
|
export declare class Shape {
|
|
19
34
|
private internalShape;
|
|
20
35
|
private pageId;
|
package/dist/Shape.js
CHANGED
|
@@ -8,6 +8,21 @@ const VisioConstants_1 = require("./core/VisioConstants");
|
|
|
8
8
|
function fmtCoord(n) {
|
|
9
9
|
return parseFloat(n.toFixed(10)).toString();
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* A handle to a single shape on a Visio page.
|
|
13
|
+
*
|
|
14
|
+
* Obtain instances via {@link Page.addShape}, {@link Page.getShapes},
|
|
15
|
+
* {@link Page.getShapeById}, or {@link Page.findShapes}.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const shape = await page.addShape({ text: 'Box', x: 1, y: 1, width: 2, height: 1 });
|
|
20
|
+
* await shape.setStyle({ fillColor: '#4472C4', fontColor: '#ffffff', bold: true });
|
|
21
|
+
* console.log(shape.id, shape.x, shape.y);
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @category Shapes
|
|
25
|
+
*/
|
|
11
26
|
class Shape {
|
|
12
27
|
constructor(internalShape, pageId, pkg, modifier) {
|
|
13
28
|
this.internalShape = internalShape;
|