woodml-parser 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 (82) hide show
  1. package/README.md +181 -0
  2. package/dist/cli.d.ts +7 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +554 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/cost.d.ts +94 -0
  7. package/dist/cost.d.ts.map +1 -0
  8. package/dist/cost.js +340 -0
  9. package/dist/cost.js.map +1 -0
  10. package/dist/cost.test.d.ts +2 -0
  11. package/dist/cost.test.d.ts.map +1 -0
  12. package/dist/cost.test.js +241 -0
  13. package/dist/cost.test.js.map +1 -0
  14. package/dist/example.d.ts +6 -0
  15. package/dist/example.d.ts.map +1 -0
  16. package/dist/example.js +136 -0
  17. package/dist/example.js.map +1 -0
  18. package/dist/formulas.d.ts +23 -0
  19. package/dist/formulas.d.ts.map +1 -0
  20. package/dist/formulas.js +442 -0
  21. package/dist/formulas.js.map +1 -0
  22. package/dist/formulas.test.d.ts +5 -0
  23. package/dist/formulas.test.d.ts.map +1 -0
  24. package/dist/formulas.test.js +360 -0
  25. package/dist/formulas.test.js.map +1 -0
  26. package/dist/index.d.ts +23 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +93 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/integration.test.d.ts +6 -0
  31. package/dist/integration.test.d.ts.map +1 -0
  32. package/dist/integration.test.js +271 -0
  33. package/dist/integration.test.js.map +1 -0
  34. package/dist/optimizer.d.ts +119 -0
  35. package/dist/optimizer.d.ts.map +1 -0
  36. package/dist/optimizer.js +423 -0
  37. package/dist/optimizer.js.map +1 -0
  38. package/dist/optimizer.test.d.ts +2 -0
  39. package/dist/optimizer.test.d.ts.map +1 -0
  40. package/dist/optimizer.test.js +225 -0
  41. package/dist/optimizer.test.js.map +1 -0
  42. package/dist/parser.d.ts +59 -0
  43. package/dist/parser.d.ts.map +1 -0
  44. package/dist/parser.js +305 -0
  45. package/dist/parser.js.map +1 -0
  46. package/dist/parser.test.d.ts +5 -0
  47. package/dist/parser.test.d.ts.map +1 -0
  48. package/dist/parser.test.js +486 -0
  49. package/dist/parser.test.js.map +1 -0
  50. package/dist/pdf.d.ts +36 -0
  51. package/dist/pdf.d.ts.map +1 -0
  52. package/dist/pdf.js +316 -0
  53. package/dist/pdf.js.map +1 -0
  54. package/dist/svg.d.ts +73 -0
  55. package/dist/svg.d.ts.map +1 -0
  56. package/dist/svg.js +613 -0
  57. package/dist/svg.js.map +1 -0
  58. package/dist/svg.test.d.ts +5 -0
  59. package/dist/svg.test.d.ts.map +1 -0
  60. package/dist/svg.test.js +333 -0
  61. package/dist/svg.test.js.map +1 -0
  62. package/dist/templates.d.ts +126 -0
  63. package/dist/templates.d.ts.map +1 -0
  64. package/dist/templates.js +448 -0
  65. package/dist/templates.js.map +1 -0
  66. package/dist/templates.test.d.ts +5 -0
  67. package/dist/templates.test.d.ts.map +1 -0
  68. package/dist/templates.test.js +630 -0
  69. package/dist/templates.test.js.map +1 -0
  70. package/dist/types.d.ts +250 -0
  71. package/dist/types.d.ts.map +1 -0
  72. package/dist/types.js +7 -0
  73. package/dist/types.js.map +1 -0
  74. package/dist/units.d.ts +53 -0
  75. package/dist/units.d.ts.map +1 -0
  76. package/dist/units.js +359 -0
  77. package/dist/units.js.map +1 -0
  78. package/dist/units.test.d.ts +5 -0
  79. package/dist/units.test.d.ts.map +1 -0
  80. package/dist/units.test.js +364 -0
  81. package/dist/units.test.js.map +1 -0
  82. package/package.json +46 -0
