ts-visio 1.10.0 → 1.11.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/dist/Page.js +1 -0
- package/dist/Shape.d.ts +24 -0
- package/dist/Shape.js +33 -1
- package/dist/ShapeModifier.d.ts +6 -0
- package/dist/ShapeModifier.js +31 -21
- package/dist/ShapeReader.d.ts +6 -0
- package/dist/ShapeReader.js +29 -3
- package/dist/core/VisioConstants.d.ts +29 -0
- package/dist/core/VisioConstants.js +30 -1
- package/dist/core/VisioValidator.js +2 -1
- package/dist/shapes/ShapeBuilder.js +3 -2
- package/dist/utils/StubHelpers.d.ts +1 -0
- package/dist/utils/StubHelpers.js +2 -1
- package/package.json +1 -1
package/dist/Page.js
CHANGED
|
@@ -113,6 +113,7 @@ class Page {
|
|
|
113
113
|
// In a real scenario, we might want to re-read the shape from disk to get full defaults
|
|
114
114
|
const internalStub = (0, StubHelpers_1.createVisioShapeStub)({
|
|
115
115
|
ID: newId,
|
|
116
|
+
Type: props.type,
|
|
116
117
|
Text: props.text,
|
|
117
118
|
Cells: {
|
|
118
119
|
'Width': props.width,
|
package/dist/Shape.d.ts
CHANGED
|
@@ -23,6 +23,16 @@ export declare class Shape {
|
|
|
23
23
|
constructor(internalShape: VisioShape, pageId: string, pkg: VisioPackage, modifier?: ShapeModifier);
|
|
24
24
|
get id(): string;
|
|
25
25
|
get name(): string;
|
|
26
|
+
/**
|
|
27
|
+
* The shape's Type attribute — `'Group'` for group shapes, `'Shape'` (or `undefined`
|
|
28
|
+
* normalised to `'Shape'`) for regular shapes.
|
|
29
|
+
*/
|
|
30
|
+
get type(): string;
|
|
31
|
+
/**
|
|
32
|
+
* `true` if this shape is a Group (i.e. it can contain nested child shapes).
|
|
33
|
+
* Use `shape.getChildren()` to retrieve those children.
|
|
34
|
+
*/
|
|
35
|
+
get isGroup(): boolean;
|
|
26
36
|
get text(): string;
|
|
27
37
|
setText(newText: string): Promise<void>;
|
|
28
38
|
get width(): number;
|
|
@@ -73,6 +83,20 @@ export declare class Shape {
|
|
|
73
83
|
* Returns an empty array if the shape has no layer assignment.
|
|
74
84
|
*/
|
|
75
85
|
getLayerIndices(): number[];
|
|
86
|
+
/**
|
|
87
|
+
* Return the direct child shapes of this group.
|
|
88
|
+
* Returns an empty array for non-group shapes or groups with no children.
|
|
89
|
+
*
|
|
90
|
+
* Only direct children are returned — grandchildren are accessible by calling
|
|
91
|
+
* `getChildren()` on the child shape.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* const group = await page.addShape({ text: 'G', x: 5, y: 5, width: 4, height: 4, type: 'Group' });
|
|
95
|
+
* await page.addShape({ text: 'Child A', x: 1, y: 1, width: 1, height: 1 }, group.id);
|
|
96
|
+
* await page.addShape({ text: 'Child B', x: 2, y: 1, width: 1, height: 1 }, group.id);
|
|
97
|
+
* group.getChildren(); // → [Shape('Child A'), Shape('Child B')]
|
|
98
|
+
*/
|
|
99
|
+
getChildren(): Shape[];
|
|
76
100
|
/** Current rotation angle in degrees (0 if no Angle cell is set). */
|
|
77
101
|
get angle(): number;
|
|
78
102
|
/**
|
package/dist/Shape.js
CHANGED
|
@@ -3,6 +3,7 @@ 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
|
+
const VisioConstants_1 = require("./core/VisioConstants");
|
|
6
7
|
/** Round a coordinate to 10 decimal places to prevent float-to-string-to-float precision drift. */
|
|
7
8
|
function fmtCoord(n) {
|
|
8
9
|
return parseFloat(n.toFixed(10)).toString();
|
|
@@ -20,6 +21,20 @@ class Shape {
|
|
|
20
21
|
get name() {
|
|
21
22
|
return this.internalShape.Name;
|
|
22
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* The shape's Type attribute — `'Group'` for group shapes, `'Shape'` (or `undefined`
|
|
26
|
+
* normalised to `'Shape'`) for regular shapes.
|
|
27
|
+
*/
|
|
28
|
+
get type() {
|
|
29
|
+
return this.internalShape.Type ?? 'Shape';
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* `true` if this shape is a Group (i.e. it can contain nested child shapes).
|
|
33
|
+
* Use `shape.getChildren()` to retrieve those children.
|
|
34
|
+
*/
|
|
35
|
+
get isGroup() {
|
|
36
|
+
return this.internalShape.Type === VisioConstants_1.SHAPE_TYPES.Group;
|
|
37
|
+
}
|
|
23
38
|
get text() {
|
|
24
39
|
return this.internalShape.Text || '';
|
|
25
40
|
}
|
|
@@ -139,6 +154,23 @@ class Shape {
|
|
|
139
154
|
getLayerIndices() {
|
|
140
155
|
return this.modifier.getShapeLayerIndices(this.pageId, this.id);
|
|
141
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* Return the direct child shapes of this group.
|
|
159
|
+
* Returns an empty array for non-group shapes or groups with no children.
|
|
160
|
+
*
|
|
161
|
+
* Only direct children are returned — grandchildren are accessible by calling
|
|
162
|
+
* `getChildren()` on the child shape.
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* const group = await page.addShape({ text: 'G', x: 5, y: 5, width: 4, height: 4, type: 'Group' });
|
|
166
|
+
* await page.addShape({ text: 'Child A', x: 1, y: 1, width: 1, height: 1 }, group.id);
|
|
167
|
+
* await page.addShape({ text: 'Child B', x: 2, y: 1, width: 1, height: 1 }, group.id);
|
|
168
|
+
* group.getChildren(); // → [Shape('Child A'), Shape('Child B')]
|
|
169
|
+
*/
|
|
170
|
+
getChildren() {
|
|
171
|
+
const children = this.modifier.getShapeChildren(this.pageId, this.id);
|
|
172
|
+
return children.map(c => new Shape(c, this.pageId, this.pkg, this.modifier));
|
|
173
|
+
}
|
|
142
174
|
/** Current rotation angle in degrees (0 if no Angle cell is set). */
|
|
143
175
|
get angle() {
|
|
144
176
|
const cell = this.internalShape.Cells['Angle'];
|
|
@@ -185,7 +217,7 @@ class Shape {
|
|
|
185
217
|
return this;
|
|
186
218
|
}
|
|
187
219
|
async addMember(memberShape) {
|
|
188
|
-
await this.modifier.addRelationship(this.pageId, this.id, memberShape.id,
|
|
220
|
+
await this.modifier.addRelationship(this.pageId, this.id, memberShape.id, VisioConstants_1.STRUCT_RELATIONSHIP_TYPES.Container);
|
|
189
221
|
return this;
|
|
190
222
|
}
|
|
191
223
|
async addListItem(item) {
|
package/dist/ShapeModifier.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { VisioPackage } from './VisioPackage';
|
|
|
2
2
|
import { HorzAlign, VertAlign } from './utils/StyleHelpers';
|
|
3
3
|
import { NewShapeProps, ConnectorStyle, ConnectionTarget, ConnectionPointDef } from './types/VisioTypes';
|
|
4
4
|
import type { ShapeData, ShapeHyperlink } from './Shape';
|
|
5
|
+
import type { VisioShape } from './types/VisioTypes';
|
|
5
6
|
export declare class ShapeModifier {
|
|
6
7
|
private pkg;
|
|
7
8
|
addContainer(pageId: string, props: NewShapeProps): Promise<string>;
|
|
@@ -128,6 +129,11 @@ export declare class ShapeModifier {
|
|
|
128
129
|
* Returns an empty array if the shape has no layer assignment.
|
|
129
130
|
*/
|
|
130
131
|
getShapeLayerIndices(pageId: string, shapeId: string): number[];
|
|
132
|
+
/**
|
|
133
|
+
* Return the direct child shapes of a group or container shape.
|
|
134
|
+
* Returns an empty array for non-group shapes or shapes with no children.
|
|
135
|
+
*/
|
|
136
|
+
getShapeChildren(pageId: string, shapeId: string): VisioShape[];
|
|
131
137
|
}
|
|
132
138
|
export interface ShapeStyle {
|
|
133
139
|
fillColor?: string;
|
package/dist/ShapeModifier.js
CHANGED
|
@@ -6,6 +6,7 @@ const StyleHelpers_1 = require("./utils/StyleHelpers");
|
|
|
6
6
|
const VisioConstants_1 = require("./core/VisioConstants");
|
|
7
7
|
const VisioTypes_1 = require("./types/VisioTypes");
|
|
8
8
|
const ConnectionPointBuilder_1 = require("./shapes/ConnectionPointBuilder");
|
|
9
|
+
const ShapeReader_1 = require("./ShapeReader");
|
|
9
10
|
const ForeignShapeBuilder_1 = require("./shapes/ForeignShapeBuilder");
|
|
10
11
|
const ShapeBuilder_1 = require("./shapes/ShapeBuilder");
|
|
11
12
|
const ConnectorBuilder_1 = require("./shapes/ConnectorBuilder");
|
|
@@ -230,9 +231,9 @@ class ShapeModifier {
|
|
|
230
231
|
if (!Array.isArray(shape.Section))
|
|
231
232
|
shape.Section = [shape.Section];
|
|
232
233
|
// Find or create Connection section
|
|
233
|
-
let connSection = shape.Section.find((s) => s['@_N'] ===
|
|
234
|
+
let connSection = shape.Section.find((s) => s['@_N'] === VisioConstants_1.SECTION_NAMES.Connection);
|
|
234
235
|
if (!connSection) {
|
|
235
|
-
connSection = { '@_N':
|
|
236
|
+
connSection = { '@_N': VisioConstants_1.SECTION_NAMES.Connection, Row: [] };
|
|
236
237
|
shape.Section.push(connSection);
|
|
237
238
|
}
|
|
238
239
|
if (!connSection.Row)
|
|
@@ -282,7 +283,7 @@ class ShapeModifier {
|
|
|
282
283
|
newId = this.getNextId(parsed);
|
|
283
284
|
}
|
|
284
285
|
let newShape;
|
|
285
|
-
if (props.type ===
|
|
286
|
+
if (props.type === VisioConstants_1.SHAPE_TYPES.Foreign && props.imgRelId) {
|
|
286
287
|
newShape = ForeignShapeBuilder_1.ForeignShapeBuilder.createImageShapeObject(newId, props.imgRelId, props);
|
|
287
288
|
// Text for foreign shapes? Usually none, but we can support it.
|
|
288
289
|
if (props.text !== undefined && props.text !== null) {
|
|
@@ -311,8 +312,8 @@ class ShapeModifier {
|
|
|
311
312
|
parent.Shapes.Shape = parent.Shapes.Shape ? [parent.Shapes.Shape] : [];
|
|
312
313
|
}
|
|
313
314
|
// Mark parent as Group if not already
|
|
314
|
-
if (parent['@_Type'] !==
|
|
315
|
-
parent['@_Type'] =
|
|
315
|
+
if (parent['@_Type'] !== VisioConstants_1.SHAPE_TYPES.Group) {
|
|
316
|
+
parent['@_Type'] = VisioConstants_1.SHAPE_TYPES.Group;
|
|
316
317
|
}
|
|
317
318
|
parent.Shapes.Shape.push(newShape);
|
|
318
319
|
}
|
|
@@ -397,7 +398,7 @@ class ShapeModifier {
|
|
|
397
398
|
// Update/Add Fill
|
|
398
399
|
if (style.fillColor) {
|
|
399
400
|
// Remove existing Fill section if any (simplified: assuming IX=0)
|
|
400
|
-
shape.Section = shape.Section.filter((s) => s['@_N'] !==
|
|
401
|
+
shape.Section = shape.Section.filter((s) => s['@_N'] !== VisioConstants_1.SECTION_NAMES.Fill);
|
|
401
402
|
shape.Section.push((0, StyleHelpers_1.createFillSection)(style.fillColor));
|
|
402
403
|
}
|
|
403
404
|
// Update/Add Line
|
|
@@ -405,7 +406,7 @@ class ShapeModifier {
|
|
|
405
406
|
|| style.lineWeight !== undefined
|
|
406
407
|
|| style.linePattern !== undefined;
|
|
407
408
|
if (hasLineProps) {
|
|
408
|
-
shape.Section = shape.Section.filter((s) => s['@_N'] !==
|
|
409
|
+
shape.Section = shape.Section.filter((s) => s['@_N'] !== VisioConstants_1.SECTION_NAMES.Line);
|
|
409
410
|
shape.Section.push((0, StyleHelpers_1.createLineSection)({
|
|
410
411
|
color: style.lineColor,
|
|
411
412
|
weight: style.lineWeight !== undefined ? (style.lineWeight / 72).toString() : undefined,
|
|
@@ -421,7 +422,7 @@ class ShapeModifier {
|
|
|
421
422
|
|| style.fontSize !== undefined
|
|
422
423
|
|| style.fontFamily !== undefined;
|
|
423
424
|
if (hasCharProps) {
|
|
424
|
-
shape.Section = shape.Section.filter((s) => s['@_N'] !==
|
|
425
|
+
shape.Section = shape.Section.filter((s) => s['@_N'] !== VisioConstants_1.SECTION_NAMES.Character);
|
|
425
426
|
shape.Section.push((0, StyleHelpers_1.createCharacterSection)({
|
|
426
427
|
bold: style.bold,
|
|
427
428
|
italic: style.italic,
|
|
@@ -438,7 +439,7 @@ class ShapeModifier {
|
|
|
438
439
|
|| style.spaceAfter !== undefined
|
|
439
440
|
|| style.lineSpacing !== undefined;
|
|
440
441
|
if (hasParagraphProps) {
|
|
441
|
-
shape.Section = shape.Section.filter((s) => s['@_N'] !==
|
|
442
|
+
shape.Section = shape.Section.filter((s) => s['@_N'] !== VisioConstants_1.SECTION_NAMES.Paragraph);
|
|
442
443
|
shape.Section.push((0, StyleHelpers_1.createParagraphSection)({
|
|
443
444
|
horzAlign: style.horzAlign,
|
|
444
445
|
spaceBefore: style.spaceBefore,
|
|
@@ -452,7 +453,7 @@ class ShapeModifier {
|
|
|
452
453
|
|| style.textMarginLeft !== undefined
|
|
453
454
|
|| style.textMarginRight !== undefined;
|
|
454
455
|
if (hasTextBlockProps) {
|
|
455
|
-
shape.Section = shape.Section.filter((s) => s['@_N'] !==
|
|
456
|
+
shape.Section = shape.Section.filter((s) => s['@_N'] !== VisioConstants_1.SECTION_NAMES.TextBlock);
|
|
456
457
|
shape.Section.push((0, StyleHelpers_1.createTextBlockSection)({
|
|
457
458
|
topMargin: style.textMarginTop,
|
|
458
459
|
bottomMargin: style.textMarginBottom,
|
|
@@ -570,7 +571,7 @@ class ShapeModifier {
|
|
|
570
571
|
if (shape.Section) {
|
|
571
572
|
const sections = Array.isArray(shape.Section) ? shape.Section : [shape.Section];
|
|
572
573
|
for (const section of sections) {
|
|
573
|
-
if (section['@_N'] !==
|
|
574
|
+
if (section['@_N'] !== VisioConstants_1.SECTION_NAMES.Geometry || !section.Row)
|
|
574
575
|
continue;
|
|
575
576
|
const rows = Array.isArray(section.Row) ? section.Row : [section.Row];
|
|
576
577
|
for (const row of rows) {
|
|
@@ -627,9 +628,9 @@ class ShapeModifier {
|
|
|
627
628
|
if (!Array.isArray(shape.Section))
|
|
628
629
|
shape.Section = [shape.Section];
|
|
629
630
|
// Find or Create Property Section
|
|
630
|
-
let propSection = shape.Section.find((s) => s['@_N'] ===
|
|
631
|
+
let propSection = shape.Section.find((s) => s['@_N'] === VisioConstants_1.SECTION_NAMES.Property);
|
|
631
632
|
if (!propSection) {
|
|
632
|
-
propSection = { '@_N':
|
|
633
|
+
propSection = { '@_N': VisioConstants_1.SECTION_NAMES.Property, Row: [] };
|
|
633
634
|
shape.Section.push(propSection);
|
|
634
635
|
}
|
|
635
636
|
// Ensure Row array exists
|
|
@@ -681,7 +682,7 @@ class ShapeModifier {
|
|
|
681
682
|
}
|
|
682
683
|
// Ensure Section array exists
|
|
683
684
|
const sections = shape.Section ? (Array.isArray(shape.Section) ? shape.Section : [shape.Section]) : [];
|
|
684
|
-
const propSection = sections.find((s) => s['@_N'] ===
|
|
685
|
+
const propSection = sections.find((s) => s['@_N'] === VisioConstants_1.SECTION_NAMES.Property);
|
|
685
686
|
if (!propSection) {
|
|
686
687
|
throw new Error(`Property definition 'Prop.${name}' does not exist on shape ${shapeId}. Call addPropertyDefinition first.`);
|
|
687
688
|
}
|
|
@@ -770,7 +771,7 @@ class ShapeModifier {
|
|
|
770
771
|
return [];
|
|
771
772
|
const relsArray = Array.isArray(rels) ? rels : [rels];
|
|
772
773
|
return relsArray
|
|
773
|
-
.filter((r) => r['@_Type'] ===
|
|
774
|
+
.filter((r) => r['@_Type'] === VisioConstants_1.STRUCT_RELATIONSHIP_TYPES.Container && r['@_ShapeID'] === containerId)
|
|
774
775
|
.map((r) => r['@_RelatedShapeID']);
|
|
775
776
|
}
|
|
776
777
|
async reorderShape(pageId, shapeId, position) {
|
|
@@ -805,7 +806,7 @@ class ShapeModifier {
|
|
|
805
806
|
const getUserVal = (name, def) => {
|
|
806
807
|
if (!listShape.Section)
|
|
807
808
|
return def;
|
|
808
|
-
const userSec = listShape.Section.find((s) => s['@_N'] ===
|
|
809
|
+
const userSec = listShape.Section.find((s) => s['@_N'] === VisioConstants_1.SECTION_NAMES.User);
|
|
809
810
|
if (!userSec || !userSec.Row)
|
|
810
811
|
return def;
|
|
811
812
|
const rows = Array.isArray(userSec.Row) ? userSec.Row : [userSec.Row];
|
|
@@ -850,7 +851,7 @@ class ShapeModifier {
|
|
|
850
851
|
// 3. Update Item Position
|
|
851
852
|
await this.updateShapePosition(pageId, itemId, newX, newY);
|
|
852
853
|
// 4. Add Relationship
|
|
853
|
-
await this.addRelationship(pageId, listId, itemId,
|
|
854
|
+
await this.addRelationship(pageId, listId, itemId, VisioConstants_1.STRUCT_RELATIONSHIP_TYPES.Container);
|
|
854
855
|
// 5. Resize List Container
|
|
855
856
|
await this.resizeContainerToFit(pageId, listId, 0.25);
|
|
856
857
|
}
|
|
@@ -990,9 +991,9 @@ class ShapeModifier {
|
|
|
990
991
|
if (!Array.isArray(shape.Section))
|
|
991
992
|
shape.Section = [shape.Section];
|
|
992
993
|
// Find or Create LayerMem Section
|
|
993
|
-
let memSection = shape.Section.find((s) => s['@_N'] ===
|
|
994
|
+
let memSection = shape.Section.find((s) => s['@_N'] === VisioConstants_1.SECTION_NAMES.LayerMem);
|
|
994
995
|
if (!memSection) {
|
|
995
|
-
memSection = { '@_N':
|
|
996
|
+
memSection = { '@_N': VisioConstants_1.SECTION_NAMES.LayerMem, Row: [] };
|
|
996
997
|
shape.Section.push(memSection);
|
|
997
998
|
}
|
|
998
999
|
// Ensure Row array
|
|
@@ -1073,7 +1074,7 @@ class ShapeModifier {
|
|
|
1073
1074
|
if (!shape.Section)
|
|
1074
1075
|
return result;
|
|
1075
1076
|
const sections = Array.isArray(shape.Section) ? shape.Section : [shape.Section];
|
|
1076
|
-
const propSection = sections.find((s) => s['@_N'] ===
|
|
1077
|
+
const propSection = sections.find((s) => s['@_N'] === VisioConstants_1.SECTION_NAMES.Property);
|
|
1077
1078
|
if (!propSection?.Row)
|
|
1078
1079
|
return result;
|
|
1079
1080
|
const rows = Array.isArray(propSection.Row) ? propSection.Row : [propSection.Row];
|
|
@@ -1188,7 +1189,7 @@ class ShapeModifier {
|
|
|
1188
1189
|
if (!shape.Section)
|
|
1189
1190
|
return [];
|
|
1190
1191
|
const sections = Array.isArray(shape.Section) ? shape.Section : [shape.Section];
|
|
1191
|
-
const memSection = sections.find((s) => s['@_N'] ===
|
|
1192
|
+
const memSection = sections.find((s) => s['@_N'] === VisioConstants_1.SECTION_NAMES.LayerMem);
|
|
1192
1193
|
if (!memSection?.Row)
|
|
1193
1194
|
return [];
|
|
1194
1195
|
const rows = Array.isArray(memSection.Row) ? memSection.Row : [memSection.Row];
|
|
@@ -1205,5 +1206,14 @@ class ShapeModifier {
|
|
|
1205
1206
|
.map((s) => parseInt(s))
|
|
1206
1207
|
.filter((n) => !isNaN(n));
|
|
1207
1208
|
}
|
|
1209
|
+
/**
|
|
1210
|
+
* Return the direct child shapes of a group or container shape.
|
|
1211
|
+
* Returns an empty array for non-group shapes or shapes with no children.
|
|
1212
|
+
*/
|
|
1213
|
+
getShapeChildren(pageId, shapeId) {
|
|
1214
|
+
const pagePath = this.getPagePath(pageId);
|
|
1215
|
+
const reader = new ShapeReader_1.ShapeReader(this.pkg);
|
|
1216
|
+
return reader.readChildShapes(pagePath, shapeId);
|
|
1217
|
+
}
|
|
1208
1218
|
}
|
|
1209
1219
|
exports.ShapeModifier = ShapeModifier;
|
package/dist/ShapeReader.d.ts
CHANGED
|
@@ -25,6 +25,12 @@ export declare class ShapeReader {
|
|
|
25
25
|
/** Decode a Visio ToPart integer string to a ConnectionTarget. */
|
|
26
26
|
private decodeToPart;
|
|
27
27
|
private gatherShapes;
|
|
28
|
+
/**
|
|
29
|
+
* Return the direct child shapes of a group or container shape.
|
|
30
|
+
* Returns an empty array if the shape has no children or does not exist.
|
|
31
|
+
*/
|
|
32
|
+
readChildShapes(path: string, parentId: string): VisioShape[];
|
|
28
33
|
private findShapeById;
|
|
34
|
+
private findRawShape;
|
|
29
35
|
private parseShape;
|
|
30
36
|
}
|
package/dist/ShapeReader.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ShapeReader = void 0;
|
|
4
4
|
const fast_xml_parser_1 = require("fast-xml-parser");
|
|
5
5
|
const VisioParsers_1 = require("./utils/VisioParsers");
|
|
6
|
+
const VisioConstants_1 = require("./core/VisioConstants");
|
|
6
7
|
class ShapeReader {
|
|
7
8
|
constructor(pkg) {
|
|
8
9
|
this.pkg = pkg;
|
|
@@ -138,7 +139,7 @@ class ShapeReader {
|
|
|
138
139
|
let lineWeight;
|
|
139
140
|
let linePattern;
|
|
140
141
|
for (const sec of sections) {
|
|
141
|
-
if (sec['@_N'] ===
|
|
142
|
+
if (sec['@_N'] === VisioConstants_1.SECTION_NAMES.Line) {
|
|
142
143
|
const lineCells = (0, VisioParsers_1.parseCells)(sec);
|
|
143
144
|
if (lineCells['LineColor']?.V)
|
|
144
145
|
lineColor = lineCells['LineColor'].V;
|
|
@@ -190,12 +191,37 @@ class ShapeReader {
|
|
|
190
191
|
}
|
|
191
192
|
}
|
|
192
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* Return the direct child shapes of a group or container shape.
|
|
196
|
+
* Returns an empty array if the shape has no children or does not exist.
|
|
197
|
+
*/
|
|
198
|
+
readChildShapes(path, parentId) {
|
|
199
|
+
let content;
|
|
200
|
+
try {
|
|
201
|
+
content = this.pkg.getFileText(path);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return [];
|
|
205
|
+
}
|
|
206
|
+
const parsed = this.parser.parse(content);
|
|
207
|
+
const shapesData = parsed.PageContents?.Shapes?.Shape;
|
|
208
|
+
if (!shapesData)
|
|
209
|
+
return [];
|
|
210
|
+
const rawParent = this.findRawShape((0, VisioParsers_1.asArray)(shapesData), parentId);
|
|
211
|
+
if (!rawParent?.Shapes?.Shape)
|
|
212
|
+
return [];
|
|
213
|
+
return (0, VisioParsers_1.asArray)(rawParent.Shapes.Shape).map((s) => this.parseShape(s));
|
|
214
|
+
}
|
|
193
215
|
findShapeById(rawShapes, shapeId) {
|
|
216
|
+
const raw = this.findRawShape(rawShapes, shapeId);
|
|
217
|
+
return raw ? this.parseShape(raw) : undefined;
|
|
218
|
+
}
|
|
219
|
+
findRawShape(rawShapes, shapeId) {
|
|
194
220
|
for (const s of rawShapes) {
|
|
195
221
|
if (s['@_ID'] === shapeId)
|
|
196
|
-
return
|
|
222
|
+
return s;
|
|
197
223
|
if (s.Shapes?.Shape) {
|
|
198
|
-
const found = this.
|
|
224
|
+
const found = this.findRawShape((0, VisioParsers_1.asArray)(s.Shapes.Shape), shapeId);
|
|
199
225
|
if (found)
|
|
200
226
|
return found;
|
|
201
227
|
}
|
|
@@ -21,6 +21,35 @@ export declare const RELATIONSHIP_TYPES: {
|
|
|
21
21
|
readonly CORE_PROPERTIES: "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
|
|
22
22
|
readonly EXTENDED_PROPERTIES: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties";
|
|
23
23
|
};
|
|
24
|
+
/** Visio shape `Type` attribute values. */
|
|
25
|
+
export declare const SHAPE_TYPES: {
|
|
26
|
+
readonly Shape: "Shape";
|
|
27
|
+
readonly Group: "Group";
|
|
28
|
+
readonly Foreign: "Foreign";
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Visio ShapeSheet section names (the `N` attribute on `<Section>` elements).
|
|
32
|
+
* Used when finding or filtering sections by name in page/master XML.
|
|
33
|
+
*/
|
|
34
|
+
export declare const SECTION_NAMES: {
|
|
35
|
+
readonly Line: "Line";
|
|
36
|
+
readonly Fill: "Fill";
|
|
37
|
+
readonly Character: "Character";
|
|
38
|
+
readonly Paragraph: "Paragraph";
|
|
39
|
+
readonly TextBlock: "TextBlock";
|
|
40
|
+
readonly Geometry: "Geometry";
|
|
41
|
+
readonly Connection: "Connection";
|
|
42
|
+
readonly Property: "Property";
|
|
43
|
+
readonly User: "User";
|
|
44
|
+
readonly LayerMem: "LayerMem";
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Structural relationship types stored in `<Relationship>` elements
|
|
48
|
+
* inside Visio page XML (distinct from OPC `.rels` relationship types).
|
|
49
|
+
*/
|
|
50
|
+
export declare const STRUCT_RELATIONSHIP_TYPES: {
|
|
51
|
+
readonly Container: "Container";
|
|
52
|
+
};
|
|
24
53
|
export declare const CONTENT_TYPES: {
|
|
25
54
|
readonly PNG: "image/png";
|
|
26
55
|
readonly JPEG: "image/jpeg";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CONTENT_TYPES = exports.RELATIONSHIP_TYPES = exports.XML_NAMESPACES = void 0;
|
|
3
|
+
exports.CONTENT_TYPES = exports.STRUCT_RELATIONSHIP_TYPES = exports.SECTION_NAMES = exports.SHAPE_TYPES = exports.RELATIONSHIP_TYPES = exports.XML_NAMESPACES = void 0;
|
|
4
4
|
exports.XML_NAMESPACES = {
|
|
5
5
|
VISIO_MAIN: 'http://schemas.microsoft.com/office/visio/2012/main',
|
|
6
6
|
RELATIONSHIPS: 'http://schemas.openxmlformats.org/package/2006/relationships',
|
|
@@ -24,6 +24,35 @@ exports.RELATIONSHIP_TYPES = {
|
|
|
24
24
|
CORE_PROPERTIES: 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties',
|
|
25
25
|
EXTENDED_PROPERTIES: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties'
|
|
26
26
|
};
|
|
27
|
+
/** Visio shape `Type` attribute values. */
|
|
28
|
+
exports.SHAPE_TYPES = {
|
|
29
|
+
Shape: 'Shape',
|
|
30
|
+
Group: 'Group',
|
|
31
|
+
Foreign: 'Foreign',
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Visio ShapeSheet section names (the `N` attribute on `<Section>` elements).
|
|
35
|
+
* Used when finding or filtering sections by name in page/master XML.
|
|
36
|
+
*/
|
|
37
|
+
exports.SECTION_NAMES = {
|
|
38
|
+
Line: 'Line',
|
|
39
|
+
Fill: 'Fill',
|
|
40
|
+
Character: 'Character',
|
|
41
|
+
Paragraph: 'Paragraph',
|
|
42
|
+
TextBlock: 'TextBlock',
|
|
43
|
+
Geometry: 'Geometry',
|
|
44
|
+
Connection: 'Connection',
|
|
45
|
+
Property: 'Property',
|
|
46
|
+
User: 'User',
|
|
47
|
+
LayerMem: 'LayerMem',
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Structural relationship types stored in `<Relationship>` elements
|
|
51
|
+
* inside Visio page XML (distinct from OPC `.rels` relationship types).
|
|
52
|
+
*/
|
|
53
|
+
exports.STRUCT_RELATIONSHIP_TYPES = {
|
|
54
|
+
Container: 'Container',
|
|
55
|
+
};
|
|
27
56
|
exports.CONTENT_TYPES = {
|
|
28
57
|
PNG: 'image/png',
|
|
29
58
|
JPEG: 'image/jpeg',
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.VisioValidator = void 0;
|
|
4
4
|
const fast_xml_parser_1 = require("fast-xml-parser");
|
|
5
|
+
const VisioConstants_1 = require("./VisioConstants");
|
|
5
6
|
// Known Visio section names per Microsoft schema
|
|
6
7
|
const VALID_SECTION_NAMES = new Set([
|
|
7
8
|
'Geometry', 'Character', 'Paragraph', 'Tabs', 'Scratch', 'Connection',
|
|
@@ -241,7 +242,7 @@ class VisioValidator {
|
|
|
241
242
|
validateImageShapes(pkg, pageId, parsed, pagePath, errors, warnings) {
|
|
242
243
|
const shapes = this.getAllShapes(parsed);
|
|
243
244
|
for (const shape of shapes) {
|
|
244
|
-
if (shape['@_Type'] !==
|
|
245
|
+
if (shape['@_Type'] !== VisioConstants_1.SHAPE_TYPES.Foreign)
|
|
245
246
|
continue;
|
|
246
247
|
if (!shape.ForeignData) {
|
|
247
248
|
warnings.push(`${pagePath}: Foreign shape ${shape['@_ID']} missing ForeignData`);
|
|
@@ -4,6 +4,7 @@ exports.ShapeBuilder = void 0;
|
|
|
4
4
|
const StyleHelpers_1 = require("../utils/StyleHelpers");
|
|
5
5
|
const GeometryBuilder_1 = require("./GeometryBuilder");
|
|
6
6
|
const ConnectionPointBuilder_1 = require("./ConnectionPointBuilder");
|
|
7
|
+
const VisioConstants_1 = require("../core/VisioConstants");
|
|
7
8
|
class ShapeBuilder {
|
|
8
9
|
static createStandardShape(id, props) {
|
|
9
10
|
// Validate dimensions
|
|
@@ -14,7 +15,7 @@ class ShapeBuilder {
|
|
|
14
15
|
'@_ID': id,
|
|
15
16
|
'@_NameU': `Sheet.${id}`,
|
|
16
17
|
'@_Name': `Sheet.${id}`,
|
|
17
|
-
'@_Type': props.type ||
|
|
18
|
+
'@_Type': props.type || VisioConstants_1.SHAPE_TYPES.Shape,
|
|
18
19
|
Cell: [
|
|
19
20
|
{ '@_N': 'PinX', '@_V': props.x.toString() },
|
|
20
21
|
{ '@_N': 'PinY', '@_V': props.y.toString() },
|
|
@@ -103,7 +104,7 @@ class ShapeBuilder {
|
|
|
103
104
|
}
|
|
104
105
|
// Add Geometry
|
|
105
106
|
// Only if NOT a Group AND NOT a Master Instance
|
|
106
|
-
if (props.type !==
|
|
107
|
+
if (props.type !== VisioConstants_1.SHAPE_TYPES.Group && !props.masterId) {
|
|
107
108
|
shape.Section.push(GeometryBuilder_1.GeometryBuilder.build(props));
|
|
108
109
|
}
|
|
109
110
|
// Handle Text if provided
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createVisioShapeStub = createVisioShapeStub;
|
|
4
|
+
const VisioConstants_1 = require("../core/VisioConstants");
|
|
4
5
|
function createVisioShapeStub(props) {
|
|
5
6
|
return {
|
|
6
7
|
ID: props.ID,
|
|
7
8
|
Name: props.Name || `Sheet.${props.ID}`,
|
|
8
|
-
Type:
|
|
9
|
+
Type: props.Type ?? VisioConstants_1.SHAPE_TYPES.Shape,
|
|
9
10
|
Text: props.Text,
|
|
10
11
|
Cells: Object.entries(props.Cells || {}).reduce((acc, [k, v]) => {
|
|
11
12
|
acc[k] = { N: k, V: v.toString() };
|