@omrips/viewstl 2.0.0-rc.1 → 2.0.0-rc.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,3833 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ try {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ } catch (e) {
11
+ throw mod = 0, e;
12
+ }
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
+ mod
29
+ ));
30
+
31
+ // node_modules/.pnpm/xmlchars@2.2.0/node_modules/xmlchars/xml/1.0/ed5.js
32
+ var require_ed5 = __commonJS({
33
+ "node_modules/.pnpm/xmlchars@2.2.0/node_modules/xmlchars/xml/1.0/ed5.js"(exports) {
34
+ "use strict";
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.CHAR = " \n\r -\uD7FF\uE000-\uFFFD\u{10000}-\u{10FFFF}";
37
+ exports.S = " \r\n";
38
+ exports.NAME_START_CHAR = ":A-Z_a-z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u{10000}-\u{EFFFF}";
39
+ exports.NAME_CHAR = "-" + exports.NAME_START_CHAR + ".0-9\xB7\u0300-\u036F\u203F-\u2040";
40
+ exports.CHAR_RE = new RegExp("^[" + exports.CHAR + "]$", "u");
41
+ exports.S_RE = new RegExp("^[" + exports.S + "]+$", "u");
42
+ exports.NAME_START_CHAR_RE = new RegExp("^[" + exports.NAME_START_CHAR + "]$", "u");
43
+ exports.NAME_CHAR_RE = new RegExp("^[" + exports.NAME_CHAR + "]$", "u");
44
+ exports.NAME_RE = new RegExp("^[" + exports.NAME_START_CHAR + "][" + exports.NAME_CHAR + "]*$", "u");
45
+ exports.NMTOKEN_RE = new RegExp("^[" + exports.NAME_CHAR + "]+$", "u");
46
+ var TAB = 9;
47
+ var NL = 10;
48
+ var CR = 13;
49
+ var SPACE = 32;
50
+ exports.S_LIST = [SPACE, NL, CR, TAB];
51
+ function isChar(c) {
52
+ return c >= SPACE && c <= 55295 || c === NL || c === CR || c === TAB || c >= 57344 && c <= 65533 || c >= 65536 && c <= 1114111;
53
+ }
54
+ exports.isChar = isChar;
55
+ function isS(c) {
56
+ return c === SPACE || c === NL || c === CR || c === TAB;
57
+ }
58
+ exports.isS = isS;
59
+ function isNameStartChar(c) {
60
+ return c >= 65 && c <= 90 || c >= 97 && c <= 122 || c === 58 || c === 95 || c === 8204 || c === 8205 || c >= 192 && c <= 214 || c >= 216 && c <= 246 || c >= 248 && c <= 767 || c >= 880 && c <= 893 || c >= 895 && c <= 8191 || c >= 8304 && c <= 8591 || c >= 11264 && c <= 12271 || c >= 12289 && c <= 55295 || c >= 63744 && c <= 64975 || c >= 65008 && c <= 65533 || c >= 65536 && c <= 983039;
61
+ }
62
+ exports.isNameStartChar = isNameStartChar;
63
+ function isNameChar(c) {
64
+ return isNameStartChar(c) || c >= 48 && c <= 57 || c === 45 || c === 46 || c === 183 || c >= 768 && c <= 879 || c >= 8255 && c <= 8256;
65
+ }
66
+ exports.isNameChar = isNameChar;
67
+ }
68
+ });
69
+
70
+ // node_modules/.pnpm/xmlchars@2.2.0/node_modules/xmlchars/xml/1.1/ed2.js
71
+ var require_ed2 = __commonJS({
72
+ "node_modules/.pnpm/xmlchars@2.2.0/node_modules/xmlchars/xml/1.1/ed2.js"(exports) {
73
+ "use strict";
74
+ Object.defineProperty(exports, "__esModule", { value: true });
75
+ exports.CHAR = "-\uD7FF\uE000-\uFFFD\u{10000}-\u{10FFFF}";
76
+ exports.RESTRICTED_CHAR = "-\b\v\f-\x7F-\x84\x86-\x9F";
77
+ exports.S = " \r\n";
78
+ exports.NAME_START_CHAR = ":A-Z_a-z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u{10000}-\u{EFFFF}";
79
+ exports.NAME_CHAR = "-" + exports.NAME_START_CHAR + ".0-9\xB7\u0300-\u036F\u203F-\u2040";
80
+ exports.CHAR_RE = new RegExp("^[" + exports.CHAR + "]$", "u");
81
+ exports.RESTRICTED_CHAR_RE = new RegExp("^[" + exports.RESTRICTED_CHAR + "]$", "u");
82
+ exports.S_RE = new RegExp("^[" + exports.S + "]+$", "u");
83
+ exports.NAME_START_CHAR_RE = new RegExp("^[" + exports.NAME_START_CHAR + "]$", "u");
84
+ exports.NAME_CHAR_RE = new RegExp("^[" + exports.NAME_CHAR + "]$", "u");
85
+ exports.NAME_RE = new RegExp("^[" + exports.NAME_START_CHAR + "][" + exports.NAME_CHAR + "]*$", "u");
86
+ exports.NMTOKEN_RE = new RegExp("^[" + exports.NAME_CHAR + "]+$", "u");
87
+ var TAB = 9;
88
+ var NL = 10;
89
+ var CR = 13;
90
+ var SPACE = 32;
91
+ exports.S_LIST = [SPACE, NL, CR, TAB];
92
+ function isChar(c) {
93
+ return c >= 1 && c <= 55295 || c >= 57344 && c <= 65533 || c >= 65536 && c <= 1114111;
94
+ }
95
+ exports.isChar = isChar;
96
+ function isRestrictedChar(c) {
97
+ return c >= 1 && c <= 8 || c === 11 || c === 12 || c >= 14 && c <= 31 || c >= 127 && c <= 132 || c >= 134 && c <= 159;
98
+ }
99
+ exports.isRestrictedChar = isRestrictedChar;
100
+ function isCharAndNotRestricted(c) {
101
+ return c === 9 || c === 10 || c === 13 || c > 31 && c < 127 || c === 133 || c > 159 && c <= 55295 || c >= 57344 && c <= 65533 || c >= 65536 && c <= 1114111;
102
+ }
103
+ exports.isCharAndNotRestricted = isCharAndNotRestricted;
104
+ function isS(c) {
105
+ return c === SPACE || c === NL || c === CR || c === TAB;
106
+ }
107
+ exports.isS = isS;
108
+ function isNameStartChar(c) {
109
+ return c >= 65 && c <= 90 || c >= 97 && c <= 122 || c === 58 || c === 95 || c === 8204 || c === 8205 || c >= 192 && c <= 214 || c >= 216 && c <= 246 || c >= 248 && c <= 767 || c >= 880 && c <= 893 || c >= 895 && c <= 8191 || c >= 8304 && c <= 8591 || c >= 11264 && c <= 12271 || c >= 12289 && c <= 55295 || c >= 63744 && c <= 64975 || c >= 65008 && c <= 65533 || c >= 65536 && c <= 983039;
110
+ }
111
+ exports.isNameStartChar = isNameStartChar;
112
+ function isNameChar(c) {
113
+ return isNameStartChar(c) || c >= 48 && c <= 57 || c === 45 || c === 46 || c === 183 || c >= 768 && c <= 879 || c >= 8255 && c <= 8256;
114
+ }
115
+ exports.isNameChar = isNameChar;
116
+ }
117
+ });
118
+
119
+ // node_modules/.pnpm/xmlchars@2.2.0/node_modules/xmlchars/xmlns/1.0/ed3.js
120
+ var require_ed3 = __commonJS({
121
+ "node_modules/.pnpm/xmlchars@2.2.0/node_modules/xmlchars/xmlns/1.0/ed3.js"(exports) {
122
+ "use strict";
123
+ Object.defineProperty(exports, "__esModule", { value: true });
124
+ exports.NC_NAME_START_CHAR = "A-Z_a-z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u{10000}-\u{EFFFF}";
125
+ exports.NC_NAME_CHAR = "-" + exports.NC_NAME_START_CHAR + ".0-9\xB7\u0300-\u036F\u203F-\u2040";
126
+ exports.NC_NAME_START_CHAR_RE = new RegExp("^[" + exports.NC_NAME_START_CHAR + "]$", "u");
127
+ exports.NC_NAME_CHAR_RE = new RegExp("^[" + exports.NC_NAME_CHAR + "]$", "u");
128
+ exports.NC_NAME_RE = new RegExp("^[" + exports.NC_NAME_START_CHAR + "][" + exports.NC_NAME_CHAR + "]*$", "u");
129
+ function isNCNameStartChar(c) {
130
+ return c >= 65 && c <= 90 || c === 95 || c >= 97 && c <= 122 || c >= 192 && c <= 214 || c >= 216 && c <= 246 || c >= 248 && c <= 767 || c >= 880 && c <= 893 || c >= 895 && c <= 8191 || c >= 8204 && c <= 8205 || c >= 8304 && c <= 8591 || c >= 11264 && c <= 12271 || c >= 12289 && c <= 55295 || c >= 63744 && c <= 64975 || c >= 65008 && c <= 65533 || c >= 65536 && c <= 983039;
131
+ }
132
+ exports.isNCNameStartChar = isNCNameStartChar;
133
+ function isNCNameChar(c) {
134
+ return isNCNameStartChar(c) || (c === 45 || c === 46 || c >= 48 && c <= 57 || c === 183 || c >= 768 && c <= 879 || c >= 8255 && c <= 8256);
135
+ }
136
+ exports.isNCNameChar = isNCNameChar;
137
+ }
138
+ });
139
+
140
+ // node_modules/.pnpm/saxes@6.0.0/node_modules/saxes/saxes.js
141
+ var require_saxes = __commonJS({
142
+ "node_modules/.pnpm/saxes@6.0.0/node_modules/saxes/saxes.js"(exports) {
143
+ "use strict";
144
+ Object.defineProperty(exports, "__esModule", { value: true });
145
+ exports.SaxesParser = exports.EVENTS = void 0;
146
+ var ed5 = require_ed5();
147
+ var ed2 = require_ed2();
148
+ var NSed3 = require_ed3();
149
+ var isS = ed5.isS;
150
+ var isChar10 = ed5.isChar;
151
+ var isNameStartChar = ed5.isNameStartChar;
152
+ var isNameChar = ed5.isNameChar;
153
+ var S_LIST = ed5.S_LIST;
154
+ var NAME_RE = ed5.NAME_RE;
155
+ var isChar11 = ed2.isChar;
156
+ var isNCNameStartChar = NSed3.isNCNameStartChar;
157
+ var isNCNameChar = NSed3.isNCNameChar;
158
+ var NC_NAME_RE = NSed3.NC_NAME_RE;
159
+ var XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace";
160
+ var XMLNS_NAMESPACE = "http://www.w3.org/2000/xmlns/";
161
+ var rootNS = {
162
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment
163
+ __proto__: null,
164
+ xml: XML_NAMESPACE,
165
+ xmlns: XMLNS_NAMESPACE
166
+ };
167
+ var XML_ENTITIES = {
168
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment
169
+ __proto__: null,
170
+ amp: "&",
171
+ gt: ">",
172
+ lt: "<",
173
+ quot: '"',
174
+ apos: "'"
175
+ };
176
+ var EOC = -1;
177
+ var NL_LIKE = -2;
178
+ var S_BEGIN = 0;
179
+ var S_BEGIN_WHITESPACE = 1;
180
+ var S_DOCTYPE = 2;
181
+ var S_DOCTYPE_QUOTE = 3;
182
+ var S_DTD = 4;
183
+ var S_DTD_QUOTED = 5;
184
+ var S_DTD_OPEN_WAKA = 6;
185
+ var S_DTD_OPEN_WAKA_BANG = 7;
186
+ var S_DTD_COMMENT = 8;
187
+ var S_DTD_COMMENT_ENDING = 9;
188
+ var S_DTD_COMMENT_ENDED = 10;
189
+ var S_DTD_PI = 11;
190
+ var S_DTD_PI_ENDING = 12;
191
+ var S_TEXT = 13;
192
+ var S_ENTITY = 14;
193
+ var S_OPEN_WAKA = 15;
194
+ var S_OPEN_WAKA_BANG = 16;
195
+ var S_COMMENT = 17;
196
+ var S_COMMENT_ENDING = 18;
197
+ var S_COMMENT_ENDED = 19;
198
+ var S_CDATA = 20;
199
+ var S_CDATA_ENDING = 21;
200
+ var S_CDATA_ENDING_2 = 22;
201
+ var S_PI_FIRST_CHAR = 23;
202
+ var S_PI_REST = 24;
203
+ var S_PI_BODY = 25;
204
+ var S_PI_ENDING = 26;
205
+ var S_XML_DECL_NAME_START = 27;
206
+ var S_XML_DECL_NAME = 28;
207
+ var S_XML_DECL_EQ = 29;
208
+ var S_XML_DECL_VALUE_START = 30;
209
+ var S_XML_DECL_VALUE = 31;
210
+ var S_XML_DECL_SEPARATOR = 32;
211
+ var S_XML_DECL_ENDING = 33;
212
+ var S_OPEN_TAG = 34;
213
+ var S_OPEN_TAG_SLASH = 35;
214
+ var S_ATTRIB = 36;
215
+ var S_ATTRIB_NAME = 37;
216
+ var S_ATTRIB_NAME_SAW_WHITE = 38;
217
+ var S_ATTRIB_VALUE = 39;
218
+ var S_ATTRIB_VALUE_QUOTED = 40;
219
+ var S_ATTRIB_VALUE_CLOSED = 41;
220
+ var S_ATTRIB_VALUE_UNQUOTED = 42;
221
+ var S_CLOSE_TAG = 43;
222
+ var S_CLOSE_TAG_SAW_WHITE = 44;
223
+ var TAB = 9;
224
+ var NL = 10;
225
+ var CR = 13;
226
+ var SPACE = 32;
227
+ var BANG = 33;
228
+ var DQUOTE = 34;
229
+ var AMP = 38;
230
+ var SQUOTE = 39;
231
+ var MINUS = 45;
232
+ var FORWARD_SLASH = 47;
233
+ var SEMICOLON = 59;
234
+ var LESS = 60;
235
+ var EQUAL = 61;
236
+ var GREATER = 62;
237
+ var QUESTION = 63;
238
+ var OPEN_BRACKET = 91;
239
+ var CLOSE_BRACKET = 93;
240
+ var NEL = 133;
241
+ var LS = 8232;
242
+ var isQuote = (c) => c === DQUOTE || c === SQUOTE;
243
+ var QUOTES = [DQUOTE, SQUOTE];
244
+ var DOCTYPE_TERMINATOR = [...QUOTES, OPEN_BRACKET, GREATER];
245
+ var DTD_TERMINATOR = [...QUOTES, LESS, CLOSE_BRACKET];
246
+ var XML_DECL_NAME_TERMINATOR = [EQUAL, QUESTION, ...S_LIST];
247
+ var ATTRIB_VALUE_UNQUOTED_TERMINATOR = [...S_LIST, GREATER, AMP, LESS];
248
+ function nsPairCheck(parser, prefix, uri) {
249
+ switch (prefix) {
250
+ case "xml":
251
+ if (uri !== XML_NAMESPACE) {
252
+ parser.fail(`xml prefix must be bound to ${XML_NAMESPACE}.`);
253
+ }
254
+ break;
255
+ case "xmlns":
256
+ if (uri !== XMLNS_NAMESPACE) {
257
+ parser.fail(`xmlns prefix must be bound to ${XMLNS_NAMESPACE}.`);
258
+ }
259
+ break;
260
+ default:
261
+ }
262
+ switch (uri) {
263
+ case XMLNS_NAMESPACE:
264
+ parser.fail(prefix === "" ? `the default namespace may not be set to ${uri}.` : `may not assign a prefix (even "xmlns") to the URI ${XMLNS_NAMESPACE}.`);
265
+ break;
266
+ case XML_NAMESPACE:
267
+ switch (prefix) {
268
+ case "xml":
269
+ break;
270
+ case "":
271
+ parser.fail(`the default namespace may not be set to ${uri}.`);
272
+ break;
273
+ default:
274
+ parser.fail("may not assign the xml namespace to another prefix.");
275
+ }
276
+ break;
277
+ default:
278
+ }
279
+ }
280
+ function nsMappingCheck(parser, mapping) {
281
+ for (const local of Object.keys(mapping)) {
282
+ nsPairCheck(parser, local, mapping[local]);
283
+ }
284
+ }
285
+ var isNCName = (name) => NC_NAME_RE.test(name);
286
+ var isName = (name) => NAME_RE.test(name);
287
+ var FORBIDDEN_START = 0;
288
+ var FORBIDDEN_BRACKET = 1;
289
+ var FORBIDDEN_BRACKET_BRACKET = 2;
290
+ exports.EVENTS = [
291
+ "xmldecl",
292
+ "text",
293
+ "processinginstruction",
294
+ "doctype",
295
+ "comment",
296
+ "opentagstart",
297
+ "attribute",
298
+ "opentag",
299
+ "closetag",
300
+ "cdata",
301
+ "error",
302
+ "end",
303
+ "ready"
304
+ ];
305
+ var EVENT_NAME_TO_HANDLER_NAME = {
306
+ xmldecl: "xmldeclHandler",
307
+ text: "textHandler",
308
+ processinginstruction: "piHandler",
309
+ doctype: "doctypeHandler",
310
+ comment: "commentHandler",
311
+ opentagstart: "openTagStartHandler",
312
+ attribute: "attributeHandler",
313
+ opentag: "openTagHandler",
314
+ closetag: "closeTagHandler",
315
+ cdata: "cdataHandler",
316
+ error: "errorHandler",
317
+ end: "endHandler",
318
+ ready: "readyHandler"
319
+ };
320
+ var SaxesParser2 = class {
321
+ /**
322
+ * @param opt The parser options.
323
+ */
324
+ constructor(opt) {
325
+ this.opt = opt !== null && opt !== void 0 ? opt : {};
326
+ this.fragmentOpt = !!this.opt.fragment;
327
+ const xmlnsOpt = this.xmlnsOpt = !!this.opt.xmlns;
328
+ this.trackPosition = this.opt.position !== false;
329
+ this.fileName = this.opt.fileName;
330
+ if (xmlnsOpt) {
331
+ this.nameStartCheck = isNCNameStartChar;
332
+ this.nameCheck = isNCNameChar;
333
+ this.isName = isNCName;
334
+ this.processAttribs = this.processAttribsNS;
335
+ this.pushAttrib = this.pushAttribNS;
336
+ this.ns = Object.assign({ __proto__: null }, rootNS);
337
+ const additional = this.opt.additionalNamespaces;
338
+ if (additional != null) {
339
+ nsMappingCheck(this, additional);
340
+ Object.assign(this.ns, additional);
341
+ }
342
+ } else {
343
+ this.nameStartCheck = isNameStartChar;
344
+ this.nameCheck = isNameChar;
345
+ this.isName = isName;
346
+ this.processAttribs = this.processAttribsPlain;
347
+ this.pushAttrib = this.pushAttribPlain;
348
+ }
349
+ this.stateTable = [
350
+ /* eslint-disable @typescript-eslint/unbound-method */
351
+ this.sBegin,
352
+ this.sBeginWhitespace,
353
+ this.sDoctype,
354
+ this.sDoctypeQuote,
355
+ this.sDTD,
356
+ this.sDTDQuoted,
357
+ this.sDTDOpenWaka,
358
+ this.sDTDOpenWakaBang,
359
+ this.sDTDComment,
360
+ this.sDTDCommentEnding,
361
+ this.sDTDCommentEnded,
362
+ this.sDTDPI,
363
+ this.sDTDPIEnding,
364
+ this.sText,
365
+ this.sEntity,
366
+ this.sOpenWaka,
367
+ this.sOpenWakaBang,
368
+ this.sComment,
369
+ this.sCommentEnding,
370
+ this.sCommentEnded,
371
+ this.sCData,
372
+ this.sCDataEnding,
373
+ this.sCDataEnding2,
374
+ this.sPIFirstChar,
375
+ this.sPIRest,
376
+ this.sPIBody,
377
+ this.sPIEnding,
378
+ this.sXMLDeclNameStart,
379
+ this.sXMLDeclName,
380
+ this.sXMLDeclEq,
381
+ this.sXMLDeclValueStart,
382
+ this.sXMLDeclValue,
383
+ this.sXMLDeclSeparator,
384
+ this.sXMLDeclEnding,
385
+ this.sOpenTag,
386
+ this.sOpenTagSlash,
387
+ this.sAttrib,
388
+ this.sAttribName,
389
+ this.sAttribNameSawWhite,
390
+ this.sAttribValue,
391
+ this.sAttribValueQuoted,
392
+ this.sAttribValueClosed,
393
+ this.sAttribValueUnquoted,
394
+ this.sCloseTag,
395
+ this.sCloseTagSawWhite
396
+ /* eslint-enable @typescript-eslint/unbound-method */
397
+ ];
398
+ this._init();
399
+ }
400
+ /**
401
+ * Indicates whether or not the parser is closed. If ``true``, wait for
402
+ * the ``ready`` event to write again.
403
+ */
404
+ get closed() {
405
+ return this._closed;
406
+ }
407
+ _init() {
408
+ var _a2;
409
+ this.openWakaBang = "";
410
+ this.text = "";
411
+ this.name = "";
412
+ this.piTarget = "";
413
+ this.entity = "";
414
+ this.q = null;
415
+ this.tags = [];
416
+ this.tag = null;
417
+ this.topNS = null;
418
+ this.chunk = "";
419
+ this.chunkPosition = 0;
420
+ this.i = 0;
421
+ this.prevI = 0;
422
+ this.carriedFromPrevious = void 0;
423
+ this.forbiddenState = FORBIDDEN_START;
424
+ this.attribList = [];
425
+ const { fragmentOpt } = this;
426
+ this.state = fragmentOpt ? S_TEXT : S_BEGIN;
427
+ this.reportedTextBeforeRoot = this.reportedTextAfterRoot = this.closedRoot = this.sawRoot = fragmentOpt;
428
+ this.xmlDeclPossible = !fragmentOpt;
429
+ this.xmlDeclExpects = ["version"];
430
+ this.entityReturnState = void 0;
431
+ let { defaultXMLVersion } = this.opt;
432
+ if (defaultXMLVersion === void 0) {
433
+ if (this.opt.forceXMLVersion === true) {
434
+ throw new Error("forceXMLVersion set but defaultXMLVersion is not set");
435
+ }
436
+ defaultXMLVersion = "1.0";
437
+ }
438
+ this.setXMLVersion(defaultXMLVersion);
439
+ this.positionAtNewLine = 0;
440
+ this.doctype = false;
441
+ this._closed = false;
442
+ this.xmlDecl = {
443
+ version: void 0,
444
+ encoding: void 0,
445
+ standalone: void 0
446
+ };
447
+ this.line = 1;
448
+ this.column = 0;
449
+ this.ENTITIES = Object.create(XML_ENTITIES);
450
+ (_a2 = this.readyHandler) === null || _a2 === void 0 ? void 0 : _a2.call(this);
451
+ }
452
+ /**
453
+ * The stream position the parser is currently looking at. This field is
454
+ * zero-based.
455
+ *
456
+ * This field is not based on counting Unicode characters but is to be
457
+ * interpreted as a plain index into a JavaScript string.
458
+ */
459
+ get position() {
460
+ return this.chunkPosition + this.i;
461
+ }
462
+ /**
463
+ * The column number of the next character to be read by the parser. *
464
+ * This field is zero-based. (The first column in a line is 0.)
465
+ *
466
+ * This field reports the index at which the next character would be in the
467
+ * line if the line were represented as a JavaScript string. Note that this
468
+ * *can* be different to a count based on the number of *Unicode characters*
469
+ * due to how JavaScript handles astral plane characters.
470
+ *
471
+ * See [[column]] for a number that corresponds to a count of Unicode
472
+ * characters.
473
+ */
474
+ get columnIndex() {
475
+ return this.position - this.positionAtNewLine;
476
+ }
477
+ /**
478
+ * Set an event listener on an event. The parser supports one handler per
479
+ * event type. If you try to set an event handler over an existing handler,
480
+ * the old handler is silently overwritten.
481
+ *
482
+ * @param name The event to listen to.
483
+ *
484
+ * @param handler The handler to set.
485
+ */
486
+ on(name, handler) {
487
+ this[EVENT_NAME_TO_HANDLER_NAME[name]] = handler;
488
+ }
489
+ /**
490
+ * Unset an event handler.
491
+ *
492
+ * @parma name The event to stop listening to.
493
+ */
494
+ off(name) {
495
+ this[EVENT_NAME_TO_HANDLER_NAME[name]] = void 0;
496
+ }
497
+ /**
498
+ * Make an error object. The error object will have a message that contains
499
+ * the ``fileName`` option passed at the creation of the parser. If position
500
+ * tracking was turned on, it will also have line and column number
501
+ * information.
502
+ *
503
+ * @param message The message describing the error to report.
504
+ *
505
+ * @returns An error object with a properly formatted message.
506
+ */
507
+ makeError(message) {
508
+ var _a2;
509
+ let msg = (_a2 = this.fileName) !== null && _a2 !== void 0 ? _a2 : "";
510
+ if (this.trackPosition) {
511
+ if (msg.length > 0) {
512
+ msg += ":";
513
+ }
514
+ msg += `${this.line}:${this.column}`;
515
+ }
516
+ if (msg.length > 0) {
517
+ msg += ": ";
518
+ }
519
+ return new Error(msg + message);
520
+ }
521
+ /**
522
+ * Report a parsing error. This method is made public so that client code may
523
+ * check for issues that are outside the scope of this project and can report
524
+ * errors.
525
+ *
526
+ * @param message The error to report.
527
+ *
528
+ * @returns this
529
+ */
530
+ fail(message) {
531
+ const err2 = this.makeError(message);
532
+ const handler = this.errorHandler;
533
+ if (handler === void 0) {
534
+ throw err2;
535
+ } else {
536
+ handler(err2);
537
+ }
538
+ return this;
539
+ }
540
+ /**
541
+ * Write a XML data to the parser.
542
+ *
543
+ * @param chunk The XML data to write.
544
+ *
545
+ * @returns this
546
+ */
547
+ // We do need object for the type here. Yes, it often causes problems
548
+ // but not in this case.
549
+ write(chunk) {
550
+ if (this.closed) {
551
+ return this.fail("cannot write after close; assign an onready handler.");
552
+ }
553
+ let end = false;
554
+ if (chunk === null) {
555
+ end = true;
556
+ chunk = "";
557
+ } else if (typeof chunk === "object") {
558
+ chunk = chunk.toString();
559
+ }
560
+ if (this.carriedFromPrevious !== void 0) {
561
+ chunk = `${this.carriedFromPrevious}${chunk}`;
562
+ this.carriedFromPrevious = void 0;
563
+ }
564
+ let limit = chunk.length;
565
+ const lastCode = chunk.charCodeAt(limit - 1);
566
+ if (!end && // A trailing CR or surrogate must be carried over to the next
567
+ // chunk.
568
+ (lastCode === CR || lastCode >= 55296 && lastCode <= 56319)) {
569
+ this.carriedFromPrevious = chunk[limit - 1];
570
+ limit--;
571
+ chunk = chunk.slice(0, limit);
572
+ }
573
+ const { stateTable } = this;
574
+ this.chunk = chunk;
575
+ this.i = 0;
576
+ while (this.i < limit) {
577
+ stateTable[this.state].call(this);
578
+ }
579
+ this.chunkPosition += limit;
580
+ return end ? this.end() : this;
581
+ }
582
+ /**
583
+ * Close the current stream. Perform final well-formedness checks and reset
584
+ * the parser tstate.
585
+ *
586
+ * @returns this
587
+ */
588
+ close() {
589
+ return this.write(null);
590
+ }
591
+ /**
592
+ * Get a single code point out of the current chunk. This updates the current
593
+ * position if we do position tracking.
594
+ *
595
+ * This is the algorithm to use for XML 1.0.
596
+ *
597
+ * @returns The character read.
598
+ */
599
+ getCode10() {
600
+ const { chunk, i: i2 } = this;
601
+ this.prevI = i2;
602
+ this.i = i2 + 1;
603
+ if (i2 >= chunk.length) {
604
+ return EOC;
605
+ }
606
+ const code = chunk.charCodeAt(i2);
607
+ this.column++;
608
+ if (code < 55296) {
609
+ if (code >= SPACE || code === TAB) {
610
+ return code;
611
+ }
612
+ switch (code) {
613
+ case NL:
614
+ this.line++;
615
+ this.column = 0;
616
+ this.positionAtNewLine = this.position;
617
+ return NL;
618
+ case CR:
619
+ if (chunk.charCodeAt(i2 + 1) === NL) {
620
+ this.i = i2 + 2;
621
+ }
622
+ this.line++;
623
+ this.column = 0;
624
+ this.positionAtNewLine = this.position;
625
+ return NL_LIKE;
626
+ default:
627
+ this.fail("disallowed character.");
628
+ return code;
629
+ }
630
+ }
631
+ if (code > 56319) {
632
+ if (!(code >= 57344 && code <= 65533)) {
633
+ this.fail("disallowed character.");
634
+ }
635
+ return code;
636
+ }
637
+ const final = 65536 + (code - 55296) * 1024 + (chunk.charCodeAt(i2 + 1) - 56320);
638
+ this.i = i2 + 2;
639
+ if (final > 1114111) {
640
+ this.fail("disallowed character.");
641
+ }
642
+ return final;
643
+ }
644
+ /**
645
+ * Get a single code point out of the current chunk. This updates the current
646
+ * position if we do position tracking.
647
+ *
648
+ * This is the algorithm to use for XML 1.1.
649
+ *
650
+ * @returns {number} The character read.
651
+ */
652
+ getCode11() {
653
+ const { chunk, i: i2 } = this;
654
+ this.prevI = i2;
655
+ this.i = i2 + 1;
656
+ if (i2 >= chunk.length) {
657
+ return EOC;
658
+ }
659
+ const code = chunk.charCodeAt(i2);
660
+ this.column++;
661
+ if (code < 55296) {
662
+ if (code > 31 && code < 127 || code > 159 && code !== LS || code === TAB) {
663
+ return code;
664
+ }
665
+ switch (code) {
666
+ case NL:
667
+ this.line++;
668
+ this.column = 0;
669
+ this.positionAtNewLine = this.position;
670
+ return NL;
671
+ case CR: {
672
+ const next = chunk.charCodeAt(i2 + 1);
673
+ if (next === NL || next === NEL) {
674
+ this.i = i2 + 2;
675
+ }
676
+ }
677
+ /* yes, fall through */
678
+ case NEL:
679
+ // 0x85
680
+ case LS:
681
+ this.line++;
682
+ this.column = 0;
683
+ this.positionAtNewLine = this.position;
684
+ return NL_LIKE;
685
+ default:
686
+ this.fail("disallowed character.");
687
+ return code;
688
+ }
689
+ }
690
+ if (code > 56319) {
691
+ if (!(code >= 57344 && code <= 65533)) {
692
+ this.fail("disallowed character.");
693
+ }
694
+ return code;
695
+ }
696
+ const final = 65536 + (code - 55296) * 1024 + (chunk.charCodeAt(i2 + 1) - 56320);
697
+ this.i = i2 + 2;
698
+ if (final > 1114111) {
699
+ this.fail("disallowed character.");
700
+ }
701
+ return final;
702
+ }
703
+ /**
704
+ * Like ``getCode`` but with the return value normalized so that ``NL`` is
705
+ * returned for ``NL_LIKE``.
706
+ */
707
+ getCodeNorm() {
708
+ const c = this.getCode();
709
+ return c === NL_LIKE ? NL : c;
710
+ }
711
+ unget() {
712
+ this.i = this.prevI;
713
+ this.column--;
714
+ }
715
+ /**
716
+ * Capture characters into a buffer until encountering one of a set of
717
+ * characters.
718
+ *
719
+ * @param chars An array of codepoints. Encountering a character in the array
720
+ * ends the capture. (``chars`` may safely contain ``NL``.)
721
+ *
722
+ * @return The character code that made the capture end, or ``EOC`` if we hit
723
+ * the end of the chunk. The return value cannot be NL_LIKE: NL is returned
724
+ * instead.
725
+ */
726
+ captureTo(chars) {
727
+ let { i: start2 } = this;
728
+ const { chunk } = this;
729
+ while (true) {
730
+ const c = this.getCode();
731
+ const isNLLike = c === NL_LIKE;
732
+ const final = isNLLike ? NL : c;
733
+ if (final === EOC || chars.includes(final)) {
734
+ this.text += chunk.slice(start2, this.prevI);
735
+ return final;
736
+ }
737
+ if (isNLLike) {
738
+ this.text += `${chunk.slice(start2, this.prevI)}
739
+ `;
740
+ start2 = this.i;
741
+ }
742
+ }
743
+ }
744
+ /**
745
+ * Capture characters into a buffer until encountering a character.
746
+ *
747
+ * @param char The codepoint that ends the capture. **NOTE ``char`` MAY NOT
748
+ * CONTAIN ``NL``.** Passing ``NL`` will result in buggy behavior.
749
+ *
750
+ * @return ``true`` if we ran into the character. Otherwise, we ran into the
751
+ * end of the current chunk.
752
+ */
753
+ captureToChar(char) {
754
+ let { i: start2 } = this;
755
+ const { chunk } = this;
756
+ while (true) {
757
+ let c = this.getCode();
758
+ switch (c) {
759
+ case NL_LIKE:
760
+ this.text += `${chunk.slice(start2, this.prevI)}
761
+ `;
762
+ start2 = this.i;
763
+ c = NL;
764
+ break;
765
+ case EOC:
766
+ this.text += chunk.slice(start2);
767
+ return false;
768
+ default:
769
+ }
770
+ if (c === char) {
771
+ this.text += chunk.slice(start2, this.prevI);
772
+ return true;
773
+ }
774
+ }
775
+ }
776
+ /**
777
+ * Capture characters that satisfy ``isNameChar`` into the ``name`` field of
778
+ * this parser.
779
+ *
780
+ * @return The character code that made the test fail, or ``EOC`` if we hit
781
+ * the end of the chunk. The return value cannot be NL_LIKE: NL is returned
782
+ * instead.
783
+ */
784
+ captureNameChars() {
785
+ const { chunk, i: start2 } = this;
786
+ while (true) {
787
+ const c = this.getCode();
788
+ if (c === EOC) {
789
+ this.name += chunk.slice(start2);
790
+ return EOC;
791
+ }
792
+ if (!isNameChar(c)) {
793
+ this.name += chunk.slice(start2, this.prevI);
794
+ return c === NL_LIKE ? NL : c;
795
+ }
796
+ }
797
+ }
798
+ /**
799
+ * Skip white spaces.
800
+ *
801
+ * @return The character that ended the skip, or ``EOC`` if we hit
802
+ * the end of the chunk. The return value cannot be NL_LIKE: NL is returned
803
+ * instead.
804
+ */
805
+ skipSpaces() {
806
+ while (true) {
807
+ const c = this.getCodeNorm();
808
+ if (c === EOC || !isS(c)) {
809
+ return c;
810
+ }
811
+ }
812
+ }
813
+ setXMLVersion(version) {
814
+ this.currentXMLVersion = version;
815
+ if (version === "1.0") {
816
+ this.isChar = isChar10;
817
+ this.getCode = this.getCode10;
818
+ } else {
819
+ this.isChar = isChar11;
820
+ this.getCode = this.getCode11;
821
+ }
822
+ }
823
+ // STATE ENGINE METHODS
824
+ // This needs to be a state separate from S_BEGIN_WHITESPACE because we want
825
+ // to be sure never to come back to this state later.
826
+ sBegin() {
827
+ if (this.chunk.charCodeAt(0) === 65279) {
828
+ this.i++;
829
+ this.column++;
830
+ }
831
+ this.state = S_BEGIN_WHITESPACE;
832
+ }
833
+ sBeginWhitespace() {
834
+ const iBefore = this.i;
835
+ const c = this.skipSpaces();
836
+ if (this.prevI !== iBefore) {
837
+ this.xmlDeclPossible = false;
838
+ }
839
+ switch (c) {
840
+ case LESS:
841
+ this.state = S_OPEN_WAKA;
842
+ if (this.text.length !== 0) {
843
+ throw new Error("no-empty text at start");
844
+ }
845
+ break;
846
+ case EOC:
847
+ break;
848
+ default:
849
+ this.unget();
850
+ this.state = S_TEXT;
851
+ this.xmlDeclPossible = false;
852
+ }
853
+ }
854
+ sDoctype() {
855
+ var _a2;
856
+ const c = this.captureTo(DOCTYPE_TERMINATOR);
857
+ switch (c) {
858
+ case GREATER: {
859
+ (_a2 = this.doctypeHandler) === null || _a2 === void 0 ? void 0 : _a2.call(this, this.text);
860
+ this.text = "";
861
+ this.state = S_TEXT;
862
+ this.doctype = true;
863
+ break;
864
+ }
865
+ case EOC:
866
+ break;
867
+ default:
868
+ this.text += String.fromCodePoint(c);
869
+ if (c === OPEN_BRACKET) {
870
+ this.state = S_DTD;
871
+ } else if (isQuote(c)) {
872
+ this.state = S_DOCTYPE_QUOTE;
873
+ this.q = c;
874
+ }
875
+ }
876
+ }
877
+ sDoctypeQuote() {
878
+ const q = this.q;
879
+ if (this.captureToChar(q)) {
880
+ this.text += String.fromCodePoint(q);
881
+ this.q = null;
882
+ this.state = S_DOCTYPE;
883
+ }
884
+ }
885
+ sDTD() {
886
+ const c = this.captureTo(DTD_TERMINATOR);
887
+ if (c === EOC) {
888
+ return;
889
+ }
890
+ this.text += String.fromCodePoint(c);
891
+ if (c === CLOSE_BRACKET) {
892
+ this.state = S_DOCTYPE;
893
+ } else if (c === LESS) {
894
+ this.state = S_DTD_OPEN_WAKA;
895
+ } else if (isQuote(c)) {
896
+ this.state = S_DTD_QUOTED;
897
+ this.q = c;
898
+ }
899
+ }
900
+ sDTDQuoted() {
901
+ const q = this.q;
902
+ if (this.captureToChar(q)) {
903
+ this.text += String.fromCodePoint(q);
904
+ this.state = S_DTD;
905
+ this.q = null;
906
+ }
907
+ }
908
+ sDTDOpenWaka() {
909
+ const c = this.getCodeNorm();
910
+ this.text += String.fromCodePoint(c);
911
+ switch (c) {
912
+ case BANG:
913
+ this.state = S_DTD_OPEN_WAKA_BANG;
914
+ this.openWakaBang = "";
915
+ break;
916
+ case QUESTION:
917
+ this.state = S_DTD_PI;
918
+ break;
919
+ default:
920
+ this.state = S_DTD;
921
+ }
922
+ }
923
+ sDTDOpenWakaBang() {
924
+ const char = String.fromCodePoint(this.getCodeNorm());
925
+ const owb = this.openWakaBang += char;
926
+ this.text += char;
927
+ if (owb !== "-") {
928
+ this.state = owb === "--" ? S_DTD_COMMENT : S_DTD;
929
+ this.openWakaBang = "";
930
+ }
931
+ }
932
+ sDTDComment() {
933
+ if (this.captureToChar(MINUS)) {
934
+ this.text += "-";
935
+ this.state = S_DTD_COMMENT_ENDING;
936
+ }
937
+ }
938
+ sDTDCommentEnding() {
939
+ const c = this.getCodeNorm();
940
+ this.text += String.fromCodePoint(c);
941
+ this.state = c === MINUS ? S_DTD_COMMENT_ENDED : S_DTD_COMMENT;
942
+ }
943
+ sDTDCommentEnded() {
944
+ const c = this.getCodeNorm();
945
+ this.text += String.fromCodePoint(c);
946
+ if (c === GREATER) {
947
+ this.state = S_DTD;
948
+ } else {
949
+ this.fail("malformed comment.");
950
+ this.state = S_DTD_COMMENT;
951
+ }
952
+ }
953
+ sDTDPI() {
954
+ if (this.captureToChar(QUESTION)) {
955
+ this.text += "?";
956
+ this.state = S_DTD_PI_ENDING;
957
+ }
958
+ }
959
+ sDTDPIEnding() {
960
+ const c = this.getCodeNorm();
961
+ this.text += String.fromCodePoint(c);
962
+ if (c === GREATER) {
963
+ this.state = S_DTD;
964
+ }
965
+ }
966
+ sText() {
967
+ if (this.tags.length !== 0) {
968
+ this.handleTextInRoot();
969
+ } else {
970
+ this.handleTextOutsideRoot();
971
+ }
972
+ }
973
+ sEntity() {
974
+ let { i: start2 } = this;
975
+ const { chunk } = this;
976
+ loop:
977
+ while (true) {
978
+ switch (this.getCode()) {
979
+ case NL_LIKE:
980
+ this.entity += `${chunk.slice(start2, this.prevI)}
981
+ `;
982
+ start2 = this.i;
983
+ break;
984
+ case SEMICOLON: {
985
+ const { entityReturnState } = this;
986
+ const entity = this.entity + chunk.slice(start2, this.prevI);
987
+ this.state = entityReturnState;
988
+ let parsed;
989
+ if (entity === "") {
990
+ this.fail("empty entity name.");
991
+ parsed = "&;";
992
+ } else {
993
+ parsed = this.parseEntity(entity);
994
+ this.entity = "";
995
+ }
996
+ if (entityReturnState !== S_TEXT || this.textHandler !== void 0) {
997
+ this.text += parsed;
998
+ }
999
+ break loop;
1000
+ }
1001
+ case EOC:
1002
+ this.entity += chunk.slice(start2);
1003
+ break loop;
1004
+ default:
1005
+ }
1006
+ }
1007
+ }
1008
+ sOpenWaka() {
1009
+ const c = this.getCode();
1010
+ if (isNameStartChar(c)) {
1011
+ this.state = S_OPEN_TAG;
1012
+ this.unget();
1013
+ this.xmlDeclPossible = false;
1014
+ } else {
1015
+ switch (c) {
1016
+ case FORWARD_SLASH:
1017
+ this.state = S_CLOSE_TAG;
1018
+ this.xmlDeclPossible = false;
1019
+ break;
1020
+ case BANG:
1021
+ this.state = S_OPEN_WAKA_BANG;
1022
+ this.openWakaBang = "";
1023
+ this.xmlDeclPossible = false;
1024
+ break;
1025
+ case QUESTION:
1026
+ this.state = S_PI_FIRST_CHAR;
1027
+ break;
1028
+ default:
1029
+ this.fail("disallowed character in tag name");
1030
+ this.state = S_TEXT;
1031
+ this.xmlDeclPossible = false;
1032
+ }
1033
+ }
1034
+ }
1035
+ sOpenWakaBang() {
1036
+ this.openWakaBang += String.fromCodePoint(this.getCodeNorm());
1037
+ switch (this.openWakaBang) {
1038
+ case "[CDATA[":
1039
+ if (!this.sawRoot && !this.reportedTextBeforeRoot) {
1040
+ this.fail("text data outside of root node.");
1041
+ this.reportedTextBeforeRoot = true;
1042
+ }
1043
+ if (this.closedRoot && !this.reportedTextAfterRoot) {
1044
+ this.fail("text data outside of root node.");
1045
+ this.reportedTextAfterRoot = true;
1046
+ }
1047
+ this.state = S_CDATA;
1048
+ this.openWakaBang = "";
1049
+ break;
1050
+ case "--":
1051
+ this.state = S_COMMENT;
1052
+ this.openWakaBang = "";
1053
+ break;
1054
+ case "DOCTYPE":
1055
+ this.state = S_DOCTYPE;
1056
+ if (this.doctype || this.sawRoot) {
1057
+ this.fail("inappropriately located doctype declaration.");
1058
+ }
1059
+ this.openWakaBang = "";
1060
+ break;
1061
+ default:
1062
+ if (this.openWakaBang.length >= 7) {
1063
+ this.fail("incorrect syntax.");
1064
+ }
1065
+ }
1066
+ }
1067
+ sComment() {
1068
+ if (this.captureToChar(MINUS)) {
1069
+ this.state = S_COMMENT_ENDING;
1070
+ }
1071
+ }
1072
+ sCommentEnding() {
1073
+ var _a2;
1074
+ const c = this.getCodeNorm();
1075
+ if (c === MINUS) {
1076
+ this.state = S_COMMENT_ENDED;
1077
+ (_a2 = this.commentHandler) === null || _a2 === void 0 ? void 0 : _a2.call(this, this.text);
1078
+ this.text = "";
1079
+ } else {
1080
+ this.text += `-${String.fromCodePoint(c)}`;
1081
+ this.state = S_COMMENT;
1082
+ }
1083
+ }
1084
+ sCommentEnded() {
1085
+ const c = this.getCodeNorm();
1086
+ if (c !== GREATER) {
1087
+ this.fail("malformed comment.");
1088
+ this.text += `--${String.fromCodePoint(c)}`;
1089
+ this.state = S_COMMENT;
1090
+ } else {
1091
+ this.state = S_TEXT;
1092
+ }
1093
+ }
1094
+ sCData() {
1095
+ if (this.captureToChar(CLOSE_BRACKET)) {
1096
+ this.state = S_CDATA_ENDING;
1097
+ }
1098
+ }
1099
+ sCDataEnding() {
1100
+ const c = this.getCodeNorm();
1101
+ if (c === CLOSE_BRACKET) {
1102
+ this.state = S_CDATA_ENDING_2;
1103
+ } else {
1104
+ this.text += `]${String.fromCodePoint(c)}`;
1105
+ this.state = S_CDATA;
1106
+ }
1107
+ }
1108
+ sCDataEnding2() {
1109
+ var _a2;
1110
+ const c = this.getCodeNorm();
1111
+ switch (c) {
1112
+ case GREATER: {
1113
+ (_a2 = this.cdataHandler) === null || _a2 === void 0 ? void 0 : _a2.call(this, this.text);
1114
+ this.text = "";
1115
+ this.state = S_TEXT;
1116
+ break;
1117
+ }
1118
+ case CLOSE_BRACKET:
1119
+ this.text += "]";
1120
+ break;
1121
+ default:
1122
+ this.text += `]]${String.fromCodePoint(c)}`;
1123
+ this.state = S_CDATA;
1124
+ }
1125
+ }
1126
+ // We need this separate state to check the first character fo the pi target
1127
+ // with this.nameStartCheck which allows less characters than this.nameCheck.
1128
+ sPIFirstChar() {
1129
+ const c = this.getCodeNorm();
1130
+ if (this.nameStartCheck(c)) {
1131
+ this.piTarget += String.fromCodePoint(c);
1132
+ this.state = S_PI_REST;
1133
+ } else if (c === QUESTION || isS(c)) {
1134
+ this.fail("processing instruction without a target.");
1135
+ this.state = c === QUESTION ? S_PI_ENDING : S_PI_BODY;
1136
+ } else {
1137
+ this.fail("disallowed character in processing instruction name.");
1138
+ this.piTarget += String.fromCodePoint(c);
1139
+ this.state = S_PI_REST;
1140
+ }
1141
+ }
1142
+ sPIRest() {
1143
+ const { chunk, i: start2 } = this;
1144
+ while (true) {
1145
+ const c = this.getCodeNorm();
1146
+ if (c === EOC) {
1147
+ this.piTarget += chunk.slice(start2);
1148
+ return;
1149
+ }
1150
+ if (!this.nameCheck(c)) {
1151
+ this.piTarget += chunk.slice(start2, this.prevI);
1152
+ const isQuestion = c === QUESTION;
1153
+ if (isQuestion || isS(c)) {
1154
+ if (this.piTarget === "xml") {
1155
+ if (!this.xmlDeclPossible) {
1156
+ this.fail("an XML declaration must be at the start of the document.");
1157
+ }
1158
+ this.state = isQuestion ? S_XML_DECL_ENDING : S_XML_DECL_NAME_START;
1159
+ } else {
1160
+ this.state = isQuestion ? S_PI_ENDING : S_PI_BODY;
1161
+ }
1162
+ } else {
1163
+ this.fail("disallowed character in processing instruction name.");
1164
+ this.piTarget += String.fromCodePoint(c);
1165
+ }
1166
+ break;
1167
+ }
1168
+ }
1169
+ }
1170
+ sPIBody() {
1171
+ if (this.text.length === 0) {
1172
+ const c = this.getCodeNorm();
1173
+ if (c === QUESTION) {
1174
+ this.state = S_PI_ENDING;
1175
+ } else if (!isS(c)) {
1176
+ this.text = String.fromCodePoint(c);
1177
+ }
1178
+ } else if (this.captureToChar(QUESTION)) {
1179
+ this.state = S_PI_ENDING;
1180
+ }
1181
+ }
1182
+ sPIEnding() {
1183
+ var _a2;
1184
+ const c = this.getCodeNorm();
1185
+ if (c === GREATER) {
1186
+ const { piTarget } = this;
1187
+ if (piTarget.toLowerCase() === "xml") {
1188
+ this.fail("the XML declaration must appear at the start of the document.");
1189
+ }
1190
+ (_a2 = this.piHandler) === null || _a2 === void 0 ? void 0 : _a2.call(this, {
1191
+ target: piTarget,
1192
+ body: this.text
1193
+ });
1194
+ this.piTarget = this.text = "";
1195
+ this.state = S_TEXT;
1196
+ } else if (c === QUESTION) {
1197
+ this.text += "?";
1198
+ } else {
1199
+ this.text += `?${String.fromCodePoint(c)}`;
1200
+ this.state = S_PI_BODY;
1201
+ }
1202
+ this.xmlDeclPossible = false;
1203
+ }
1204
+ sXMLDeclNameStart() {
1205
+ const c = this.skipSpaces();
1206
+ if (c === QUESTION) {
1207
+ this.state = S_XML_DECL_ENDING;
1208
+ return;
1209
+ }
1210
+ if (c !== EOC) {
1211
+ this.state = S_XML_DECL_NAME;
1212
+ this.name = String.fromCodePoint(c);
1213
+ }
1214
+ }
1215
+ sXMLDeclName() {
1216
+ const c = this.captureTo(XML_DECL_NAME_TERMINATOR);
1217
+ if (c === QUESTION) {
1218
+ this.state = S_XML_DECL_ENDING;
1219
+ this.name += this.text;
1220
+ this.text = "";
1221
+ this.fail("XML declaration is incomplete.");
1222
+ return;
1223
+ }
1224
+ if (!(isS(c) || c === EQUAL)) {
1225
+ return;
1226
+ }
1227
+ this.name += this.text;
1228
+ this.text = "";
1229
+ if (!this.xmlDeclExpects.includes(this.name)) {
1230
+ switch (this.name.length) {
1231
+ case 0:
1232
+ this.fail("did not expect any more name/value pairs.");
1233
+ break;
1234
+ case 1:
1235
+ this.fail(`expected the name ${this.xmlDeclExpects[0]}.`);
1236
+ break;
1237
+ default:
1238
+ this.fail(`expected one of ${this.xmlDeclExpects.join(", ")}`);
1239
+ }
1240
+ }
1241
+ this.state = c === EQUAL ? S_XML_DECL_VALUE_START : S_XML_DECL_EQ;
1242
+ }
1243
+ sXMLDeclEq() {
1244
+ const c = this.getCodeNorm();
1245
+ if (c === QUESTION) {
1246
+ this.state = S_XML_DECL_ENDING;
1247
+ this.fail("XML declaration is incomplete.");
1248
+ return;
1249
+ }
1250
+ if (isS(c)) {
1251
+ return;
1252
+ }
1253
+ if (c !== EQUAL) {
1254
+ this.fail("value required.");
1255
+ }
1256
+ this.state = S_XML_DECL_VALUE_START;
1257
+ }
1258
+ sXMLDeclValueStart() {
1259
+ const c = this.getCodeNorm();
1260
+ if (c === QUESTION) {
1261
+ this.state = S_XML_DECL_ENDING;
1262
+ this.fail("XML declaration is incomplete.");
1263
+ return;
1264
+ }
1265
+ if (isS(c)) {
1266
+ return;
1267
+ }
1268
+ if (!isQuote(c)) {
1269
+ this.fail("value must be quoted.");
1270
+ this.q = SPACE;
1271
+ } else {
1272
+ this.q = c;
1273
+ }
1274
+ this.state = S_XML_DECL_VALUE;
1275
+ }
1276
+ sXMLDeclValue() {
1277
+ const c = this.captureTo([this.q, QUESTION]);
1278
+ if (c === QUESTION) {
1279
+ this.state = S_XML_DECL_ENDING;
1280
+ this.text = "";
1281
+ this.fail("XML declaration is incomplete.");
1282
+ return;
1283
+ }
1284
+ if (c === EOC) {
1285
+ return;
1286
+ }
1287
+ const value = this.text;
1288
+ this.text = "";
1289
+ switch (this.name) {
1290
+ case "version": {
1291
+ this.xmlDeclExpects = ["encoding", "standalone"];
1292
+ const version = value;
1293
+ this.xmlDecl.version = version;
1294
+ if (!/^1\.[0-9]+$/.test(version)) {
1295
+ this.fail("version number must match /^1\\.[0-9]+$/.");
1296
+ } else if (!this.opt.forceXMLVersion) {
1297
+ this.setXMLVersion(version);
1298
+ }
1299
+ break;
1300
+ }
1301
+ case "encoding":
1302
+ if (!/^[A-Za-z][A-Za-z0-9._-]*$/.test(value)) {
1303
+ this.fail("encoding value must match /^[A-Za-z0-9][A-Za-z0-9._-]*$/.");
1304
+ }
1305
+ this.xmlDeclExpects = ["standalone"];
1306
+ this.xmlDecl.encoding = value;
1307
+ break;
1308
+ case "standalone":
1309
+ if (value !== "yes" && value !== "no") {
1310
+ this.fail('standalone value must match "yes" or "no".');
1311
+ }
1312
+ this.xmlDeclExpects = [];
1313
+ this.xmlDecl.standalone = value;
1314
+ break;
1315
+ default:
1316
+ }
1317
+ this.name = "";
1318
+ this.state = S_XML_DECL_SEPARATOR;
1319
+ }
1320
+ sXMLDeclSeparator() {
1321
+ const c = this.getCodeNorm();
1322
+ if (c === QUESTION) {
1323
+ this.state = S_XML_DECL_ENDING;
1324
+ return;
1325
+ }
1326
+ if (!isS(c)) {
1327
+ this.fail("whitespace required.");
1328
+ this.unget();
1329
+ }
1330
+ this.state = S_XML_DECL_NAME_START;
1331
+ }
1332
+ sXMLDeclEnding() {
1333
+ var _a2;
1334
+ const c = this.getCodeNorm();
1335
+ if (c === GREATER) {
1336
+ if (this.piTarget !== "xml") {
1337
+ this.fail("processing instructions are not allowed before root.");
1338
+ } else if (this.name !== "version" && this.xmlDeclExpects.includes("version")) {
1339
+ this.fail("XML declaration must contain a version.");
1340
+ }
1341
+ (_a2 = this.xmldeclHandler) === null || _a2 === void 0 ? void 0 : _a2.call(this, this.xmlDecl);
1342
+ this.name = "";
1343
+ this.piTarget = this.text = "";
1344
+ this.state = S_TEXT;
1345
+ } else {
1346
+ this.fail("The character ? is disallowed anywhere in XML declarations.");
1347
+ }
1348
+ this.xmlDeclPossible = false;
1349
+ }
1350
+ sOpenTag() {
1351
+ var _a2;
1352
+ const c = this.captureNameChars();
1353
+ if (c === EOC) {
1354
+ return;
1355
+ }
1356
+ const tag = this.tag = {
1357
+ name: this.name,
1358
+ attributes: /* @__PURE__ */ Object.create(null)
1359
+ };
1360
+ this.name = "";
1361
+ if (this.xmlnsOpt) {
1362
+ this.topNS = tag.ns = /* @__PURE__ */ Object.create(null);
1363
+ }
1364
+ (_a2 = this.openTagStartHandler) === null || _a2 === void 0 ? void 0 : _a2.call(this, tag);
1365
+ this.sawRoot = true;
1366
+ if (!this.fragmentOpt && this.closedRoot) {
1367
+ this.fail("documents may contain only one root.");
1368
+ }
1369
+ switch (c) {
1370
+ case GREATER:
1371
+ this.openTag();
1372
+ break;
1373
+ case FORWARD_SLASH:
1374
+ this.state = S_OPEN_TAG_SLASH;
1375
+ break;
1376
+ default:
1377
+ if (!isS(c)) {
1378
+ this.fail("disallowed character in tag name.");
1379
+ }
1380
+ this.state = S_ATTRIB;
1381
+ }
1382
+ }
1383
+ sOpenTagSlash() {
1384
+ if (this.getCode() === GREATER) {
1385
+ this.openSelfClosingTag();
1386
+ } else {
1387
+ this.fail("forward-slash in opening tag not followed by >.");
1388
+ this.state = S_ATTRIB;
1389
+ }
1390
+ }
1391
+ sAttrib() {
1392
+ const c = this.skipSpaces();
1393
+ if (c === EOC) {
1394
+ return;
1395
+ }
1396
+ if (isNameStartChar(c)) {
1397
+ this.unget();
1398
+ this.state = S_ATTRIB_NAME;
1399
+ } else if (c === GREATER) {
1400
+ this.openTag();
1401
+ } else if (c === FORWARD_SLASH) {
1402
+ this.state = S_OPEN_TAG_SLASH;
1403
+ } else {
1404
+ this.fail("disallowed character in attribute name.");
1405
+ }
1406
+ }
1407
+ sAttribName() {
1408
+ const c = this.captureNameChars();
1409
+ if (c === EQUAL) {
1410
+ this.state = S_ATTRIB_VALUE;
1411
+ } else if (isS(c)) {
1412
+ this.state = S_ATTRIB_NAME_SAW_WHITE;
1413
+ } else if (c === GREATER) {
1414
+ this.fail("attribute without value.");
1415
+ this.pushAttrib(this.name, this.name);
1416
+ this.name = this.text = "";
1417
+ this.openTag();
1418
+ } else if (c !== EOC) {
1419
+ this.fail("disallowed character in attribute name.");
1420
+ }
1421
+ }
1422
+ sAttribNameSawWhite() {
1423
+ const c = this.skipSpaces();
1424
+ switch (c) {
1425
+ case EOC:
1426
+ return;
1427
+ case EQUAL:
1428
+ this.state = S_ATTRIB_VALUE;
1429
+ break;
1430
+ default:
1431
+ this.fail("attribute without value.");
1432
+ this.text = "";
1433
+ this.name = "";
1434
+ if (c === GREATER) {
1435
+ this.openTag();
1436
+ } else if (isNameStartChar(c)) {
1437
+ this.unget();
1438
+ this.state = S_ATTRIB_NAME;
1439
+ } else {
1440
+ this.fail("disallowed character in attribute name.");
1441
+ this.state = S_ATTRIB;
1442
+ }
1443
+ }
1444
+ }
1445
+ sAttribValue() {
1446
+ const c = this.getCodeNorm();
1447
+ if (isQuote(c)) {
1448
+ this.q = c;
1449
+ this.state = S_ATTRIB_VALUE_QUOTED;
1450
+ } else if (!isS(c)) {
1451
+ this.fail("unquoted attribute value.");
1452
+ this.state = S_ATTRIB_VALUE_UNQUOTED;
1453
+ this.unget();
1454
+ }
1455
+ }
1456
+ sAttribValueQuoted() {
1457
+ const { q, chunk } = this;
1458
+ let { i: start2 } = this;
1459
+ while (true) {
1460
+ switch (this.getCode()) {
1461
+ case q:
1462
+ this.pushAttrib(this.name, this.text + chunk.slice(start2, this.prevI));
1463
+ this.name = this.text = "";
1464
+ this.q = null;
1465
+ this.state = S_ATTRIB_VALUE_CLOSED;
1466
+ return;
1467
+ case AMP:
1468
+ this.text += chunk.slice(start2, this.prevI);
1469
+ this.state = S_ENTITY;
1470
+ this.entityReturnState = S_ATTRIB_VALUE_QUOTED;
1471
+ return;
1472
+ case NL:
1473
+ case NL_LIKE:
1474
+ case TAB:
1475
+ this.text += `${chunk.slice(start2, this.prevI)} `;
1476
+ start2 = this.i;
1477
+ break;
1478
+ case LESS:
1479
+ this.text += chunk.slice(start2, this.prevI);
1480
+ this.fail("disallowed character.");
1481
+ return;
1482
+ case EOC:
1483
+ this.text += chunk.slice(start2);
1484
+ return;
1485
+ default:
1486
+ }
1487
+ }
1488
+ }
1489
+ sAttribValueClosed() {
1490
+ const c = this.getCodeNorm();
1491
+ if (isS(c)) {
1492
+ this.state = S_ATTRIB;
1493
+ } else if (c === GREATER) {
1494
+ this.openTag();
1495
+ } else if (c === FORWARD_SLASH) {
1496
+ this.state = S_OPEN_TAG_SLASH;
1497
+ } else if (isNameStartChar(c)) {
1498
+ this.fail("no whitespace between attributes.");
1499
+ this.unget();
1500
+ this.state = S_ATTRIB_NAME;
1501
+ } else {
1502
+ this.fail("disallowed character in attribute name.");
1503
+ }
1504
+ }
1505
+ sAttribValueUnquoted() {
1506
+ const c = this.captureTo(ATTRIB_VALUE_UNQUOTED_TERMINATOR);
1507
+ switch (c) {
1508
+ case AMP:
1509
+ this.state = S_ENTITY;
1510
+ this.entityReturnState = S_ATTRIB_VALUE_UNQUOTED;
1511
+ break;
1512
+ case LESS:
1513
+ this.fail("disallowed character.");
1514
+ break;
1515
+ case EOC:
1516
+ break;
1517
+ default:
1518
+ if (this.text.includes("]]>")) {
1519
+ this.fail('the string "]]>" is disallowed in char data.');
1520
+ }
1521
+ this.pushAttrib(this.name, this.text);
1522
+ this.name = this.text = "";
1523
+ if (c === GREATER) {
1524
+ this.openTag();
1525
+ } else {
1526
+ this.state = S_ATTRIB;
1527
+ }
1528
+ }
1529
+ }
1530
+ sCloseTag() {
1531
+ const c = this.captureNameChars();
1532
+ if (c === GREATER) {
1533
+ this.closeTag();
1534
+ } else if (isS(c)) {
1535
+ this.state = S_CLOSE_TAG_SAW_WHITE;
1536
+ } else if (c !== EOC) {
1537
+ this.fail("disallowed character in closing tag.");
1538
+ }
1539
+ }
1540
+ sCloseTagSawWhite() {
1541
+ switch (this.skipSpaces()) {
1542
+ case GREATER:
1543
+ this.closeTag();
1544
+ break;
1545
+ case EOC:
1546
+ break;
1547
+ default:
1548
+ this.fail("disallowed character in closing tag.");
1549
+ }
1550
+ }
1551
+ // END OF STATE ENGINE METHODS
1552
+ handleTextInRoot() {
1553
+ let { i: start2, forbiddenState } = this;
1554
+ const { chunk, textHandler: handler } = this;
1555
+ scanLoop:
1556
+ while (true) {
1557
+ switch (this.getCode()) {
1558
+ case LESS: {
1559
+ this.state = S_OPEN_WAKA;
1560
+ if (handler !== void 0) {
1561
+ const { text } = this;
1562
+ const slice = chunk.slice(start2, this.prevI);
1563
+ if (text.length !== 0) {
1564
+ handler(text + slice);
1565
+ this.text = "";
1566
+ } else if (slice.length !== 0) {
1567
+ handler(slice);
1568
+ }
1569
+ }
1570
+ forbiddenState = FORBIDDEN_START;
1571
+ break scanLoop;
1572
+ }
1573
+ case AMP:
1574
+ this.state = S_ENTITY;
1575
+ this.entityReturnState = S_TEXT;
1576
+ if (handler !== void 0) {
1577
+ this.text += chunk.slice(start2, this.prevI);
1578
+ }
1579
+ forbiddenState = FORBIDDEN_START;
1580
+ break scanLoop;
1581
+ case CLOSE_BRACKET:
1582
+ switch (forbiddenState) {
1583
+ case FORBIDDEN_START:
1584
+ forbiddenState = FORBIDDEN_BRACKET;
1585
+ break;
1586
+ case FORBIDDEN_BRACKET:
1587
+ forbiddenState = FORBIDDEN_BRACKET_BRACKET;
1588
+ break;
1589
+ case FORBIDDEN_BRACKET_BRACKET:
1590
+ break;
1591
+ default:
1592
+ throw new Error("impossible state");
1593
+ }
1594
+ break;
1595
+ case GREATER:
1596
+ if (forbiddenState === FORBIDDEN_BRACKET_BRACKET) {
1597
+ this.fail('the string "]]>" is disallowed in char data.');
1598
+ }
1599
+ forbiddenState = FORBIDDEN_START;
1600
+ break;
1601
+ case NL_LIKE:
1602
+ if (handler !== void 0) {
1603
+ this.text += `${chunk.slice(start2, this.prevI)}
1604
+ `;
1605
+ }
1606
+ start2 = this.i;
1607
+ forbiddenState = FORBIDDEN_START;
1608
+ break;
1609
+ case EOC:
1610
+ if (handler !== void 0) {
1611
+ this.text += chunk.slice(start2);
1612
+ }
1613
+ break scanLoop;
1614
+ default:
1615
+ forbiddenState = FORBIDDEN_START;
1616
+ }
1617
+ }
1618
+ this.forbiddenState = forbiddenState;
1619
+ }
1620
+ handleTextOutsideRoot() {
1621
+ let { i: start2 } = this;
1622
+ const { chunk, textHandler: handler } = this;
1623
+ let nonSpace = false;
1624
+ outRootLoop:
1625
+ while (true) {
1626
+ const code = this.getCode();
1627
+ switch (code) {
1628
+ case LESS: {
1629
+ this.state = S_OPEN_WAKA;
1630
+ if (handler !== void 0) {
1631
+ const { text } = this;
1632
+ const slice = chunk.slice(start2, this.prevI);
1633
+ if (text.length !== 0) {
1634
+ handler(text + slice);
1635
+ this.text = "";
1636
+ } else if (slice.length !== 0) {
1637
+ handler(slice);
1638
+ }
1639
+ }
1640
+ break outRootLoop;
1641
+ }
1642
+ case AMP:
1643
+ this.state = S_ENTITY;
1644
+ this.entityReturnState = S_TEXT;
1645
+ if (handler !== void 0) {
1646
+ this.text += chunk.slice(start2, this.prevI);
1647
+ }
1648
+ nonSpace = true;
1649
+ break outRootLoop;
1650
+ case NL_LIKE:
1651
+ if (handler !== void 0) {
1652
+ this.text += `${chunk.slice(start2, this.prevI)}
1653
+ `;
1654
+ }
1655
+ start2 = this.i;
1656
+ break;
1657
+ case EOC:
1658
+ if (handler !== void 0) {
1659
+ this.text += chunk.slice(start2);
1660
+ }
1661
+ break outRootLoop;
1662
+ default:
1663
+ if (!isS(code)) {
1664
+ nonSpace = true;
1665
+ }
1666
+ }
1667
+ }
1668
+ if (!nonSpace) {
1669
+ return;
1670
+ }
1671
+ if (!this.sawRoot && !this.reportedTextBeforeRoot) {
1672
+ this.fail("text data outside of root node.");
1673
+ this.reportedTextBeforeRoot = true;
1674
+ }
1675
+ if (this.closedRoot && !this.reportedTextAfterRoot) {
1676
+ this.fail("text data outside of root node.");
1677
+ this.reportedTextAfterRoot = true;
1678
+ }
1679
+ }
1680
+ pushAttribNS(name, value) {
1681
+ var _a2;
1682
+ const { prefix, local } = this.qname(name);
1683
+ const attr = { name, prefix, local, value };
1684
+ this.attribList.push(attr);
1685
+ (_a2 = this.attributeHandler) === null || _a2 === void 0 ? void 0 : _a2.call(this, attr);
1686
+ if (prefix === "xmlns") {
1687
+ const trimmed = value.trim();
1688
+ if (this.currentXMLVersion === "1.0" && trimmed === "") {
1689
+ this.fail("invalid attempt to undefine prefix in XML 1.0");
1690
+ }
1691
+ this.topNS[local] = trimmed;
1692
+ nsPairCheck(this, local, trimmed);
1693
+ } else if (name === "xmlns") {
1694
+ const trimmed = value.trim();
1695
+ this.topNS[""] = trimmed;
1696
+ nsPairCheck(this, "", trimmed);
1697
+ }
1698
+ }
1699
+ pushAttribPlain(name, value) {
1700
+ var _a2;
1701
+ const attr = { name, value };
1702
+ this.attribList.push(attr);
1703
+ (_a2 = this.attributeHandler) === null || _a2 === void 0 ? void 0 : _a2.call(this, attr);
1704
+ }
1705
+ /**
1706
+ * End parsing. This performs final well-formedness checks and resets the
1707
+ * parser to a clean state.
1708
+ *
1709
+ * @returns this
1710
+ */
1711
+ end() {
1712
+ var _a2, _b2;
1713
+ if (!this.sawRoot) {
1714
+ this.fail("document must contain a root element.");
1715
+ }
1716
+ const { tags } = this;
1717
+ while (tags.length > 0) {
1718
+ const tag = tags.pop();
1719
+ this.fail(`unclosed tag: ${tag.name}`);
1720
+ }
1721
+ if (this.state !== S_BEGIN && this.state !== S_TEXT) {
1722
+ this.fail("unexpected end.");
1723
+ }
1724
+ const { text } = this;
1725
+ if (text.length !== 0) {
1726
+ (_a2 = this.textHandler) === null || _a2 === void 0 ? void 0 : _a2.call(this, text);
1727
+ this.text = "";
1728
+ }
1729
+ this._closed = true;
1730
+ (_b2 = this.endHandler) === null || _b2 === void 0 ? void 0 : _b2.call(this);
1731
+ this._init();
1732
+ return this;
1733
+ }
1734
+ /**
1735
+ * Resolve a namespace prefix.
1736
+ *
1737
+ * @param prefix The prefix to resolve.
1738
+ *
1739
+ * @returns The namespace URI or ``undefined`` if the prefix is not defined.
1740
+ */
1741
+ resolve(prefix) {
1742
+ var _a2, _b2;
1743
+ let uri = this.topNS[prefix];
1744
+ if (uri !== void 0) {
1745
+ return uri;
1746
+ }
1747
+ const { tags } = this;
1748
+ for (let index = tags.length - 1; index >= 0; index--) {
1749
+ uri = tags[index].ns[prefix];
1750
+ if (uri !== void 0) {
1751
+ return uri;
1752
+ }
1753
+ }
1754
+ uri = this.ns[prefix];
1755
+ if (uri !== void 0) {
1756
+ return uri;
1757
+ }
1758
+ return (_b2 = (_a2 = this.opt).resolvePrefix) === null || _b2 === void 0 ? void 0 : _b2.call(_a2, prefix);
1759
+ }
1760
+ /**
1761
+ * Parse a qname into its prefix and local name parts.
1762
+ *
1763
+ * @param name The name to parse
1764
+ *
1765
+ * @returns
1766
+ */
1767
+ qname(name) {
1768
+ const colon = name.indexOf(":");
1769
+ if (colon === -1) {
1770
+ return { prefix: "", local: name };
1771
+ }
1772
+ const local = name.slice(colon + 1);
1773
+ const prefix = name.slice(0, colon);
1774
+ if (prefix === "" || local === "" || local.includes(":")) {
1775
+ this.fail(`malformed name: ${name}.`);
1776
+ }
1777
+ return { prefix, local };
1778
+ }
1779
+ processAttribsNS() {
1780
+ var _a2;
1781
+ const { attribList } = this;
1782
+ const tag = this.tag;
1783
+ {
1784
+ const { prefix, local } = this.qname(tag.name);
1785
+ tag.prefix = prefix;
1786
+ tag.local = local;
1787
+ const uri = tag.uri = (_a2 = this.resolve(prefix)) !== null && _a2 !== void 0 ? _a2 : "";
1788
+ if (prefix !== "") {
1789
+ if (prefix === "xmlns") {
1790
+ this.fail('tags may not have "xmlns" as prefix.');
1791
+ }
1792
+ if (uri === "") {
1793
+ this.fail(`unbound namespace prefix: ${JSON.stringify(prefix)}.`);
1794
+ tag.uri = prefix;
1795
+ }
1796
+ }
1797
+ }
1798
+ if (attribList.length === 0) {
1799
+ return;
1800
+ }
1801
+ const { attributes } = tag;
1802
+ const seen = /* @__PURE__ */ new Set();
1803
+ for (const attr of attribList) {
1804
+ const { name, prefix, local } = attr;
1805
+ let uri;
1806
+ let eqname;
1807
+ if (prefix === "") {
1808
+ uri = name === "xmlns" ? XMLNS_NAMESPACE : "";
1809
+ eqname = name;
1810
+ } else {
1811
+ uri = this.resolve(prefix);
1812
+ if (uri === void 0) {
1813
+ this.fail(`unbound namespace prefix: ${JSON.stringify(prefix)}.`);
1814
+ uri = prefix;
1815
+ }
1816
+ eqname = `{${uri}}${local}`;
1817
+ }
1818
+ if (seen.has(eqname)) {
1819
+ this.fail(`duplicate attribute: ${eqname}.`);
1820
+ }
1821
+ seen.add(eqname);
1822
+ attr.uri = uri;
1823
+ attributes[name] = attr;
1824
+ }
1825
+ this.attribList = [];
1826
+ }
1827
+ processAttribsPlain() {
1828
+ const { attribList } = this;
1829
+ const attributes = this.tag.attributes;
1830
+ for (const { name, value } of attribList) {
1831
+ if (attributes[name] !== void 0) {
1832
+ this.fail(`duplicate attribute: ${name}.`);
1833
+ }
1834
+ attributes[name] = value;
1835
+ }
1836
+ this.attribList = [];
1837
+ }
1838
+ /**
1839
+ * Handle a complete open tag. This parser code calls this once it has seen
1840
+ * the whole tag. This method checks for well-formeness and then emits
1841
+ * ``onopentag``.
1842
+ */
1843
+ openTag() {
1844
+ var _a2;
1845
+ this.processAttribs();
1846
+ const { tags } = this;
1847
+ const tag = this.tag;
1848
+ tag.isSelfClosing = false;
1849
+ (_a2 = this.openTagHandler) === null || _a2 === void 0 ? void 0 : _a2.call(this, tag);
1850
+ tags.push(tag);
1851
+ this.state = S_TEXT;
1852
+ this.name = "";
1853
+ }
1854
+ /**
1855
+ * Handle a complete self-closing tag. This parser code calls this once it has
1856
+ * seen the whole tag. This method checks for well-formeness and then emits
1857
+ * ``onopentag`` and ``onclosetag``.
1858
+ */
1859
+ openSelfClosingTag() {
1860
+ var _a2, _b2, _c;
1861
+ this.processAttribs();
1862
+ const { tags } = this;
1863
+ const tag = this.tag;
1864
+ tag.isSelfClosing = true;
1865
+ (_a2 = this.openTagHandler) === null || _a2 === void 0 ? void 0 : _a2.call(this, tag);
1866
+ (_b2 = this.closeTagHandler) === null || _b2 === void 0 ? void 0 : _b2.call(this, tag);
1867
+ const top = this.tag = (_c = tags[tags.length - 1]) !== null && _c !== void 0 ? _c : null;
1868
+ if (top === null) {
1869
+ this.closedRoot = true;
1870
+ }
1871
+ this.state = S_TEXT;
1872
+ this.name = "";
1873
+ }
1874
+ /**
1875
+ * Handle a complete close tag. This parser code calls this once it has seen
1876
+ * the whole tag. This method checks for well-formeness and then emits
1877
+ * ``onclosetag``.
1878
+ */
1879
+ closeTag() {
1880
+ const { tags, name } = this;
1881
+ this.state = S_TEXT;
1882
+ this.name = "";
1883
+ if (name === "") {
1884
+ this.fail("weird empty close tag.");
1885
+ this.text += "</>";
1886
+ return;
1887
+ }
1888
+ const handler = this.closeTagHandler;
1889
+ let l = tags.length;
1890
+ while (l-- > 0) {
1891
+ const tag = this.tag = tags.pop();
1892
+ this.topNS = tag.ns;
1893
+ handler === null || handler === void 0 ? void 0 : handler(tag);
1894
+ if (tag.name === name) {
1895
+ break;
1896
+ }
1897
+ this.fail("unexpected close tag.");
1898
+ }
1899
+ if (l === 0) {
1900
+ this.closedRoot = true;
1901
+ } else if (l < 0) {
1902
+ this.fail(`unmatched closing tag: ${name}.`);
1903
+ this.text += `</${name}>`;
1904
+ }
1905
+ }
1906
+ /**
1907
+ * Resolves an entity. Makes any necessary well-formedness checks.
1908
+ *
1909
+ * @param entity The entity to resolve.
1910
+ *
1911
+ * @returns The parsed entity.
1912
+ */
1913
+ parseEntity(entity) {
1914
+ if (entity[0] !== "#") {
1915
+ const defined = this.ENTITIES[entity];
1916
+ if (defined !== void 0) {
1917
+ return defined;
1918
+ }
1919
+ this.fail(this.isName(entity) ? "undefined entity." : "disallowed character in entity name.");
1920
+ return `&${entity};`;
1921
+ }
1922
+ let num = NaN;
1923
+ if (entity[1] === "x" && /^#x[0-9a-f]+$/i.test(entity)) {
1924
+ num = parseInt(entity.slice(2), 16);
1925
+ } else if (/^#[0-9]+$/.test(entity)) {
1926
+ num = parseInt(entity.slice(1), 10);
1927
+ }
1928
+ if (!this.isChar(num)) {
1929
+ this.fail("malformed character entity.");
1930
+ return `&${entity};`;
1931
+ }
1932
+ return String.fromCodePoint(num);
1933
+ }
1934
+ };
1935
+ exports.SaxesParser = SaxesParser2;
1936
+ }
1937
+ });
1938
+
1939
+ // src/v2/node/analysis-worker.js
1940
+ import { parentPort, workerData as task } from "node:worker_threads";
1941
+ import { open, readFile, stat } from "node:fs/promises";
1942
+ import { constants } from "node:fs";
1943
+
1944
+ // src/v2/math.js
1945
+ var identity = () => new Float64Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
1946
+ function multiply(a, b) {
1947
+ const out = new Float64Array(16);
1948
+ for (let c = 0; c < 4; c++)
1949
+ for (let r = 0; r < 4; r++)
1950
+ for (let k = 0; k < 4; k++) out[c * 4 + r] += a[k * 4 + r] * b[c * 4 + k];
1951
+ return out;
1952
+ }
1953
+ function transform(m, p, w = 1) {
1954
+ const d = m[3] * p[0] + m[7] * p[1] + m[11] * p[2] + m[15] * w;
1955
+ return [0, 1, 2].map(
1956
+ (r) => (m[r] * p[0] + m[4 + r] * p[1] + m[8 + r] * p[2] + m[12 + r] * w) / (w && d ? d : 1)
1957
+ );
1958
+ }
1959
+
1960
+ // src/v2/memory.js
1961
+ var MEMORY_OVERHEAD = 64 * 1024 * 1024;
1962
+ var TRIANGLE_MEMORY = 224;
1963
+ function geometryMemory(g) {
1964
+ if (!g) return 0;
1965
+ return g.triangles * TRIANGLE_MEMORY + (g.smoothNormals?.byteLength || 0) * 4 + ((g.edges?.byteLength || 0) + (g.wire?.byteLength || 0)) * 2;
1966
+ }
1967
+ function assertMemory(limits, bytes, operation = "model") {
1968
+ if (bytes > (limits.max_memory_bytes ?? Number.MAX_SAFE_INTEGER))
1969
+ throw new Error(
1970
+ `Estimated memory for this ${operation} exceeds the device safety budget. Use a smaller model or a device with more memory.`
1971
+ );
1972
+ }
1973
+
1974
+ // src/v2/geometry.js
1975
+ var DEFAULT_LIMITS = Object.freeze({
1976
+ max_file_bytes: 256 * 1024 * 1024,
1977
+ max_triangles: 5e6,
1978
+ max_uncompressed_bytes: 256 * 1024 * 1024,
1979
+ max_archive_entries: 1024,
1980
+ max_memory_bytes: Number.MAX_SAFE_INTEGER
1981
+ });
1982
+ function colorRGB(value) {
1983
+ if (typeof value !== "string" || !/^#[\da-f]{6}$/i.test(value))
1984
+ throw new Error("Color must be #RRGGBB");
1985
+ return [1, 3, 5].map((i2) => parseInt(value.slice(i2, i2 + 2), 16) / 255);
1986
+ }
1987
+ function finishGeometry(positions, colors = null, limits = DEFAULT_LIMITS) {
1988
+ if (!(positions instanceof Float32Array) || !positions.length || positions.length % 9)
1989
+ throw new Error("Geometry must contain complete triangles");
1990
+ if (positions.length / 9 > limits.max_triangles)
1991
+ throw new Error("Triangle limit exceeded");
1992
+ assertMemory(
1993
+ limits,
1994
+ MEMORY_OVERHEAD + positions.length / 9 * TRIANGLE_MEMORY
1995
+ );
1996
+ if (colors && (!(colors instanceof Float32Array) || colors.length !== positions.length))
1997
+ throw new Error("Invalid vertex colors");
1998
+ const bounds = {
1999
+ min: [Infinity, Infinity, Infinity],
2000
+ max: [-Infinity, -Infinity, -Infinity]
2001
+ };
2002
+ for (let i2 = 0; i2 < positions.length; i2++) {
2003
+ const v = positions[i2], a = i2 % 3;
2004
+ if (!Number.isFinite(v)) throw new Error("Non-finite vertex coordinate");
2005
+ bounds.min[a] = Math.min(bounds.min[a], v);
2006
+ bounds.max[a] = Math.max(bounds.max[a], v);
2007
+ if (colors && (!Number.isFinite(colors[i2]) || colors[i2] < 0 || colors[i2] > 1))
2008
+ throw new Error("Invalid vertex color");
2009
+ }
2010
+ const normals = new Float32Array(positions.length), blocks = new Float32Array(Math.ceil(positions.length / 9 / 64) * 6);
2011
+ let area = 0, volume = 0, degenerateTriangles = 0;
2012
+ for (let i2 = 0; i2 < positions.length; i2 += 9) {
2013
+ const ax = positions[i2 + 3] - positions[i2], ay = positions[i2 + 4] - positions[i2 + 1], az = positions[i2 + 5] - positions[i2 + 2];
2014
+ const bx = positions[i2 + 6] - positions[i2], by = positions[i2 + 7] - positions[i2 + 1], bz = positions[i2 + 8] - positions[i2 + 2];
2015
+ const nx = ay * bz - az * by, ny = az * bx - ax * bz, nz = ax * by - ay * bx, length = Math.hypot(nx, ny, nz);
2016
+ area += length / 2;
2017
+ volume += (positions[i2] * nx + positions[i2 + 1] * ny + positions[i2 + 2] * nz) / 6;
2018
+ if (!length) degenerateTriangles++;
2019
+ for (let k = 0; k < 9; k += 3) {
2020
+ normals[i2 + k] = nx / (length || 1);
2021
+ normals[i2 + k + 1] = ny / (length || 1);
2022
+ normals[i2 + k + 2] = nz / (length || 1);
2023
+ }
2024
+ const block = Math.floor(i2 / 9 / 64) * 6;
2025
+ if (i2 / 9 % 64 === 0) {
2026
+ blocks.set(
2027
+ [Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity],
2028
+ block
2029
+ );
2030
+ }
2031
+ for (let k = 0; k < 9; k++) {
2032
+ const a = k % 3;
2033
+ blocks[block + a] = Math.min(blocks[block + a], positions[i2 + k]);
2034
+ blocks[block + 3 + a] = Math.max(blocks[block + 3 + a], positions[i2 + k]);
2035
+ }
2036
+ }
2037
+ if (!Number.isFinite(area) || !Number.isFinite(volume))
2038
+ throw new Error("Geometry magnitude exceeds numeric limits");
2039
+ return {
2040
+ positions,
2041
+ normals,
2042
+ colors,
2043
+ blocks,
2044
+ bounds,
2045
+ triangles: positions.length / 9,
2046
+ area,
2047
+ volume: Math.abs(volume),
2048
+ degenerateTriangles
2049
+ };
2050
+ }
2051
+
2052
+ // src/v2/parser.js
2053
+ function binaryWriter(count, header, limits, inputBytes = 0) {
2054
+ if (count > limits.max_triangles) throw new Error("Triangle limit exceeded");
2055
+ assertMemory(limits, MEMORY_OVERHEAD + inputBytes + count * TRIANGLE_MEMORY);
2056
+ const positions = new Float32Array(count * 9);
2057
+ let colors = null;
2058
+ const text = new TextDecoder().decode(header), ci = text.indexOf("COLOR=");
2059
+ const magics = ci >= 0 && ci + 10 <= 80;
2060
+ const legacy = /^Binary colored STL by viewstl\.com/i.test(text);
2061
+ const fallback = magics ? [...header.subarray(ci + 6, ci + 9)].map((v) => v / 255) : [144 / 255, 144 / 255, 144 / 255];
2062
+ return {
2063
+ write(d, offset, t) {
2064
+ for (let k = 0; k < 9; k++)
2065
+ positions[t * 9 + k] = d.getFloat32(offset + 12 + k * 4, true);
2066
+ const attr = d.getUint16(offset + 48, true), colored = magics || legacy || !!(attr & 32768);
2067
+ if (colored && !colors) {
2068
+ colors = new Float32Array(count * 9);
2069
+ for (let i2 = 0; i2 < colors.length; i2++) colors[i2] = fallback[i2 % 3];
2070
+ }
2071
+ if (colored) {
2072
+ const c = magics && attr & 32768 ? fallback : (magics || legacy ? [attr & 31, attr >> 5 & 31, attr >> 10 & 31] : [attr >> 10 & 31, attr >> 5 & 31, attr & 31]).map((v) => v / 31);
2073
+ for (let k = 0; k < 9; k++) colors[t * 9 + k] = c[k % 3];
2074
+ }
2075
+ },
2076
+ finish() {
2077
+ return {
2078
+ ...finishGeometry(positions, colors, limits),
2079
+ format: "stl-binary"
2080
+ };
2081
+ }
2082
+ };
2083
+ }
2084
+ function parseSTL(buffer, limits = DEFAULT_LIMITS) {
2085
+ if (!(buffer instanceof ArrayBuffer) || buffer.byteLength > limits.max_file_bytes)
2086
+ throw new Error("Invalid or oversized STL");
2087
+ const d = new DataView(buffer), count = buffer.byteLength >= 84 ? d.getUint32(80, true) : 0;
2088
+ const binary = count > 0 && 84 + count * 50 === buffer.byteLength;
2089
+ let positions, colors = null;
2090
+ if (binary) {
2091
+ const writer = binaryWriter(
2092
+ count,
2093
+ new Uint8Array(buffer, 0, 80),
2094
+ limits,
2095
+ buffer.byteLength
2096
+ );
2097
+ for (let t = 0; t < count; t++) writer.write(d, 84 + t * 50, t);
2098
+ return writer.finish();
2099
+ } else {
2100
+ assertMemory(limits, MEMORY_OVERHEAD + buffer.byteLength * 3);
2101
+ const text = new TextDecoder().decode(buffer);
2102
+ if (!/^\s*solid(?:\s|$)/i.test(text) || !/\bendsolid\b/i.test(text))
2103
+ throw new Error("Invalid or truncated STL");
2104
+ const pattern = /\bvertex\s+(\S+)\s+(\S+)\s+(\S+)/gi;
2105
+ let vertices = 0, match;
2106
+ while (pattern.exec(text)) {
2107
+ vertices++;
2108
+ if (vertices > limits.max_triangles * 3)
2109
+ throw new Error("Triangle limit exceeded");
2110
+ assertMemory(
2111
+ limits,
2112
+ MEMORY_OVERHEAD + buffer.byteLength * 3 + vertices / 3 * TRIANGLE_MEMORY
2113
+ );
2114
+ }
2115
+ if (!vertices || vertices % 3 || (text.match(/\bendfacet\b/gi) || []).length !== vertices / 3)
2116
+ throw new Error("Incomplete ASCII STL triangles");
2117
+ positions = new Float32Array(vertices * 3);
2118
+ pattern.lastIndex = 0;
2119
+ let i2 = 0;
2120
+ while (match = pattern.exec(text))
2121
+ for (let k = 1; k <= 3; k++) positions[i2++] = Number(match[k]);
2122
+ }
2123
+ return {
2124
+ ...finishGeometry(positions, colors, limits),
2125
+ format: binary ? "stl-binary" : "stl-ascii"
2126
+ };
2127
+ }
2128
+ function parseOBJ(buffer, limits = DEFAULT_LIMITS) {
2129
+ if (buffer.byteLength > limits.max_file_bytes)
2130
+ throw new Error("File size limit exceeded");
2131
+ assertMemory(limits, MEMORY_OVERHEAD + buffer.byteLength * 3);
2132
+ const text = new TextDecoder().decode(buffer), vertices = [], faces = [];
2133
+ for (const [line] of text.matchAll(/[^\r\n]+/g)) {
2134
+ const parts = line.trim().split(/\s+/);
2135
+ if (!parts[0] || parts[0].startsWith("#")) continue;
2136
+ if (parts[0] === "v") {
2137
+ if (parts.length < 4) throw new Error("Invalid OBJ vertex");
2138
+ const p = parts.slice(1, 4).map(Number);
2139
+ if (p.some((v) => !Number.isFinite(v)))
2140
+ throw new Error("Invalid OBJ coordinate");
2141
+ vertices.push(p);
2142
+ assertMemory(
2143
+ limits,
2144
+ MEMORY_OVERHEAD + buffer.byteLength * 3 + vertices.length * 128 + faces.length / 3 * 320
2145
+ );
2146
+ if (vertices.length > limits.max_triangles * 3)
2147
+ throw new Error("Vertex limit exceeded");
2148
+ } else if (parts[0] === "f") {
2149
+ const comment = parts.findIndex((p) => p.startsWith("#"));
2150
+ if (comment >= 0) parts.length = comment;
2151
+ if (parts.length < 4) throw new Error("Invalid OBJ face");
2152
+ const ids = parts.slice(1).map((p) => {
2153
+ const id = Number(p.split("/")[0]);
2154
+ const index = id < 0 ? vertices.length + id : id - 1;
2155
+ if (!Number.isInteger(id) || id === 0 || index < 0 || index >= vertices.length)
2156
+ throw new Error("Invalid OBJ index");
2157
+ return index;
2158
+ });
2159
+ for (let j = 1; j < ids.length - 1; j++) {
2160
+ faces.push(ids[0], ids[j], ids[j + 1]);
2161
+ assertMemory(
2162
+ limits,
2163
+ MEMORY_OVERHEAD + buffer.byteLength * 3 + vertices.length * 128 + faces.length / 3 * 320
2164
+ );
2165
+ if (faces.length / 3 > limits.max_triangles)
2166
+ throw new Error("Triangle limit exceeded");
2167
+ }
2168
+ }
2169
+ }
2170
+ const positions = new Float32Array(faces.length * 3);
2171
+ faces.forEach((id, i2) => positions.set(vertices[id], i2 * 3));
2172
+ return { ...finishGeometry(positions, null, limits), format: "obj" };
2173
+ }
2174
+ function parseGeometry(buffer, name = "", limits = DEFAULT_LIMITS) {
2175
+ return /\.obj(?:[?#]|$)/i.test(name) ? parseOBJ(buffer, limits) : parseSTL(buffer, limits);
2176
+ }
2177
+
2178
+ // node_modules/.pnpm/fflate@0.8.3/node_modules/fflate/esm/index.mjs
2179
+ import { createRequire } from "module";
2180
+ var require2 = createRequire("/");
2181
+ var _a;
2182
+ var Worker;
2183
+ var isMarkedAsUntransferable;
2184
+ try {
2185
+ _a = require2("worker_threads"), Worker = _a.Worker, isMarkedAsUntransferable = _a.isMarkedAsUntransferable;
2186
+ } catch (e) {
2187
+ }
2188
+ var u8 = Uint8Array;
2189
+ var u16 = Uint16Array;
2190
+ var i32 = Int32Array;
2191
+ var fleb = new u8([
2192
+ 0,
2193
+ 0,
2194
+ 0,
2195
+ 0,
2196
+ 0,
2197
+ 0,
2198
+ 0,
2199
+ 0,
2200
+ 1,
2201
+ 1,
2202
+ 1,
2203
+ 1,
2204
+ 2,
2205
+ 2,
2206
+ 2,
2207
+ 2,
2208
+ 3,
2209
+ 3,
2210
+ 3,
2211
+ 3,
2212
+ 4,
2213
+ 4,
2214
+ 4,
2215
+ 4,
2216
+ 5,
2217
+ 5,
2218
+ 5,
2219
+ 5,
2220
+ 0,
2221
+ /* unused */
2222
+ 0,
2223
+ 0,
2224
+ /* impossible */
2225
+ 0
2226
+ ]);
2227
+ var fdeb = new u8([
2228
+ 0,
2229
+ 0,
2230
+ 0,
2231
+ 0,
2232
+ 1,
2233
+ 1,
2234
+ 2,
2235
+ 2,
2236
+ 3,
2237
+ 3,
2238
+ 4,
2239
+ 4,
2240
+ 5,
2241
+ 5,
2242
+ 6,
2243
+ 6,
2244
+ 7,
2245
+ 7,
2246
+ 8,
2247
+ 8,
2248
+ 9,
2249
+ 9,
2250
+ 10,
2251
+ 10,
2252
+ 11,
2253
+ 11,
2254
+ 12,
2255
+ 12,
2256
+ 13,
2257
+ 13,
2258
+ /* unused */
2259
+ 0,
2260
+ 0
2261
+ ]);
2262
+ var clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
2263
+ var freb = function(eb, start2) {
2264
+ var b = new u16(31);
2265
+ for (var i2 = 0; i2 < 31; ++i2) {
2266
+ b[i2] = start2 += 1 << eb[i2 - 1];
2267
+ }
2268
+ var r = new i32(b[30]);
2269
+ for (var i2 = 1; i2 < 30; ++i2) {
2270
+ for (var j = b[i2]; j < b[i2 + 1]; ++j) {
2271
+ r[j] = j - b[i2] << 5 | i2;
2272
+ }
2273
+ }
2274
+ return { b, r };
2275
+ };
2276
+ var _a = freb(fleb, 2);
2277
+ var fl = _a.b;
2278
+ var revfl = _a.r;
2279
+ fl[28] = 258, revfl[258] = 28;
2280
+ var _b = freb(fdeb, 0);
2281
+ var fd = _b.b;
2282
+ var revfd = _b.r;
2283
+ var rev = new u16(32768);
2284
+ for (i = 0; i < 32768; ++i) {
2285
+ x = (i & 43690) >> 1 | (i & 21845) << 1;
2286
+ x = (x & 52428) >> 2 | (x & 13107) << 2;
2287
+ x = (x & 61680) >> 4 | (x & 3855) << 4;
2288
+ rev[i] = ((x & 65280) >> 8 | (x & 255) << 8) >> 1;
2289
+ }
2290
+ var x;
2291
+ var i;
2292
+ var hMap = (function(cd, mb, r) {
2293
+ var s = cd.length;
2294
+ var i2 = 0;
2295
+ var l = new u16(mb);
2296
+ for (; i2 < s; ++i2) {
2297
+ if (cd[i2])
2298
+ ++l[cd[i2] - 1];
2299
+ }
2300
+ var le = new u16(mb);
2301
+ for (i2 = 1; i2 < mb; ++i2) {
2302
+ le[i2] = le[i2 - 1] + l[i2 - 1] << 1;
2303
+ }
2304
+ var co;
2305
+ if (r) {
2306
+ co = new u16(1 << mb);
2307
+ var rvb = 15 - mb;
2308
+ for (i2 = 0; i2 < s; ++i2) {
2309
+ if (cd[i2]) {
2310
+ var sv = i2 << 4 | cd[i2];
2311
+ var r_1 = mb - cd[i2];
2312
+ var v = le[cd[i2] - 1]++ << r_1;
2313
+ for (var m = v | (1 << r_1) - 1; v <= m; ++v) {
2314
+ co[rev[v] >> rvb] = sv;
2315
+ }
2316
+ }
2317
+ }
2318
+ } else {
2319
+ co = new u16(s);
2320
+ for (i2 = 0; i2 < s; ++i2) {
2321
+ if (cd[i2]) {
2322
+ co[i2] = rev[le[cd[i2] - 1]++] >> 15 - cd[i2];
2323
+ }
2324
+ }
2325
+ }
2326
+ return co;
2327
+ });
2328
+ var flt = new u8(288);
2329
+ for (i = 0; i < 144; ++i)
2330
+ flt[i] = 8;
2331
+ var i;
2332
+ for (i = 144; i < 256; ++i)
2333
+ flt[i] = 9;
2334
+ var i;
2335
+ for (i = 256; i < 280; ++i)
2336
+ flt[i] = 7;
2337
+ var i;
2338
+ for (i = 280; i < 288; ++i)
2339
+ flt[i] = 8;
2340
+ var i;
2341
+ var fdt = new u8(32);
2342
+ for (i = 0; i < 32; ++i)
2343
+ fdt[i] = 5;
2344
+ var i;
2345
+ var flrm = /* @__PURE__ */ hMap(flt, 9, 1);
2346
+ var fdrm = /* @__PURE__ */ hMap(fdt, 5, 1);
2347
+ var max = function(a) {
2348
+ var m = a[0];
2349
+ for (var i2 = 1; i2 < a.length; ++i2) {
2350
+ if (a[i2] > m)
2351
+ m = a[i2];
2352
+ }
2353
+ return m;
2354
+ };
2355
+ var bits = function(d, p, m) {
2356
+ var o = p / 8 | 0;
2357
+ return (d[o] | d[o + 1] << 8) >> (p & 7) & m;
2358
+ };
2359
+ var bits16 = function(d, p) {
2360
+ var o = p / 8 | 0;
2361
+ return (d[o] | d[o + 1] << 8 | d[o + 2] << 16) >> (p & 7);
2362
+ };
2363
+ var shft = function(p) {
2364
+ return (p + 7) / 8 | 0;
2365
+ };
2366
+ var slc = function(v, s, e) {
2367
+ if (s == null || s < 0)
2368
+ s = 0;
2369
+ if (e == null || e > v.length)
2370
+ e = v.length;
2371
+ return new u8(v.subarray(s, e));
2372
+ };
2373
+ var ec = [
2374
+ "unexpected EOF",
2375
+ "invalid block type",
2376
+ "invalid length/literal",
2377
+ "invalid distance",
2378
+ "stream finished",
2379
+ "no stream handler",
2380
+ ,
2381
+ // determined by compression function
2382
+ "no callback",
2383
+ "invalid UTF-8 data",
2384
+ "extra field too long",
2385
+ "date not in range 1980-2099",
2386
+ "filename too long",
2387
+ "stream finishing",
2388
+ "invalid zip data"
2389
+ // determined by unknown compression method
2390
+ ];
2391
+ var err = function(ind, msg, nt) {
2392
+ var e = new Error(msg || ec[ind]);
2393
+ e.code = ind;
2394
+ if (Error.captureStackTrace)
2395
+ Error.captureStackTrace(e, err);
2396
+ if (!nt)
2397
+ throw e;
2398
+ return e;
2399
+ };
2400
+ var inflt = function(dat, st, buf, dict) {
2401
+ var sl = dat.length, dl = dict ? dict.length : 0;
2402
+ if (!sl || st.f && !st.l)
2403
+ return buf || new u8(0);
2404
+ var noBuf = !buf;
2405
+ var resize = noBuf || st.i != 2;
2406
+ var noSt = st.i;
2407
+ if (noBuf)
2408
+ buf = new u8(sl * 3);
2409
+ var cbuf = function(l2) {
2410
+ var bl = buf.length;
2411
+ if (l2 > bl) {
2412
+ var nbuf = new u8(Math.max(bl * 2, l2));
2413
+ nbuf.set(buf);
2414
+ buf = nbuf;
2415
+ }
2416
+ };
2417
+ var final = st.f || 0, pos = st.p || 0, bt = st.b || 0, lm = st.l, dm = st.d, lbt = st.m, dbt = st.n;
2418
+ var tbts = sl * 8;
2419
+ do {
2420
+ if (!lm) {
2421
+ final = bits(dat, pos, 1);
2422
+ var type = bits(dat, pos + 1, 3);
2423
+ pos += 3;
2424
+ if (!type) {
2425
+ var s = shft(pos) + 4, l = dat[s - 4] | dat[s - 3] << 8, t = s + l;
2426
+ if (t > sl) {
2427
+ if (noSt)
2428
+ err(0);
2429
+ break;
2430
+ }
2431
+ if (resize)
2432
+ cbuf(bt + l);
2433
+ buf.set(dat.subarray(s, t), bt);
2434
+ st.b = bt += l, st.p = pos = t * 8, st.f = final;
2435
+ continue;
2436
+ } else if (type == 1)
2437
+ lm = flrm, dm = fdrm, lbt = 9, dbt = 5;
2438
+ else if (type == 2) {
2439
+ var hLit = bits(dat, pos, 31) + 257, hcLen = bits(dat, pos + 10, 15) + 4;
2440
+ var tl = hLit + bits(dat, pos + 5, 31) + 1;
2441
+ pos += 14;
2442
+ var ldt = new u8(tl);
2443
+ var clt = new u8(19);
2444
+ for (var i2 = 0; i2 < hcLen; ++i2) {
2445
+ clt[clim[i2]] = bits(dat, pos + i2 * 3, 7);
2446
+ }
2447
+ pos += hcLen * 3;
2448
+ var clb = max(clt), clbmsk = (1 << clb) - 1;
2449
+ var clm = hMap(clt, clb, 1);
2450
+ for (var i2 = 0; i2 < tl; ) {
2451
+ var r = clm[bits(dat, pos, clbmsk)];
2452
+ pos += r & 15;
2453
+ var s = r >> 4;
2454
+ if (s < 16) {
2455
+ ldt[i2++] = s;
2456
+ } else {
2457
+ var c = 0, n = 0;
2458
+ if (s == 16)
2459
+ n = 3 + bits(dat, pos, 3), pos += 2, c = ldt[i2 - 1];
2460
+ else if (s == 17)
2461
+ n = 3 + bits(dat, pos, 7), pos += 3;
2462
+ else if (s == 18)
2463
+ n = 11 + bits(dat, pos, 127), pos += 7;
2464
+ while (n--)
2465
+ ldt[i2++] = c;
2466
+ }
2467
+ }
2468
+ var lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);
2469
+ lbt = max(lt);
2470
+ dbt = max(dt);
2471
+ lm = hMap(lt, lbt, 1);
2472
+ dm = hMap(dt, dbt, 1);
2473
+ } else
2474
+ err(1);
2475
+ if (pos > tbts) {
2476
+ if (noSt)
2477
+ err(0);
2478
+ break;
2479
+ }
2480
+ }
2481
+ if (resize)
2482
+ cbuf(bt + 131072);
2483
+ var lms = (1 << lbt) - 1, dms = (1 << dbt) - 1;
2484
+ var lpos = pos;
2485
+ for (; ; lpos = pos) {
2486
+ var c = lm[bits16(dat, pos) & lms], sym = c >> 4;
2487
+ pos += c & 15;
2488
+ if (pos > tbts) {
2489
+ if (noSt)
2490
+ err(0);
2491
+ break;
2492
+ }
2493
+ if (!c)
2494
+ err(2);
2495
+ if (sym < 256)
2496
+ buf[bt++] = sym;
2497
+ else if (sym == 256) {
2498
+ lpos = pos, lm = null;
2499
+ break;
2500
+ } else {
2501
+ var add = sym - 254;
2502
+ if (sym > 264) {
2503
+ var i2 = sym - 257, b = fleb[i2];
2504
+ add = bits(dat, pos, (1 << b) - 1) + fl[i2];
2505
+ pos += b;
2506
+ }
2507
+ var d = dm[bits16(dat, pos) & dms], dsym = d >> 4;
2508
+ if (!d)
2509
+ err(3);
2510
+ pos += d & 15;
2511
+ var dt = fd[dsym];
2512
+ if (dsym > 3) {
2513
+ var b = fdeb[dsym];
2514
+ dt += bits16(dat, pos) & (1 << b) - 1, pos += b;
2515
+ }
2516
+ if (pos > tbts) {
2517
+ if (noSt)
2518
+ err(0);
2519
+ break;
2520
+ }
2521
+ if (resize)
2522
+ cbuf(bt + 131072);
2523
+ var end = bt + add;
2524
+ if (bt < dt) {
2525
+ var shift = dl - dt, dend = Math.min(dt, end);
2526
+ if (shift + bt < 0)
2527
+ err(3);
2528
+ for (; bt < dend; ++bt)
2529
+ buf[bt] = dict[shift + bt];
2530
+ }
2531
+ for (; bt < end; ++bt)
2532
+ buf[bt] = buf[bt - dt];
2533
+ }
2534
+ }
2535
+ st.l = lm, st.p = lpos, st.b = bt, st.f = final;
2536
+ if (lm)
2537
+ final = 1, st.m = lbt, st.d = dm, st.n = dbt;
2538
+ } while (!final);
2539
+ return bt != buf.length && noBuf ? slc(buf, 0, bt) : buf.subarray(0, bt);
2540
+ };
2541
+ var et = /* @__PURE__ */ new u8(0);
2542
+ var Inflate = /* @__PURE__ */ (function() {
2543
+ function Inflate2(opts, cb) {
2544
+ if (typeof opts == "function")
2545
+ cb = opts, opts = {};
2546
+ this.ondata = cb;
2547
+ var dict = opts && opts.dictionary && opts.dictionary.subarray(-32768);
2548
+ this.s = { i: 0, b: dict ? dict.length : 0 };
2549
+ this.o = new u8(32768);
2550
+ this.p = new u8(0);
2551
+ if (dict)
2552
+ this.o.set(dict);
2553
+ }
2554
+ Inflate2.prototype.e = function(c) {
2555
+ if (!this.ondata)
2556
+ err(5);
2557
+ if (this.d)
2558
+ err(4);
2559
+ if (!this.p.length)
2560
+ this.p = c;
2561
+ else if (c.length) {
2562
+ var n = new u8(this.p.length + c.length);
2563
+ n.set(this.p), n.set(c, this.p.length), this.p = n;
2564
+ }
2565
+ };
2566
+ Inflate2.prototype.c = function(final) {
2567
+ this.s.i = +(this.d = final || false);
2568
+ var bts = this.s.b;
2569
+ var dt = inflt(this.p, this.s, this.o);
2570
+ this.ondata(slc(dt, bts, this.s.b), this.d);
2571
+ this.o = slc(dt, this.s.b - 32768), this.s.b = this.o.length;
2572
+ this.p = slc(this.p, this.s.p / 8 | 0), this.s.p &= 7;
2573
+ };
2574
+ Inflate2.prototype.push = function(chunk, final) {
2575
+ this.e(chunk), this.c(final);
2576
+ };
2577
+ return Inflate2;
2578
+ })();
2579
+ var td = typeof TextDecoder != "undefined" && /* @__PURE__ */ new TextDecoder();
2580
+ var tds = 0;
2581
+ try {
2582
+ td.decode(et, { stream: true });
2583
+ tds = 1;
2584
+ } catch (e) {
2585
+ }
2586
+
2587
+ // src/v2/archive.js
2588
+ var import_saxes = __toESM(require_saxes(), 1);
2589
+ var decoder = new TextDecoder("utf-8", { fatal: true });
2590
+ var crcTable = Uint32Array.from({ length: 256 }, (_, n) => {
2591
+ for (let k = 0; k < 8; k++) n = n & 1 ? 3988292384 ^ n >>> 1 : n >>> 1;
2592
+ return n >>> 0;
2593
+ });
2594
+ function crc(data, state = 4294967295) {
2595
+ for (const b of data) state = crcTable[(state ^ b) & 255] ^ state >>> 8;
2596
+ return state >>> 0;
2597
+ }
2598
+ function safePath(name) {
2599
+ if (!name || name.includes("\\") || name.startsWith("/") || name.includes("\0") || name.split("/").some((p) => p === ".." || p === ".") || /^[a-z]+:/i.test(name))
2600
+ throw new Error("Unsafe archive path");
2601
+ return name;
2602
+ }
2603
+ function unzipChecked(buffer, limits = DEFAULT_LIMITS) {
2604
+ if (buffer.byteLength > limits.max_file_bytes)
2605
+ throw new Error("Archive size limit exceeded");
2606
+ const bytes = new Uint8Array(buffer), d = new DataView(buffer);
2607
+ let end = -1;
2608
+ for (let i2 = bytes.length - 22; i2 >= Math.max(0, bytes.length - 65557); i2--)
2609
+ if (d.getUint32(i2, true) === 101010256 && i2 + 22 + d.getUint16(i2 + 20, true) === bytes.length) {
2610
+ end = i2;
2611
+ break;
2612
+ }
2613
+ if (end < 0) throw new Error("ZIP central directory not found");
2614
+ const count = d.getUint16(end + 10, true), size = d.getUint32(end + 12, true), start2 = d.getUint32(end + 16, true);
2615
+ if (d.getUint16(end + 4, true) || d.getUint16(end + 6, true) || count !== d.getUint16(end + 8, true))
2616
+ throw new Error("Multi-disk ZIP is unsupported");
2617
+ if (count === 65535 || start2 === 4294967295 || size === 4294967295)
2618
+ throw new Error("ZIP64 is unsupported");
2619
+ if (count > limits.max_archive_entries || start2 + size > end)
2620
+ throw new Error("Invalid or oversized ZIP directory");
2621
+ const entries = [], seen = /* @__PURE__ */ new Set();
2622
+ let offset = start2, total = 0;
2623
+ for (let i2 = 0; i2 < count; i2++) {
2624
+ if (offset + 46 > start2 + size || d.getUint32(offset, true) !== 33639248)
2625
+ throw new Error("Invalid ZIP directory entry");
2626
+ const flags = d.getUint16(offset + 8, true), method = d.getUint16(offset + 10, true), checksum = d.getUint32(offset + 16, true), compressed = d.getUint32(offset + 20, true), original = d.getUint32(offset + 24, true);
2627
+ const n = d.getUint16(offset + 28, true), extra = d.getUint16(offset + 30, true), comment = d.getUint16(offset + 32, true), local = d.getUint32(offset + 42, true);
2628
+ if (offset + 46 + n + extra + comment > start2 + size)
2629
+ throw new Error("Truncated ZIP directory");
2630
+ const name = safePath(
2631
+ decoder.decode(bytes.subarray(offset + 46, offset + 46 + n))
2632
+ );
2633
+ if (seen.has(name)) throw new Error("Duplicate archive entry");
2634
+ seen.add(name);
2635
+ if (flags & 1 || ![0, 8].includes(method))
2636
+ throw new Error("Encrypted or unsupported ZIP compression");
2637
+ total += original;
2638
+ assertMemory(
2639
+ limits,
2640
+ MEMORY_OVERHEAD + buffer.byteLength + total * 4,
2641
+ "expanded archive"
2642
+ );
2643
+ if (total > limits.max_uncompressed_bytes)
2644
+ throw new Error("Archive expansion limit exceeded");
2645
+ entries.push({ name, method, checksum, compressed, original, local });
2646
+ offset += 46 + n + extra + comment;
2647
+ }
2648
+ if (offset !== start2 + size) throw new Error("ZIP directory size mismatch");
2649
+ const files = /* @__PURE__ */ new Map();
2650
+ for (const e of entries) {
2651
+ const o = e.local;
2652
+ if (o + 30 > start2 || d.getUint32(o, true) !== 67324752)
2653
+ throw new Error("Invalid ZIP local header");
2654
+ const n = d.getUint16(o + 26, true), extra = d.getUint16(o + 28, true), dataStart = o + 30 + n + extra;
2655
+ if (dataStart + e.compressed > start2 || d.getUint16(o + 8, true) !== e.method || d.getUint16(o + 6, true) & 1 || decoder.decode(bytes.subarray(o + 30, o + 30 + n)) !== e.name)
2656
+ throw new Error("ZIP header mismatch");
2657
+ const out = new Uint8Array(e.original);
2658
+ let written = 0, state = 4294967295, finished = false;
2659
+ const consume = (chunk, final) => {
2660
+ if (written + chunk.length > out.length)
2661
+ throw new Error("ZIP entry exceeds declared size");
2662
+ out.set(chunk, written);
2663
+ written += chunk.length;
2664
+ state = crc(chunk, state);
2665
+ finished = final;
2666
+ };
2667
+ if (e.method === 0)
2668
+ consume(bytes.subarray(dataStart, dataStart + e.compressed), true);
2669
+ else {
2670
+ const inflate = new Inflate(consume);
2671
+ for (let p = 0; p < e.compressed; p += 1024)
2672
+ inflate.push(
2673
+ bytes.subarray(
2674
+ dataStart + p,
2675
+ dataStart + Math.min(p + 1024, e.compressed)
2676
+ ),
2677
+ p + 1024 >= e.compressed
2678
+ );
2679
+ }
2680
+ if (!finished || written !== e.original || (state ^ 4294967295) >>> 0 !== e.checksum)
2681
+ throw new Error("ZIP checksum or length mismatch");
2682
+ if (!e.name.endsWith("/")) files.set(e.name, out);
2683
+ }
2684
+ return files;
2685
+ }
2686
+ function parseXML(bytes, open2, close = () => {
2687
+ }) {
2688
+ const parser = new import_saxes.SaxesParser({ xmlns: true });
2689
+ parser.on("doctype", () => {
2690
+ throw new Error("XML document types are not supported");
2691
+ });
2692
+ parser.on("error", (error) => {
2693
+ throw error;
2694
+ });
2695
+ parser.on("opentag", (tag) => {
2696
+ const a = /* @__PURE__ */ Object.create(null);
2697
+ for (const v of Object.values(tag.attributes)) a[v.local] = v.value;
2698
+ open2(tag.local, a, tag);
2699
+ });
2700
+ parser.on("closetag", (tag) => close(tag.local));
2701
+ parser.write(decoder.decode(bytes)).close();
2702
+ }
2703
+ function matrix(value) {
2704
+ if (!value) return identity();
2705
+ const v = value.trim().split(/\s+/).map(Number);
2706
+ if (v.length !== 12 || v.some((x2) => !Number.isFinite(x2)))
2707
+ throw new Error("Invalid 3MF transform");
2708
+ return new Float64Array([
2709
+ v[0],
2710
+ v[1],
2711
+ v[2],
2712
+ 0,
2713
+ v[3],
2714
+ v[4],
2715
+ v[5],
2716
+ 0,
2717
+ v[6],
2718
+ v[7],
2719
+ v[8],
2720
+ 0,
2721
+ v[9],
2722
+ v[10],
2723
+ v[11],
2724
+ 1
2725
+ ]);
2726
+ }
2727
+ function parse3MF(buffer, limits = DEFAULT_LIMITS) {
2728
+ const files = unzipChecked(buffer, limits);
2729
+ const baseMemory = MEMORY_OVERHEAD + buffer.byteLength + [...files.values()].reduce((sum, b) => sum + b.byteLength * 3, 0);
2730
+ let path = null;
2731
+ if (files.has("_rels/.rels"))
2732
+ parseXML(files.get("_rels/.rels"), (name, a) => {
2733
+ if (name === "Relationship" && a.Type?.endsWith("/3dmodel")) {
2734
+ if (a.TargetMode === "External")
2735
+ throw new Error("External 3MF resources are unsupported");
2736
+ path = safePath(a.Target.replace(/^\//, ""));
2737
+ }
2738
+ });
2739
+ path ??= [...files.keys()].find((k) => /^3d\/3dmodel\.model$/i.test(k));
2740
+ if (!path || !files.has(path)) throw new Error("3MF model part not found");
2741
+ const objects = /* @__PURE__ */ new Map(), materials = /* @__PURE__ */ new Map(), build = [];
2742
+ let current = null, resource = null, inBuild = false, unit = 1, triangles = 0, vertices = 0, root = false;
2743
+ parseXML(
2744
+ files.get(path),
2745
+ (name, a, tag) => {
2746
+ if (name === "model") {
2747
+ if (root) throw new Error("Multiple 3MF roots");
2748
+ root = true;
2749
+ const scales = {
2750
+ micron: 1e-3,
2751
+ millimeter: 1,
2752
+ centimeter: 10,
2753
+ inch: 25.4,
2754
+ foot: 304.8,
2755
+ meter: 1e3
2756
+ };
2757
+ unit = scales[a.unit || "millimeter"];
2758
+ if (!unit) throw new Error("Unsupported 3MF unit");
2759
+ for (const prefix of (a.requiredextensions || "").split(/\s+/).filter(Boolean))
2760
+ if (!/material\/2015\/02$/.test(tag.ns[prefix] || ""))
2761
+ throw new Error(`Unsupported required 3MF extension: ${prefix}`);
2762
+ } else if (name === "object") {
2763
+ if (objects.has(a.id)) throw new Error("Duplicate 3MF object");
2764
+ current = {
2765
+ id: a.id,
2766
+ vertices: [],
2767
+ triangles: [],
2768
+ components: [],
2769
+ pid: a.pid,
2770
+ pindex: a.pindex
2771
+ };
2772
+ objects.set(a.id, current);
2773
+ } else if (name === "vertex" && current) {
2774
+ const p = [Number(a.x), Number(a.y), Number(a.z)];
2775
+ if (p.some((v) => !Number.isFinite(v)))
2776
+ throw new Error("Invalid 3MF vertex");
2777
+ current.vertices.push(p);
2778
+ if (++vertices > limits.max_triangles * 3)
2779
+ throw new Error("3MF vertex limit exceeded");
2780
+ assertMemory(limits, baseMemory + vertices * 128 + triangles * 320);
2781
+ } else if (name === "triangle" && current) {
2782
+ current.triangles.push(a);
2783
+ if (++triangles > limits.max_triangles)
2784
+ throw new Error("Triangle limit exceeded");
2785
+ assertMemory(limits, baseMemory + vertices * 128 + triangles * 320);
2786
+ } else if (name === "component" && current) {
2787
+ if (a.path) throw new Error("External 3MF components are unsupported");
2788
+ current.components.push({
2789
+ id: a.objectid,
2790
+ matrix: matrix(a.transform)
2791
+ });
2792
+ } else if (name === "build") inBuild = true;
2793
+ else if (name === "item" && inBuild) {
2794
+ if (a.path) throw new Error("External 3MF build items are unsupported");
2795
+ if (a.printable !== "0")
2796
+ build.push({ id: a.objectid, matrix: matrix(a.transform) });
2797
+ } else if (name === "basematerials" || name === "colorgroup") {
2798
+ resource = [];
2799
+ materials.set(a.id, resource);
2800
+ } else if ((name === "base" || name === "color") && resource) {
2801
+ const color = a.displaycolor || a.color;
2802
+ if (!/^#[\da-f]{6}(?:[\da-f]{2})?$/i.test(color || ""))
2803
+ throw new Error("Invalid 3MF color");
2804
+ resource.push(colorRGB(color.slice(0, 7)));
2805
+ } else if (name === "texture2d" || name === "texture2dgroup" || name === "multiproperties")
2806
+ throw new Error(
2807
+ "3MF textures and composite materials are not supported"
2808
+ );
2809
+ },
2810
+ (name) => {
2811
+ if (name === "object") current = null;
2812
+ if (name === "build") inBuild = false;
2813
+ if (name === "basematerials" || name === "colorgroup") resource = null;
2814
+ }
2815
+ );
2816
+ if (!root || !build.length) throw new Error("3MF build is empty");
2817
+ const instances = [];
2818
+ let total = 0, visits = 0;
2819
+ const visit = (id, parent, stack) => {
2820
+ if (stack.includes(id) || stack.length >= 64)
2821
+ throw new Error("Cyclic or excessively nested 3MF components");
2822
+ if (++visits > limits.max_archive_entries * 1024)
2823
+ throw new Error("3MF component expansion limit exceeded");
2824
+ const obj = objects.get(id);
2825
+ if (!obj) throw new Error("Missing 3MF object");
2826
+ total += obj.triangles.length;
2827
+ if (total > limits.max_triangles)
2828
+ throw new Error("Expanded triangle limit exceeded");
2829
+ assertMemory(
2830
+ limits,
2831
+ baseMemory + vertices * 128 + triangles * 320 + total * TRIANGLE_MEMORY,
2832
+ "expanded model"
2833
+ );
2834
+ if (obj.triangles.length) instances.push({ obj, matrix: parent });
2835
+ for (const c of obj.components)
2836
+ visit(c.id, multiply(parent, c.matrix), [...stack, id]);
2837
+ };
2838
+ for (const item of build) visit(item.id, item.matrix, []);
2839
+ const positions = new Float32Array(total * 9), colors = new Float32Array(total * 9);
2840
+ let index = 0, hasColors = false;
2841
+ for (const instance of instances)
2842
+ for (const face of instance.obj.triangles) {
2843
+ for (let k = 0; k < 3; k++) {
2844
+ const id = Number(face[`v${k + 1}`]);
2845
+ if (!Number.isInteger(id) || id < 0 || id >= instance.obj.vertices.length)
2846
+ throw new Error("Invalid 3MF triangle index");
2847
+ positions.set(
2848
+ transform(instance.matrix, instance.obj.vertices[id]).map(
2849
+ (v) => v * unit
2850
+ ),
2851
+ index
2852
+ );
2853
+ const pid = face.pid ?? instance.obj.pid, pindex = Number(
2854
+ face[`p${k + 1}`] ?? face.p1 ?? instance.obj.pindex ?? 0
2855
+ );
2856
+ let color = [144 / 255, 144 / 255, 144 / 255];
2857
+ if (pid !== void 0) {
2858
+ color = materials.get(pid)?.[pindex];
2859
+ if (!color)
2860
+ throw new Error("Unsupported or invalid 3MF material reference");
2861
+ hasColors = true;
2862
+ }
2863
+ colors.set(color, index);
2864
+ index += 3;
2865
+ }
2866
+ }
2867
+ return {
2868
+ ...finishGeometry(positions, hasColors ? colors : null, limits),
2869
+ format: "3mf"
2870
+ };
2871
+ }
2872
+
2873
+ // src/v2/cad.js
2874
+ var CAD_OVERHEAD = 128 * 1024 ** 2;
2875
+ function cadMemory(inputBytes) {
2876
+ return CAD_OVERHEAD + inputBytes * 40;
2877
+ }
2878
+ async function loadCAD(options) {
2879
+ const { default: factory } = await import(new URL("../cad/occt-import-js.js", import.meta.url).href);
2880
+ return factory({
2881
+ ...options,
2882
+ locateFile: () => new URL("../cad/occt-import-js.wasm", import.meta.url).href
2883
+ });
2884
+ }
2885
+ function cadGeometry(result, limits = DEFAULT_LIMITS, workingBytes = 0) {
2886
+ if (!result?.success || !Array.isArray(result.meshes) || !result.meshes.length)
2887
+ throw new Error(
2888
+ "No supported surfaces were found in this CAD file. Export a self-contained STEP or IGES solid/surface model."
2889
+ );
2890
+ let triangles = 0, arrayBytes = 0, hasColors = false;
2891
+ for (const mesh of result.meshes) {
2892
+ const positions2 = mesh.attributes?.position?.array, indices = mesh.index?.array;
2893
+ if (!positions2?.length || positions2.length % 3 || !indices || indices.length % 3)
2894
+ throw new Error("Invalid CAD mesh");
2895
+ triangles += indices.length / 3;
2896
+ if (!Number.isSafeInteger(triangles) || triangles > limits.max_triangles)
2897
+ throw new Error("Triangle limit exceeded");
2898
+ arrayBytes += (positions2.length + indices.length + (mesh.attributes.normal?.array?.length || 0)) * 16;
2899
+ hasColors ||= !!mesh.color || !!mesh.brep_faces?.some((face) => face.color);
2900
+ }
2901
+ if (!triangles)
2902
+ throw new Error("This CAD file contains no viewable surfaces.");
2903
+ assertMemory(
2904
+ limits,
2905
+ workingBytes + arrayBytes + triangles * TRIANGLE_MEMORY,
2906
+ "CAD model"
2907
+ );
2908
+ const positions = new Float32Array(triangles * 9);
2909
+ const colors = hasColors ? new Float32Array(positions.length) : null;
2910
+ const fallback = [144 / 255, 144 / 255, 144 / 255];
2911
+ let offset = 0;
2912
+ function colorAt(color, start2, end) {
2913
+ if (!color || color.length !== 3 || color.some((v) => !Number.isFinite(v) || v < 0 || v > 1))
2914
+ throw new Error("Invalid CAD color");
2915
+ for (let p = start2; p < end; p += 3) colors.set(color, p);
2916
+ }
2917
+ for (const mesh of result.meshes) {
2918
+ const source = mesh.attributes.position.array, indices = mesh.index.array;
2919
+ for (let i2 = 0; i2 < indices.length; i2++) {
2920
+ const index = indices[i2];
2921
+ if (!Number.isSafeInteger(index) || index < 0 || index * 3 + 2 >= source.length)
2922
+ throw new Error("Invalid CAD triangle index");
2923
+ for (let axis = 0; axis < 3; axis++)
2924
+ positions[offset + i2 * 3 + axis] = source[index * 3 + axis];
2925
+ }
2926
+ if (colors) {
2927
+ colorAt(mesh.color || fallback, offset, offset + indices.length * 3);
2928
+ for (const face of mesh.brep_faces || []) {
2929
+ if (!face.color) continue;
2930
+ if (!Number.isSafeInteger(face.first) || !Number.isSafeInteger(face.last) || face.first < 0 || face.last < face.first || face.last >= indices.length / 3)
2931
+ throw new Error("Invalid CAD face range");
2932
+ colorAt(
2933
+ face.color,
2934
+ offset + face.first * 9,
2935
+ offset + (face.last + 1) * 9
2936
+ );
2937
+ }
2938
+ }
2939
+ offset += indices.length * 3;
2940
+ }
2941
+ return finishGeometry(positions, colors, limits);
2942
+ }
2943
+ async function parseCAD(buffer, name, limits = DEFAULT_LIMITS, progress2 = () => {
2944
+ }, initialize = loadCAD) {
2945
+ const extension = /\.(step|stp|iges|igs)(?:[?#]|$)/i.exec(name)?.[1].toLowerCase();
2946
+ if (!extension) throw new Error("Unsupported CAD format");
2947
+ if (!(buffer instanceof ArrayBuffer) || !buffer.byteLength || buffer.byteLength > limits.max_file_bytes)
2948
+ throw new Error("Invalid or oversized CAD file");
2949
+ assertMemory(limits, cadMemory(buffer.byteLength), "CAD file");
2950
+ const heapLimit = Math.floor(
2951
+ Math.min(
2952
+ 512 * 1024 ** 2,
2953
+ ((limits.max_memory_bytes ?? Number.MAX_SAFE_INTEGER) - CAD_OVERHEAD - buffer.byteLength * 3) / 2
2954
+ ) / 65536
2955
+ ) * 65536;
2956
+ if (heapLimit < 32 * 1024 ** 2)
2957
+ throw new Error("CAD import exceeds the device safety budget.");
2958
+ progress2("loading-cad");
2959
+ let engine;
2960
+ try {
2961
+ engine = await initialize({
2962
+ viewstlMaxHeapBytes: heapLimit,
2963
+ print() {
2964
+ },
2965
+ printErr() {
2966
+ }
2967
+ });
2968
+ } catch {
2969
+ throw new Error(
2970
+ "The CAD reader could not start. Check the connection and that WebAssembly is allowed, then try again."
2971
+ );
2972
+ }
2973
+ progress2("parsing-cad");
2974
+ const format = /^(step|stp)$/.test(extension) ? "step" : "iges";
2975
+ let result;
2976
+ try {
2977
+ result = engine[format === "step" ? "ReadStepFile" : "ReadIgesFile"](
2978
+ new Uint8Array(buffer),
2979
+ {
2980
+ linearUnit: "millimeter",
2981
+ linearDeflectionType: "bounding_box_ratio",
2982
+ linearDeflection: 1e-3,
2983
+ angularDeflection: 0.5
2984
+ }
2985
+ );
2986
+ } catch {
2987
+ throw new Error(
2988
+ "This CAD file could not be processed within the reader limits. Try a smaller or simplified STEP/IGES export."
2989
+ );
2990
+ }
2991
+ const geometry = cadGeometry(
2992
+ result,
2993
+ limits,
2994
+ CAD_OVERHEAD + buffer.byteLength * 3 + engine.HEAPU8.byteLength
2995
+ );
2996
+ return { ...geometry, format, units: "mm" };
2997
+ }
2998
+
2999
+ // src/v2/print-options.js
3000
+ function printOptions(input = {}) {
3001
+ const level = input.level ?? "basic";
3002
+ if (!["basic", "detailed"].includes(level))
3003
+ throw new Error("Choose basic or detailed print checks");
3004
+ const number = (v, name, max2 = 1e9) => {
3005
+ if (!Number.isFinite(v) || v <= 0 || v > max2)
3006
+ throw new Error(`Invalid ${name}`);
3007
+ return v;
3008
+ };
3009
+ let profile = null;
3010
+ if (input.profile != null) {
3011
+ if (input.profile.technology !== "fdm")
3012
+ throw new Error("Only FDM profiles are supported");
3013
+ profile = { technology: "fdm" };
3014
+ for (const key of ["min_wall_mm", "line_width_mm"])
3015
+ if (input.profile[key] != null)
3016
+ profile[key] = number(input.profile[key], key);
3017
+ if (input.profile.overhang_degrees != null)
3018
+ profile.overhang_degrees = number(
3019
+ input.profile.overhang_degrees,
3020
+ "overhang angle",
3021
+ 89.9
3022
+ );
3023
+ if (input.profile.build_volume_mm != null) {
3024
+ if (!Array.isArray(input.profile.build_volume_mm) || input.profile.build_volume_mm.length !== 3)
3025
+ throw new Error("Build volume requires X, Y and Z");
3026
+ profile.build_volume_mm = input.profile.build_volume_mm.map(
3027
+ (v) => number(v, "build volume")
3028
+ );
3029
+ }
3030
+ }
3031
+ const time = number(input.max_time_ms ?? 3e4, "check time limit", 12e4);
3032
+ return {
3033
+ level,
3034
+ profile,
3035
+ apply_transforms: input.apply_transforms !== false,
3036
+ units_confirmed: input.units_confirmed === true,
3037
+ max_time_ms: time
3038
+ };
3039
+ }
3040
+ var printMemory = (triangles) => 64 * 1024 ** 2 + triangles * 2400;
3041
+
3042
+ // src/v2/print-spatial.js
3043
+ var sub = (a, b) => a.map((v, i2) => v - b[i2]);
3044
+ var dot = (a, b) => a.reduce((s, v, i2) => s + v * b[i2], 0);
3045
+ var cross = (a, b) => [
3046
+ a[1] * b[2] - a[2] * b[1],
3047
+ a[2] * b[0] - a[0] * b[2],
3048
+ a[0] * b[1] - a[1] * b[0]
3049
+ ];
3050
+ function triangleAt(p, i2) {
3051
+ return [0, 3, 6].map((k) => Array.from(p.subarray(i2 * 9 + k, i2 * 9 + k + 3)));
3052
+ }
3053
+ function makeTree(p, tick) {
3054
+ const count = p.length / 9, boxes = new Float64Array(count * 6);
3055
+ for (let i2 = 0; i2 < count; i2++) {
3056
+ if (i2 % 1024 === 0) tick();
3057
+ for (let a = 0; a < 3; a++) {
3058
+ boxes[i2 * 6 + a] = Math.min(
3059
+ p[i2 * 9 + a],
3060
+ p[i2 * 9 + 3 + a],
3061
+ p[i2 * 9 + 6 + a]
3062
+ );
3063
+ boxes[i2 * 6 + a + 3] = Math.max(
3064
+ p[i2 * 9 + a],
3065
+ p[i2 * 9 + 3 + a],
3066
+ p[i2 * 9 + 6 + a]
3067
+ );
3068
+ }
3069
+ }
3070
+ const ids = Uint32Array.from({ length: count }, (_, i2) => i2);
3071
+ const build = (start2, end) => {
3072
+ tick();
3073
+ const b = [Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity];
3074
+ for (let j = start2; j < end; j++)
3075
+ for (let a = 0; a < 3; a++) {
3076
+ b[a] = Math.min(b[a], boxes[ids[j] * 6 + a]);
3077
+ b[a + 3] = Math.max(b[a + 3], boxes[ids[j] * 6 + a + 3]);
3078
+ }
3079
+ const node = { b, start: start2, end };
3080
+ if (end - start2 > 16) {
3081
+ const extent = [0, 1, 2].map((a) => b[a + 3] - b[a]), axis = extent.indexOf(Math.max(...extent));
3082
+ ids.subarray(start2, end).sort(
3083
+ (a, c) => boxes[a * 6 + axis] + boxes[a * 6 + axis + 3] - (boxes[c * 6 + axis] + boxes[c * 6 + axis + 3])
3084
+ );
3085
+ const mid = start2 + end >>> 1;
3086
+ node.left = build(start2, mid);
3087
+ node.right = build(mid, end);
3088
+ }
3089
+ return node;
3090
+ };
3091
+ return { root: build(0, count), ids, boxes };
3092
+ }
3093
+ var overlap = (a, b, e) => [0, 1, 2].every((k) => a[k] <= b[k + 3] + e && a[k + 3] + e >= b[k]);
3094
+ function visitPairs(tree, eps, visit, tick) {
3095
+ const walk = (a, b, same) => {
3096
+ tick();
3097
+ if (!overlap(a.b, b.b, eps)) return;
3098
+ if (!a.left && !b.left) {
3099
+ for (let i2 = a.start; i2 < a.end; i2++)
3100
+ for (let j = b.start; j < b.end; j++) {
3101
+ const x2 = tree.ids[i2], y = tree.ids[j];
3102
+ if (same && x2 >= y) continue;
3103
+ if (overlap(
3104
+ tree.boxes.subarray(x2 * 6, x2 * 6 + 6),
3105
+ tree.boxes.subarray(y * 6, y * 6 + 6),
3106
+ eps
3107
+ ))
3108
+ visit(x2, y);
3109
+ }
3110
+ } else if (same) {
3111
+ walk(a.left, a.left, true);
3112
+ walk(a.left, a.right, false);
3113
+ walk(a.right, a.right, true);
3114
+ } else if (a.left && (!b.left || a.end - a.start >= b.end - b.start)) {
3115
+ walk(a.left, b, false);
3116
+ walk(a.right, b, false);
3117
+ } else {
3118
+ walk(a, b.left, false);
3119
+ walk(a, b.right, false);
3120
+ }
3121
+ };
3122
+ walk(tree.root, tree.root, true);
3123
+ }
3124
+ var orient = (a, b, c) => (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
3125
+ function trianglesIntersect(a, b, shared, eps) {
3126
+ const na = cross(sub(a[1], a[0]), sub(a[2], a[0])), nb = cross(sub(b[1], b[0]), sub(b[2], b[0]));
3127
+ const la = Math.hypot(...na), lb = Math.hypot(...nb);
3128
+ if (!la || !lb) return 0;
3129
+ const da = b.map((p) => dot(sub(p, a[0]), na) / la), db = a.map((p) => dot(sub(p, b[0]), nb) / lb);
3130
+ if ([da, db].some((d) => d.every((v) => v > eps) || d.every((v) => v < -eps)))
3131
+ return 0;
3132
+ const line = cross(
3133
+ na.map((v) => v / la),
3134
+ nb.map((v) => v / lb)
3135
+ );
3136
+ if (Math.hypot(...line) < 1e-10) {
3137
+ if (Math.max(...da.map(Math.abs)) > eps) return 0;
3138
+ const axis = na.map(Math.abs).indexOf(Math.max(...na.map(Math.abs))), project = (p) => p.filter((_, k) => k !== axis);
3139
+ if (shared >= 2) {
3140
+ const same = (p, q) => p.every((v, k) => v === q[k]);
3141
+ const common = a.filter((p) => b.some((q) => same(p, q)));
3142
+ if (common.length === 3) return 1;
3143
+ if (common.length === 2) {
3144
+ const otherA = a.find((p) => !common.some((q) => same(p, q)));
3145
+ const otherB = b.find((p) => !common.some((q) => same(p, q)));
3146
+ return orient(project(common[0]), project(common[1]), project(otherA)) * orient(project(common[0]), project(common[1]), project(otherB)) > 0 ? 1 : 0;
3147
+ }
3148
+ }
3149
+ let polygon = a.map(project);
3150
+ const clip = b.map(project), sign = Math.sign(orient(...clip));
3151
+ for (let k = 0; k < 3 && polygon.length; k++) {
3152
+ const u = clip[k], v = clip[(k + 1) % 3], out = [];
3153
+ for (let j = 0; j < polygon.length; j++) {
3154
+ const s = polygon[j], t = polygon[(j + 1) % polygon.length], ds = sign * orient(u, v, s), dt = sign * orient(u, v, t);
3155
+ if (ds >= 0) out.push(s);
3156
+ if (ds >= 0 !== dt >= 0) {
3157
+ const f = ds / (ds - dt);
3158
+ out.push(s.map((x3, i2) => x3 + (t[i2] - x3) * f));
3159
+ }
3160
+ }
3161
+ polygon = out;
3162
+ }
3163
+ const area = Math.abs(
3164
+ polygon.reduce((s, p, i2) => {
3165
+ const q = polygon[(i2 + 1) % polygon.length];
3166
+ const o = polygon[0];
3167
+ return s + (p[0] - o[0]) * (q[1] - o[1]) - (p[1] - o[1]) * (q[0] - o[0]);
3168
+ }, 0)
3169
+ ) / 2;
3170
+ return area > eps * eps * 4 ? 1 : 0;
3171
+ }
3172
+ if (shared >= 2) return 0;
3173
+ const direction = line.map((v) => v / Math.hypot(...line));
3174
+ const interval = (tri, d) => {
3175
+ const hits = [];
3176
+ for (let k = 0; k < 3; k++) {
3177
+ if (Math.abs(d[k]) <= eps) hits.push(dot(tri[k], direction));
3178
+ const j = (k + 1) % 3;
3179
+ if (d[k] * d[j] < 0) {
3180
+ const f = d[k] / (d[k] - d[j]);
3181
+ hits.push(
3182
+ dot(
3183
+ tri[k].map((v, i2) => v + (tri[j][i2] - v) * f),
3184
+ direction
3185
+ )
3186
+ );
3187
+ }
3188
+ }
3189
+ return hits.length ? [Math.min(...hits), Math.max(...hits)] : null;
3190
+ };
3191
+ const x2 = interval(a, db), y = interval(b, da);
3192
+ if (!x2 || !y) return 0;
3193
+ const length = Math.min(x2[1], y[1]) - Math.max(x2[0], y[0]);
3194
+ return length > eps ? 1 : shared ? 0 : length >= -eps ? 2 : 0;
3195
+ }
3196
+ function rayHit(o, d, tri, eps) {
3197
+ const e1 = sub(tri[1], tri[0]), e2 = sub(tri[2], tri[0]), h = cross(d, e2), det = dot(e1, h);
3198
+ if (Math.abs(det) <= Math.hypot(...e1) * Math.hypot(...e2) * 1e-12)
3199
+ return null;
3200
+ const s = sub(o, tri[0]), u = dot(s, h) / det, q = cross(s, e1), v = dot(d, q) / det, t = dot(e2, q) / det;
3201
+ if (u < -1e-10 || v < -1e-10 || u + v > 1 + 1e-10 || t <= eps) return null;
3202
+ return { t, edge: Math.min(u, v, 1 - u - v) < 1e-8 };
3203
+ }
3204
+ function rayBox2(o, d, b, eps) {
3205
+ let lo = 0, hi = Infinity;
3206
+ for (let k = 0; k < 3; k++) {
3207
+ if (Math.abs(d[k]) < 1e-15) {
3208
+ if (o[k] < b[k] - eps || o[k] > b[k + 3] + eps) return false;
3209
+ } else {
3210
+ const x2 = (b[k] - eps - o[k]) / d[k], y = (b[k + 3] + eps - o[k]) / d[k];
3211
+ lo = Math.max(lo, Math.min(x2, y));
3212
+ hi = Math.min(hi, Math.max(x2, y));
3213
+ if (lo > hi) return false;
3214
+ }
3215
+ }
3216
+ return true;
3217
+ }
3218
+ function rayQuery(tree, p, o, d, eps, accept, tick) {
3219
+ const hits = [];
3220
+ const walk = (node) => {
3221
+ tick();
3222
+ if (!rayBox2(o, d, node.b, eps)) return;
3223
+ if (node.left) {
3224
+ walk(node.left);
3225
+ walk(node.right);
3226
+ } else
3227
+ for (let j = node.start; j < node.end; j++) {
3228
+ const id = tree.ids[j];
3229
+ if (!accept(id)) continue;
3230
+ const h = rayHit(o, d, triangleAt(p, id), eps);
3231
+ if (h) hits.push({ ...h, id });
3232
+ }
3233
+ };
3234
+ walk(tree.root);
3235
+ return hits;
3236
+ }
3237
+
3238
+ // src/v2/print-check.js
3239
+ var definitions = [
3240
+ ["degenerate_faces", "Degenerate triangles", "error"],
3241
+ ["near_degenerate_faces", "Very small or thin triangles", "warning"],
3242
+ ["duplicate_faces", "Duplicate triangles", "error"],
3243
+ ["boundary_edges", "Open boundaries", "error"],
3244
+ ["nonmanifold_edges", "Non-manifold edges", "error"],
3245
+ ["nonmanifold_vertices", "Non-manifold vertices", "error"],
3246
+ ["winding", "Triangle winding", "error"],
3247
+ ["components", "Separate connected parts", "info"],
3248
+ ["intersections", "Self-intersections", "error"],
3249
+ ["shell_orientation", "Shell orientation and volume", "error"],
3250
+ ["units", "Physical units", "warning"],
3251
+ ["build_volume", "Build volume fit", "warning"],
3252
+ ["overhangs", "Overhangs", "warning"],
3253
+ ["bed_contact", "Bed contact", "warning"],
3254
+ ["thin_walls", "Thin walls / small features", "warning"]
3255
+ ];
3256
+ function checkMesh(model, input = {}, limits = {}, progress2 = () => {
3257
+ }) {
3258
+ const settings = printOptions(input), n = model.positions.length / 9;
3259
+ if (!(model.positions instanceof Float32Array) || !Number.isSafeInteger(n) || n < 1 || model.matrix?.length !== 16 || Array.from(model.matrix).some((v) => !Number.isFinite(v)))
3260
+ throw new Error("Invalid print-check geometry");
3261
+ if (n > (limits.max_triangles ?? 5e6))
3262
+ throw new Error("Print check triangle limit exceeded");
3263
+ assertMemory(limits, printMemory(n), "print check");
3264
+ const start2 = performance.now(), deadline = start2 + settings.max_time_ms;
3265
+ let ticks = 0, stage = "Topology";
3266
+ const tick = () => {
3267
+ if (++ticks % 128 === 0) {
3268
+ if (performance.now() > deadline) throw new Error("PRINT_TIME_LIMIT");
3269
+ progress2({ phase: stage, elapsed_ms: performance.now() - start2 });
3270
+ }
3271
+ };
3272
+ const checks = definitions.map(([code, label, severity]) => ({
3273
+ code,
3274
+ label,
3275
+ severity,
3276
+ status: "not_run",
3277
+ count: 0,
3278
+ triangle_ids: [],
3279
+ edge_vertices: [],
3280
+ message: "Not run"
3281
+ }));
3282
+ const get = (code) => checks.find((c) => c.code === code);
3283
+ const mark = (code, status, message) => Object.assign(get(code), { status, message });
3284
+ const issue = (code, face) => {
3285
+ const c = get(code);
3286
+ c.count++;
3287
+ if (face != null && c.triangle_ids.length < 128) c.triangle_ids.push(face);
3288
+ };
3289
+ const finish = (code, message) => {
3290
+ const c = get(code);
3291
+ c.status = c.count ? "issue" : "pass";
3292
+ c.message = message || `${c.count} found`;
3293
+ };
3294
+ const positions = new Float64Array(model.positions.length), min = [Infinity, Infinity, Infinity], max2 = [-Infinity, -Infinity, -Infinity];
3295
+ let topologyComplete = false, tree, volumes = [], componentFaces = [], rootOf, eps = 0;
3296
+ const report = {
3297
+ model_id: model.id,
3298
+ name: model.name,
3299
+ triangles: n,
3300
+ checks,
3301
+ settings,
3302
+ dimensions_mm: null,
3303
+ volume_mm3: null,
3304
+ volume_valid: false,
3305
+ elapsed_ms: 0,
3306
+ summary: "incomplete"
3307
+ };
3308
+ try {
3309
+ progress2({ phase: stage, elapsed_ms: 0 });
3310
+ for (let i2 = 0; i2 < model.positions.length; i2 += 3) {
3311
+ if (i2 % 3072 === 0) tick();
3312
+ const p = transform(
3313
+ model.matrix,
3314
+ Array.from(model.positions.subarray(i2, i2 + 3))
3315
+ );
3316
+ if (p.some((v) => !Number.isFinite(v)))
3317
+ throw new Error("Invalid print-check coordinate");
3318
+ positions.set(p, i2);
3319
+ for (let k = 0; k < 3; k++) {
3320
+ min[k] = Math.min(min[k], p[k]);
3321
+ max2[k] = Math.max(max2[k], p[k]);
3322
+ }
3323
+ }
3324
+ report.dimensions_mm = max2.map((v, k) => v - min[k]);
3325
+ const span = Math.max(...report.dimensions_mm), magnitude = Math.max(...min.map(Math.abs), ...max2.map(Math.abs));
3326
+ eps = Math.max(span * 1e-10, magnitude * Number.EPSILON * 64, 1e-12);
3327
+ report.tolerance_mm = eps;
3328
+ for (let i2 = 0; i2 < positions.length; i2++) positions[i2] -= min[i2 % 3];
3329
+ const ids = new Uint32Array(n * 3), vertices = [], lookup = /* @__PURE__ */ new Map(), edges = /* @__PURE__ */ new Map(), faces = /* @__PURE__ */ new Map(), incidence = [];
3330
+ const parents = Int32Array.from({ length: n }, (_, i2) => i2);
3331
+ const find = (i2) => {
3332
+ while (parents[i2] !== i2) {
3333
+ parents[i2] = parents[parents[i2]];
3334
+ i2 = parents[i2];
3335
+ }
3336
+ return i2;
3337
+ };
3338
+ const join = (a, b) => {
3339
+ a = find(a);
3340
+ b = find(b);
3341
+ if (a !== b) parents[b] = a;
3342
+ };
3343
+ for (let i2 = 0; i2 < n; i2++) {
3344
+ tick();
3345
+ for (let k = 0; k < 3; k++) {
3346
+ const offset = i2 * 9 + k * 3, key2 = Array.from(model.positions.subarray(offset, offset + 3)).join(
3347
+ ","
3348
+ );
3349
+ let id = lookup.get(key2);
3350
+ if (id === void 0) {
3351
+ id = vertices.length;
3352
+ lookup.set(key2, id);
3353
+ vertices.push(offset);
3354
+ incidence.push([]);
3355
+ }
3356
+ ids[i2 * 3 + k] = id;
3357
+ incidence[id].push(i2);
3358
+ }
3359
+ const tri = triangleAt(positions, i2), normal = cross(sub(tri[1], tri[0]), sub(tri[2], tri[0])), area = Math.hypot(...normal);
3360
+ if (!area) issue("degenerate_faces", i2);
3361
+ else if (area <= eps * Math.max(
3362
+ ...tri.map((p, k) => Math.hypot(...sub(p, tri[(k + 1) % 3])))
3363
+ ))
3364
+ issue("near_degenerate_faces", i2);
3365
+ const key = Array.from(ids.subarray(i2 * 3, i2 * 3 + 3)).sort((a, b) => a - b).join(":");
3366
+ if (faces.has(key)) issue("duplicate_faces", i2);
3367
+ else faces.set(key, i2);
3368
+ for (let k = 0; k < 3; k++) {
3369
+ const a = ids[i2 * 3 + k], b = ids[i2 * 3 + (k + 1) % 3], key2 = Math.min(a, b) + ":" + Math.max(a, b);
3370
+ let edge = edges.get(key2);
3371
+ if (!edge) {
3372
+ edge = { a, b, faces: [], direction: 0 };
3373
+ edges.set(key2, edge);
3374
+ }
3375
+ if (edge.faces.length) join(i2, edge.faces[0]);
3376
+ edge.faces.push(i2);
3377
+ edge.direction += a < b ? 1 : -1;
3378
+ }
3379
+ }
3380
+ const badVertices = /* @__PURE__ */ new Set();
3381
+ for (const edge of edges.values()) {
3382
+ tick();
3383
+ let code;
3384
+ if (edge.faces.length === 1) code = "boundary_edges";
3385
+ else if (edge.faces.length !== 2) {
3386
+ code = "nonmanifold_edges";
3387
+ badVertices.add(edge.a);
3388
+ badVertices.add(edge.b);
3389
+ } else if (edge.direction !== 0) code = "winding";
3390
+ if (code) {
3391
+ issue(code, edge.faces[0]);
3392
+ const c = get(code);
3393
+ if (c.edge_vertices.length < 256 * 6)
3394
+ c.edge_vertices.push(
3395
+ ...model.positions.subarray(vertices[edge.a], vertices[edge.a] + 3),
3396
+ ...model.positions.subarray(vertices[edge.b], vertices[edge.b] + 3)
3397
+ );
3398
+ }
3399
+ }
3400
+ for (let v = 0; v < incidence.length; v++) {
3401
+ tick();
3402
+ if (badVertices.has(v)) {
3403
+ issue("nonmanifold_vertices", incidence[v][0]);
3404
+ continue;
3405
+ }
3406
+ const around = new Set(incidence[v]), seen = /* @__PURE__ */ new Set(), stack = [incidence[v][0]];
3407
+ while (stack.length) {
3408
+ tick();
3409
+ const f = stack.pop();
3410
+ if (seen.has(f)) continue;
3411
+ seen.add(f);
3412
+ for (let k = 0; k < 3; k++) {
3413
+ const a = ids[f * 3 + k], b = ids[f * 3 + (k + 1) % 3];
3414
+ if (a !== v && b !== v) continue;
3415
+ const e = edges.get(Math.min(a, b) + ":" + Math.max(a, b));
3416
+ for (const next of e.faces) if (!seen.has(next)) stack.push(next);
3417
+ }
3418
+ }
3419
+ if (seen.size !== around.size)
3420
+ issue("nonmanifold_vertices", incidence[v][0]);
3421
+ }
3422
+ const roots = /* @__PURE__ */ new Map();
3423
+ rootOf = new Int32Array(n);
3424
+ for (let i2 = 0; i2 < n; i2++) {
3425
+ tick();
3426
+ const r = find(i2);
3427
+ if (!roots.has(r)) {
3428
+ roots.set(r, roots.size);
3429
+ componentFaces.push([]);
3430
+ volumes.push(0);
3431
+ }
3432
+ const c = roots.get(r);
3433
+ rootOf[i2] = c;
3434
+ componentFaces[c].push(i2);
3435
+ const tri = triangleAt(positions, i2), origin = triangleAt(positions, componentFaces[c][0])[0];
3436
+ volumes[c] += dot(
3437
+ sub(tri[0], origin),
3438
+ cross(sub(tri[1], origin), sub(tri[2], origin))
3439
+ ) / 6;
3440
+ }
3441
+ for (const code of [
3442
+ "degenerate_faces",
3443
+ "near_degenerate_faces",
3444
+ "duplicate_faces",
3445
+ "boundary_edges",
3446
+ "nonmanifold_edges",
3447
+ "nonmanifold_vertices",
3448
+ "winding"
3449
+ ])
3450
+ finish(code);
3451
+ get("components").count = roots.size;
3452
+ mark(
3453
+ "components",
3454
+ roots.size > 1 ? "issue" : "pass",
3455
+ `${roots.size} connected part${roots.size === 1 ? "" : "s"}. Separate parts can be intentional.`
3456
+ );
3457
+ topologyComplete = true;
3458
+ mark(
3459
+ "units",
3460
+ model.source_units || settings.units_confirmed ? "pass" : "inconclusive",
3461
+ model.source_units ? `File units: ${model.source_units}; measurements in mm.` : settings.units_confirmed ? "Current scale confirmed as millimetres." : "File has no physical units. Confirm the current millimetre scale before using size estimates."
3462
+ );
3463
+ const profile = settings.profile;
3464
+ if (profile?.build_volume_mm) {
3465
+ get("build_volume").count = report.dimensions_mm.filter(
3466
+ (v, k) => v > profile.build_volume_mm[k] + eps
3467
+ ).length;
3468
+ finish(
3469
+ "build_volume",
3470
+ get("build_volume").count ? "Exceeds the supplied build volume in the current orientation. Try another orientation or scale in your slicer." : "Fits by dimensions only in the current orientation; placement and printer exclusions are not checked."
3471
+ );
3472
+ }
3473
+ const solidBasics = checks.filter((c) => c.severity === "error" && c.status !== "not_run").every((c) => c.status === "pass");
3474
+ if (settings.level === "detailed") {
3475
+ stage = "Spatial index";
3476
+ tree = makeTree(positions, tick);
3477
+ stage = "Self-intersections";
3478
+ let uncertain = 0;
3479
+ visitPairs(
3480
+ tree,
3481
+ eps,
3482
+ (a, b) => {
3483
+ tick();
3484
+ const shared = Array.from(ids.subarray(a * 3, a * 3 + 3)).filter(
3485
+ (v) => ids.subarray(b * 3, b * 3 + 3).includes(v)
3486
+ ).length;
3487
+ const hit = trianglesIntersect(
3488
+ triangleAt(positions, a),
3489
+ triangleAt(positions, b),
3490
+ shared,
3491
+ eps
3492
+ );
3493
+ if (hit === 1) {
3494
+ issue("intersections", a);
3495
+ const c = get("intersections");
3496
+ if (c.triangle_ids.length < 128) c.triangle_ids.push(b);
3497
+ } else if (hit === 2) uncertain++;
3498
+ },
3499
+ tick
3500
+ );
3501
+ finish("intersections");
3502
+ if (uncertain && !get("intersections").count)
3503
+ mark(
3504
+ "intersections",
3505
+ "inconclusive",
3506
+ `${uncertain} near-contact pairs require inspection at the reported numerical tolerance.`
3507
+ );
3508
+ if (solidBasics && get("intersections").status === "pass") {
3509
+ stage = "Shell containment";
3510
+ let ambiguous = false;
3511
+ for (let c = 0; c < componentFaces.length; c++) {
3512
+ tick();
3513
+ const tri = triangleAt(positions, componentFaces[c][0]), point = [0, 1, 2].map(
3514
+ (k) => (tri[0][k] + tri[1][k] + tri[2][k]) / 3
3515
+ );
3516
+ let depth = null;
3517
+ for (const direction of [
3518
+ [1, 0.371, 0.529],
3519
+ [0.217, 1, 0.413],
3520
+ [0.317, 0.193, 1]
3521
+ ]) {
3522
+ const hits = rayQuery(
3523
+ tree,
3524
+ positions,
3525
+ point,
3526
+ direction,
3527
+ eps,
3528
+ (id) => rootOf[id] !== c,
3529
+ tick
3530
+ );
3531
+ if (hits.some((h) => h.edge)) continue;
3532
+ const counts = /* @__PURE__ */ new Map();
3533
+ for (const h of hits)
3534
+ counts.set(rootOf[h.id], (counts.get(rootOf[h.id]) || 0) + 1);
3535
+ depth = [...counts.values()].filter((v) => v % 2 === 1).length;
3536
+ break;
3537
+ }
3538
+ if (depth === null) {
3539
+ ambiguous = true;
3540
+ continue;
3541
+ }
3542
+ if (Math.abs(volumes[c]) <= eps ** 3 || Math.sign(volumes[c]) !== (depth % 2 ? -1 : 1))
3543
+ issue("shell_orientation", componentFaces[c][0]);
3544
+ }
3545
+ finish(
3546
+ "shell_orientation",
3547
+ "Outer shells must face outward; cavity shells face inward."
3548
+ );
3549
+ if (ambiguous && !get("shell_orientation").count)
3550
+ mark(
3551
+ "shell_orientation",
3552
+ "inconclusive",
3553
+ "Shell containment is numerically ambiguous."
3554
+ );
3555
+ if (get("shell_orientation").status === "pass") {
3556
+ report.volume_mm3 = volumes.reduce((a, b) => a + b, 0);
3557
+ report.volume_valid = true;
3558
+ }
3559
+ } else
3560
+ mark(
3561
+ "shell_orientation",
3562
+ "inconclusive",
3563
+ "Requires a closed, consistently wound mesh without intersections."
3564
+ );
3565
+ } else
3566
+ mark(
3567
+ "shell_orientation",
3568
+ "not_run",
3569
+ "Run Detailed check for intersections, nested shells and validated volume."
3570
+ );
3571
+ if (profile) {
3572
+ stage = "FDM estimates";
3573
+ const physical = get("units").status === "pass";
3574
+ if (!physical)
3575
+ for (const code of ["build_volume", "bed_contact", "thin_walls"])
3576
+ mark(code, "inconclusive", "Confirm physical units first.");
3577
+ if (profile.overhang_degrees != null) {
3578
+ if (!solidBasics || (settings.level === "detailed" ? !report.volume_valid : componentFaces.length !== 1 || volumes[0] <= 0))
3579
+ mark(
3580
+ "overhangs",
3581
+ "inconclusive",
3582
+ "Fix triangle winding and mesh defects before estimating overhangs."
3583
+ );
3584
+ else {
3585
+ const threshold = -Math.sin(
3586
+ profile.overhang_degrees * Math.PI / 180
3587
+ );
3588
+ let area = 0;
3589
+ for (let i2 = 0; i2 < n; i2++) {
3590
+ tick();
3591
+ const t = triangleAt(positions, i2), normal = cross(sub(t[1], t[0]), sub(t[2], t[0])), length = Math.hypot(...normal);
3592
+ if (t.every((p) => p[2] <= eps * 8)) continue;
3593
+ if (normal[2] / length < threshold) {
3594
+ issue("overhangs", i2);
3595
+ area += length / 2;
3596
+ }
3597
+ }
3598
+ get("overhangs").estimated = true;
3599
+ get("overhangs").area_mm2 = area;
3600
+ finish(
3601
+ "overhangs",
3602
+ `Potential support regions above ${profile.overhang_degrees}\xB0 from vertical. +Z is up; bridges/supports are not simulated.`
3603
+ );
3604
+ }
3605
+ }
3606
+ if (physical) {
3607
+ let contact = 0;
3608
+ for (let i2 = 0; i2 < n; i2++) {
3609
+ tick();
3610
+ const t = triangleAt(positions, i2);
3611
+ if (t.every((p) => p[2] <= eps * 8))
3612
+ contact += Math.hypot(...cross(sub(t[1], t[0]), sub(t[2], t[0]))) / 2;
3613
+ }
3614
+ get("bed_contact").area_mm2 = contact;
3615
+ get("bed_contact").estimated = true;
3616
+ get("bed_contact").count = contact <= eps ** 2 ? 1 : 0;
3617
+ finish(
3618
+ "bed_contact",
3619
+ "Contact area after virtually lowering this model onto an XY bed. Adhesion/stability are not predicted; scene placement is unchanged."
3620
+ );
3621
+ const threshold = profile.min_wall_mm ?? profile.line_width_mm;
3622
+ if (threshold != null && settings.level === "detailed" && report.volume_valid) {
3623
+ stage = "Sampled wall thickness";
3624
+ let tested = 0, missed = 0, minimum = Infinity;
3625
+ const step = Math.max(1, Math.ceil(n / 2048));
3626
+ for (let i2 = 0; i2 < n; i2 += step) {
3627
+ tick();
3628
+ const t = triangleAt(positions, i2), normal = cross(sub(t[1], t[0]), sub(t[2], t[0])), length = Math.hypot(...normal), direction = normal.map((v) => -v / length), point = [0, 1, 2].map((k) => (t[0][k] + t[1][k] + t[2][k]) / 3);
3629
+ const hits = rayQuery(
3630
+ tree,
3631
+ positions,
3632
+ point,
3633
+ direction,
3634
+ eps * 8,
3635
+ (id) => id !== i2,
3636
+ tick
3637
+ ).sort((a, b) => a.t - b.t);
3638
+ if (!hits.length || hits[0].edge) {
3639
+ missed++;
3640
+ continue;
3641
+ }
3642
+ tested++;
3643
+ minimum = Math.min(minimum, hits[0].t);
3644
+ if (hits[0].t < threshold) issue("thin_walls", i2);
3645
+ }
3646
+ Object.assign(get("thin_walls"), {
3647
+ estimated: true,
3648
+ samples: tested,
3649
+ unresolved_samples: missed,
3650
+ minimum_sampled_mm: Number.isFinite(minimum) ? minimum : null
3651
+ });
3652
+ mark(
3653
+ "thin_walls",
3654
+ get("thin_walls").count ? "issue" : "inconclusive",
3655
+ `${tested} face-centre samples; threshold ${threshold} mm. Sampling can miss thin features and does not prove a minimum wall thickness.`
3656
+ );
3657
+ } else if (threshold != null)
3658
+ mark(
3659
+ "thin_walls",
3660
+ "inconclusive",
3661
+ "Requires Detailed check with valid closed volume and confirmed units."
3662
+ );
3663
+ }
3664
+ }
3665
+ } catch (error) {
3666
+ if (error.message !== "PRINT_TIME_LIMIT") throw error;
3667
+ for (const c of checks)
3668
+ if (c.status === "not_run")
3669
+ c.message = `Time limit reached during ${stage}; this check was not completed.`;
3670
+ if (!topologyComplete)
3671
+ for (const c of checks.slice(0, 8)) {
3672
+ c.status = "inconclusive";
3673
+ c.message = "Topology check exceeded the time limit; counts are partial.";
3674
+ }
3675
+ report.limit_reason = "time";
3676
+ }
3677
+ const required = checks.slice(0, 11);
3678
+ report.summary = checks.some(
3679
+ (c) => c.status === "issue" && c.severity !== "info"
3680
+ ) ? "issues_found" : required.some((c) => ["not_run", "inconclusive"].includes(c.status)) || checks.some((c) => c.status === "inconclusive") ? "incomplete" : "no_issues_found";
3681
+ report.elapsed_ms = performance.now() - start2;
3682
+ return report;
3683
+ }
3684
+
3685
+ // src/v2/node/analysis-worker.js
3686
+ var start = performance.now();
3687
+ var cadEngine;
3688
+ var progress = (details) => parentPort.postMessage({
3689
+ progress: { ...details, elapsed_ms: performance.now() - start }
3690
+ });
3691
+ async function loadFile() {
3692
+ if (task.buffer) return task.buffer;
3693
+ const before = await stat(task.path);
3694
+ if (!before.isFile()) throw new Error("Input must be a regular file");
3695
+ const flags = constants.O_RDONLY | (process.platform === "win32" ? 0 : constants.O_NONBLOCK);
3696
+ const file = await open(task.path, flags);
3697
+ try {
3698
+ const info = await file.stat();
3699
+ if (!info.isFile()) throw new Error("Input must be a regular file");
3700
+ if (info.size > task.limits.max_file_bytes)
3701
+ throw Object.assign(new Error("File size limit exceeded"), {
3702
+ code: "ERR_FILE_TOO_LARGE"
3703
+ });
3704
+ assertMemory(task.limits, info.size * 2 + 64 * 1024 ** 2, "file input");
3705
+ const bytes = new Uint8Array(info.size);
3706
+ let offset = 0;
3707
+ while (offset < bytes.length) {
3708
+ const { bytesRead } = await file.read(
3709
+ bytes,
3710
+ offset,
3711
+ Math.min(1024 ** 2, bytes.length - offset),
3712
+ offset
3713
+ );
3714
+ if (!bytesRead) throw new Error("File changed while being read");
3715
+ offset += bytesRead;
3716
+ }
3717
+ if ((await file.read(new Uint8Array(1), 0, 1, offset)).bytesRead)
3718
+ throw new Error("File changed while being read");
3719
+ return bytes.buffer;
3720
+ } finally {
3721
+ await file.close();
3722
+ }
3723
+ }
3724
+ async function initializeCAD(options) {
3725
+ const { default: factory } = await import(new URL("../cad/occt-import-js.js", import.meta.url).href);
3726
+ const wasmBinary = await readFile(
3727
+ new URL("../cad/occt-import-js.wasm", import.meta.url)
3728
+ );
3729
+ cadEngine = await factory({ ...options, wasmBinary });
3730
+ return cadEngine;
3731
+ }
3732
+ try {
3733
+ progress({ phase: "reading" });
3734
+ const buffer = await loadFile();
3735
+ const fileBytes = buffer.byteLength;
3736
+ progress({ phase: "parsing", loaded: fileBytes, total: fileBytes });
3737
+ const name = `model.${task.format}`;
3738
+ const geometry = ["step", "iges"].includes(task.format) ? await parseCAD(
3739
+ buffer,
3740
+ name,
3741
+ task.limits,
3742
+ (phase) => progress({ phase }),
3743
+ initializeCAD
3744
+ ) : task.format === "3mf" ? parse3MF(buffer, task.limits) : parseGeometry(buffer, name, task.limits);
3745
+ const cadBytes = cadEngine ? 128 * 1024 ** 2 + cadEngine.HEAPU8.byteLength : 0;
3746
+ assertMemory(
3747
+ task.limits,
3748
+ fileBytes + cadBytes + geometryMemory(geometry) + printMemory(geometry.triangles),
3749
+ "analysis"
3750
+ );
3751
+ const fileUnits = task.format === "3mf" ? "mm" : geometry.units;
3752
+ const units = fileUnits ?? task.units ?? null;
3753
+ const scale = fileUnits ? 1 : { mm: 1, cm: 10, m: 1e3, in: 25.4, ft: 304.8, um: 1e-3 }[units] ?? 1;
3754
+ const matrix2 = identity();
3755
+ matrix2[0] = matrix2[5] = matrix2[10] = scale;
3756
+ const report = checkMesh(
3757
+ {
3758
+ id: 0,
3759
+ name: task.filename,
3760
+ positions: geometry.positions,
3761
+ matrix: matrix2,
3762
+ source_units: units
3763
+ },
3764
+ task.checks,
3765
+ task.limits,
3766
+ progress
3767
+ );
3768
+ if (!units) {
3769
+ delete report.tolerance_mm;
3770
+ for (const check of report.checks) delete check.area_mm2;
3771
+ } else if (!fileUnits) {
3772
+ const unitCheck = report.checks.find((check) => check.code === "units");
3773
+ if (unitCheck.status === "pass")
3774
+ unitCheck.message = `Input scale supplied as ${units}; measurements normalized to mm.`;
3775
+ }
3776
+ const area = geometry.area * scale ** 2;
3777
+ if (!Number.isFinite(area))
3778
+ throw new Error("Surface area exceeds numeric limits");
3779
+ const result = {
3780
+ ...report,
3781
+ schema_version: 1,
3782
+ filename: task.filename,
3783
+ format: task.format,
3784
+ file_bytes: fileBytes,
3785
+ units: units ? "mm" : null,
3786
+ units_source: fileUnits ? "file" : task.units ? "option" : null,
3787
+ dimensions: report.dimensions_mm,
3788
+ surface_area: area,
3789
+ volume: report.volume_valid ? report.volume_mm3 : null,
3790
+ dimensions_mm: units ? report.dimensions_mm : null,
3791
+ surface_area_mm2: units ? area : null,
3792
+ volume_mm3: units && report.volume_valid ? report.volume_mm3 : null,
3793
+ elapsed_ms: performance.now() - start
3794
+ };
3795
+ parentPort.postMessage({ result });
3796
+ } catch (error) {
3797
+ parentPort.postMessage({
3798
+ error: {
3799
+ name: error.name || "Error",
3800
+ code: error.code || "ERR_ANALYSIS",
3801
+ message: error instanceof RangeError ? "Analysis could not allocate memory within the available resources" : error.message || String(error)
3802
+ }
3803
+ });
3804
+ }
3805
+ /*! Bundled license information:
3806
+
3807
+ xmlchars/xml/1.0/ed5.js:
3808
+ (**
3809
+ * Character classes and associated utilities for the 5th edition of XML 1.0.
3810
+ *
3811
+ * @author Louis-Dominique Dubeau
3812
+ * @license MIT
3813
+ * @copyright Louis-Dominique Dubeau
3814
+ *)
3815
+
3816
+ xmlchars/xml/1.1/ed2.js:
3817
+ (**
3818
+ * Character classes and associated utilities for the 2nd edition of XML 1.1.
3819
+ *
3820
+ * @author Louis-Dominique Dubeau
3821
+ * @license MIT
3822
+ * @copyright Louis-Dominique Dubeau
3823
+ *)
3824
+
3825
+ xmlchars/xmlns/1.0/ed3.js:
3826
+ (**
3827
+ * Character class utilities for XML NS 1.0 edition 3.
3828
+ *
3829
+ * @author Louis-Dominique Dubeau
3830
+ * @license MIT
3831
+ * @copyright Louis-Dominique Dubeau
3832
+ *)
3833
+ */