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,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ContainerBuilder = void 0;
4
+ const ShapeBuilder_1 = require("./ShapeBuilder");
5
+ class ContainerBuilder {
6
+ static createContainerShape(id, props) {
7
+ // Reuse basic shape creation (transform, text, etc)
8
+ const shape = ShapeBuilder_1.ShapeBuilder.createStandardShape(id, props);
9
+ // Styling Override for "Classic Container":
10
+ // Usually containers have a Header implementation or specific Geometry.
11
+ // For Phase 1, we will stick to a basic Rectangle with the Metadata.
12
+ // If the user wants "classic" look, we might need 2 geometries (Header + Body).
13
+ // 1. Inject Container Metadata (User Cells)
14
+ this.makeContainer(shape);
15
+ // 2. Adjust styling if necessary
16
+ // Containers often have 'NoFill' for the body so you can see behind,
17
+ // or they have a Group structure.
18
+ // For a simple single-shape container, we rely on the Geometry.
19
+ return shape;
20
+ }
21
+ static makeContainer(shape) {
22
+ // Ensure Section array
23
+ if (!shape.Section)
24
+ shape.Section = [];
25
+ if (!Array.isArray(shape.Section))
26
+ shape.Section = [shape.Section];
27
+ // 1. User Section (Metadata)
28
+ let userSection = shape.Section.find((s) => s['@_N'] === 'User');
29
+ if (!userSection) {
30
+ userSection = { '@_N': 'User', Row: [] };
31
+ shape.Section.push(userSection);
32
+ }
33
+ // Ensure Row is array (Critical for XML parser edge cases)
34
+ if (!userSection.Row)
35
+ userSection.Row = [];
36
+ if (!Array.isArray(userSection.Row))
37
+ userSection.Row = [userSection.Row];
38
+ // Helper to add/update user row
39
+ const addUserRow = (name, value) => {
40
+ const rowIdx = userSection.Row.findIndex((r) => r['@_N'] === name);
41
+ const newRow = {
42
+ '@_N': name,
43
+ Cell: [{ '@_N': 'Value', '@_V': value }]
44
+ };
45
+ if (rowIdx >= 0) {
46
+ userSection.Row[rowIdx] = newRow;
47
+ }
48
+ else {
49
+ userSection.Row.push(newRow);
50
+ }
51
+ };
52
+ // Critical Metadata
53
+ addUserRow('msvStructureType', '"Container"');
54
+ addUserRow('msvSDContainerMargin', '10 mm');
55
+ // 2. Adjust Text Position (Simulate Header)
56
+ // Find or create TextXform
57
+ let textXform = shape.Section.find((s) => s['@_N'] === 'TextXform');
58
+ if (!textXform) {
59
+ textXform = { '@_N': 'TextXform', Cell: [] };
60
+ shape.Section.push(textXform);
61
+ }
62
+ // Ensure Cell is array
63
+ if (!textXform.Cell)
64
+ textXform.Cell = [];
65
+ if (!Array.isArray(textXform.Cell))
66
+ textXform.Cell = [textXform.Cell];
67
+ const upsertCell = (name, val, unit) => {
68
+ const idx = textXform.Cell.findIndex((c) => c['@_N'] === name);
69
+ const cell = { '@_N': name, '@_V': val, '@_U': unit };
70
+ if (idx >= 0)
71
+ textXform.Cell[idx] = cell;
72
+ else
73
+ textXform.Cell.push(cell);
74
+ };
75
+ // Move text to top of shape: TxtPinY = Height, TxtLocPinY = TxtHeight
76
+ // Removed redundant '*1' from formulas
77
+ upsertCell('TxtPinY', 'Height', 'DY');
78
+ upsertCell('TxtLocPinY', 'TxtHeight', 'DY');
79
+ }
80
+ static makeList(shape, direction = 'vertical') {
81
+ // 1. Convert basic container to List
82
+ this.makeContainer(shape);
83
+ // 2. User Section Override
84
+ let userSection = shape.Section.find((s) => s['@_N'] === 'User');
85
+ // Helper to add/update user row
86
+ const upsertUserRow = (name, value) => {
87
+ const rowIdx = userSection.Row.findIndex((r) => r['@_N'] === name);
88
+ const newRow = {
89
+ '@_N': name,
90
+ Cell: [{ '@_N': 'Value', '@_V': value }]
91
+ };
92
+ if (rowIdx >= 0)
93
+ userSection.Row[rowIdx] = newRow;
94
+ else
95
+ userSection.Row.push(newRow);
96
+ };
97
+ upsertUserRow('msvStructureType', '"List"'); // Override "Container"
98
+ upsertUserRow('msvSDListDirection', direction === 'vertical' ? '1' : '0'); // 1=Vert, 0=Horiz
99
+ upsertUserRow('msvSDListSpacing', '0.125'); // Default spacing (can be param later)
100
+ upsertUserRow('msvSDListAlignment', '1'); // 1=Center
101
+ }
102
+ }
103
+ exports.ContainerBuilder = ContainerBuilder;
@@ -0,0 +1,4 @@
1
+ import { NewShapeProps } from '../types/VisioTypes';
2
+ export declare class ForeignShapeBuilder {
3
+ static createImageShapeObject(id: string, rId: string, props: NewShapeProps): any;
4
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ForeignShapeBuilder = void 0;
4
+ class ForeignShapeBuilder {
5
+ static createImageShapeObject(id, rId, props) {
6
+ return {
7
+ '@_ID': id,
8
+ '@_NameU': `Sheet.${id}`,
9
+ '@_Name': `Sheet.${id}`,
10
+ '@_Type': 'Foreign',
11
+ ForeignData: { '@_r:id': rId },
12
+ Cell: [
13
+ { '@_N': 'PinX', '@_V': props.x.toString() },
14
+ { '@_N': 'PinY', '@_V': props.y.toString() },
15
+ { '@_N': 'Width', '@_V': props.width.toString() },
16
+ { '@_N': 'Height', '@_V': props.height.toString() },
17
+ { '@_N': 'LocPinX', '@_V': (props.width / 2).toString() },
18
+ { '@_N': 'LocPinY', '@_V': (props.height / 2).toString() }
19
+ ],
20
+ Section: [
21
+ // Foreign shapes typically have no border (LinePattern=0)
22
+ {
23
+ '@_N': 'Line',
24
+ Cell: [
25
+ { '@_N': 'LinePattern', '@_V': '0' }, // 0 = Null/No Line
26
+ { '@_N': 'LineColor', '@_V': '#000000' },
27
+ { '@_N': 'LineWeight', '@_V': '0' }
28
+ ]
29
+ },
30
+ // Geometry is required for selection bounds
31
+ {
32
+ '@_N': 'Geometry',
33
+ '@_IX': '0',
34
+ Cell: [{ '@_N': 'NoFill', '@_V': '1' }], // Images usually don't have a fill behind them
35
+ Row: [
36
+ { '@_T': 'MoveTo', '@_IX': '1', Cell: [{ '@_N': 'X', '@_V': '0' }, { '@_N': 'Y', '@_V': '0' }] },
37
+ { '@_T': 'LineTo', '@_IX': '2', Cell: [{ '@_N': 'X', '@_V': props.width.toString() }, { '@_N': 'Y', '@_V': '0' }] },
38
+ { '@_T': 'LineTo', '@_IX': '3', Cell: [{ '@_N': 'X', '@_V': props.width.toString() }, { '@_N': 'Y', '@_V': props.height.toString() }] },
39
+ { '@_T': 'LineTo', '@_IX': '4', Cell: [{ '@_N': 'X', '@_V': '0' }, { '@_N': 'Y', '@_V': props.height.toString() }] },
40
+ { '@_T': 'LineTo', '@_IX': '5', Cell: [{ '@_N': 'X', '@_V': '0' }, { '@_N': 'Y', '@_V': '0' }] }
41
+ ]
42
+ }
43
+ ]
44
+ };
45
+ }
46
+ }
47
+ exports.ForeignShapeBuilder = ForeignShapeBuilder;
@@ -0,0 +1,4 @@
1
+ import { NewShapeProps } from '../types/VisioTypes';
2
+ export declare class ShapeBuilder {
3
+ static createStandardShape(id: string, props: NewShapeProps): any;
4
+ }
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ShapeBuilder = void 0;
4
+ const StyleHelpers_1 = require("../utils/StyleHelpers");
5
+ class ShapeBuilder {
6
+ static createStandardShape(id, props) {
7
+ // Validate dimensions
8
+ if (props.width <= 0 || props.height <= 0) {
9
+ throw new Error('Shape dimensions must be positive numbers');
10
+ }
11
+ const shape = {
12
+ '@_ID': id,
13
+ '@_NameU': `Sheet.${id}`,
14
+ '@_Name': `Sheet.${id}`,
15
+ '@_Type': props.type || 'Shape',
16
+ Cell: [
17
+ { '@_N': 'PinX', '@_V': props.x.toString() },
18
+ { '@_N': 'PinY', '@_V': props.y.toString() },
19
+ { '@_N': 'Width', '@_V': props.width.toString() },
20
+ { '@_N': 'Height', '@_V': props.height.toString() },
21
+ { '@_N': 'LocPinX', '@_V': (props.width / 2).toString() },
22
+ { '@_N': 'LocPinY', '@_V': (props.height / 2).toString() }
23
+ ],
24
+ Section: []
25
+ // Text added at end by caller or we can do it here if props.text is final
26
+ };
27
+ if (props.masterId) {
28
+ shape['@_Master'] = props.masterId;
29
+ }
30
+ // Add Styles
31
+ if (props.fillColor) {
32
+ shape.Section.push((0, StyleHelpers_1.createFillSection)(props.fillColor));
33
+ // Standard Line for fillable shapes
34
+ shape.Section.push((0, StyleHelpers_1.createLineSection)({
35
+ color: props.lineColor || '#000000',
36
+ weight: '0.01'
37
+ }));
38
+ }
39
+ if (props.fontColor || props.bold) {
40
+ shape.Section.push((0, StyleHelpers_1.createCharacterSection)({
41
+ bold: props.bold,
42
+ color: props.fontColor
43
+ }));
44
+ }
45
+ // Add Geometry
46
+ // Only if NOT a Group AND NOT a Master Instance
47
+ if (props.type !== 'Group' && !props.masterId) {
48
+ shape.Section.push({
49
+ '@_N': 'Geometry',
50
+ '@_IX': '0',
51
+ Cell: [{ '@_N': 'NoFill', '@_V': props.fillColor ? '0' : '1' }],
52
+ Row: [
53
+ { '@_T': 'MoveTo', '@_IX': '1', Cell: [{ '@_N': 'X', '@_V': '0' }, { '@_N': 'Y', '@_V': '0' }] },
54
+ { '@_T': 'LineTo', '@_IX': '2', Cell: [{ '@_N': 'X', '@_V': props.width.toString() }, { '@_N': 'Y', '@_V': '0' }] },
55
+ { '@_T': 'LineTo', '@_IX': '3', Cell: [{ '@_N': 'X', '@_V': props.width.toString() }, { '@_N': 'Y', '@_V': props.height.toString() }] },
56
+ { '@_T': 'LineTo', '@_IX': '4', Cell: [{ '@_N': 'X', '@_V': '0' }, { '@_N': 'Y', '@_V': props.height.toString() }] },
57
+ { '@_T': 'LineTo', '@_IX': '5', Cell: [{ '@_N': 'X', '@_V': '0' }, { '@_N': 'Y', '@_V': '0' }] }
58
+ ]
59
+ });
60
+ }
61
+ // Handle Text if provided
62
+ if (props.text !== undefined && props.text !== null) {
63
+ shape.Text = { '#text': props.text };
64
+ }
65
+ return shape;
66
+ }
67
+ }
68
+ exports.ShapeBuilder = ShapeBuilder;
@@ -0,0 +1,10 @@
1
+ export declare const CONTENT_TYPES_XML: string;
2
+ export declare const RELS_XML: string;
3
+ export declare const DOCUMENT_XML: string;
4
+ export declare const DOCUMENT_RELS_XML: string;
5
+ export declare const PAGES_XML: string;
6
+ export declare const PAGES_RELS_XML: string;
7
+ export declare const PAGE1_XML: string;
8
+ export declare const WINDOWS_XML: string;
9
+ export declare const CORE_XML: string;
10
+ export declare const APP_XML: string;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.APP_XML = exports.CORE_XML = exports.WINDOWS_XML = exports.PAGE1_XML = exports.PAGES_RELS_XML = exports.PAGES_XML = exports.DOCUMENT_RELS_XML = exports.DOCUMENT_XML = exports.RELS_XML = exports.CONTENT_TYPES_XML = void 0;
4
+ const VisioConstants_1 = require("../core/VisioConstants");
5
+ exports.CONTENT_TYPES_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
6
+ <Types xmlns="${VisioConstants_1.XML_NAMESPACES.CONTENT_TYPES}">
7
+ <Default Extension="rels" ContentType="${VisioConstants_1.CONTENT_TYPES.XML_RELATIONSHIPS}"/>
8
+ <Default Extension="xml" ContentType="${VisioConstants_1.CONTENT_TYPES.XML}"/>
9
+ <Override PartName="/visio/document.xml" ContentType="${VisioConstants_1.CONTENT_TYPES.VISIO_DRAWING}"/>
10
+ <Override PartName="/visio/pages/pages.xml" ContentType="${VisioConstants_1.CONTENT_TYPES.VISIO_PAGES}"/>
11
+ <Override PartName="/visio/pages/page1.xml" ContentType="${VisioConstants_1.CONTENT_TYPES.VISIO_PAGE}"/>
12
+ <Override PartName="/visio/windows.xml" ContentType="${VisioConstants_1.CONTENT_TYPES.VISIO_WINDOWS}"/>
13
+ <Override PartName="/docProps/core.xml" ContentType="${VisioConstants_1.CONTENT_TYPES.CORE_PROPERTIES}"/>
14
+ <Override PartName="/docProps/app.xml" ContentType="${VisioConstants_1.CONTENT_TYPES.EXTENDED_PROPERTIES}"/>
15
+ </Types>`;
16
+ exports.RELS_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
17
+ <Relationships xmlns="${VisioConstants_1.XML_NAMESPACES.RELATIONSHIPS}">
18
+ <Relationship Id="rId1" Type="${VisioConstants_1.RELATIONSHIP_TYPES.DOCUMENT}" Target="visio/document.xml"/>
19
+ <Relationship Id="rId2" Type="${VisioConstants_1.RELATIONSHIP_TYPES.CORE_PROPERTIES}" Target="docProps/core.xml"/>
20
+ <Relationship Id="rId3" Type="${VisioConstants_1.RELATIONSHIP_TYPES.EXTENDED_PROPERTIES}" Target="docProps/app.xml"/>
21
+ </Relationships>`;
22
+ exports.DOCUMENT_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
23
+ <VisioDocument xmlns="${VisioConstants_1.XML_NAMESPACES.VISIO_MAIN}" xmlns:r="${VisioConstants_1.XML_NAMESPACES.RELATIONSHIPS_OFFICE}" xml:space="preserve" Language="en-US">
24
+ <DocumentSettings TopPage="0" DefaultTextStyle="0" DefaultLineStyle="0" DefaultFillStyle="0" DefaultGuideStyle="0"/>
25
+ <Colors>
26
+ <ColorEntry IX="0" RGB="#000000"/>
27
+ <ColorEntry IX="1" RGB="#FFFFFF"/>
28
+ </Colors>
29
+ <FaceNames/>
30
+ <StyleSheets/>
31
+ </VisioDocument>`;
32
+ exports.DOCUMENT_RELS_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
33
+ <Relationships xmlns="${VisioConstants_1.XML_NAMESPACES.RELATIONSHIPS}">
34
+ <Relationship Id="rId1" Type="${VisioConstants_1.RELATIONSHIP_TYPES.PAGES}" Target="pages/pages.xml"/>
35
+ <Relationship Id="rId2" Type="${VisioConstants_1.RELATIONSHIP_TYPES.WINDOWS}" Target="windows.xml"/>
36
+ </Relationships>`;
37
+ exports.PAGES_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
38
+ <Pages xmlns="${VisioConstants_1.XML_NAMESPACES.VISIO_MAIN}" xmlns:r="${VisioConstants_1.XML_NAMESPACES.RELATIONSHIPS_OFFICE}" xml:space="preserve">
39
+ <Page ID="1" Name="Page-1" NameU="Page-1" ViewScale="1" ViewCenterX="4.133858267716535" ViewCenterY="5.846456692913386">
40
+ <Rel r:id="rId1"/>
41
+ </Page>
42
+ </Pages>`;
43
+ exports.PAGES_RELS_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
44
+ <Relationships xmlns="${VisioConstants_1.XML_NAMESPACES.RELATIONSHIPS}">
45
+ <Relationship Id="rId1" Type="${VisioConstants_1.RELATIONSHIP_TYPES.PAGE}" Target="page1.xml"/>
46
+ </Relationships>`;
47
+ exports.PAGE1_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
48
+ <PageContents xmlns="${VisioConstants_1.XML_NAMESPACES.VISIO_MAIN}" xmlns:r="${VisioConstants_1.XML_NAMESPACES.RELATIONSHIPS_OFFICE}" xml:space="preserve">
49
+ <Shapes/>
50
+ </PageContents>`;
51
+ exports.WINDOWS_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
52
+ <Windows xmlns="${VisioConstants_1.XML_NAMESPACES.VISIO_MAIN}" xmlns:r="${VisioConstants_1.XML_NAMESPACES.RELATIONSHIPS_OFFICE}" xml:space="preserve">
53
+ <Window ID="0" WindowType="Drawing" WindowState="1073741824" WindowLeft="0" WindowTop="0" WindowWidth="1024" WindowHeight="768" Container="0" ContainerType="Page" Sheet="0"/>
54
+ </Windows>`;
55
+ exports.CORE_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
56
+ <cp:coreProperties xmlns:cp="${VisioConstants_1.XML_NAMESPACES.CORE_PROPERTIES}" xmlns:dc="${VisioConstants_1.XML_NAMESPACES.DC_ELEMENTS}" xmlns:dcterms="${VisioConstants_1.XML_NAMESPACES.DC_TERMS}" xmlns:dcmitype="${VisioConstants_1.XML_NAMESPACES.DC_DCMITYPE}" xmlns:xsi="${VisioConstants_1.XML_NAMESPACES.XSI}">
57
+ <dc:title>Drawing1</dc:title>
58
+ <dc:creator>ts-visio</dc:creator>
59
+ <cp:lastModifiedBy>ts-visio</cp:lastModifiedBy>
60
+ <cp:revision>1</cp:revision>
61
+ </cp:coreProperties>`;
62
+ exports.APP_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
63
+ <Properties xmlns="${VisioConstants_1.XML_NAMESPACES.EXTENDED_PROPERTIES}" xmlns:vt="${VisioConstants_1.XML_NAMESPACES.DOC_PROPS_VTYPES}">
64
+ <Template>Basic</Template>
65
+ <Application>ts-visio</Application>
66
+ </Properties>`;
@@ -0,0 +1,85 @@
1
+ export interface VisioCell {
2
+ N: string;
3
+ V: string;
4
+ U?: string;
5
+ F?: string;
6
+ }
7
+ export interface VisioRow {
8
+ T?: string;
9
+ N?: string;
10
+ IX?: number;
11
+ Cells: {
12
+ [name: string]: VisioCell;
13
+ };
14
+ }
15
+ export interface VisioSection {
16
+ N: string;
17
+ Rows: VisioRow[];
18
+ Cells?: {
19
+ [name: string]: VisioCell;
20
+ };
21
+ }
22
+ export interface VisioShape {
23
+ ID: string;
24
+ Name: string;
25
+ NameU?: string;
26
+ Type: string;
27
+ Master?: string;
28
+ Text?: string;
29
+ Cells: {
30
+ [name: string]: VisioCell;
31
+ };
32
+ Sections: {
33
+ [name: string]: VisioSection;
34
+ };
35
+ }
36
+ export interface VisioConnect {
37
+ FromSheet: string;
38
+ FromCell: string;
39
+ FromPart?: number;
40
+ ToSheet: string;
41
+ ToCell: string;
42
+ ToPart?: number;
43
+ }
44
+ export interface VisioPage {
45
+ ID: string;
46
+ Name: string;
47
+ NameU?: string;
48
+ Shapes: VisioShape[];
49
+ Connects: VisioConnect[];
50
+ isBackground?: boolean;
51
+ backPageId?: string;
52
+ PageSheet?: {
53
+ Cells: {
54
+ [name: string]: VisioCell;
55
+ };
56
+ Sections: {
57
+ [name: string]: VisioSection;
58
+ };
59
+ };
60
+ }
61
+ export declare enum VisioPropType {
62
+ String = 0,
63
+ FixedList = 1,
64
+ Number = 2,
65
+ Boolean = 3,
66
+ VariableList = 4,
67
+ Date = 5,
68
+ Duration = 6,
69
+ Currency = 7
70
+ }
71
+ export interface NewShapeProps {
72
+ text: string;
73
+ x: number;
74
+ y: number;
75
+ width: number;
76
+ height: number;
77
+ id?: string;
78
+ fillColor?: string;
79
+ fontColor?: string;
80
+ bold?: boolean;
81
+ type?: string;
82
+ masterId?: string;
83
+ imgRelId?: string;
84
+ lineColor?: string;
85
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VisioPropType = void 0;
4
+ var VisioPropType;
5
+ (function (VisioPropType) {
6
+ VisioPropType[VisioPropType["String"] = 0] = "String";
7
+ VisioPropType[VisioPropType["FixedList"] = 1] = "FixedList";
8
+ VisioPropType[VisioPropType["Number"] = 2] = "Number";
9
+ VisioPropType[VisioPropType["Boolean"] = 3] = "Boolean";
10
+ VisioPropType[VisioPropType["VariableList"] = 4] = "VariableList";
11
+ VisioPropType[VisioPropType["Date"] = 5] = "Date";
12
+ VisioPropType[VisioPropType["Duration"] = 6] = "Duration";
13
+ VisioPropType[VisioPropType["Currency"] = 7] = "Currency";
14
+ })(VisioPropType || (exports.VisioPropType = VisioPropType = {}));
@@ -0,0 +1,7 @@
1
+ import { VisioShape } from '../types/VisioTypes';
2
+ export declare function createVisioShapeStub(props: {
3
+ ID: string;
4
+ Name?: string;
5
+ Text?: string;
6
+ Cells?: Record<string, string | number>;
7
+ }): VisioShape;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createVisioShapeStub = createVisioShapeStub;
4
+ function createVisioShapeStub(props) {
5
+ return {
6
+ ID: props.ID,
7
+ Name: props.Name || `Sheet.${props.ID}`,
8
+ Type: 'Shape',
9
+ Text: props.Text,
10
+ Cells: Object.entries(props.Cells || {}).reduce((acc, [k, v]) => {
11
+ acc[k] = { N: k, V: v.toString() };
12
+ return acc;
13
+ }, {}),
14
+ Sections: {}
15
+ };
16
+ }
@@ -0,0 +1,30 @@
1
+ export interface VisioSection {
2
+ '@_N': string;
3
+ '@_IX'?: string;
4
+ Row?: any[];
5
+ Cell?: any[];
6
+ }
7
+ export declare function createFillSection(hexColor: string): VisioSection;
8
+ export declare const ArrowHeads: {
9
+ None: string;
10
+ Standard: string;
11
+ Open: string;
12
+ Stealth: string;
13
+ Diamond: string;
14
+ Oneway: string;
15
+ CrowsFoot: string;
16
+ One: string;
17
+ };
18
+ export declare function createCharacterSection(props: {
19
+ bold?: boolean;
20
+ color?: string;
21
+ }): VisioSection;
22
+ export declare function createLineSection(props: {
23
+ color?: string;
24
+ pattern?: string;
25
+ weight?: string;
26
+ beginArrow?: string;
27
+ beginArrowSize?: string;
28
+ endArrow?: string;
29
+ endArrowSize?: string;
30
+ }): VisioSection;
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ArrowHeads = void 0;
4
+ exports.createFillSection = createFillSection;
5
+ exports.createCharacterSection = createCharacterSection;
6
+ exports.createLineSection = createLineSection;
7
+ const hexToRgb = (hex) => {
8
+ // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
9
+ const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
10
+ hex = hex.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b);
11
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
12
+ return result ? `RGB(${parseInt(result[1], 16)},${parseInt(result[2], 16)},${parseInt(result[3], 16)})` : 'RGB(0,0,0)';
13
+ };
14
+ function createFillSection(hexColor) {
15
+ // Visio uses FillForegnd for the main background color.
16
+ // Ideally we should sanitize hexColor to be #RRGGBB.
17
+ const rgbFormula = hexToRgb(hexColor);
18
+ return {
19
+ '@_N': 'Fill',
20
+ Cell: [
21
+ { '@_N': 'FillForegnd', '@_V': hexColor, '@_F': rgbFormula },
22
+ { '@_N': 'FillBkgnd', '@_V': '#FFFFFF' }, // Default background pattern color usually white
23
+ { '@_N': 'FillPattern', '@_V': '1' } // 1 = Solid fill
24
+ ]
25
+ };
26
+ }
27
+ exports.ArrowHeads = {
28
+ None: '0',
29
+ Standard: '1',
30
+ Open: '2',
31
+ Stealth: '3',
32
+ Diamond: '4',
33
+ Oneway: '5',
34
+ CrowsFoot: '29', // Visio "Many"
35
+ One: '24', // Visio "One" (Dash) - Approximate, or '26'
36
+ // There are many variants, but 29 is the standard "Fork"
37
+ };
38
+ function createCharacterSection(props) {
39
+ // Visio Character Section
40
+ // N="Character"
41
+ // Row T="Character"
42
+ // Cell N="Color" V="#FF0000"
43
+ // Cell N="Style" V="1" (1=Bold, 2=Italic, 4=Underline) - Bitwise
44
+ // Visio booleans are often 0 or 1.
45
+ // Style=1 (Bold)
46
+ // Default Style is 0 (Normal)
47
+ let styleVal = 0;
48
+ if (props.bold) {
49
+ styleVal += 1; // Add Bold bit
50
+ }
51
+ // Default Color is usually 0 (Black) or specific hex
52
+ const colorVal = props.color || '#000000';
53
+ return {
54
+ '@_N': 'Character',
55
+ Row: [
56
+ {
57
+ '@_T': 'Character',
58
+ '@_IX': '0',
59
+ Cell: [
60
+ { '@_N': 'Color', '@_V': colorVal, '@_F': hexToRgb(colorVal) },
61
+ { '@_N': 'Style', '@_V': styleVal.toString() },
62
+ // Size, Font, etc could go here
63
+ { '@_N': 'Font', '@_V': '1' } // Default font (Calibri usually)
64
+ ]
65
+ }
66
+ ]
67
+ };
68
+ }
69
+ function createLineSection(props) {
70
+ const cells = [
71
+ { '@_N': 'LineColor', '@_V': props.color || '#000000' },
72
+ { '@_N': 'LinePattern', '@_V': props.pattern || '1' }, // 1 = Solid
73
+ { '@_N': 'LineWeight', '@_V': props.weight || '0.01' } // ~0.72pt
74
+ ];
75
+ // Add RGB Formula for custom colors
76
+ if (props.color) {
77
+ cells[0]['@_F'] = hexToRgb(props.color);
78
+ }
79
+ if (props.beginArrow) {
80
+ cells.push({ '@_N': 'BeginArrow', '@_V': props.beginArrow });
81
+ }
82
+ if (props.beginArrowSize) {
83
+ cells.push({ '@_N': 'BeginArrowSize', '@_V': props.beginArrowSize });
84
+ }
85
+ if (props.endArrow) {
86
+ cells.push({ '@_N': 'EndArrow', '@_V': props.endArrow });
87
+ }
88
+ if (props.endArrowSize) {
89
+ cells.push({ '@_N': 'EndArrowSize', '@_V': props.endArrowSize });
90
+ }
91
+ return {
92
+ '@_N': 'Line',
93
+ Cell: cells
94
+ };
95
+ }
@@ -0,0 +1,6 @@
1
+ import { VisioCell, VisioSection } from '../types/VisioTypes';
2
+ export declare const asArray: <T>(obj: any) => T[];
3
+ export declare const parseCells: (container: any) => {
4
+ [name: string]: VisioCell;
5
+ };
6
+ export declare const parseSection: (sectionData: any) => VisioSection;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseSection = exports.parseCells = exports.asArray = void 0;
4
+ const asArray = (obj) => {
5
+ if (!obj)
6
+ return [];
7
+ return Array.isArray(obj) ? obj : [obj];
8
+ };
9
+ exports.asArray = asArray;
10
+ const parseCells = (container) => {
11
+ const cells = {};
12
+ const cellData = (0, exports.asArray)(container.Cell);
13
+ for (const c of cellData) {
14
+ const cell = c;
15
+ if (cell['@_N']) {
16
+ cells[cell['@_N']] = {
17
+ N: cell['@_N'],
18
+ V: cell['@_V'],
19
+ U: cell['@_U'],
20
+ F: cell['@_F']
21
+ };
22
+ }
23
+ }
24
+ return cells;
25
+ };
26
+ exports.parseCells = parseCells;
27
+ const parseSection = (sectionData) => {
28
+ const rows = [];
29
+ const rowData = (0, exports.asArray)(sectionData.Row);
30
+ for (const r of rowData) {
31
+ const row = r;
32
+ rows.push({
33
+ T: row['@_T'],
34
+ N: row['@_N'],
35
+ IX: row['@_IX'],
36
+ Cells: (0, exports.parseCells)(row)
37
+ });
38
+ }
39
+ return {
40
+ N: sectionData['@_N'],
41
+ Rows: rows,
42
+ Cells: (0, exports.parseCells)(sectionData) // Attempt to parse direct cells
43
+ };
44
+ };
45
+ exports.parseSection = parseSection;
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "ts-visio",
3
+ "version": "1.0.0",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "scripts": {
7
+ "test": "vitest",
8
+ "build": "tsc",
9
+ "prepublishOnly": "npm run build"
10
+ },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "keywords": [],
15
+ "author": "Walt Zimmerman (me@waltzimmerman.com)",
16
+ "license": "MIT",
17
+ "description": "A npm package for creating Visio files (vsdx) using TypeScript.",
18
+ "dependencies": {
19
+ "fast-xml-parser": "^5.3.3",
20
+ "jszip": "^3.10.1"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^25.0.9",
24
+ "typescript": "^5.9.3",
25
+ "vitest": "^4.0.17"
26
+ }
27
+ }