@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.
- package/README.md +6 -0
- package/dist/parser.cjs.js +4 -0
- package/dist/parser.cjs.js.map +1 -0
- package/dist/parser.es.js +727 -0
- package/dist/parser.es.js.map +1 -0
- package/dist/parser.umd.js +4 -0
- package/dist/parser.umd.js.map +1 -0
- package/dist/{parser.d.ts → types/parser.d.ts} +33 -1
- package/package.json +16 -9
- package/dist/example.js +0 -125
- package/dist/parser.js +0 -1036
- package/dist/parser.test.d.ts +0 -1
- package/dist/parser.test.js +0 -733
- /package/dist/{example.d.ts → types/example.d.ts} +0 -0
|
@@ -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
|