@mlightcad/mtext-parser 1.3.3 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/parser.es.js DELETED
@@ -1,1095 +0,0 @@
1
- var _ = /* @__PURE__ */ ((s) => (s[s.NONE = 0] = "NONE", s[s.WORD = 1] = "WORD", s[s.STACK = 2] = "STACK", s[s.SPACE = 3] = "SPACE", s[s.NBSP = 4] = "NBSP", s[s.TABULATOR = 5] = "TABULATOR", s[s.NEW_PARAGRAPH = 6] = "NEW_PARAGRAPH", s[s.NEW_COLUMN = 7] = "NEW_COLUMN", s[s.WRAP_AT_DIMLINE = 8] = "WRAP_AT_DIMLINE", s[s.PROPERTIES_CHANGED = 9] = "PROPERTIES_CHANGED", s))(_ || {}), F = /* @__PURE__ */ ((s) => (s[s.BOTTOM = 0] = "BOTTOM", s[s.MIDDLE = 1] = "MIDDLE", s[s.TOP = 2] = "TOP", s))(F || {}), S = /* @__PURE__ */ ((s) => (s[s.DEFAULT = 0] = "DEFAULT", s[s.LEFT = 1] = "LEFT", s[s.RIGHT = 2] = "RIGHT", s[s.CENTER = 3] = "CENTER", s[s.JUSTIFIED = 4] = "JUSTIFIED", s[s.DISTRIBUTED = 5] = "DISTRIBUTED", s))(S || {}), E = /* @__PURE__ */ ((s) => (s[s.NONE = 0] = "NONE", s[s.UNDERLINE = 1] = "UNDERLINE", s[s.OVERLINE = 2] = "OVERLINE", s[s.STRIKE_THROUGH = 4] = "STRIKE_THROUGH", s))(E || {});
2
- const R = {
3
- c: "Ø",
4
- d: "°",
5
- p: "±",
6
- "%": "%"
7
- }, v = {
8
- l: 1,
9
- r: 2,
10
- c: 3,
11
- j: 4,
12
- d: 5
13
- /* DISTRIBUTED */
14
- };
15
- function I(s) {
16
- const [t, e, r] = s;
17
- return t << 16 | e << 8 | r;
18
- }
19
- function O(s) {
20
- const t = s >> 16 & 255, e = s >> 8 & 255, r = s & 255;
21
- return [t, e, r];
22
- }
23
- function N(s) {
24
- return s.replace(/\r\n|\r|\n/g, "\\P");
25
- }
26
- function w(s) {
27
- return s.replace(/\\P/g, "").replace(/\\~/g, "").includes("\\");
28
- }
29
- function D(s, t = !1) {
30
- const e = /* @__PURE__ */ new Set(), r = /\\[fF](.*?)[;|]/g;
31
- return [...s.matchAll(r)].forEach((a) => {
32
- let h = a[1].toLowerCase();
33
- t && (h = h.replace(/\.(ttf|otf|woff|shx)$/, "")), e.add(h);
34
- }), e;
35
- }
36
- class y {
37
- /**
38
- * Creates a new ContextStack with an initial context.
39
- * @param initial The initial MTextContext to use as the base of the stack.
40
- */
41
- constructor(t) {
42
- this.stack = [], this.stack.push(t);
43
- }
44
- /**
45
- * Pushes a copy of the given context onto the stack.
46
- * @param ctx The MTextContext to push (copied).
47
- */
48
- push(t) {
49
- this.stack.push(t);
50
- }
51
- /**
52
- * Pops the top context from the stack and merges its paragraph properties into the new top context.
53
- * If only one context remains, nothing is popped.
54
- * @returns The popped MTextContext, or undefined if the stack has only one context.
55
- */
56
- pop() {
57
- if (this.stack.length <= 1) return;
58
- const t = this.stack.pop(), e = this.stack[this.stack.length - 1];
59
- return JSON.stringify(e.paragraph) !== JSON.stringify(t.paragraph) && (e.paragraph = { ...t.paragraph }), t;
60
- }
61
- /**
62
- * Returns the current (top) context on the stack.
63
- */
64
- get current() {
65
- return this.stack[this.stack.length - 1];
66
- }
67
- /**
68
- * Returns the current stack depth (number of nested blocks), not counting the root context.
69
- */
70
- get depth() {
71
- return this.stack.length - 1;
72
- }
73
- /**
74
- * Returns the root (bottom) context, which represents the global formatting state.
75
- * Used for paragraph property application.
76
- */
77
- get root() {
78
- return this.stack[0];
79
- }
80
- /**
81
- * Replaces the current (top) context with the given context.
82
- * @param ctx The new context to set as the current context.
83
- */
84
- setCurrent(t) {
85
- this.stack[this.stack.length - 1] = t;
86
- }
87
- }
88
- class x {
89
- /**
90
- * Creates a new MTextParser instance
91
- * @param content - The MText content to parse
92
- * @param ctx - Optional initial MText context
93
- * @param options - Parser options
94
- */
95
- constructor(t, e, r = {}) {
96
- this.continueStroke = !1, this.inStackContext = !1, this.scanner = new d(t);
97
- const a = e ?? new m();
98
- this.ctxStack = new y(a), this.yieldPropertyCommands = r.yieldPropertyCommands ?? !1, this.resetParagraphParameters = r.resetParagraphParameters ?? !1, this.mifDecoder = r.mifDecoder ?? this.decodeMultiByteChar.bind(this), this.mifCodeLength = r.mifCodeLength ?? "auto";
99
- }
100
- /**
101
- * Decode multi-byte character from hex code
102
- * @param hex - Hex code string (e.g. "C4E3" or "1A2B3")
103
- * @returns Decoded character or empty square if invalid
104
- */
105
- decodeMultiByteChar(t) {
106
- try {
107
- if (t.length === 5) {
108
- const e = t[0];
109
- let r = "gbk";
110
- e === "1" ? r = "shift-jis" : e === "2" && (r = "big5");
111
- const a = new Uint8Array([
112
- parseInt(t.substr(1, 2), 16),
113
- parseInt(t.substr(3, 2), 16)
114
- ]);
115
- return new TextDecoder(r).decode(a);
116
- } else if (t.length === 4) {
117
- const e = new Uint8Array([
118
- parseInt(t.substr(0, 2), 16),
119
- parseInt(t.substr(2, 2), 16)
120
- ]), a = new TextDecoder("gbk").decode(e);
121
- if (a !== "▯")
122
- return a;
123
- const i = new TextDecoder("big5").decode(e);
124
- if (i !== "▯")
125
- return i;
126
- }
127
- return "▯";
128
- } catch {
129
- return "▯";
130
- }
131
- }
132
- /**
133
- * Extract MIF hex code from scanner
134
- * @param length - The length of the hex code to extract (4 or 5), or 'auto' to detect
135
- * @returns The extracted hex code, or null if not found
136
- */
137
- extractMifCode(t) {
138
- var e, r, a;
139
- if (t === "auto") {
140
- const h = (e = this.scanner.tail.match(/^[0-9A-Fa-f]{5}/)) == null ? void 0 : e[0];
141
- if (h)
142
- return h;
143
- const i = (r = this.scanner.tail.match(/^[0-9A-Fa-f]{4}/)) == null ? void 0 : r[0];
144
- return i || null;
145
- } else
146
- return ((a = this.scanner.tail.match(new RegExp(`^[0-9A-Fa-f]{${t}}`))) == null ? void 0 : a[0]) || null;
147
- }
148
- /**
149
- * Push current context onto the stack
150
- */
151
- pushCtx() {
152
- this.ctxStack.push(this.ctxStack.current);
153
- }
154
- /**
155
- * Pop context from the stack
156
- */
157
- popCtx() {
158
- this.ctxStack.pop();
159
- }
160
- /**
161
- * Parse stacking expression (numerator/denominator)
162
- * @returns Tuple of [TokenType.STACK, [numerator, denominator, type]]
163
- */
164
- parseStacking() {
165
- const t = new d(this.extractExpression(!0));
166
- let e = "", r = "", a = "";
167
- const h = () => {
168
- let n = t.peek(), l = !1;
169
- return n.charCodeAt(0) < 32 && (n = " "), n === "\\" && (l = !0, t.consume(1), n = t.peek()), t.consume(1), [n, l];
170
- }, i = () => {
171
- let n = "";
172
- for (; t.hasData; ) {
173
- const [l, o] = h();
174
- if (!o && (l === "/" || l === "#" || l === "^"))
175
- return [n, l];
176
- n += l;
177
- }
178
- return [n, ""];
179
- }, u = (n) => {
180
- let l = "", o = n;
181
- for (; t.hasData; ) {
182
- const [c, p] = h();
183
- if (!(o && c === " ")) {
184
- if (o = !1, !p && c === ";")
185
- break;
186
- l += c;
187
- }
188
- }
189
- return l;
190
- };
191
- return [e, a] = i(), a && (r = u(a === "^")), e === "" && r.includes("I/") ? [2, [" ", " ", "/"]] : a === "^" ? [2, [e, r, "^"]] : [2, [e, r, a]];
192
- }
193
- /**
194
- * Parse MText properties
195
- * @param cmd - The property command to parse
196
- * @returns Property changes if yieldPropertyCommands is true and changes occurred
197
- */
198
- parseProperties(t) {
199
- const e = this.ctxStack.current.copy(), r = this.ctxStack.current.copy();
200
- switch (t) {
201
- case "L":
202
- r.underline = !0, this.continueStroke = !0;
203
- break;
204
- case "l":
205
- r.underline = !1, r.hasAnyStroke || (this.continueStroke = !1);
206
- break;
207
- case "O":
208
- r.overline = !0, this.continueStroke = !0;
209
- break;
210
- case "o":
211
- r.overline = !1, r.hasAnyStroke || (this.continueStroke = !1);
212
- break;
213
- case "K":
214
- r.strikeThrough = !0, this.continueStroke = !0;
215
- break;
216
- case "k":
217
- r.strikeThrough = !1, r.hasAnyStroke || (this.continueStroke = !1);
218
- break;
219
- case "A":
220
- this.parseAlign(r);
221
- break;
222
- case "C":
223
- this.parseAciColor(r);
224
- break;
225
- case "c":
226
- this.parseRgbColor(r);
227
- break;
228
- case "H":
229
- this.parseHeight(r);
230
- break;
231
- case "W":
232
- this.parseWidth(r);
233
- break;
234
- case "Q":
235
- this.parseOblique(r);
236
- break;
237
- case "T":
238
- this.parseCharTracking(r);
239
- break;
240
- case "p":
241
- this.parseParagraphProperties(r);
242
- break;
243
- case "f":
244
- case "F":
245
- this.parseFontProperties(r);
246
- break;
247
- default:
248
- throw new Error(`Unknown command: ${t}`);
249
- }
250
- if (this.continueStroke = r.hasAnyStroke, r.continueStroke = this.continueStroke, this.ctxStack.setCurrent(r), this.yieldPropertyCommands) {
251
- const a = this.getPropertyChanges(e, r);
252
- if (Object.keys(a).length > 0)
253
- return {
254
- command: t,
255
- changes: a,
256
- depth: this.ctxStack.depth
257
- };
258
- }
259
- }
260
- /**
261
- * Get property changes between two contexts
262
- * @param oldCtx - The old context
263
- * @param newCtx - The new context
264
- * @returns Object containing changed properties
265
- */
266
- getPropertyChanges(t, e) {
267
- const r = {};
268
- if (t.underline !== e.underline && (r.underline = e.underline), t.overline !== e.overline && (r.overline = e.overline), t.strikeThrough !== e.strikeThrough && (r.strikeThrough = e.strikeThrough), t.color.aci !== e.color.aci && (r.aci = e.color.aci), t.color.rgbValue !== e.color.rgbValue && (r.rgb = e.color.rgb), t.align !== e.align && (r.align = e.align), JSON.stringify(t.fontFace) !== JSON.stringify(e.fontFace) && (r.fontFace = e.fontFace), (t.capHeight.value !== e.capHeight.value || t.capHeight.isRelative !== e.capHeight.isRelative) && (r.capHeight = e.capHeight), (t.widthFactor.value !== e.widthFactor.value || t.widthFactor.isRelative !== e.widthFactor.isRelative) && (r.widthFactor = e.widthFactor), (t.charTrackingFactor.value !== e.charTrackingFactor.value || t.charTrackingFactor.isRelative !== e.charTrackingFactor.isRelative) && (r.charTrackingFactor = e.charTrackingFactor), t.oblique !== e.oblique && (r.oblique = e.oblique), JSON.stringify(t.paragraph) !== JSON.stringify(e.paragraph)) {
269
- const a = {};
270
- t.paragraph.indent !== e.paragraph.indent && (a.indent = e.paragraph.indent), t.paragraph.align !== e.paragraph.align && (a.align = e.paragraph.align), t.paragraph.left !== e.paragraph.left && (a.left = e.paragraph.left), t.paragraph.right !== e.paragraph.right && (a.right = e.paragraph.right), JSON.stringify(t.paragraph.tabs) !== JSON.stringify(e.paragraph.tabs) && (a.tabs = e.paragraph.tabs), Object.keys(a).length > 0 && (r.paragraph = a);
271
- }
272
- return r;
273
- }
274
- /**
275
- * Parse alignment property
276
- * @param ctx - The context to update
277
- */
278
- parseAlign(t) {
279
- const e = this.scanner.get();
280
- "012".includes(e) ? t.align = parseInt(e) : t.align = 0, this.consumeOptionalTerminator();
281
- }
282
- /**
283
- * Parse height property
284
- * @param ctx - The context to update
285
- */
286
- parseHeight(t) {
287
- const e = this.extractFloatExpression(!0);
288
- if (e)
289
- try {
290
- e.endsWith("x") ? t.capHeight = {
291
- value: parseFloat(e.slice(0, -1)),
292
- isRelative: !0
293
- } : t.capHeight = {
294
- value: parseFloat(e),
295
- isRelative: !1
296
- };
297
- } catch {
298
- this.scanner.consume(-e.length);
299
- return;
300
- }
301
- this.consumeOptionalTerminator();
302
- }
303
- /**
304
- * Parse width property
305
- * @param ctx - The context to update
306
- */
307
- parseWidth(t) {
308
- const e = this.extractFloatExpression(!0);
309
- if (e)
310
- try {
311
- e.endsWith("x") ? t.widthFactor = {
312
- value: parseFloat(e.slice(0, -1)),
313
- isRelative: !0
314
- } : t.widthFactor = {
315
- value: parseFloat(e),
316
- isRelative: !1
317
- };
318
- } catch {
319
- this.scanner.consume(-e.length);
320
- return;
321
- }
322
- this.consumeOptionalTerminator();
323
- }
324
- /**
325
- * Parse character tracking property
326
- * @param ctx - The context to update
327
- */
328
- parseCharTracking(t) {
329
- const e = this.extractFloatExpression(!0);
330
- if (e)
331
- try {
332
- e.endsWith("x") ? t.charTrackingFactor = {
333
- value: Math.abs(parseFloat(e.slice(0, -1))),
334
- isRelative: !0
335
- } : t.charTrackingFactor = {
336
- value: Math.abs(parseFloat(e)),
337
- isRelative: !1
338
- };
339
- } catch {
340
- this.scanner.consume(-e.length);
341
- return;
342
- }
343
- this.consumeOptionalTerminator();
344
- }
345
- /**
346
- * Parse float value or factor
347
- * @param value - Current value to apply factor to
348
- * @returns New value
349
- */
350
- parseFloatValueOrFactor(t) {
351
- const e = this.extractFloatExpression(!0);
352
- if (e)
353
- if (e.endsWith("x")) {
354
- const r = parseFloat(e.slice(0, -1));
355
- t *= r;
356
- } else
357
- t = parseFloat(e);
358
- return t;
359
- }
360
- /**
361
- * Parse oblique angle property
362
- * @param ctx - The context to update
363
- */
364
- parseOblique(t) {
365
- const e = this.extractFloatExpression(!1);
366
- e && (t.oblique = parseFloat(e)), this.consumeOptionalTerminator();
367
- }
368
- /**
369
- * Parse ACI color property
370
- * @param ctx - The context to update
371
- */
372
- parseAciColor(t) {
373
- const e = this.extractIntExpression();
374
- if (e) {
375
- const r = parseInt(e);
376
- r < 257 && (t.color.aci = r);
377
- }
378
- this.consumeOptionalTerminator();
379
- }
380
- /**
381
- * Parse RGB color property
382
- * @param ctx - The context to update
383
- */
384
- parseRgbColor(t) {
385
- const e = this.extractIntExpression();
386
- if (e) {
387
- const r = parseInt(e) & 16777215;
388
- t.color.rgbValue = r;
389
- }
390
- this.consumeOptionalTerminator();
391
- }
392
- /**
393
- * Extract float expression from scanner
394
- * @param relative - Whether to allow relative values (ending in 'x')
395
- * @returns Extracted expression
396
- */
397
- extractFloatExpression(t = !1) {
398
- const e = t ? /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?x?/ : /^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?/, r = this.scanner.tail.match(e);
399
- if (r) {
400
- const a = r[0];
401
- return this.scanner.consume(a.length), a;
402
- }
403
- return "";
404
- }
405
- /**
406
- * Extract integer expression from scanner
407
- * @returns Extracted expression
408
- */
409
- extractIntExpression() {
410
- const t = this.scanner.tail.match(/^\d+/);
411
- if (t) {
412
- const e = t[0];
413
- return this.scanner.consume(e.length), e;
414
- }
415
- return "";
416
- }
417
- /**
418
- * Extract expression until semicolon or end
419
- * @param escape - Whether to handle escaped semicolons
420
- * @returns Extracted expression
421
- */
422
- extractExpression(t = !1) {
423
- const e = this.scanner.find(";", t);
424
- if (e < 0) {
425
- const i = this.scanner.tail;
426
- return this.scanner.consume(i.length), i;
427
- }
428
- const a = this.scanner.peek(e - this.scanner.currentIndex - 1) === "\\", h = this.scanner.tail.slice(0, e - this.scanner.currentIndex + (a ? 1 : 0));
429
- return this.scanner.consume(h.length + 1), h;
430
- }
431
- /**
432
- * Parse font properties
433
- * @param ctx - The context to update
434
- */
435
- parseFontProperties(t) {
436
- const e = this.extractExpression().split("|");
437
- if (e.length > 0 && e[0]) {
438
- const r = e[0];
439
- let a = "Regular", h = 400;
440
- for (const i of e.slice(1))
441
- i.startsWith("b1") ? h = 700 : i === "i" || i.startsWith("i1") ? a = "Italic" : (i === "i0" || i.startsWith("i0")) && (a = "Regular");
442
- t.fontFace = {
443
- family: r,
444
- style: a,
445
- weight: h
446
- };
447
- }
448
- }
449
- /**
450
- * Parse paragraph properties from the MText content
451
- * Handles properties like indentation, alignment, and tab stops
452
- * @param ctx - The context to update
453
- */
454
- parseParagraphProperties(t) {
455
- const e = new d(this.extractExpression());
456
- let r = t.paragraph.indent, a = t.paragraph.left, h = t.paragraph.right, i = t.paragraph.align, u = [];
457
- const n = () => {
458
- const l = e.tail.match(/^[+-]?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?/);
459
- if (l) {
460
- const o = parseFloat(l[0]);
461
- for (e.consume(l[0].length); e.peek() === ","; )
462
- e.consume(1);
463
- return o;
464
- }
465
- return 0;
466
- };
467
- for (; e.hasData; )
468
- switch (e.get()) {
469
- case "i":
470
- r = n();
471
- break;
472
- case "l":
473
- a = n();
474
- break;
475
- case "r":
476
- h = n();
477
- break;
478
- case "x":
479
- break;
480
- case "q": {
481
- const o = e.get();
482
- for (i = v[o] || 0; e.peek() === ","; )
483
- e.consume(1);
484
- break;
485
- }
486
- case "t":
487
- for (u = []; e.hasData; ) {
488
- const o = e.peek();
489
- if (o === "r" || o === "c") {
490
- e.consume(1);
491
- const c = n();
492
- u.push(o + c.toString());
493
- } else {
494
- const c = n();
495
- isNaN(c) ? e.consume(1) : u.push(c);
496
- }
497
- }
498
- break;
499
- }
500
- t.paragraph = {
501
- indent: r,
502
- left: a,
503
- right: h,
504
- align: i,
505
- tabs: u
506
- };
507
- }
508
- /**
509
- * Consume optional terminator (semicolon)
510
- */
511
- consumeOptionalTerminator() {
512
- this.scanner.peek() === ";" && this.scanner.consume(1);
513
- }
514
- /**
515
- * Parse MText content into tokens
516
- * @yields MTextToken objects
517
- */
518
- *parse() {
519
- let r = null;
520
- function a(i) {
521
- const u = { ...i.paragraph };
522
- i.paragraph = {
523
- indent: 0,
524
- left: 0,
525
- right: 0,
526
- align: 0,
527
- tabs: []
528
- };
529
- const n = {};
530
- return u.indent !== 0 && (n.indent = 0), u.left !== 0 && (n.left = 0), u.right !== 0 && (n.right = 0), u.align !== 0 && (n.align = 0), JSON.stringify(u.tabs) !== JSON.stringify([]) && (n.tabs = []), n;
531
- }
532
- const h = () => {
533
- let i = "";
534
- for (; this.scanner.hasData; ) {
535
- let u = !1, n = this.scanner.peek();
536
- const l = this.scanner.currentIndex;
537
- if (n.charCodeAt(0) < 32) {
538
- if (this.scanner.consume(1), n === " ")
539
- return [5, null];
540
- if (n === `
541
- `)
542
- return [6, null];
543
- n = " ";
544
- }
545
- if (n === "\\")
546
- if ("\\{}".includes(this.scanner.peek(1)))
547
- u = !0, this.scanner.consume(1), n = this.scanner.peek();
548
- else {
549
- if (i)
550
- return [1, i];
551
- this.scanner.consume(1);
552
- const o = this.scanner.get();
553
- switch (o) {
554
- case "~":
555
- return [4, null];
556
- case "P":
557
- return [6, null];
558
- case "N":
559
- return [7, null];
560
- case "X":
561
- return [8, null];
562
- case "S": {
563
- this.inStackContext = !0;
564
- const c = this.parseStacking();
565
- return this.inStackContext = !1, c;
566
- }
567
- case "m":
568
- case "M":
569
- if (this.scanner.peek() === "+") {
570
- this.scanner.consume(1);
571
- const c = this.extractMifCode(this.mifCodeLength);
572
- if (c) {
573
- this.scanner.consume(c.length);
574
- const p = this.mifDecoder(c);
575
- return i ? [1, i] : [1, p];
576
- }
577
- this.scanner.consume(-1);
578
- }
579
- i += "\\M";
580
- continue;
581
- case "U":
582
- if (this.scanner.peek() === "+") {
583
- this.scanner.consume(1);
584
- const c = this.scanner.tail.match(/^[0-9A-Fa-f]{4,8}/);
585
- if (c) {
586
- const p = c[0];
587
- this.scanner.consume(p.length);
588
- const g = parseInt(p, 16);
589
- let f = "";
590
- try {
591
- f = String.fromCodePoint(g);
592
- } catch {
593
- f = "▯";
594
- }
595
- return i ? [1, i] : [1, f];
596
- }
597
- this.scanner.consume(-1);
598
- }
599
- i += "\\U";
600
- continue;
601
- default:
602
- if (o)
603
- try {
604
- const c = this.parseProperties(o);
605
- if (this.yieldPropertyCommands && c)
606
- return [9, c];
607
- continue;
608
- } catch {
609
- const c = this.scanner.tail.slice(
610
- l,
611
- this.scanner.currentIndex
612
- );
613
- i += c;
614
- }
615
- }
616
- continue;
617
- }
618
- if (n === "%" && this.scanner.peek(1) === "%") {
619
- const o = this.scanner.peek(2).toLowerCase(), c = R[o];
620
- if (c) {
621
- this.scanner.consume(3), i += c;
622
- continue;
623
- } else {
624
- const p = [o, this.scanner.peek(3), this.scanner.peek(4)];
625
- if (p.every((g) => g >= "0" && g <= "9")) {
626
- const g = Number.parseInt(p.join(""), 10);
627
- this.scanner.consume(5), i += String.fromCharCode(g);
628
- } else
629
- this.scanner.consume(3);
630
- continue;
631
- }
632
- }
633
- if (n === " ")
634
- return i ? (this.scanner.consume(1), r = 3, [1, i]) : (this.scanner.consume(1), [3, null]);
635
- if (!u) {
636
- if (n === "{") {
637
- if (i)
638
- return [1, i];
639
- this.scanner.consume(1), this.pushCtx();
640
- continue;
641
- } else if (n === "}") {
642
- if (i)
643
- return [1, i];
644
- if (this.scanner.consume(1), this.yieldPropertyCommands) {
645
- const o = this.ctxStack.current;
646
- this.popCtx();
647
- const c = this.getPropertyChanges(o, this.ctxStack.current);
648
- if (Object.keys(c).length > 0)
649
- return [
650
- 9,
651
- { command: void 0, changes: c, depth: this.ctxStack.depth }
652
- ];
653
- } else
654
- this.popCtx();
655
- continue;
656
- }
657
- }
658
- if (!this.inStackContext && n === "^") {
659
- const o = this.scanner.peek(1);
660
- if (o) {
661
- const c = o.charCodeAt(0);
662
- if (this.scanner.consume(2), c === 32)
663
- i += "^";
664
- else {
665
- if (c === 73)
666
- return i ? [1, i] : [5, null];
667
- if (c === 74)
668
- return i ? [1, i] : [6, null];
669
- if (c === 77)
670
- continue;
671
- i += "▯";
672
- }
673
- continue;
674
- }
675
- }
676
- this.scanner.consume(1), n.charCodeAt(0) >= 32 && (i += n);
677
- }
678
- return i ? [1, i] : [0, null];
679
- };
680
- for (; ; ) {
681
- const [i, u] = h.call(this);
682
- if (i) {
683
- if (yield new k(i, this.ctxStack.current.copy(), u), i === 6 && this.resetParagraphParameters) {
684
- const n = this.ctxStack.current, l = a(n);
685
- this.yieldPropertyCommands && Object.keys(l).length > 0 && (yield new k(9, n.copy(), {
686
- command: void 0,
687
- changes: { paragraph: l },
688
- depth: this.ctxStack.depth
689
- }));
690
- }
691
- r && (yield new k(r, this.ctxStack.current.copy(), null), r = null);
692
- } else
693
- break;
694
- }
695
- }
696
- }
697
- class d {
698
- /**
699
- * Create a new text scanner
700
- * @param text - The text to scan
701
- */
702
- constructor(t) {
703
- this.text = t, this.textLen = t.length, this._index = 0;
704
- }
705
- /**
706
- * Get the current index in the text
707
- */
708
- get currentIndex() {
709
- return this._index;
710
- }
711
- /**
712
- * Check if the scanner has reached the end of the text
713
- */
714
- get isEmpty() {
715
- return this._index >= this.textLen;
716
- }
717
- /**
718
- * Check if there is more text to scan
719
- */
720
- get hasData() {
721
- return this._index < this.textLen;
722
- }
723
- /**
724
- * Get the next character and advance the index
725
- * @returns The next character, or empty string if at end
726
- */
727
- get() {
728
- if (this.isEmpty)
729
- return "";
730
- const t = this.text[this._index];
731
- return this._index++, t;
732
- }
733
- /**
734
- * Advance the index by the specified count
735
- * @param count - Number of characters to advance
736
- */
737
- consume(t = 1) {
738
- this._index = Math.max(0, Math.min(this._index + t, this.textLen));
739
- }
740
- /**
741
- * Look at a character without advancing the index
742
- * @param offset - Offset from current position
743
- * @returns The character at the offset position, or empty string if out of bounds
744
- */
745
- peek(t = 0) {
746
- const e = this._index + t;
747
- return e >= this.textLen || e < 0 ? "" : this.text[e];
748
- }
749
- /**
750
- * Find the next occurrence of a character
751
- * @param char - The character to find
752
- * @param escape - Whether to handle escaped characters
753
- * @returns Index of the character, or -1 if not found
754
- */
755
- find(t, e = !1) {
756
- let r = this._index;
757
- for (; r < this.textLen; ) {
758
- if (e && this.text[r] === "\\") {
759
- if (r + 1 < this.textLen) {
760
- if (this.text[r + 1] === t)
761
- return r + 1;
762
- r += 2;
763
- continue;
764
- }
765
- r++;
766
- continue;
767
- }
768
- if (this.text[r] === t)
769
- return r;
770
- r++;
771
- }
772
- return -1;
773
- }
774
- /**
775
- * Get the remaining text from the current position
776
- */
777
- get tail() {
778
- return this.text.slice(this._index);
779
- }
780
- /**
781
- * Check if the next character is a space
782
- */
783
- isNextSpace() {
784
- return this.peek() === " ";
785
- }
786
- /**
787
- * Consume spaces until a non-space character is found
788
- * @returns Number of spaces consumed
789
- */
790
- consumeSpaces() {
791
- let t = 0;
792
- for (; this.isNextSpace(); )
793
- this.consume(), t++;
794
- return t;
795
- }
796
- }
797
- class b {
798
- // Store as 0xRRGGBB or null
799
- /**
800
- * Create a new MTextColor instance.
801
- * @param color The initial color: number for ACI, [r,g,b] for RGB, or null/undefined for default (ACI=256).
802
- */
803
- constructor(t) {
804
- this._aci = 256, this._rgbValue = null, Array.isArray(t) ? this.rgb = t : typeof t == "number" ? this.aci = t : this.aci = 256;
805
- }
806
- /**
807
- * Get the current ACI color value.
808
- * @returns The ACI color (0-256), or null if using RGB.
809
- */
810
- get aci() {
811
- return this._aci;
812
- }
813
- /**
814
- * Set the ACI color value. Setting this disables any RGB color.
815
- * @param value The ACI color (0-256), or null to unset.
816
- * @throws Error if value is out of range.
817
- */
818
- set aci(t) {
819
- if (t === null)
820
- this._aci = null;
821
- else if (t >= 0 && t <= 256)
822
- this._aci = t, this._rgbValue = null;
823
- else
824
- throw new Error("ACI not in range [0, 256]");
825
- }
826
- /**
827
- * Get the current RGB color as a tuple [r, g, b], or null if not set.
828
- * @returns The RGB color tuple, or null if using ACI.
829
- */
830
- get rgb() {
831
- if (this._rgbValue === null) return null;
832
- const t = this._rgbValue >> 16 & 255, e = this._rgbValue >> 8 & 255, r = this._rgbValue & 255;
833
- return [t, e, r];
834
- }
835
- /**
836
- * Set the RGB color. Setting this disables ACI color.
837
- * @param value The RGB color tuple [r, g, b], or null to use ACI.
838
- */
839
- set rgb(t) {
840
- if (t) {
841
- const [e, r, a] = t;
842
- this._rgbValue = (e & 255) << 16 | (r & 255) << 8 | a & 255, this._aci = null;
843
- } else
844
- this._rgbValue = null;
845
- }
846
- /**
847
- * Returns true if the color is set by RGB, false if by ACI.
848
- */
849
- get isRgb() {
850
- return this._rgbValue !== null;
851
- }
852
- /**
853
- * Returns true if the color is set by ACI, false if by RGB.
854
- */
855
- get isAci() {
856
- return this._rgbValue === null && this._aci !== null;
857
- }
858
- /**
859
- * Get or set the internal RGB value as a number (0xRRGGBB), or null if not set.
860
- * Setting this will switch to RGB mode and set ACI to null.
861
- */
862
- get rgbValue() {
863
- return this._rgbValue;
864
- }
865
- set rgbValue(t) {
866
- t === null ? this._rgbValue = null : (this._rgbValue = t & 16777215, this._aci = null);
867
- }
868
- /**
869
- * Returns a deep copy of this color.
870
- * @returns A new MTextColor instance with the same color state.
871
- */
872
- copy() {
873
- const t = new b();
874
- return t._aci = this._aci, t._rgbValue = this._rgbValue, t;
875
- }
876
- /**
877
- * Returns a plain object for serialization.
878
- * @returns An object with aci, rgb (tuple), and rgbValue (number or null).
879
- */
880
- toObject() {
881
- return { aci: this._aci, rgb: this.rgb, rgbValue: this._rgbValue };
882
- }
883
- /**
884
- * Equality check for color.
885
- * @param other The other MTextColor to compare.
886
- * @returns True if both ACI and RGB values are equal.
887
- */
888
- equals(t) {
889
- return this._aci === t._aci && this._rgbValue === t._rgbValue;
890
- }
891
- }
892
- class m {
893
- constructor() {
894
- this._stroke = 0, this.continueStroke = !1, this.color = new b(), this.align = 0, this.fontFace = { family: "", style: "Regular", weight: 400 }, this._capHeight = { value: 1, isRelative: !1 }, this._widthFactor = { value: 1, isRelative: !1 }, this._charTrackingFactor = { value: 1, isRelative: !1 }, this.oblique = 0, this.paragraph = {
895
- indent: 0,
896
- left: 0,
897
- right: 0,
898
- align: 0,
899
- tabs: []
900
- };
901
- }
902
- /**
903
- * Get the capital letter height
904
- */
905
- get capHeight() {
906
- return this._capHeight;
907
- }
908
- /**
909
- * Set the capital letter height
910
- * @param value - Height value
911
- */
912
- set capHeight(t) {
913
- this._capHeight = {
914
- value: Math.abs(t.value),
915
- isRelative: t.isRelative
916
- };
917
- }
918
- /**
919
- * Get the character width factor
920
- */
921
- get widthFactor() {
922
- return this._widthFactor;
923
- }
924
- /**
925
- * Set the character width factor
926
- * @param value - Width factor value
927
- */
928
- set widthFactor(t) {
929
- this._widthFactor = {
930
- value: Math.abs(t.value),
931
- isRelative: t.isRelative
932
- };
933
- }
934
- /**
935
- * Get the character tracking factor
936
- */
937
- get charTrackingFactor() {
938
- return this._charTrackingFactor;
939
- }
940
- /**
941
- * Set the character tracking factor
942
- * @param value - Tracking factor value
943
- */
944
- set charTrackingFactor(t) {
945
- this._charTrackingFactor = {
946
- value: Math.abs(t.value),
947
- isRelative: t.isRelative
948
- };
949
- }
950
- /**
951
- * Get the ACI color value
952
- */
953
- get aci() {
954
- return this.color.aci;
955
- }
956
- /**
957
- * Set the ACI color value
958
- * @param value - ACI color value (0-256)
959
- * @throws Error if value is out of range
960
- */
961
- set aci(t) {
962
- this.color.aci = t;
963
- }
964
- /**
965
- * Get the RGB color value
966
- */
967
- get rgb() {
968
- return this.color.rgb;
969
- }
970
- /**
971
- * Set the RGB color value
972
- */
973
- set rgb(t) {
974
- this.color.rgb = t;
975
- }
976
- /**
977
- * Gets whether the current text should be rendered in italic style.
978
- * @returns {boolean} True if the font style is 'Italic', otherwise false.
979
- */
980
- get italic() {
981
- return this.fontFace.style === "Italic";
982
- }
983
- /**
984
- * Sets whether the current text should be rendered in italic style.
985
- * @param value - If true, sets the font style to 'Italic'; if false, sets it to 'Regular'.
986
- */
987
- set italic(t) {
988
- this.fontFace.style = t ? "Italic" : "Regular";
989
- }
990
- /**
991
- * Gets whether the current text should be rendered in bold style.
992
- * This is primarily used for mesh fonts and affects font selection.
993
- * @returns {boolean} True if the font weight is 700 or higher, otherwise false.
994
- */
995
- get bold() {
996
- return (this.fontFace.weight || 400) >= 700;
997
- }
998
- /**
999
- * Sets whether the current text should be rendered in bold style.
1000
- * This is primarily used for mesh fonts and affects font selection.
1001
- * @param value - If true, sets the font weight to 700; if false, sets it to 400.
1002
- */
1003
- set bold(t) {
1004
- this.fontFace.weight = t ? 700 : 400;
1005
- }
1006
- /**
1007
- * Get whether text is underlined
1008
- */
1009
- get underline() {
1010
- return !!(this._stroke & 1);
1011
- }
1012
- /**
1013
- * Set whether text is underlined
1014
- * @param value - Whether to underline
1015
- */
1016
- set underline(t) {
1017
- this._setStrokeState(1, t);
1018
- }
1019
- /**
1020
- * Get whether text has strike-through
1021
- */
1022
- get strikeThrough() {
1023
- return !!(this._stroke & 4);
1024
- }
1025
- /**
1026
- * Set whether text has strike-through
1027
- * @param value - Whether to strike through
1028
- */
1029
- set strikeThrough(t) {
1030
- this._setStrokeState(4, t);
1031
- }
1032
- /**
1033
- * Get whether text has overline
1034
- */
1035
- get overline() {
1036
- return !!(this._stroke & 2);
1037
- }
1038
- /**
1039
- * Set whether text has overline
1040
- * @param value - Whether to overline
1041
- */
1042
- set overline(t) {
1043
- this._setStrokeState(2, t);
1044
- }
1045
- /**
1046
- * Check if any stroke formatting is active
1047
- */
1048
- get hasAnyStroke() {
1049
- return !!this._stroke;
1050
- }
1051
- /**
1052
- * Set the state of a stroke type
1053
- * @param stroke - The stroke type to set
1054
- * @param state - Whether to enable or disable the stroke
1055
- */
1056
- _setStrokeState(t, e = !0) {
1057
- e ? this._stroke |= t : this._stroke &= ~t;
1058
- }
1059
- /**
1060
- * Create a copy of this context
1061
- * @returns A new context with the same properties
1062
- */
1063
- copy() {
1064
- const t = new m();
1065
- return t._stroke = this._stroke, t.continueStroke = this.continueStroke, t.color = this.color.copy(), t.align = this.align, t.fontFace = { ...this.fontFace }, t._capHeight = { ...this._capHeight }, t._widthFactor = { ...this._widthFactor }, t._charTrackingFactor = { ...this._charTrackingFactor }, t.oblique = this.oblique, t.paragraph = { ...this.paragraph }, t;
1066
- }
1067
- }
1068
- class k {
1069
- /**
1070
- * Create a new MText token
1071
- * @param type - The token type
1072
- * @param ctx - The text context at this token
1073
- * @param data - Optional token data
1074
- */
1075
- constructor(t, e, r) {
1076
- this.type = t, this.ctx = e, this.data = r;
1077
- }
1078
- }
1079
- export {
1080
- b as MTextColor,
1081
- m as MTextContext,
1082
- F as MTextLineAlignment,
1083
- S as MTextParagraphAlignment,
1084
- x as MTextParser,
1085
- E as MTextStroke,
1086
- k as MTextToken,
1087
- d as TextScanner,
1088
- _ as TokenType,
1089
- N as escapeDxfLineEndings,
1090
- D as getFonts,
1091
- w as hasInlineFormattingCodes,
1092
- O as int2rgb,
1093
- I as rgb2int
1094
- };
1095
- //# sourceMappingURL=parser.es.js.map