@mlightcad/mtext-parser 1.0.0 → 1.0.3

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.
@@ -0,0 +1,727 @@
1
+ var k = /* @__PURE__ */ ((r) => (r[r.NONE = 0] = "NONE", r[r.WORD = 1] = "WORD", r[r.STACK = 2] = "STACK", r[r.SPACE = 3] = "SPACE", r[r.NBSP = 4] = "NBSP", r[r.TABULATOR = 5] = "TABULATOR", r[r.NEW_PARAGRAPH = 6] = "NEW_PARAGRAPH", r[r.NEW_COLUMN = 7] = "NEW_COLUMN", r[r.WRAP_AT_DIMLINE = 8] = "WRAP_AT_DIMLINE", r[r.PROPERTIES_CHANGED = 9] = "PROPERTIES_CHANGED", r))(k || {}), b = /* @__PURE__ */ ((r) => (r[r.BOTTOM = 0] = "BOTTOM", r[r.MIDDLE = 1] = "MIDDLE", r[r.TOP = 2] = "TOP", r))(b || {}), E = /* @__PURE__ */ ((r) => (r[r.DEFAULT = 0] = "DEFAULT", r[r.LEFT = 1] = "LEFT", r[r.RIGHT = 2] = "RIGHT", r[r.CENTER = 3] = "CENTER", r[r.JUSTIFIED = 4] = "JUSTIFIED", r[r.DISTRIBUTED = 5] = "DISTRIBUTED", r))(E || {}), m = /* @__PURE__ */ ((r) => (r[r.NONE = 0] = "NONE", r[r.UNDERLINE = 1] = "UNDERLINE", r[r.OVERLINE = 2] = "OVERLINE", r[r.STRIKE_THROUGH = 4] = "STRIKE_THROUGH", r))(m || {});
2
+ const F = {
3
+ c: "Ø",
4
+ d: "°",
5
+ p: "±"
6
+ }, S = {
7
+ l: 1,
8
+ r: 2,
9
+ c: 3,
10
+ j: 4,
11
+ d: 5
12
+ /* DISTRIBUTED */
13
+ };
14
+ function N(r) {
15
+ const [e, t, s] = r;
16
+ return s << 16 | t << 8 | e;
17
+ }
18
+ function _(r) {
19
+ const e = r & 255, t = r >> 8 & 255, s = r >> 16 & 255;
20
+ return [e, t, s];
21
+ }
22
+ function I(r) {
23
+ return r.replace(/\^(.)/g, (e, t) => {
24
+ const s = t.charCodeAt(0);
25
+ return s === 32 ? "^" : s === 73 ? " " : s === 74 ? `
26
+ ` : s === 77 ? "" : "▯";
27
+ });
28
+ }
29
+ function O(r) {
30
+ return r.replace(/\r\n|\r|\n/g, "\\P");
31
+ }
32
+ function R(r) {
33
+ return r.replace(/\\P/g, "").replace(/\\~/g, "").includes("\\");
34
+ }
35
+ class D {
36
+ /**
37
+ * Creates a new MTextParser instance
38
+ * @param content - The MText content to parse
39
+ * @param ctx - Optional initial MText context
40
+ * @param yieldPropertyCommands - Whether to yield property change commands
41
+ */
42
+ constructor(e, t, s = !1) {
43
+ this.ctxStack = [], this.continueStroke = !1, this.scanner = new p(I(e)), this.ctx = t ?? new f(), this.lastCtx = this.ctx.copy(), this.yieldPropertyCommands = s, this.decoder = new TextDecoder("gbk");
44
+ }
45
+ /**
46
+ * Decode multi-byte character from hex code
47
+ * @param hex - Hex code string (e.g. "C4E3")
48
+ * @returns Decoded character or empty square if invalid
49
+ */
50
+ decodeMultiByteChar(e) {
51
+ try {
52
+ const t = new Uint8Array([
53
+ parseInt(e.substr(0, 2), 16),
54
+ parseInt(e.substr(2, 2), 16)
55
+ ]);
56
+ return this.decoder.decode(t);
57
+ } catch {
58
+ return "▯";
59
+ }
60
+ }
61
+ /**
62
+ * Push current context onto the stack
63
+ */
64
+ pushCtx() {
65
+ this.ctxStack.push(this.ctx);
66
+ }
67
+ /**
68
+ * Pop context from the stack
69
+ */
70
+ popCtx() {
71
+ this.ctxStack.length > 0 && (this.ctx = this.ctxStack.pop());
72
+ }
73
+ /**
74
+ * Parse stacking expression (numerator/denominator)
75
+ * @returns Tuple of [TokenType.STACK, [numerator, denominator, type]]
76
+ */
77
+ parseStacking() {
78
+ const e = new p(this.extractExpression(!0));
79
+ let t = "", s = "", n = "";
80
+ const i = () => {
81
+ let a = e.peek(), h = !1;
82
+ return a.charCodeAt(0) < 32 && (a = " "), a === "\\" && (h = !0, e.consume(1), a = e.peek()), e.consume(1), [a, h];
83
+ }, c = () => {
84
+ let a = "";
85
+ for (; e.hasData; ) {
86
+ const [h, o] = i();
87
+ if (!o && "^/#".includes(h))
88
+ return [a, h];
89
+ a += h;
90
+ }
91
+ return [a, ""];
92
+ }, l = () => {
93
+ let a = "";
94
+ for (; e.hasData; ) {
95
+ const [h, o] = i();
96
+ o && h === ";" ? a += ";" : a += h;
97
+ }
98
+ return a;
99
+ };
100
+ return [t, n] = c(), n && (s = l()), [2, [t, s, n]];
101
+ }
102
+ /**
103
+ * Parse MText properties
104
+ * @param cmd - The property command to parse
105
+ * @returns Property changes if yieldPropertyCommands is true and changes occurred
106
+ */
107
+ parseProperties(e) {
108
+ const t = this.ctx.copy();
109
+ switch (e) {
110
+ case "L":
111
+ t.underline = !0, this.continueStroke = !0;
112
+ break;
113
+ case "l":
114
+ t.underline = !1, t.hasAnyStroke || (this.continueStroke = !1);
115
+ break;
116
+ case "O":
117
+ t.overline = !0, this.continueStroke = !0;
118
+ break;
119
+ case "o":
120
+ t.overline = !1, t.hasAnyStroke || (this.continueStroke = !1);
121
+ break;
122
+ case "K":
123
+ t.strikeThrough = !0, this.continueStroke = !0;
124
+ break;
125
+ case "k":
126
+ t.strikeThrough = !1, t.hasAnyStroke || (this.continueStroke = !1);
127
+ break;
128
+ case "A":
129
+ this.parseAlign(t);
130
+ break;
131
+ case "C":
132
+ this.parseAciColor(t);
133
+ break;
134
+ case "c":
135
+ this.parseRgbColor(t);
136
+ break;
137
+ case "H":
138
+ this.parseHeight(t);
139
+ break;
140
+ case "W":
141
+ this.parseWidth(t);
142
+ break;
143
+ case "Q":
144
+ this.parseOblique(t);
145
+ break;
146
+ case "T":
147
+ this.parseCharTracking(t);
148
+ break;
149
+ case "p":
150
+ this.parseParagraphProperties(t);
151
+ break;
152
+ case "f":
153
+ case "F":
154
+ this.parseFontProperties(t);
155
+ break;
156
+ default:
157
+ throw new Error(`Unknown command: ${e}`);
158
+ }
159
+ if (t.continueStroke = this.continueStroke, this.ctx = t, this.yieldPropertyCommands) {
160
+ const s = this.getPropertyChanges(this.lastCtx, t);
161
+ if (Object.keys(s).length > 0)
162
+ return this.lastCtx = this.ctx.copy(), {
163
+ command: e,
164
+ changes: s
165
+ };
166
+ }
167
+ }
168
+ /**
169
+ * Get property changes between two contexts
170
+ * @param oldCtx - The old context
171
+ * @param newCtx - The new context
172
+ * @returns Object containing changed properties
173
+ */
174
+ getPropertyChanges(e, t) {
175
+ const s = {};
176
+ if (e.underline !== t.underline && (s.underline = t.underline), e.overline !== t.overline && (s.overline = t.overline), e.strikeThrough !== t.strikeThrough && (s.strikeThrough = t.strikeThrough), e.aci !== t.aci && (s.aci = t.aci, s.rgb = t.rgb), e.rgb !== t.rgb && (s.rgb = t.rgb), e.align !== t.align && (s.align = t.align), JSON.stringify(e.fontFace) !== JSON.stringify(t.fontFace) && (s.fontFace = t.fontFace), e.capHeight !== t.capHeight && (s.capHeight = t.capHeight), e.widthFactor !== t.widthFactor && (s.widthFactor = t.widthFactor), e.charTrackingFactor !== t.charTrackingFactor && (s.charTrackingFactor = t.charTrackingFactor), e.oblique !== t.oblique && (s.oblique = t.oblique), JSON.stringify(e.paragraph) !== JSON.stringify(t.paragraph)) {
177
+ const n = {};
178
+ e.paragraph.indent !== t.paragraph.indent && (n.indent = t.paragraph.indent), e.paragraph.align !== t.paragraph.align && (n.align = t.paragraph.align), e.paragraph.left !== t.paragraph.left && (n.left = t.paragraph.left), e.paragraph.right !== t.paragraph.right && (n.right = t.paragraph.right), JSON.stringify(e.paragraph.tab_stops) !== JSON.stringify(t.paragraph.tab_stops) && (n.tab_stops = t.paragraph.tab_stops), Object.keys(n).length > 0 && (s.paragraph = n);
179
+ }
180
+ return s;
181
+ }
182
+ /**
183
+ * Parse alignment property
184
+ * @param ctx - The context to update
185
+ */
186
+ parseAlign(e) {
187
+ const t = this.scanner.get();
188
+ "012".includes(t) ? e.align = parseInt(t) : e.align = 0, this.consumeOptionalTerminator();
189
+ }
190
+ /**
191
+ * Parse height property
192
+ * @param ctx - The context to update
193
+ */
194
+ parseHeight(e) {
195
+ const t = this.extractFloatExpression(!0);
196
+ if (t)
197
+ try {
198
+ t.endsWith("x") ? e.capHeight = Math.abs(parseFloat(t.slice(0, -1))) : e.capHeight = Math.abs(parseFloat(t));
199
+ } catch {
200
+ this.scanner.consume(-t.length);
201
+ return;
202
+ }
203
+ this.consumeOptionalTerminator();
204
+ }
205
+ /**
206
+ * Parse width property
207
+ * @param ctx - The context to update
208
+ */
209
+ parseWidth(e) {
210
+ const t = this.extractFloatExpression(!0);
211
+ if (t)
212
+ try {
213
+ t.endsWith("x") ? e.widthFactor = Math.abs(parseFloat(t.slice(0, -1))) : e.widthFactor = Math.abs(parseFloat(t));
214
+ } catch {
215
+ this.scanner.consume(-t.length);
216
+ return;
217
+ }
218
+ this.consumeOptionalTerminator();
219
+ }
220
+ /**
221
+ * Parse character tracking property
222
+ * @param ctx - The context to update
223
+ */
224
+ parseCharTracking(e) {
225
+ const t = this.extractFloatExpression(!0);
226
+ if (t)
227
+ try {
228
+ t.endsWith("x") ? e.charTrackingFactor = Math.abs(parseFloat(t.slice(0, -1))) : e.charTrackingFactor = Math.abs(parseFloat(t));
229
+ } catch {
230
+ this.scanner.consume(-t.length);
231
+ return;
232
+ }
233
+ this.consumeOptionalTerminator();
234
+ }
235
+ /**
236
+ * Parse float value or factor
237
+ * @param value - Current value to apply factor to
238
+ * @returns New value
239
+ */
240
+ parseFloatValueOrFactor(e) {
241
+ const t = this.extractFloatExpression(!0);
242
+ if (t)
243
+ if (t.endsWith("x")) {
244
+ const s = parseFloat(t.slice(0, -1));
245
+ e *= Math.abs(s);
246
+ } else
247
+ e = Math.abs(parseFloat(t));
248
+ return e;
249
+ }
250
+ /**
251
+ * Parse oblique angle property
252
+ * @param ctx - The context to update
253
+ */
254
+ parseOblique(e) {
255
+ const t = this.extractFloatExpression(!1);
256
+ t && (e.oblique = parseFloat(t)), this.consumeOptionalTerminator();
257
+ }
258
+ /**
259
+ * Parse ACI color property
260
+ * @param ctx - The context to update
261
+ */
262
+ parseAciColor(e) {
263
+ const t = this.extractIntExpression();
264
+ if (t) {
265
+ const s = parseInt(t);
266
+ s < 257 && (e.aci = s, e.rgb = null);
267
+ }
268
+ this.consumeOptionalTerminator();
269
+ }
270
+ /**
271
+ * Parse RGB color property
272
+ * @param ctx - The context to update
273
+ */
274
+ parseRgbColor(e) {
275
+ const t = this.extractIntExpression();
276
+ if (t) {
277
+ const s = parseInt(t) & 16777215, [n, i, c] = _(s);
278
+ e.rgb = [c, i, n];
279
+ }
280
+ this.consumeOptionalTerminator();
281
+ }
282
+ /**
283
+ * Extract float expression from scanner
284
+ * @param relative - Whether to allow relative values (ending in 'x')
285
+ * @returns Extracted expression
286
+ */
287
+ extractFloatExpression(e = !1) {
288
+ const t = e ? /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?x?/ : /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/, s = this.scanner.tail.match(t);
289
+ if (s) {
290
+ const n = s[0];
291
+ return this.scanner.consume(n.length), n;
292
+ }
293
+ return "";
294
+ }
295
+ /**
296
+ * Extract integer expression from scanner
297
+ * @returns Extracted expression
298
+ */
299
+ extractIntExpression() {
300
+ const e = this.scanner.tail.match(/^\d+/);
301
+ if (e) {
302
+ const t = e[0];
303
+ return this.scanner.consume(t.length), t;
304
+ }
305
+ return "";
306
+ }
307
+ /**
308
+ * Extract expression until semicolon or end
309
+ * @param escape - Whether to handle escaped semicolons
310
+ * @returns Extracted expression
311
+ */
312
+ extractExpression(e = !1) {
313
+ const t = this.scanner.find(";", e);
314
+ if (t < 0) {
315
+ const c = this.scanner.tail;
316
+ return this.scanner.consume(c.length), c;
317
+ }
318
+ const n = this.scanner.peek(t - this.scanner.currentIndex - 1) === "\\", i = this.scanner.tail.slice(0, t - this.scanner.currentIndex + (n ? 1 : 0));
319
+ return this.scanner.consume(i.length + 1), i;
320
+ }
321
+ /**
322
+ * Parse font properties
323
+ * @param ctx - The context to update
324
+ */
325
+ parseFontProperties(e) {
326
+ const t = this.extractExpression().split("|");
327
+ if (t.length > 0 && t[0]) {
328
+ const s = t[0];
329
+ let n = "Regular", i = 400;
330
+ for (const c of t.slice(1))
331
+ c.startsWith("b1") ? i = 700 : c.startsWith("i1") && (n = "Italic");
332
+ e.fontFace = {
333
+ family: s,
334
+ style: n,
335
+ weight: i
336
+ };
337
+ }
338
+ }
339
+ /**
340
+ * Parse paragraph properties from the MText content
341
+ * Handles properties like indentation, alignment, and tab stops
342
+ * @param ctx - The context to update
343
+ */
344
+ parseParagraphProperties(e) {
345
+ const t = new p(this.extractExpression());
346
+ let s = e.paragraph.indent, n = e.paragraph.left, i = e.paragraph.right, c = e.paragraph.align, l = [];
347
+ const a = () => {
348
+ const h = t.tail.match(/^[+-]?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?/);
349
+ if (h) {
350
+ const o = parseFloat(h[0]);
351
+ for (t.consume(h[0].length); t.peek() === ","; )
352
+ t.consume(1);
353
+ return o;
354
+ }
355
+ return 0;
356
+ };
357
+ for (; t.hasData; )
358
+ switch (t.get()) {
359
+ case "i":
360
+ s = a();
361
+ break;
362
+ case "l":
363
+ n = a();
364
+ break;
365
+ case "r":
366
+ i = a();
367
+ break;
368
+ case "x":
369
+ break;
370
+ case "q": {
371
+ const o = t.get();
372
+ for (c = S[o] || 0; t.peek() === ","; )
373
+ t.consume(1);
374
+ break;
375
+ }
376
+ case "t":
377
+ for (l = []; t.hasData; ) {
378
+ const o = t.peek();
379
+ if (o === "r" || o === "c") {
380
+ t.consume(1);
381
+ const u = a();
382
+ l.push(o + u.toString());
383
+ } else {
384
+ const u = a();
385
+ isNaN(u) ? t.consume(1) : l.push(u);
386
+ }
387
+ }
388
+ break;
389
+ }
390
+ e.paragraph = {
391
+ indent: s,
392
+ left: n,
393
+ right: i,
394
+ align: c,
395
+ tab_stops: l
396
+ };
397
+ }
398
+ /**
399
+ * Consume optional terminator (semicolon)
400
+ */
401
+ consumeOptionalTerminator() {
402
+ this.scanner.peek() === ";" && this.scanner.consume(1);
403
+ }
404
+ /**
405
+ * Parse MText content into tokens
406
+ * @yields MTextToken objects
407
+ */
408
+ *parse() {
409
+ let s = null;
410
+ const n = () => {
411
+ var c;
412
+ let i = "";
413
+ for (; this.scanner.hasData; ) {
414
+ let l = !1, a = this.scanner.peek();
415
+ const h = this.scanner.currentIndex;
416
+ if (a.charCodeAt(0) < 32) {
417
+ if (this.scanner.consume(1), a === " ")
418
+ return [5, null];
419
+ if (a === `
420
+ `)
421
+ return [6, null];
422
+ a = " ";
423
+ }
424
+ if (a === "\\")
425
+ if ("\\{}".includes(this.scanner.peek(1)))
426
+ l = !0, this.scanner.consume(1), a = this.scanner.peek();
427
+ else {
428
+ if (i)
429
+ return [1, i];
430
+ this.scanner.consume(1);
431
+ const o = this.scanner.get();
432
+ switch (o) {
433
+ case "~":
434
+ return [4, null];
435
+ case "P":
436
+ return [6, null];
437
+ case "N":
438
+ return [7, null];
439
+ case "X":
440
+ return [8, null];
441
+ case "S":
442
+ return this.parseStacking();
443
+ case "m":
444
+ case "M":
445
+ if (this.scanner.peek() === "+") {
446
+ this.scanner.consume(1);
447
+ const u = (c = this.scanner.tail.match(/^[0-9A-Fa-f]{4}/)) == null ? void 0 : c[0];
448
+ if (u) {
449
+ this.scanner.consume(4);
450
+ const d = this.decodeMultiByteChar(u);
451
+ return i ? [1, i] : [1, d];
452
+ }
453
+ this.scanner.consume(-1);
454
+ }
455
+ i += "\\M";
456
+ continue;
457
+ default:
458
+ if (o)
459
+ try {
460
+ const u = this.parseProperties(o);
461
+ if (this.yieldPropertyCommands && u)
462
+ return this.lastCtx = this.ctx.copy(), [9, u];
463
+ continue;
464
+ } catch {
465
+ const u = this.scanner.tail.slice(
466
+ h,
467
+ this.scanner.currentIndex
468
+ );
469
+ i += u;
470
+ }
471
+ }
472
+ continue;
473
+ }
474
+ if (a === "%" && this.scanner.peek(1) === "%") {
475
+ const o = this.scanner.peek(2).toLowerCase(), u = F[o];
476
+ if (u) {
477
+ this.scanner.consume(3), i += u;
478
+ continue;
479
+ } else {
480
+ this.scanner.consume(3);
481
+ continue;
482
+ }
483
+ }
484
+ if (a === " ")
485
+ return i ? (this.scanner.consume(1), s = 3, [1, i]) : (this.scanner.consume(1), [3, null]);
486
+ if (!l) {
487
+ if (a === "{") {
488
+ if (i)
489
+ return [1, i];
490
+ this.scanner.consume(1), this.pushCtx();
491
+ continue;
492
+ } else if (a === "}") {
493
+ if (i)
494
+ return [1, i];
495
+ this.scanner.consume(1), this.popCtx();
496
+ continue;
497
+ }
498
+ }
499
+ this.scanner.consume(1), a.charCodeAt(0) >= 32 && (i += a);
500
+ }
501
+ return i ? [1, i] : [0, null];
502
+ };
503
+ for (; ; ) {
504
+ const [i, c] = n();
505
+ if (i)
506
+ yield new g(i, this.ctx, c), s && (yield new g(s, this.ctx, null), s = null);
507
+ else
508
+ break;
509
+ }
510
+ }
511
+ }
512
+ class p {
513
+ /**
514
+ * Create a new text scanner
515
+ * @param text - The text to scan
516
+ */
517
+ constructor(e) {
518
+ this.text = e, this.textLen = e.length, this._index = 0;
519
+ }
520
+ /**
521
+ * Get the current index in the text
522
+ */
523
+ get currentIndex() {
524
+ return this._index;
525
+ }
526
+ /**
527
+ * Check if the scanner has reached the end of the text
528
+ */
529
+ get isEmpty() {
530
+ return this._index >= this.textLen;
531
+ }
532
+ /**
533
+ * Check if there is more text to scan
534
+ */
535
+ get hasData() {
536
+ return this._index < this.textLen;
537
+ }
538
+ /**
539
+ * Get the next character and advance the index
540
+ * @returns The next character, or empty string if at end
541
+ */
542
+ get() {
543
+ if (this.isEmpty)
544
+ return "";
545
+ const e = this.text[this._index];
546
+ return this._index++, e;
547
+ }
548
+ /**
549
+ * Advance the index by the specified count
550
+ * @param count - Number of characters to advance
551
+ */
552
+ consume(e = 1) {
553
+ this._index = Math.max(0, Math.min(this._index + e, this.textLen));
554
+ }
555
+ /**
556
+ * Look at a character without advancing the index
557
+ * @param offset - Offset from current position
558
+ * @returns The character at the offset position, or empty string if out of bounds
559
+ */
560
+ peek(e = 0) {
561
+ const t = this._index + e;
562
+ return t >= this.textLen || t < 0 ? "" : this.text[t];
563
+ }
564
+ /**
565
+ * Find the next occurrence of a character
566
+ * @param char - The character to find
567
+ * @param escape - Whether to handle escaped characters
568
+ * @returns Index of the character, or -1 if not found
569
+ */
570
+ find(e, t = !1) {
571
+ let s = this._index;
572
+ for (; s < this.textLen; ) {
573
+ if (t && this.text[s] === "\\") {
574
+ if (s + 1 < this.textLen) {
575
+ if (this.text[s + 1] === e)
576
+ return s + 1;
577
+ s += 2;
578
+ continue;
579
+ }
580
+ s++;
581
+ continue;
582
+ }
583
+ if (this.text[s] === e)
584
+ return s;
585
+ s++;
586
+ }
587
+ return -1;
588
+ }
589
+ /**
590
+ * Get the remaining text from the current position
591
+ */
592
+ get tail() {
593
+ return this.text.slice(this._index);
594
+ }
595
+ /**
596
+ * Check if the next character is a space
597
+ */
598
+ isNextSpace() {
599
+ return this.peek() === " ";
600
+ }
601
+ /**
602
+ * Consume spaces until a non-space character is found
603
+ * @returns Number of spaces consumed
604
+ */
605
+ consumeSpaces() {
606
+ let e = 0;
607
+ for (; this.isNextSpace(); )
608
+ this.consume(), e++;
609
+ return e;
610
+ }
611
+ }
612
+ class f {
613
+ constructor() {
614
+ this._stroke = 0, this.continueStroke = !1, this._aci = 7, this.rgb = null, this.align = 0, this.fontFace = { family: "", style: "Regular", weight: 400 }, this.capHeight = 1, this.widthFactor = 1, this.charTrackingFactor = 1, this.oblique = 0, this.paragraph = {
615
+ indent: 0,
616
+ left: 0,
617
+ right: 0,
618
+ align: 0,
619
+ tab_stops: []
620
+ };
621
+ }
622
+ /**
623
+ * Get the ACI color value
624
+ */
625
+ get aci() {
626
+ return this._aci;
627
+ }
628
+ /**
629
+ * Set the ACI color value
630
+ * @param value - ACI color value (0-256)
631
+ * @throws Error if value is out of range
632
+ */
633
+ set aci(e) {
634
+ if (e >= 0 && e <= 256)
635
+ this._aci = e, this.rgb = null;
636
+ else
637
+ throw new Error("ACI not in range [0, 256]");
638
+ }
639
+ /**
640
+ * Get whether text is underlined
641
+ */
642
+ get underline() {
643
+ return !!(this._stroke & 1);
644
+ }
645
+ /**
646
+ * Set whether text is underlined
647
+ * @param value - Whether to underline
648
+ */
649
+ set underline(e) {
650
+ this._setStrokeState(1, e);
651
+ }
652
+ /**
653
+ * Get whether text has strike-through
654
+ */
655
+ get strikeThrough() {
656
+ return !!(this._stroke & 4);
657
+ }
658
+ /**
659
+ * Set whether text has strike-through
660
+ * @param value - Whether to strike through
661
+ */
662
+ set strikeThrough(e) {
663
+ this._setStrokeState(4, e);
664
+ }
665
+ /**
666
+ * Get whether text has overline
667
+ */
668
+ get overline() {
669
+ return !!(this._stroke & 2);
670
+ }
671
+ /**
672
+ * Set whether text has overline
673
+ * @param value - Whether to overline
674
+ */
675
+ set overline(e) {
676
+ this._setStrokeState(2, e);
677
+ }
678
+ /**
679
+ * Check if any stroke formatting is active
680
+ */
681
+ get hasAnyStroke() {
682
+ return !!this._stroke;
683
+ }
684
+ /**
685
+ * Set the state of a stroke type
686
+ * @param stroke - The stroke type to set
687
+ * @param state - Whether to enable or disable the stroke
688
+ */
689
+ _setStrokeState(e, t = !0) {
690
+ t ? this._stroke |= e : this._stroke &= ~e;
691
+ }
692
+ /**
693
+ * Create a copy of this context
694
+ * @returns A new context with the same properties
695
+ */
696
+ copy() {
697
+ const e = new f();
698
+ return e._stroke = this._stroke, e.continueStroke = this.continueStroke, e._aci = this._aci, e.rgb = this.rgb, e.align = this.align, e.fontFace = { ...this.fontFace }, e.capHeight = this.capHeight, e.widthFactor = this.widthFactor, e.charTrackingFactor = this.charTrackingFactor, e.oblique = this.oblique, e.paragraph = { ...this.paragraph }, e;
699
+ }
700
+ }
701
+ class g {
702
+ /**
703
+ * Create a new MText token
704
+ * @param type - The token type
705
+ * @param ctx - The text context at this token
706
+ * @param data - Optional token data
707
+ */
708
+ constructor(e, t, s) {
709
+ this.type = e, this.ctx = t, this.data = s;
710
+ }
711
+ }
712
+ export {
713
+ f as MTextContext,
714
+ b as MTextLineAlignment,
715
+ E as MTextParagraphAlignment,
716
+ D as MTextParser,
717
+ m as MTextStroke,
718
+ g as MTextToken,
719
+ p as TextScanner,
720
+ k as TokenType,
721
+ I as caretDecode,
722
+ O as escapeDxfLineEndings,
723
+ R as hasInlineFormattingCodes,
724
+ _ as int2rgb,
725
+ N as rgb2int
726
+ };
727
+ //# sourceMappingURL=parser.es.js.map