@@ -0,0 +1,271 @@
1
+ "use strict";
2
+ /**
3
+ * Integration tests for WoodML parser
4
+ * Tests real-world example files end-to-end
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ var __importDefault = (this && this.__importDefault) || function (mod) {
40
+ return (mod && mod.__esModule) ? mod : { "default": mod };
41
+ };
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ const node_test_1 = require("node:test");
44
+ const node_assert_1 = __importDefault(require("node:assert"));
45
+ const fs = __importStar(require("fs"));
46
+ const path = __importStar(require("path"));
47
+ const parser_1 = require("./parser");
48
+ const svg_1 = require("./svg");
49
+ const EXAMPLES_DIR = path.join(__dirname, '..', '..', '..', 'examples');
50
+ function readExample(name) {
51
+ return fs.readFileSync(path.join(EXAMPLES_DIR, name), 'utf-8');
52
+ }
53
+ (0, node_test_1.describe)('Integration Tests', () => {
54
+ (0, node_test_1.describe)('simple-box.woodml', () => {
55
+ (0, node_test_1.it)('should parse and resolve', () => {
56
+ const source = readExample('simple-box.woodml');
57
+ const parser = new parser_1.WoodMLParser();
58
+ const doc = parser.parseAndResolve(source);
59
+ node_assert_1.default.strictEqual(doc.woodml, '1.0');
60
+ node_assert_1.default.ok(doc.project);
61
+ node_assert_1.default.strictEqual(doc.project.name, 'Simple Storage Box');
62
+ });
63
+ (0, node_test_1.it)('should have 4 parts', () => {
64
+ const source = readExample('simple-box.woodml');
65
+ const parser = new parser_1.WoodMLParser();
66
+ const doc = parser.parseAndResolve(source);
67
+ // front, back, 2 sides (as 1 with qty 2), bottom = 4 part definitions
68
+ node_assert_1.default.strictEqual(doc.resolvedParts.length, 4);
69
+ });
70
+ (0, node_test_1.it)('should resolve formulas correctly', () => {
71
+ const source = readExample('simple-box.woodml');
72
+ const parser = new parser_1.WoodMLParser();
73
+ const doc = parser.parseAndResolve(source);
74
+ // Check computed inside_length: $box_length - (2 * $material_thickness)
75
+ // box_length = 12", material_thickness = 0.5"
76
+ // inside_length = 12 - 1 = 11"
77
+ const insideLength = doc.resolvedVariables['inside_length'];
78
+ node_assert_1.default.ok(insideLength);
79
+ if (typeof insideLength === 'number') {
80
+ node_assert_1.default.strictEqual(insideLength, 11);
81
+ }
82
+ else {
83
+ node_assert_1.default.strictEqual(insideLength.value, 11);
84
+ }
85
+ });
86
+ (0, node_test_1.it)('should validate successfully', () => {
87
+ const source = readExample('simple-box.woodml');
88
+ const parser = new parser_1.WoodMLParser();
89
+ const doc = parser.parse(source);
90
+ const errors = (0, parser_1.validateDocument)(doc);
91
+ const critical = errors.filter(e => e.severity === 'error');
92
+ node_assert_1.default.strictEqual(critical.length, 0);
93
+ });
94
+ (0, node_test_1.it)('should generate cut list', () => {
95
+ const source = readExample('simple-box.woodml');
96
+ const parser = new parser_1.WoodMLParser();
97
+ const doc = parser.parseAndResolve(source);
98
+ const cutList = (0, parser_1.generateCutList)(doc);
99
+ node_assert_1.default.ok(cutList.length > 0);
100
+ // Each cut item should have required properties
101
+ for (const item of cutList) {
102
+ node_assert_1.default.ok(item.partId);
103
+ node_assert_1.default.ok(item.length);
104
+ node_assert_1.default.ok(item.width);
105
+ node_assert_1.default.ok(item.thickness);
106
+ node_assert_1.default.ok(item.quantity > 0);
107
+ }
108
+ });
109
+ (0, node_test_1.it)('should calculate board feet', () => {
110
+ const source = readExample('simple-box.woodml');
111
+ const parser = new parser_1.WoodMLParser();
112
+ const doc = parser.parseAndResolve(source);
113
+ const boardFeet = (0, parser_1.calculateBoardFeet)(doc);
114
+ node_assert_1.default.ok(boardFeet > 0);
115
+ node_assert_1.default.ok(boardFeet < 10); // Reasonable for a small box
116
+ });
117
+ (0, node_test_1.it)('should generate SVG diagram', () => {
118
+ const source = readExample('simple-box.woodml');
119
+ const parser = new parser_1.WoodMLParser();
120
+ const doc = parser.parseAndResolve(source);
121
+ const svg = (0, svg_1.generateSVG)(doc, 'parts');
122
+ node_assert_1.default.ok(svg.includes('<svg'));
123
+ node_assert_1.default.ok(svg.includes('</svg>'));
124
+ // Should have parts
125
+ node_assert_1.default.ok(svg.includes('data-id='));
126
+ });
127
+ });
128
+ (0, node_test_1.describe)('shaker-table.woodml', () => {
129
+ (0, node_test_1.it)('should parse complex project', () => {
130
+ const source = readExample('shaker-table.woodml');
131
+ const parser = new parser_1.WoodMLParser();
132
+ const doc = parser.parseAndResolve(source);
133
+ node_assert_1.default.strictEqual(doc.woodml, '1.0');
134
+ node_assert_1.default.ok(doc.project);
135
+ });
136
+ (0, node_test_1.it)('should have multiple parts', () => {
137
+ const source = readExample('shaker-table.woodml');
138
+ const parser = new parser_1.WoodMLParser();
139
+ const doc = parser.parseAndResolve(source);
140
+ // Should have legs, aprons, top, etc.
141
+ node_assert_1.default.ok(doc.resolvedParts.length >= 4);
142
+ });
143
+ (0, node_test_1.it)('should handle joinery', () => {
144
+ const source = readExample('shaker-table.woodml');
145
+ const parser = new parser_1.WoodMLParser();
146
+ const doc = parser.parse(source);
147
+ node_assert_1.default.ok(doc.joinery);
148
+ node_assert_1.default.ok(doc.joinery.length > 0);
149
+ });
150
+ (0, node_test_1.it)('should generate exploded view', () => {
151
+ const source = readExample('shaker-table.woodml');
152
+ const parser = new parser_1.WoodMLParser();
153
+ const doc = parser.parseAndResolve(source);
154
+ const svg = (0, svg_1.generateSVG)(doc, 'exploded');
155
+ node_assert_1.default.ok(svg.includes('<svg'));
156
+ node_assert_1.default.ok(svg.includes('class="part-3d"'));
157
+ });
158
+ });
159
+ (0, node_test_1.describe)('formulas-library.woodml', () => {
160
+ (0, node_test_1.it)('should parse formula library', () => {
161
+ const source = readExample('formulas-library.woodml');
162
+ const parser = new parser_1.WoodMLParser();
163
+ const doc = parser.parse(source);
164
+ node_assert_1.default.strictEqual(doc.woodml, '1.0');
165
+ node_assert_1.default.ok(doc.formulas);
166
+ });
167
+ });
168
+ (0, node_test_1.describe)('SVG generation options', () => {
169
+ (0, node_test_1.it)('should generate all color schemes', () => {
170
+ const source = readExample('simple-box.woodml');
171
+ const parser = new parser_1.WoodMLParser();
172
+ const doc = parser.parseAndResolve(source);
173
+ const schemes = ['default', 'blueprint', 'monochrome'];
174
+ for (const scheme of schemes) {
175
+ const generator = new svg_1.SVGGenerator({ colorScheme: scheme });
176
+ const svg = generator.generatePartsDiagram(doc);
177
+ node_assert_1.default.ok(svg.includes('<svg'), `Failed for ${scheme}`);
178
+ }
179
+ });
180
+ (0, node_test_1.it)('should generate all diagram types', () => {
181
+ const source = readExample('simple-box.woodml');
182
+ const parser = new parser_1.WoodMLParser();
183
+ const doc = parser.parseAndResolve(source);
184
+ const types = ['parts', 'exploded', 'cutlist'];
185
+ for (const type of types) {
186
+ const svg = (0, svg_1.generateSVG)(doc, type);
187
+ node_assert_1.default.ok(svg.includes('<svg'), `Failed for ${type}`);
188
+ }
189
+ });
190
+ });
191
+ (0, node_test_1.describe)('Template integration', () => {
192
+ (0, node_test_1.it)('should work with drawer template', () => {
193
+ const source = readExample('templates/drawer.woodml');
194
+ const parser = new parser_1.WoodMLParser();
195
+ // Template files are parsed but may not instantiate directly
196
+ // Just verify it parses without errors
197
+ const doc = parser.parse(source);
198
+ node_assert_1.default.ok(doc.woodml);
199
+ });
200
+ });
201
+ (0, node_test_1.describe)('Error handling', () => {
202
+ (0, node_test_1.it)('should handle invalid YAML gracefully', () => {
203
+ const parser = new parser_1.WoodMLParser();
204
+ node_assert_1.default.throws(() => {
205
+ parser.parse('this is not: valid: yaml: [');
206
+ });
207
+ });
208
+ (0, node_test_1.it)('should handle missing woodml version', () => {
209
+ const parser = new parser_1.WoodMLParser();
210
+ node_assert_1.default.throws(() => {
211
+ parser.parse('project:\n name: test');
212
+ }, /Missing required "woodml"/);
213
+ });
214
+ });
215
+ (0, node_test_1.describe)('Unit conversion in formulas', () => {
216
+ (0, node_test_1.it)('should handle mixed units', () => {
217
+ const source = `
218
+ woodml: "1.0"
219
+ project:
220
+ name: Test
221
+ units: imperial
222
+
223
+ formulas:
224
+ vars:
225
+ width_in: 24"
226
+ width_mm: 610mm
227
+
228
+ parts:
229
+ - id: test
230
+ dimensions:
231
+ length: $width_in
232
+ width: $width_mm
233
+ thickness: 3/4"
234
+ `;
235
+ const parser = new parser_1.WoodMLParser();
236
+ const doc = parser.parseAndResolve(source);
237
+ node_assert_1.default.strictEqual(doc.resolvedParts.length, 1);
238
+ const part = doc.resolvedParts[0];
239
+ // Both should be resolved to values
240
+ node_assert_1.default.ok(part.dimensions.length.value > 0);
241
+ node_assert_1.default.ok(part.dimensions.width.value > 0);
242
+ });
243
+ });
244
+ (0, node_test_1.describe)('Cut list accuracy', () => {
245
+ (0, node_test_1.it)('should account for quantities', () => {
246
+ const source = `
247
+ woodml: "1.0"
248
+ project:
249
+ name: Test
250
+
251
+ parts:
252
+ - id: shelf
253
+ dimensions:
254
+ length: 36"
255
+ width: 12"
256
+ thickness: 3/4"
257
+ quantity: 5
258
+ `;
259
+ const parser = new parser_1.WoodMLParser();
260
+ const doc = parser.parseAndResolve(source);
261
+ const cutList = (0, parser_1.generateCutList)(doc);
262
+ node_assert_1.default.strictEqual(cutList.length, 1);
263
+ node_assert_1.default.strictEqual(cutList[0].quantity, 5);
264
+ // Board feet = (36 * 12 * 0.75 / 144) * 5 = 1.875 * 5 = 11.25
265
+ // With rounding, should be close
266
+ const totalBoardFeet = cutList[0].boardFeet;
267
+ node_assert_1.default.ok(totalBoardFeet > 10 && totalBoardFeet < 13);
268
+ });
269
+ });
270
+ });
271
+ //# sourceMappingURL=integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration.test.js","sourceRoot":"","sources":["../src/integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Cut list optimization for WoodML projects
3
+ * Uses First Fit Decreasing bin packing algorithm for sheet goods
4
+ * and 1D bin packing for dimensional lumber
5
+ */
6
+ import { ResolvedDocument } from './types';
7
+ /**
8
+ * Standard sheet sizes (in inches)
9
+ */
10
+ export declare const STANDARD_SHEET_SIZES: {
11
+ '4x8': {
12
+ width: number;
13
+ length: number;
14
+ };
15
+ '4x4': {
16
+ width: number;
17
+ length: number;
18
+ };
19
+ '5x5': {
20
+ width: number;
21
+ length: number;
22
+ };
23
+ '4x10': {
24
+ width: number;
25
+ length: number;
26
+ };
27
+ '4x12': {
28
+ width: number;
29
+ length: number;
30
+ };
31
+ };
32
+ /**
33
+ * Standard board lengths (in inches)
34
+ */
35
+ export declare const STANDARD_BOARD_LENGTHS: number[];
36
+ /**
37
+ * Optimization options
38
+ */
39
+ export interface OptimizationOptions {
40
+ /** Saw kerf width in inches (default: 1/8") */
41
+ kerf?: number;
42
+ /** Allow parts to be rotated for better fit (default: true for sheet goods) */
43
+ allowRotation?: boolean;
44
+ /** Minimum usable cutoff size in inches (default: 6") */
45
+ minCutoff?: number;
46
+ /** Standard sheet size key (default: '4x8') */
47
+ sheetSize?: keyof typeof STANDARD_SHEET_SIZES;
48
+ /** Available board lengths (default: STANDARD_BOARD_LENGTHS) */
49
+ boardLengths?: number[];
50
+ /** Edge allowance for rough cuts (default: 0) */
51
+ edgeAllowance?: number;
52
+ }
53
+ /**
54
+ * A placed part on a sheet or board
55
+ */
56
+ export interface PlacedPart {
57
+ partId: string;
58
+ partName: string;
59
+ x: number;
60
+ y: number;
61
+ width: number;
62
+ length: number;
63
+ rotated: boolean;
64
+ }
65
+ /**
66
+ * A sheet with placed parts
67
+ */
68
+ export interface OptimizedSheet {
69
+ sheetNumber: number;
70
+ sheetWidth: number;
71
+ sheetLength: number;
72
+ parts: PlacedPart[];
73
+ usedArea: number;
74
+ wasteArea: number;
75
+ efficiency: number;
76
+ }
77
+ /**
78
+ * A board with placed parts (1D cutting)
79
+ */
80
+ export interface OptimizedBoard {
81
+ boardNumber: number;
82
+ boardLength: number;
83
+ boardWidth: number;
84
+ boardThickness: number;
85
+ parts: {
86
+ partId: string;
87
+ partName: string;
88
+ position: number;
89
+ length: number;
90
+ }[];
91
+ usedLength: number;
92
+ wasteLength: number;
93
+ efficiency: number;
94
+ }
95
+ /**
96
+ * Complete optimization result
97
+ */
98
+ export interface OptimizationResult {
99
+ sheets: OptimizedSheet[];
100
+ boards: OptimizedBoard[];
101
+ totalSheets: number;
102
+ totalBoards: {
103
+ length: number;
104
+ count: number;
105
+ }[];
106
+ overallEfficiency: number;
107
+ wastePercentage: number;
108
+ unplacedParts: string[];
109
+ notes: string[];
110
+ }
111
+ /**
112
+ * Optimize cut list for a project
113
+ */
114
+ export declare function optimizeCutList(doc: ResolvedDocument, options?: OptimizationOptions): OptimizationResult;
115
+ /**
116
+ * Format optimization result as text
117
+ */
118
+ export declare function formatOptimizationResult(result: OptimizationResult): string;
119
+ //# sourceMappingURL=optimizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optimizer.d.ts","sourceRoot":"","sources":["../src/optimizer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,gBAAgB,EAAgB,MAAM,SAAS,CAAC;AAIzD;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;CAMhC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,sBAAsB,UAA0B,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,OAAO,oBAAoB,CAAC;IAC9C,gEAAgE;IAChE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,iDAAiD;IACjD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE;QACL,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;KAChB,EAAE,CAAC;IACJ,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACjD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AA0WD;;GAEG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,gBAAgB,EACrB,OAAO,GAAE,mBAAwB,GAChC,kBAAkB,CA6EpB;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CA8E3E"}