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,250 @@
1
+ /**
2
+ * WoodML TypeScript Type Definitions
3
+ * Core types for the WoodML markup language
4
+ */
5
+ export type UnitSystem = 'imperial' | 'metric';
6
+ export interface Dimension {
7
+ /** Value in base units (inches for imperial, mm for metric) */
8
+ value: number;
9
+ /** Original unit system */
10
+ unit: UnitSystem;
11
+ /** Original string representation */
12
+ original: string;
13
+ }
14
+ export interface FractionalInches {
15
+ whole: number;
16
+ numerator: number;
17
+ denominator: number;
18
+ }
19
+ export interface WoodMLDocument {
20
+ woodml: string;
21
+ project?: Project;
22
+ imports?: string[];
23
+ materials?: Materials;
24
+ formulas?: Formulas;
25
+ parts?: Part[];
26
+ joinery?: Joint[];
27
+ cutlist?: CutList;
28
+ assembly?: AssemblyStep[];
29
+ finishing?: Finishing;
30
+ tools?: Tools;
31
+ notes?: string;
32
+ }
33
+ export interface Project {
34
+ name?: string;
35
+ author?: string;
36
+ version?: string;
37
+ units?: UnitSystem;
38
+ description?: string;
39
+ }
40
+ export interface Materials {
41
+ lumber?: Lumber[];
42
+ hardware?: Hardware[];
43
+ sheet_goods?: SheetGood[];
44
+ }
45
+ export interface Lumber {
46
+ id: string;
47
+ species?: string;
48
+ thickness?: string;
49
+ nominal?: string;
50
+ actual?: string;
51
+ length?: string;
52
+ width?: string;
53
+ board_feet?: number;
54
+ quantity?: number;
55
+ notes?: string;
56
+ }
57
+ export interface Hardware {
58
+ id: string;
59
+ type: 'screw' | 'nail' | 'bolt' | 'hinge' | 'knob' | 'pull' | 'slide' | 'adhesive' | 'dowel' | 'biscuit' | 'other';
60
+ name?: string;
61
+ size?: string;
62
+ quantity?: number;
63
+ notes?: string;
64
+ }
65
+ export interface SheetGood {
66
+ id: string;
67
+ type: 'plywood' | 'mdf' | 'particleboard' | 'hardboard' | 'melamine' | 'other';
68
+ thickness?: string;
69
+ grade?: string;
70
+ size?: string;
71
+ quantity?: number;
72
+ notes?: string;
73
+ }
74
+ export interface Formulas {
75
+ vars?: Record<string, string>;
76
+ computed?: Record<string, string>;
77
+ use_library?: string[];
78
+ custom?: Record<string, CustomFormula>;
79
+ }
80
+ export interface CustomFormula {
81
+ params: string[];
82
+ formula: string;
83
+ }
84
+ export interface Part {
85
+ id: string;
86
+ name?: string;
87
+ use?: string;
88
+ params?: Record<string, string>;
89
+ material?: string;
90
+ dimensions?: Dimensions;
91
+ grain?: 'long' | 'short' | 'any';
92
+ quantity?: number;
93
+ tapers?: Taper[];
94
+ profiles?: Profile[];
95
+ notes?: string;
96
+ }
97
+ export interface Dimensions {
98
+ length?: string;
99
+ width?: string;
100
+ thickness?: string;
101
+ depth?: string;
102
+ }
103
+ export interface Taper {
104
+ face?: 'inside' | 'outside' | 'front' | 'back' | 'all';
105
+ faces?: string[];
106
+ start?: string;
107
+ end_dimension?: string;
108
+ taper_per_foot?: string;
109
+ }
110
+ export interface Profile {
111
+ edge?: 'top' | 'bottom' | 'left' | 'right' | 'front' | 'back' | 'all';
112
+ type: 'roundover' | 'chamfer' | 'ogee' | 'cove' | 'bead' | 'ease' | 'bullnose' | 'custom';
113
+ radius?: string;
114
+ size?: string;
115
+ }
116
+ export type JointType = 'mortise_and_tenon' | 'dovetail' | 'box_joint' | 'dado' | 'rabbet' | 'groove' | 'tongue_and_groove' | 'biscuit' | 'dowel' | 'pocket_hole' | 'miter' | 'spline' | 'half_lap' | 'bridle' | 'finger_joint' | 'scarf' | 'butt';
117
+ export interface Joint {
118
+ type: JointType;
119
+ parts?: string[];
120
+ mortise?: MortiseSpec;
121
+ tenon?: TenonSpec;
122
+ tails?: DovetailSpec;
123
+ pins?: DovetailSpec;
124
+ ratio?: string;
125
+ style?: string;
126
+ housing?: string | HousingSpec;
127
+ insert?: string | InsertSpec;
128
+ connections?: [string, string][];
129
+ width?: string;
130
+ depth?: string;
131
+ position?: string | PositionSpec;
132
+ }
133
+ export interface MortiseSpec {
134
+ part: string;
135
+ position?: string | PositionSpec;
136
+ dimensions?: {
137
+ width?: string;
138
+ height?: string;
139
+ depth?: string;
140
+ };
141
+ }
142
+ export interface TenonSpec {
143
+ part: string;
144
+ position?: string | PositionSpec;
145
+ dimensions?: {
146
+ width?: string;
147
+ height?: string;
148
+ length?: string;
149
+ };
150
+ shoulder?: string | ShoulderSpec;
151
+ haunch?: {
152
+ height?: string;
153
+ length?: string;
154
+ };
155
+ }
156
+ export interface DovetailSpec {
157
+ part: string;
158
+ count?: number;
159
+ spacing?: 'even' | 'graduated';
160
+ half_pin?: string;
161
+ }
162
+ export interface HousingSpec {
163
+ part: string;
164
+ position?: string;
165
+ width?: string;
166
+ depth?: string;
167
+ }
168
+ export interface InsertSpec {
169
+ part: string;
170
+ }
171
+ export interface PositionSpec {
172
+ from_top?: string;
173
+ from_bottom?: string;
174
+ from_left?: string;
175
+ from_right?: string;
176
+ from_front?: string;
177
+ from_back?: string;
178
+ from_outside?: string;
179
+ from_inside?: string;
180
+ }
181
+ export interface ShoulderSpec {
182
+ top?: string;
183
+ bottom?: string;
184
+ front?: string;
185
+ back?: string;
186
+ all?: string;
187
+ }
188
+ export interface CutList {
189
+ optimize?: boolean;
190
+ kerf?: string;
191
+ groups?: CutGroup[];
192
+ }
193
+ export interface CutGroup {
194
+ from: string;
195
+ stock_size?: string;
196
+ respect_grain?: boolean;
197
+ edge_allowance?: string;
198
+ rough_length_add?: string;
199
+ rough_width_add?: string;
200
+ cuts: CutSpec[];
201
+ }
202
+ export interface CutSpec {
203
+ part: string;
204
+ quantity?: number;
205
+ grain?: 'length' | 'width' | 'any';
206
+ priority?: number;
207
+ }
208
+ export interface AssemblyStep {
209
+ step: number;
210
+ title: string;
211
+ parts?: string[];
212
+ operations?: string[];
213
+ tools?: string[];
214
+ notes?: string;
215
+ subassemblies?: Subassembly[];
216
+ }
217
+ export interface Subassembly {
218
+ name: string;
219
+ parts: string[];
220
+ clamp_time?: string;
221
+ }
222
+ export interface Finishing {
223
+ steps: FinishStep[];
224
+ }
225
+ export interface FinishStep {
226
+ type: 'sand' | 'stain' | 'dye' | 'topcoat' | 'wax' | 'oil' | 'other';
227
+ grits?: number[];
228
+ product?: string;
229
+ coats?: number;
230
+ dry_time?: string;
231
+ sand_between?: number | string;
232
+ notes?: string;
233
+ }
234
+ export interface Tools {
235
+ required?: (string | Record<string, number>)[];
236
+ optional?: (string | Record<string, number>)[];
237
+ }
238
+ export interface ResolvedPart extends Omit<Part, 'dimensions'> {
239
+ dimensions: {
240
+ length: Dimension;
241
+ width: Dimension;
242
+ thickness: Dimension;
243
+ };
244
+ resolvedQuantity: number;
245
+ }
246
+ export interface ResolvedDocument extends Omit<WoodMLDocument, 'parts'> {
247
+ resolvedParts: ResolvedPart[];
248
+ resolvedVariables: Record<string, Dimension | number>;
249
+ }
250
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * WoodML TypeScript Type Definitions
4
+ * Core types for the WoodML markup language
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * WoodML Unit Parsing and Conversion
3
+ * Handles imperial (fractional inches) and metric measurements
4
+ */
5
+ import { Dimension, FractionalInches, UnitSystem } from './types';
6
+ /**
7
+ * Parse a dimension string into a Dimension object
8
+ */
9
+ export declare function parseDimension(input: string, defaultUnit?: UnitSystem): Dimension;
10
+ /**
11
+ * Convert dimension to inches
12
+ */
13
+ export declare function toInches(dim: Dimension): number;
14
+ /**
15
+ * Convert dimension to millimeters
16
+ */
17
+ export declare function toMillimeters(dim: Dimension): number;
18
+ /**
19
+ * Convert dimension to the specified unit system
20
+ */
21
+ export declare function convertTo(dim: Dimension, targetUnit: UnitSystem): Dimension;
22
+ /**
23
+ * Convert decimal inches to fractional representation
24
+ */
25
+ export declare function decimalToFraction(decimal: number, maxDenominator?: number): FractionalInches;
26
+ /**
27
+ * Format dimension as imperial string
28
+ */
29
+ export declare function formatImperial(dim: Dimension, precision?: number): string;
30
+ /**
31
+ * Format dimension as metric string
32
+ */
33
+ export declare function formatMetric(dim: Dimension, decimals?: number): string;
34
+ /**
35
+ * Format dimension in its native unit
36
+ */
37
+ export declare function formatDimension(dim: Dimension): string;
38
+ /**
39
+ * Parse dimensional lumber notation (e.g., "2x4")
40
+ */
41
+ export declare function parseDimensionalLumber(notation: string): {
42
+ width: Dimension;
43
+ thickness: Dimension;
44
+ } | null;
45
+ /**
46
+ * Check if a string is a variable reference
47
+ */
48
+ export declare function isVariableReference(input: string): boolean;
49
+ /**
50
+ * Extract variable name from reference
51
+ */
52
+ export declare function extractVariableName(input: string): string | null;
53
+ //# sourceMappingURL=units.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"units.d.ts","sourceRoot":"","sources":["../src/units.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAoElE;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,GAAE,UAAuB,GAAG,SAAS,CAgH7F;AAiBD;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAM/C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAMpD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,GAAG,SAAS,CAkB3E;AAMD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,GAAE,MAAW,GAAG,gBAAgB,CAyChG;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,SAAS,EAAE,SAAS,GAAE,MAAW,GAAG,MAAM,CAgC7E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,GAAE,MAAU,GAAG,MAAM,CAUzE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAKtD;AAUD;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAE,GAAG,IAAI,CAa1G;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGhE"}
package/dist/units.js ADDED
@@ -0,0 +1,359 @@
1
+ "use strict";
2
+ /**
3
+ * WoodML Unit Parsing and Conversion
4
+ * Handles imperial (fractional inches) and metric measurements
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.parseDimension = parseDimension;
8
+ exports.toInches = toInches;
9
+ exports.toMillimeters = toMillimeters;
10
+ exports.convertTo = convertTo;
11
+ exports.decimalToFraction = decimalToFraction;
12
+ exports.formatImperial = formatImperial;
13
+ exports.formatMetric = formatMetric;
14
+ exports.formatDimension = formatDimension;
15
+ exports.parseDimensionalLumber = parseDimensionalLumber;
16
+ exports.isVariableReference = isVariableReference;
17
+ exports.extractVariableName = extractVariableName;
18
+ // ============================================
19
+ // CONSTANTS
20
+ // ============================================
21
+ const INCHES_PER_FOOT = 12;
22
+ const MM_PER_INCH = 25.4;
23
+ const MM_PER_CM = 10;
24
+ const MM_PER_METER = 1000;
25
+ // Common denominators for fractions (must be powers of 2)
26
+ const VALID_DENOMINATORS = [2, 4, 8, 16, 32, 64];
27
+ // ============================================
28
+ // PARSING REGULAR EXPRESSIONS
29
+ // ============================================
30
+ const PATTERNS = {
31
+ // Imperial patterns
32
+ wholeInches: /^(\d+)"$/, // 24"
33
+ fractionalInches: /^(\d+)\/(\d+)"$/, // 3/4"
34
+ mixedInches: /^(\d+)-(\d+)\/(\d+)"$/, // 3-1/2"
35
+ feetOnly: /^(\d+)'$/, // 6'
36
+ feetAndInches: /^(\d+)'(\d+)"$/, // 6'4"
37
+ feetAndMixed: /^(\d+)'(\d+)-(\d+)\/(\d+)"$/, // 6'4-1/2"
38
+ quarterNotation: /^(\d+)\/4$/, // 4/4, 8/4
39
+ // Metric patterns
40
+ millimeters: /^(\d+(?:\.\d+)?)mm$/i, // 610mm
41
+ centimeters: /^(\d+(?:\.\d+)?)cm$/i, // 61cm
42
+ meters: /^(\d+(?:\.\d+)?)m$/i, // 2.4m
43
+ // Variable reference
44
+ variable: /^\$([a-zA-Z_][a-zA-Z0-9_]*)$/, // $variable
45
+ // Dimensional lumber
46
+ dimensionalLumber: /^(\d+)x(\d+)$/, // 2x4
47
+ };
48
+ // ============================================
49
+ // DIMENSIONAL LUMBER ACTUAL SIZES
50
+ // ============================================
51
+ const DIMENSIONAL_LUMBER = {
52
+ '1x2': { width: 1.5, thickness: 0.75 },
53
+ '1x3': { width: 2.5, thickness: 0.75 },
54
+ '1x4': { width: 3.5, thickness: 0.75 },
55
+ '1x6': { width: 5.5, thickness: 0.75 },
56
+ '1x8': { width: 7.25, thickness: 0.75 },
57
+ '1x10': { width: 9.25, thickness: 0.75 },
58
+ '1x12': { width: 11.25, thickness: 0.75 },
59
+ '2x2': { width: 1.5, thickness: 1.5 },
60
+ '2x3': { width: 2.5, thickness: 1.5 },
61
+ '2x4': { width: 3.5, thickness: 1.5 },
62
+ '2x6': { width: 5.5, thickness: 1.5 },
63
+ '2x8': { width: 7.25, thickness: 1.5 },
64
+ '2x10': { width: 9.25, thickness: 1.5 },
65
+ '2x12': { width: 11.25, thickness: 1.5 },
66
+ '4x4': { width: 3.5, thickness: 3.5 },
67
+ '4x6': { width: 5.5, thickness: 3.5 },
68
+ '6x6': { width: 5.5, thickness: 5.5 },
69
+ };
70
+ // ============================================
71
+ // PARSING FUNCTIONS
72
+ // ============================================
73
+ /**
74
+ * Parse a dimension string into a Dimension object
75
+ */
76
+ function parseDimension(input, defaultUnit = 'imperial') {
77
+ const trimmed = input.trim();
78
+ // Try each pattern
79
+ let match;
80
+ // Whole inches: 24"
81
+ if ((match = trimmed.match(PATTERNS.wholeInches))) {
82
+ return {
83
+ value: parseInt(match[1], 10),
84
+ unit: 'imperial',
85
+ original: trimmed,
86
+ };
87
+ }
88
+ // Fractional inches: 3/4"
89
+ if ((match = trimmed.match(PATTERNS.fractionalInches))) {
90
+ const num = parseInt(match[1], 10);
91
+ const denom = parseInt(match[2], 10);
92
+ validateDenominator(denom);
93
+ return {
94
+ value: num / denom,
95
+ unit: 'imperial',
96
+ original: trimmed,
97
+ };
98
+ }
99
+ // Mixed inches: 3-1/2"
100
+ if ((match = trimmed.match(PATTERNS.mixedInches))) {
101
+ const whole = parseInt(match[1], 10);
102
+ const num = parseInt(match[2], 10);
103
+ const denom = parseInt(match[3], 10);
104
+ validateDenominator(denom);
105
+ return {
106
+ value: whole + num / denom,
107
+ unit: 'imperial',
108
+ original: trimmed,
109
+ };
110
+ }
111
+ // Feet only: 6'
112
+ if ((match = trimmed.match(PATTERNS.feetOnly))) {
113
+ return {
114
+ value: parseInt(match[1], 10) * INCHES_PER_FOOT,
115
+ unit: 'imperial',
116
+ original: trimmed,
117
+ };
118
+ }
119
+ // Feet and inches: 6'4"
120
+ if ((match = trimmed.match(PATTERNS.feetAndInches))) {
121
+ const feet = parseInt(match[1], 10);
122
+ const inches = parseInt(match[2], 10);
123
+ return {
124
+ value: feet * INCHES_PER_FOOT + inches,
125
+ unit: 'imperial',
126
+ original: trimmed,
127
+ };
128
+ }
129
+ // Feet and mixed inches: 6'4-1/2"
130
+ if ((match = trimmed.match(PATTERNS.feetAndMixed))) {
131
+ const feet = parseInt(match[1], 10);
132
+ const inches = parseInt(match[2], 10);
133
+ const num = parseInt(match[3], 10);
134
+ const denom = parseInt(match[4], 10);
135
+ validateDenominator(denom);
136
+ return {
137
+ value: feet * INCHES_PER_FOOT + inches + num / denom,
138
+ unit: 'imperial',
139
+ original: trimmed,
140
+ };
141
+ }
142
+ // Quarter notation: 4/4
143
+ if ((match = trimmed.match(PATTERNS.quarterNotation))) {
144
+ const quarters = parseInt(match[1], 10);
145
+ return {
146
+ value: quarters / 4,
147
+ unit: 'imperial',
148
+ original: trimmed,
149
+ };
150
+ }
151
+ // Millimeters: 610mm
152
+ if ((match = trimmed.match(PATTERNS.millimeters))) {
153
+ return {
154
+ value: parseFloat(match[1]),
155
+ unit: 'metric',
156
+ original: trimmed,
157
+ };
158
+ }
159
+ // Centimeters: 61cm
160
+ if ((match = trimmed.match(PATTERNS.centimeters))) {
161
+ return {
162
+ value: parseFloat(match[1]) * MM_PER_CM,
163
+ unit: 'metric',
164
+ original: trimmed,
165
+ };
166
+ }
167
+ // Meters: 2.4m
168
+ if ((match = trimmed.match(PATTERNS.meters))) {
169
+ return {
170
+ value: parseFloat(match[1]) * MM_PER_METER,
171
+ unit: 'metric',
172
+ original: trimmed,
173
+ };
174
+ }
175
+ throw new Error(`Invalid dimension format: "${input}"`);
176
+ }
177
+ /**
178
+ * Validate that denominator is a power of 2
179
+ */
180
+ function validateDenominator(denom) {
181
+ if (!VALID_DENOMINATORS.includes(denom)) {
182
+ throw new Error(`Invalid fraction denominator: ${denom}. Must be one of: ${VALID_DENOMINATORS.join(', ')}`);
183
+ }
184
+ }
185
+ // ============================================
186
+ // CONVERSION FUNCTIONS
187
+ // ============================================
188
+ /**
189
+ * Convert dimension to inches
190
+ */
191
+ function toInches(dim) {
192
+ if (dim.unit === 'imperial') {
193
+ return dim.value;
194
+ }
195
+ // Convert from mm to inches
196
+ return dim.value / MM_PER_INCH;
197
+ }
198
+ /**
199
+ * Convert dimension to millimeters
200
+ */
201
+ function toMillimeters(dim) {
202
+ if (dim.unit === 'metric') {
203
+ return dim.value;
204
+ }
205
+ // Convert from inches to mm
206
+ return dim.value * MM_PER_INCH;
207
+ }
208
+ /**
209
+ * Convert dimension to the specified unit system
210
+ */
211
+ function convertTo(dim, targetUnit) {
212
+ if (dim.unit === targetUnit) {
213
+ return dim;
214
+ }
215
+ if (targetUnit === 'imperial') {
216
+ return {
217
+ value: toInches(dim),
218
+ unit: 'imperial',
219
+ original: dim.original,
220
+ };
221
+ }
222
+ else {
223
+ return {
224
+ value: toMillimeters(dim),
225
+ unit: 'metric',
226
+ original: dim.original,
227
+ };
228
+ }
229
+ }
230
+ // ============================================
231
+ // FORMATTING FUNCTIONS
232
+ // ============================================
233
+ /**
234
+ * Convert decimal inches to fractional representation
235
+ */
236
+ function decimalToFraction(decimal, maxDenominator = 64) {
237
+ const whole = Math.floor(decimal);
238
+ let remainder = decimal - whole;
239
+ if (remainder < 0.001) {
240
+ return { whole, numerator: 0, denominator: 1 };
241
+ }
242
+ // Find closest fraction
243
+ let bestNumerator = 0;
244
+ let bestDenominator = 1;
245
+ let bestError = remainder;
246
+ for (const denom of VALID_DENOMINATORS) {
247
+ if (denom > maxDenominator)
248
+ break;
249
+ const num = Math.round(remainder * denom);
250
+ const error = Math.abs(remainder - num / denom);
251
+ if (error < bestError) {
252
+ bestError = error;
253
+ bestNumerator = num;
254
+ bestDenominator = denom;
255
+ }
256
+ }
257
+ // Simplify fraction
258
+ const gcd = greatestCommonDivisor(bestNumerator, bestDenominator);
259
+ bestNumerator /= gcd;
260
+ bestDenominator /= gcd;
261
+ // Handle case where fraction rounds to 1
262
+ if (bestNumerator === bestDenominator) {
263
+ return { whole: whole + 1, numerator: 0, denominator: 1 };
264
+ }
265
+ return {
266
+ whole,
267
+ numerator: bestNumerator,
268
+ denominator: bestDenominator,
269
+ };
270
+ }
271
+ /**
272
+ * Format dimension as imperial string
273
+ */
274
+ function formatImperial(dim, precision = 64) {
275
+ const inches = toInches(dim);
276
+ // Check if we should use feet
277
+ if (inches >= 12) {
278
+ const feet = Math.floor(inches / 12);
279
+ const remainingInches = inches % 12;
280
+ if (remainingInches < 0.01) {
281
+ return `${feet}'`;
282
+ }
283
+ const frac = decimalToFraction(remainingInches, precision);
284
+ if (frac.numerator === 0) {
285
+ return `${feet}'${frac.whole}"`;
286
+ }
287
+ if (frac.whole === 0) {
288
+ return `${feet}'${frac.numerator}/${frac.denominator}"`;
289
+ }
290
+ return `${feet}'${frac.whole}-${frac.numerator}/${frac.denominator}"`;
291
+ }
292
+ // Format as inches
293
+ const frac = decimalToFraction(inches, precision);
294
+ if (frac.numerator === 0) {
295
+ return `${frac.whole}"`;
296
+ }
297
+ if (frac.whole === 0) {
298
+ return `${frac.numerator}/${frac.denominator}"`;
299
+ }
300
+ return `${frac.whole}-${frac.numerator}/${frac.denominator}"`;
301
+ }
302
+ /**
303
+ * Format dimension as metric string
304
+ */
305
+ function formatMetric(dim, decimals = 1) {
306
+ const mm = toMillimeters(dim);
307
+ if (mm >= 1000) {
308
+ return `${(mm / 1000).toFixed(decimals)}m`;
309
+ }
310
+ if (mm >= 100 && mm % 10 === 0) {
311
+ return `${mm / 10}cm`;
312
+ }
313
+ return `${mm.toFixed(decimals)}mm`;
314
+ }
315
+ /**
316
+ * Format dimension in its native unit
317
+ */
318
+ function formatDimension(dim) {
319
+ if (dim.unit === 'imperial') {
320
+ return formatImperial(dim);
321
+ }
322
+ return formatMetric(dim);
323
+ }
324
+ // ============================================
325
+ // UTILITY FUNCTIONS
326
+ // ============================================
327
+ function greatestCommonDivisor(a, b) {
328
+ return b === 0 ? a : greatestCommonDivisor(b, a % b);
329
+ }
330
+ /**
331
+ * Parse dimensional lumber notation (e.g., "2x4")
332
+ */
333
+ function parseDimensionalLumber(notation) {
334
+ const match = notation.match(PATTERNS.dimensionalLumber);
335
+ if (!match)
336
+ return null;
337
+ const key = `${match[1]}x${match[2]}`;
338
+ const actual = DIMENSIONAL_LUMBER[key];
339
+ if (!actual)
340
+ return null;
341
+ return {
342
+ width: { value: actual.width, unit: 'imperial', original: `${actual.width}"` },
343
+ thickness: { value: actual.thickness, unit: 'imperial', original: `${actual.thickness}"` },
344
+ };
345
+ }
346
+ /**
347
+ * Check if a string is a variable reference
348
+ */
349
+ function isVariableReference(input) {
350
+ return PATTERNS.variable.test(input.trim());
351
+ }
352
+ /**
353
+ * Extract variable name from reference
354
+ */
355
+ function extractVariableName(input) {
356
+ const match = input.trim().match(PATTERNS.variable);
357
+ return match ? match[1] : null;
358
+ }
359
+ //# sourceMappingURL=units.js.map