cellml-text-editor 0.1.6 → 0.1.8

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.
@@ -1,5 +1,5 @@
1
- var n = /* @__PURE__ */ ((a) => (a[a.Unknown = 0] = "Unknown", a[a.EOF = 1] = "EOF", a[a.Identifier = 2] = "Identifier", a[a.Number = 3] = "Number", a[a.String = 4] = "String", a[a.KwDef = 5] = "KwDef", a[a.KwModel = 6] = "KwModel", a[a.KwComp = 7] = "KwComp", a[a.KwEndDef = 8] = "KwEndDef", a[a.KwAs = 9] = "KwAs", a[a.KwVar = 10] = "KwVar", a[a.KwUnit = 11] = "KwUnit", a[a.KwSel = 12] = "KwSel", a[a.KwCase = 13] = "KwCase", a[a.KwOtherwise = 14] = "KwOtherwise", a[a.KwEndSel = 15] = "KwEndSel", a[a.OpAss = 16] = "OpAss", a[a.OpPlus = 17] = "OpPlus", a[a.OpMinus = 18] = "OpMinus", a[a.OpTimes = 19] = "OpTimes", a[a.OpDivide = 20] = "OpDivide", a[a.OpComma = 21] = "OpComma", a[a.Colon = 22] = "Colon", a[a.SemiColon = 23] = "SemiColon", a[a.LParam = 24] = "LParam", a[a.RParam = 25] = "RParam", a[a.LBrace = 26] = "LBrace", a[a.RBrace = 27] = "RBrace", a[a.OpEq = 28] = "OpEq", a[a.OpNe = 29] = "OpNe", a[a.OpLt = 30] = "OpLt", a[a.OpLe = 31] = "OpLe", a[a.OpGt = 32] = "OpGt", a[a.OpGe = 33] = "OpGe", a[a.OpAnd = 34] = "OpAnd", a[a.OpOr = 35] = "OpOr", a))(n || {});
2
- class x {
1
+ var n = /* @__PURE__ */ ((c) => (c[c.Unknown = 0] = "Unknown", c[c.EOF = 1] = "EOF", c[c.Identifier = 2] = "Identifier", c[c.Number = 3] = "Number", c[c.String = 4] = "String", c[c.KwDef = 5] = "KwDef", c[c.KwModel = 6] = "KwModel", c[c.KwComp = 7] = "KwComp", c[c.KwEndDef = 8] = "KwEndDef", c[c.KwAs = 9] = "KwAs", c[c.KwVar = 10] = "KwVar", c[c.KwUnit = 11] = "KwUnit", c[c.KwSel = 12] = "KwSel", c[c.KwCase = 13] = "KwCase", c[c.KwOtherwise = 14] = "KwOtherwise", c[c.KwEndSel = 15] = "KwEndSel", c[c.OpAss = 16] = "OpAss", c[c.OpPlus = 17] = "OpPlus", c[c.OpMinus = 18] = "OpMinus", c[c.OpTimes = 19] = "OpTimes", c[c.OpDivide = 20] = "OpDivide", c[c.OpComma = 21] = "OpComma", c[c.Colon = 22] = "Colon", c[c.SemiColon = 23] = "SemiColon", c[c.LParam = 24] = "LParam", c[c.RParam = 25] = "RParam", c[c.LBrace = 26] = "LBrace", c[c.RBrace = 27] = "RBrace", c[c.OpEq = 28] = "OpEq", c[c.OpNe = 29] = "OpNe", c[c.OpLt = 30] = "OpLt", c[c.OpLe = 31] = "OpLe", c[c.OpGt = 32] = "OpGt", c[c.OpGe = 33] = "OpGe", c[c.OpAnd = 34] = "OpAnd", c[c.OpOr = 35] = "OpOr", c))(n || {});
2
+ class N {
3
3
  input;
4
4
  pos = 0;
5
5
  line = 1;
@@ -22,16 +22,16 @@ class x {
22
22
  this.currentToken = 1;
23
23
  return;
24
24
  }
25
- const s = this.input[this.pos];
26
- if (/[a-zA-Z_]/.test(s || "")) {
25
+ const t = this.input[this.pos];
26
+ if (/[a-zA-Z_]/.test(t || "")) {
27
27
  let i = this.pos;
28
28
  for (; this.pos < this.length && /[a-zA-Z0-9_]/.test(this.input[this.pos] || ""); )
29
29
  this.pos++;
30
- const t = this.input.slice(i, this.pos);
31
- this.currentValue = t, this.currentToken = this.getKeywordType(t);
30
+ const s = this.input.slice(i, this.pos);
31
+ this.currentValue = s, this.currentToken = this.getKeywordType(s);
32
32
  return;
33
33
  }
34
- if (/[0-9]/.test(s || "") || s === "." && /[0-9]/.test(this.input[this.pos + 1] || "")) {
34
+ if (/[0-9]/.test(t || "") || t === "." && /[0-9]/.test(this.input[this.pos + 1] || "")) {
35
35
  let i = this.pos;
36
36
  for (; this.pos < this.length && /[0-9]/.test(this.input[this.pos] || ""); ) this.pos++;
37
37
  if (this.input[this.pos] === ".")
@@ -41,7 +41,7 @@ class x {
41
41
  this.currentValue = this.input.slice(i, this.pos), this.currentToken = 3;
42
42
  return;
43
43
  }
44
- switch (this.pos++, this.currentValue = s || "", s) {
44
+ switch (this.pos++, this.currentValue = t || "", t) {
45
45
  // --- ASSIGNMENT VS EQUALITY ---
46
46
  case "=":
47
47
  this.input[this.pos] === "=" ? (this.pos++, this.currentValue = "==", this.currentToken = 28) : this.currentToken = 16;
@@ -90,7 +90,7 @@ class x {
90
90
  this.currentToken = 21;
91
91
  break;
92
92
  default:
93
- console.warn("Unknown char:", s), this.currentToken = 0;
93
+ console.warn("Unknown char:", t), this.currentToken = 0;
94
94
  }
95
95
  }
96
96
  getLine() {
@@ -99,11 +99,11 @@ class x {
99
99
  skipWhitespace() {
100
100
  let e = 0;
101
101
  for (; this.pos < this.length; ) {
102
- const s = this.input[this.pos];
103
- if (/\s/.test(s || ""))
104
- s === `
102
+ const t = this.input[this.pos];
103
+ if (/\s/.test(t || ""))
104
+ t === `
105
105
  ` && e++, this.pos++;
106
- else if (s === "/" && this.input[this.pos + 1] === "/")
106
+ else if (t === "/" && this.input[this.pos + 1] === "/")
107
107
  for (this.pos += 2; this.pos < this.length && this.input[this.pos] !== `
108
108
  `; ) this.pos++;
109
109
  else
@@ -145,7 +145,7 @@ class x {
145
145
  }
146
146
  }
147
147
  const m = "http://www.cellml.org/cellml/2.0#", h = "http://www.w3.org/1998/Math/MathML";
148
- class $ {
148
+ class E {
149
149
  scanner;
150
150
  doc;
151
151
  sourceLineAttr;
@@ -153,15 +153,15 @@ class $ {
153
153
  this.sourceLineAttr = e.sourceLineAttribute === void 0 ? "data-source-location" : e.sourceLineAttribute;
154
154
  }
155
155
  parse(e) {
156
- this.scanner = new x(e), this.doc = document.implementation.createDocument(m, "model", null);
156
+ this.scanner = new N(e), this.doc = document.implementation.createDocument(m, "model", null);
157
157
  try {
158
- const s = this.doc.documentElement;
159
- for (this.expect(n.KwDef), this.expect(n.KwModel), this.scanner.token === n.Identifier && (s.setAttribute("name", this.scanner.value), this.scanner.nextToken()), this.expect(n.KwAs); this.scanner.token !== n.KwEndDef && this.scanner.token !== n.EOF; )
160
- this.scanner.token === n.KwDef ? this.parseBlock(s) : this.scanner.nextToken();
158
+ const t = this.doc.documentElement;
159
+ for (this.expect(n.KwDef), this.expect(n.KwModel), this.scanner.token === n.Identifier && (t.setAttribute("name", this.scanner.value), this.scanner.nextToken()), this.expect(n.KwAs); this.scanner.token !== n.KwEndDef && this.scanner.token !== n.EOF; )
160
+ this.scanner.token === n.KwDef ? this.parseBlock(t) : this.scanner.nextToken();
161
161
  return this.expect(n.KwEndDef), this.expect(n.SemiColon), { xml: `<?xml version="1.0" encoding="UTF-8"?>
162
- ` + this.serialize(s), errors: [] };
163
- } catch (s) {
164
- return { xml: null, errors: [{ line: this.scanner.getLine(), message: s.message || "Unknown parsing error" }] };
162
+ ` + this.serialize(t), errors: [] };
163
+ } catch (t) {
164
+ return { xml: null, errors: [{ line: this.scanner.getLine(), message: t.message || "Unknown parsing error" }] };
165
165
  }
166
166
  }
167
167
  parseBlock(e) {
@@ -174,29 +174,29 @@ class $ {
174
174
  }
175
175
  parseComponent(e) {
176
176
  this.expect(n.KwComp);
177
- const s = this.expectValue(n.Identifier);
177
+ const t = this.expectValue(n.Identifier);
178
178
  this.expect(n.KwAs);
179
179
  const i = this.doc.createElementNS(m, "component");
180
- for (i.setAttribute("name", s), e.appendChild(i); this.scanner.token !== n.KwEndDef && this.scanner.token !== n.EOF; )
180
+ for (i.setAttribute("name", t), e.appendChild(i); this.scanner.token !== n.KwEndDef && this.scanner.token !== n.EOF; )
181
181
  this.scanner.token === n.KwVar ? this.parseVariable(i) : this.scanner.token === n.Identifier || this.scanner.token === n.KwSel ? this.parseMathEquation(i) : this.scanner.nextToken();
182
182
  this.expect(n.KwEndDef), this.expect(n.SemiColon);
183
183
  }
184
184
  // var V: millivolt {init: -65, interface: public};
185
185
  parseVariable(e) {
186
186
  this.expect(n.KwVar);
187
- const s = this.expectValue(n.Identifier);
187
+ const t = this.expectValue(n.Identifier);
188
188
  this.expect(n.Colon);
189
- const i = this.expectValue(n.Identifier), t = this.doc.createElementNS(m, "variable");
190
- if (t.setAttribute("name", s), t.setAttribute("units", i), this.scanner.token === n.LBrace) {
189
+ const i = this.expectValue(n.Identifier), s = this.doc.createElementNS(m, "variable");
190
+ if (s.setAttribute("name", t), s.setAttribute("units", i), this.scanner.token === n.LBrace) {
191
191
  for (this.scanner.nextToken(); this.scanner.token !== n.RBrace && this.scanner.token !== n.EOF; ) {
192
192
  const r = this.expectValue(n.Identifier);
193
193
  this.expect(n.Colon);
194
- let c = "";
195
- this.scanner.token === n.OpMinus ? (this.scanner.nextToken(), c = "-" + this.expectValue(n.Number)) : this.scanner.token === n.Number ? c = this.expectValue(n.Number) : c = this.expectValue(n.Identifier), r === "init" ? t.setAttribute("initial_value", c) : r === "interface" && t.setAttribute("interface", c), this.scanner.token === n.OpComma && this.scanner.nextToken();
194
+ let a = "";
195
+ this.scanner.token === n.OpMinus ? (this.scanner.nextToken(), a = "-" + this.expectValue(n.Number)) : this.scanner.token === n.Number ? a = this.expectValue(n.Number) : a = this.expectValue(n.Identifier), r === "init" ? s.setAttribute("initial_value", a) : r === "interface" && s.setAttribute("interface", a), this.scanner.token === n.OpComma && this.scanner.nextToken();
196
196
  }
197
197
  this.expect(n.RBrace);
198
198
  }
199
- this.expect(n.SemiColon), e.appendChild(t);
199
+ this.expect(n.SemiColon), e.appendChild(s);
200
200
  }
201
201
  parseUnit(e) {
202
202
  for (this.expect(n.KwUnit); this.scanner.token !== n.KwEndDef && this.scanner.token !== n.EOF; )
@@ -205,27 +205,27 @@ class $ {
205
205
  }
206
206
  // --- Math Parsing ---
207
207
  parseMathEquation(e) {
208
- const s = this.scanner.getLine();
208
+ const t = this.scanner.getLine();
209
209
  let i = e.getElementsByTagNameNS(h, "math")[0];
210
210
  i || (i = this.doc.createElementNS(h, "math"), e.appendChild(i));
211
- const t = this.doc.createElementNS(h, "apply"), r = this.doc.createElementNS(h, "eq");
212
- t.appendChild(r);
213
- const c = this.parseExpression();
211
+ const s = this.doc.createElementNS(h, "apply"), r = this.doc.createElementNS(h, "eq");
212
+ s.appendChild(r);
213
+ const a = this.parseExpression();
214
214
  this.expect(n.OpAss);
215
- const o = this.parseExpression(), u = this.scanner.getLine();
216
- this.sourceLineAttr && t.setAttribute(
215
+ const o = this.parseExpression(), l = this.scanner.getLine();
216
+ this.sourceLineAttr && s.setAttribute(
217
217
  this.sourceLineAttr,
218
- `${s.toString()}` + (u !== s ? `-${u.toString()}` : "")
219
- ), t.appendChild(c), t.appendChild(o), i.appendChild(t), this.expect(n.SemiColon);
218
+ `${t.toString()}` + (l !== t ? `-${l.toString()}` : "")
219
+ ), s.appendChild(a), s.appendChild(o), i.appendChild(s), this.expect(n.SemiColon);
220
220
  }
221
221
  // Recursive Descent for Math: Condition -> Comparison -> Expression -> Term -> Factor
222
222
  parseCondition() {
223
223
  let e = this.parseComparison();
224
224
  for (; this.scanner.token === n.OpAnd || this.scanner.token === n.OpOr; ) {
225
- const s = this.scanner.token;
225
+ const t = this.scanner.token;
226
226
  this.scanner.nextToken();
227
- const i = this.parseComparison(), t = this.doc.createElementNS(h, "apply"), r = this.doc.createElementNS(h, s === n.OpAnd ? "and" : "or");
228
- t.appendChild(r), t.appendChild(e), t.appendChild(i), e = t;
227
+ const i = this.parseComparison(), s = this.doc.createElementNS(h, "apply"), r = this.doc.createElementNS(h, t === n.OpAnd ? "and" : "or");
228
+ s.appendChild(r), s.appendChild(e), s.appendChild(i), e = s;
229
229
  }
230
230
  return e;
231
231
  }
@@ -236,11 +236,11 @@ class $ {
236
236
  parseComparison() {
237
237
  let e = this.parseExpression();
238
238
  if (this.isComparisonToken(this.scanner.token)) {
239
- const s = this.scanner.token;
239
+ const t = this.scanner.token;
240
240
  this.scanner.nextToken();
241
- const i = this.parseExpression(), t = this.doc.createElementNS(h, "apply");
241
+ const i = this.parseExpression(), s = this.doc.createElementNS(h, "apply");
242
242
  let r = "";
243
- switch (s) {
243
+ switch (t) {
244
244
  case n.OpEq:
245
245
  r = "eq";
246
246
  break;
@@ -263,8 +263,8 @@ class $ {
263
263
  r = "and";
264
264
  break;
265
265
  }
266
- const c = this.doc.createElementNS(h, r);
267
- return t.appendChild(c), t.appendChild(e), t.appendChild(i), t;
266
+ const a = this.doc.createElementNS(h, r);
267
+ return s.appendChild(a), s.appendChild(e), s.appendChild(i), s;
268
268
  }
269
269
  return e;
270
270
  }
@@ -272,22 +272,22 @@ class $ {
272
272
  * Checks if an element is an <apply> block for a specific operator.
273
273
  * e.g. isMathMLApply(node, 'plus') returns true for <apply><plus/>...</apply>
274
274
  */
275
- isMathMLApply(e, s) {
275
+ isMathMLApply(e, t) {
276
276
  if (e.localName !== "apply") return !1;
277
277
  const i = e.firstElementChild;
278
- return i ? i.localName === s : !1;
278
+ return i ? i.localName === t : !1;
279
279
  }
280
280
  parseExpression() {
281
281
  let e = this.parseTerm();
282
282
  for (; this.scanner.token === n.OpPlus || this.scanner.token === n.OpMinus; ) {
283
- const s = this.scanner.token;
283
+ const t = this.scanner.token;
284
284
  this.scanner.nextToken();
285
285
  const i = this.parseTerm();
286
- if (s === n.OpPlus && this.isMathMLApply(e, "plus"))
286
+ if (t === n.OpPlus && this.isMathMLApply(e, "plus"))
287
287
  e.appendChild(i);
288
288
  else {
289
- const t = this.doc.createElementNS(h, "apply"), r = this.doc.createElementNS(h, s === n.OpPlus ? "plus" : "minus");
290
- t.appendChild(r), t.appendChild(e), t.appendChild(i), e = t;
289
+ const s = this.doc.createElementNS(h, "apply"), r = this.doc.createElementNS(h, t === n.OpPlus ? "plus" : "minus");
290
+ s.appendChild(r), s.appendChild(e), s.appendChild(i), e = s;
291
291
  }
292
292
  }
293
293
  return e;
@@ -295,14 +295,14 @@ class $ {
295
295
  parseTerm() {
296
296
  let e = this.parseFactor();
297
297
  for (; this.scanner.token === n.OpTimes || this.scanner.token === n.OpDivide; ) {
298
- const s = this.scanner.token;
298
+ const t = this.scanner.token;
299
299
  this.scanner.nextToken();
300
300
  const i = this.parseFactor();
301
- if (s === n.OpTimes && this.isMathMLApply(e, "times"))
301
+ if (t === n.OpTimes && this.isMathMLApply(e, "times"))
302
302
  e.appendChild(i);
303
303
  else {
304
- const t = this.doc.createElementNS(h, "apply"), r = this.doc.createElementNS(h, s === n.OpTimes ? "times" : "divide");
305
- t.appendChild(r), t.appendChild(e), t.appendChild(i), e = t;
304
+ const s = this.doc.createElementNS(h, "apply"), r = this.doc.createElementNS(h, t === n.OpTimes ? "times" : "divide");
305
+ s.appendChild(r), s.appendChild(e), s.appendChild(i), e = s;
306
306
  }
307
307
  }
308
308
  return e;
@@ -312,7 +312,7 @@ class $ {
312
312
  * and returns the corresponding element, or null if it's a variable.
313
313
  */
314
314
  createMathMLConstant(e) {
315
- const s = {
315
+ const t = {
316
316
  pi: "pi",
317
317
  e: "exponentiale",
318
318
  // Standard math constant e
@@ -324,36 +324,42 @@ class $ {
324
324
  // Boolean constants
325
325
  false: "false"
326
326
  };
327
- return s.hasOwnProperty(e) ? this.doc.createElementNS(h, s[e] || "") : null;
327
+ return t.hasOwnProperty(e) ? this.doc.createElementNS(h, t[e] || "") : null;
328
328
  }
329
329
  parseFactor() {
330
330
  if (this.scanner.token === n.OpMinus) {
331
331
  this.scanner.nextToken();
332
- const e = this.parseFactor(), s = this.doc.createElementNS(h, "apply"), i = this.doc.createElementNS(h, "minus");
333
- return s.appendChild(i), s.appendChild(e), s;
332
+ const e = this.parseFactor(), t = this.doc.createElementNS(h, "apply"), i = this.doc.createElementNS(h, "minus");
333
+ return t.appendChild(i), t.appendChild(e), t;
334
334
  }
335
335
  if (this.scanner.token === n.Number) {
336
336
  const e = this.scanner.value;
337
337
  this.scanner.nextToken();
338
- const s = this.doc.createElementNS(h, "cn");
339
- if (s.textContent = e, this.scanner.token === n.LBrace) {
338
+ const t = this.doc.createElementNS(h, "cn");
339
+ if (this.scanner.token === n.LBrace) {
340
340
  if (this.scanner.nextToken(), this.scanner.value === "units") {
341
341
  this.scanner.nextToken(), this.expect(n.Colon);
342
342
  const i = this.expectValue(n.Identifier);
343
- s.setAttributeNS(m, "cellml:units", i);
343
+ t.setAttributeNS(m, "cellml:units", i);
344
344
  }
345
345
  for (; this.scanner.token !== n.RBrace && this.scanner.token !== n.EOF; )
346
346
  this.scanner.nextToken();
347
347
  this.expect(n.RBrace);
348
348
  }
349
- return s;
349
+ if (e.match(/^-?[\d.]+[eE][+-]?\d+$/)) {
350
+ t.setAttribute("type", "e-notation");
351
+ const i = this.doc.createElementNS(h, "sep"), [s, r] = e.split(/[eE]/);
352
+ t.appendChild(this.doc.createTextNode(s || "1")), t.appendChild(i), t.appendChild(this.doc.createTextNode(r || "0"));
353
+ } else
354
+ t.textContent = e;
355
+ return t;
350
356
  } else if (this.scanner.token === n.Identifier) {
351
357
  const e = this.scanner.value;
352
358
  if (this.scanner.nextToken(), this.scanner.token === n.LParam)
353
359
  return this.parseFunctionCall(e);
354
- const s = this.createMathMLConstant(e);
355
- if (s)
356
- return s;
360
+ const t = this.createMathMLConstant(e);
361
+ if (t)
362
+ return t;
357
363
  const i = this.doc.createElementNS(h, "ci");
358
364
  return i.textContent = e, i;
359
365
  } else if (this.scanner.token === n.LParam) {
@@ -368,39 +374,39 @@ class $ {
368
374
  const e = this.doc.createElementNS(h, "piecewise");
369
375
  for (this.expect(n.KwSel); this.scanner.token === n.KwCase; ) {
370
376
  this.expect(n.KwCase);
371
- const s = this.parseCondition();
377
+ const t = this.parseCondition();
372
378
  this.expect(n.Colon);
373
379
  const i = this.parseExpression();
374
380
  this.expect(n.SemiColon);
375
- const t = this.doc.createElementNS(h, "piece");
376
- t.appendChild(i), t.appendChild(s), e.appendChild(t);
381
+ const s = this.doc.createElementNS(h, "piece");
382
+ s.appendChild(i), s.appendChild(t), e.appendChild(s);
377
383
  }
378
384
  if (this.scanner.token === n.KwOtherwise) {
379
385
  this.expect(n.KwOtherwise), this.expect(n.Colon);
380
- const s = this.parseExpression();
386
+ const t = this.parseExpression();
381
387
  this.expect(n.SemiColon);
382
388
  const i = this.doc.createElementNS(h, "otherwise");
383
- i.appendChild(s), e.appendChild(i);
389
+ i.appendChild(t), e.appendChild(i);
384
390
  }
385
391
  return this.expect(n.KwEndSel), e;
386
392
  }
387
393
  parseFunctionCall(e) {
388
394
  if (this.expect(n.LParam), e === "ode") {
389
- const t = this.parseExpression();
395
+ const s = this.parseExpression();
390
396
  this.expect(n.OpComma);
391
397
  const r = this.parseExpression();
392
398
  this.expect(n.RParam);
393
- const c = this.doc.createElementNS(h, "apply");
394
- c.appendChild(this.doc.createElementNS(h, "diff"));
399
+ const a = this.doc.createElementNS(h, "apply");
400
+ a.appendChild(this.doc.createElementNS(h, "diff"));
395
401
  const o = this.doc.createElementNS(h, "bvar");
396
- return o.appendChild(r), c.appendChild(o), c.appendChild(t), c;
402
+ return o.appendChild(r), a.appendChild(o), a.appendChild(s), a;
397
403
  }
398
- const s = this.doc.createElementNS(h, "apply"), i = this.doc.createElementNS(h, e);
399
- if (s.appendChild(i), this.scanner.token !== n.RParam)
404
+ const t = this.doc.createElementNS(h, "apply"), i = this.doc.createElementNS(h, e);
405
+ if (t.appendChild(i), this.scanner.token !== n.RParam)
400
406
  do
401
- this.scanner.token === n.OpComma && this.scanner.nextToken(), s.appendChild(this.parseExpression());
407
+ this.scanner.token === n.OpComma && this.scanner.nextToken(), t.appendChild(this.parseExpression());
402
408
  while (this.scanner.token === n.OpComma);
403
- return this.expect(n.RParam), s;
409
+ return this.expect(n.RParam), t;
404
410
  }
405
411
  // --- Helpers ---
406
412
  expect(e) {
@@ -411,20 +417,20 @@ class $ {
411
417
  expectValue(e) {
412
418
  if (this.scanner.token !== e)
413
419
  throw new Error(`Expected value of type ${n[e]}, got ${this.scanner.token}`);
414
- const s = this.scanner.value;
415
- return this.scanner.nextToken(), s;
420
+ const t = this.scanner.value;
421
+ return this.scanner.nextToken(), t;
416
422
  }
417
423
  /**
418
424
  * Checks if the element or any of its descendants use a CellML attribute
419
425
  * (e.g. cellml:units).
420
426
  */
421
427
  usesCellMLNamespace(e) {
422
- const s = e.getElementsByTagName("*");
423
- for (let i = 0; i < s.length; i++) {
424
- const t = s[i];
425
- for (let r = 0; t && r < t.attributes.length; r++) {
426
- const c = t.attributes[r];
427
- if (c && c.namespaceURI === m)
428
+ const t = e.getElementsByTagName("*");
429
+ for (let i = 0; i < t.length; i++) {
430
+ const s = t[i];
431
+ for (let r = 0; s && r < s.attributes.length; r++) {
432
+ const a = s.attributes[r];
433
+ if (a && a.namespaceURI === m)
428
434
  return !0;
429
435
  }
430
436
  }
@@ -435,42 +441,44 @@ class $ {
435
441
  * and returns the prefix used (e.g. 'cellml', 'cellml2', or '' for default).
436
442
  * Returns null if not found.
437
443
  */
438
- getPrefixForNamespace(e, s) {
444
+ getPrefixForNamespace(e, t) {
439
445
  const i = "http://www.w3.org/2000/xmlns/";
440
- for (let t = 0; t < e.attributes.length; t++) {
441
- const r = e.attributes[t];
442
- if (r && r.namespaceURI === i && r.value === s)
446
+ for (let s = 0; s < e.attributes.length; s++) {
447
+ const r = e.attributes[s];
448
+ if (r && r.namespaceURI === i && r.value === t)
443
449
  return r.localName === "xmlns" ? "" : r.localName;
444
450
  }
445
451
  return null;
446
452
  }
447
- serialize(e, s = 0) {
448
- const i = " ".repeat(s), t = e.tagName, r = e.localName;
449
- let c = "";
450
- r === "model" && !e.hasAttribute("xmlns") && (c += ` xmlns="${m}"`), r === "math" && !e.hasAttribute("xmlns") && (c += ` xmlns="${h}"`, this.usesCellMLNamespace(e) && !e.hasAttribute("xmlns:cellml") && this.getPrefixForNamespace(e, m) === null && (c += ` xmlns:cellml="${m}"`));
453
+ serialize(e, t = 0) {
454
+ const i = " ".repeat(t), s = e.tagName, r = e.localName;
455
+ let a = "";
456
+ r === "model" && !e.hasAttribute("xmlns") && (a += ` xmlns="${m}"`), r === "math" && !e.hasAttribute("xmlns") && (a += ` xmlns="${h}"`, this.usesCellMLNamespace(e) && !e.hasAttribute("xmlns:cellml") && this.getPrefixForNamespace(e, m) === null && (a += ` xmlns:cellml="${m}"`));
451
457
  for (let d = 0; d < e.attributes.length; d++) {
452
458
  const f = e.attributes[d];
453
459
  if (f) {
454
460
  if (this.sourceLineAttr && f.name === this.sourceLineAttr)
455
461
  continue;
456
- c += ` ${f.name}="${f.value}"`;
462
+ a += ` ${f.name}="${f.value}"`;
457
463
  }
458
464
  }
459
- const o = Array.from(e.childNodes), u = o.some((d) => d.nodeType === 1), l = e.textContent?.trim();
460
- if (o.length === 0 && !l)
461
- return `${i}<${t}${c}/>`;
462
- if (!u)
463
- return `${i}<${t}${c}>${l}</${t}>`;
464
- let p = `${i}<${t}${c}>
465
+ const o = Array.from(e.childNodes), l = o.some((d) => d.nodeType === 1), u = e.textContent?.trim();
466
+ if (o.length === 0 && !u)
467
+ return `${i}<${s}${a}/>`;
468
+ if (l) {
469
+ if (e.tagName === "cn" && o.length === 3)
470
+ return `${i}<${s}${a}>${o[0]?.textContent}<sep/>${o[2]?.textContent}</${s}>`;
471
+ } else return `${i}<${s}${a}>${u}</${s}>`;
472
+ let p = `${i}<${s}${a}>
465
473
  `;
466
474
  return o.forEach((d) => {
467
- d.nodeType === 1 && (p += this.serialize(d, s + 1) + `
475
+ d.nodeType === 1 && (p += this.serialize(d, t + 1) + `
468
476
  `);
469
- }), p += `${i}</${t}>`, p;
477
+ }), p += `${i}</${s}>`, p;
470
478
  }
471
479
  }
472
- const g = "http://www.cellml.org/cellml/2.0#";
473
- class N {
480
+ const C = "http://www.cellml.org/cellml/2.0#";
481
+ class k {
474
482
  output = "";
475
483
  indentLevel = 0;
476
484
  domParser;
@@ -482,72 +490,72 @@ class N {
482
490
  indent() {
483
491
  return this.standardIndent.repeat(this.indentLevel);
484
492
  }
485
- append(e, s = !0) {
486
- this.output += (s ? this.indent() : "") + e + (s ? `
493
+ append(e, t = !0) {
494
+ this.output += (t ? this.indent() : "") + e + (t ? `
487
495
  ` : "");
488
496
  }
489
497
  // --- Main Entry Point ---
490
498
  generate(e) {
491
499
  this.output = "", this.indentLevel = 0;
492
500
  try {
493
- const s = this.domParser.parseFromString(e, "application/xml");
494
- if (s.querySelector("parsererror")) throw new Error("XML Parsing Error");
495
- const t = s.getElementsByTagNameNS("http://www.cellml.org/cellml/2.0#", "model")[0];
496
- if (!t) throw new Error("No CellML 2.0 Model found");
497
- this.processModel(t);
498
- } catch (s) {
499
- return `// Error generating text: ${s.message}`;
501
+ const t = this.domParser.parseFromString(e, "application/xml");
502
+ if (t.querySelector("parsererror")) throw new Error("XML Parsing Error");
503
+ const s = t.getElementsByTagNameNS("http://www.cellml.org/cellml/2.0#", "model")[0];
504
+ if (!s) throw new Error("No CellML 2.0 Model found");
505
+ this.processModel(s);
506
+ } catch (t) {
507
+ return `// Error generating text: ${t.message}`;
500
508
  }
501
509
  return this.output;
502
510
  }
503
511
  // --- Recursive Processors ---
504
512
  processModel(e) {
505
- const s = e.getAttribute("name") || "unnamed_model";
506
- this.append(`def model ${s} as`), this.indentLevel++;
513
+ const t = e.getAttribute("name") || "unnamed_model";
514
+ this.append(`def model ${t} as`), this.indentLevel++;
507
515
  const i = e.getElementsByTagName("units");
508
516
  for (let r = 0; r < i.length; r++)
509
517
  i[r]?.parentElement === e && this.processUnits(i[r]);
510
- const t = e.getElementsByTagName("component");
511
- for (let r = 0; r < t.length; r++)
512
- this.processComponent(t[r]);
518
+ const s = e.getElementsByTagName("component");
519
+ for (let r = 0; r < s.length; r++)
520
+ this.processComponent(s[r]);
513
521
  this.indentLevel--, this.append("enddef;");
514
522
  }
515
523
  processUnits(e) {
516
- const s = e?.getAttribute("name") || "unnamed_units";
517
- this.append(`def unit ${s} as`), this.indentLevel++;
524
+ const t = e?.getAttribute("name") || "unnamed_units";
525
+ this.append(`def unit ${t} as`), this.indentLevel++;
518
526
  const i = e?.getElementsByTagName("unit") || [];
519
- for (let t = 0; t < i.length; t++) {
520
- const r = i[t];
527
+ for (let s = 0; s < i.length; s++) {
528
+ const r = i[s];
521
529
  if (!r) continue;
522
- const c = r.getAttribute("prefix"), o = r.getAttribute("units"), u = r.getAttribute("exponent"), l = r.getAttribute("multiplier");
530
+ const a = r.getAttribute("prefix"), o = r.getAttribute("units"), l = r.getAttribute("exponent"), u = r.getAttribute("multiplier");
523
531
  let p = `unit ${o}`;
524
- c && (p += ` {prefix: ${c}}`), u && (p += ` {exponent: ${u}}`), l && (p += ` {multiplier: ${l}}`), p += ";", this.append(p);
532
+ a && (p += ` {prefix: ${a}}`), l && (p += ` {exponent: ${l}}`), u && (p += ` {multiplier: ${u}}`), p += ";", this.append(p);
525
533
  }
526
534
  this.indentLevel--, this.append("enddef;"), this.append("");
527
535
  }
528
536
  processComponent(e) {
529
- const s = e?.getAttribute("name") || "unnamed_component";
530
- this.append(`def comp ${s} as`), this.indentLevel++;
537
+ const t = e?.getAttribute("name") || "unnamed_component";
538
+ this.append(`def comp ${t} as`), this.indentLevel++;
531
539
  const i = e?.getElementsByTagName("variable") || [];
532
540
  for (let r = 0; r < i.length; r++)
533
541
  this.processVariable(i[r]);
534
- const t = e?.getElementsByTagNameNS("http://www.w3.org/1998/Math/MathML", "math") || [];
535
- for (let r = 0; r < t.length; r++)
536
- this.processMath(t[r]);
542
+ const s = e?.getElementsByTagNameNS("http://www.w3.org/1998/Math/MathML", "math") || [];
543
+ for (let r = 0; r < s.length; r++)
544
+ this.processMath(s[r]);
537
545
  this.indentLevel--, this.append("enddef;"), this.append("");
538
546
  }
539
547
  processVariable(e) {
540
- const s = e?.getAttribute("name"), i = e?.getAttribute("units"), t = e?.getAttribute("initial_value"), r = e?.getAttribute("interface");
541
- let c = `var ${s}: ${i}`, o = [];
542
- t && o.push(`init: ${t}`), r && o.push(`interface: ${r}`), o.length > 0 && (c += ` {${o.join(", ")}}`), c += ";", this.append(c);
548
+ const t = e?.getAttribute("name"), i = e?.getAttribute("units"), s = e?.getAttribute("initial_value"), r = e?.getAttribute("interface");
549
+ let a = `var ${t}: ${i}`, o = [];
550
+ s && o.push(`init: ${s}`), r && o.push(`interface: ${r}`), o.length > 0 && (a += ` {${o.join(", ")}}`), a += ";", this.append(a);
543
551
  }
544
552
  // --- MathML Handling ---
545
553
  processMath(e) {
546
- const s = Array.from(e?.children || []);
547
- for (const i of s)
554
+ const t = Array.from(e?.children || []);
555
+ for (const i of t)
548
556
  if (i.localName === "apply" && i.firstElementChild?.localName === "eq") {
549
- const r = Array.from(i.children).slice(1), c = this.parseMathNode(r[0]), o = this.parseMathNode(r[1]);
550
- this.append(`${c} = ${o};`);
557
+ const r = Array.from(i.children).slice(1), a = this.parseMathNode(r[0]), o = this.parseMathNode(r[1]);
558
+ this.append(`${a} = ${o};`);
551
559
  } else {
552
560
  const r = this.parseMathNode(i);
553
561
  r && this.append(r + ";");
@@ -555,56 +563,64 @@ class N {
555
563
  }
556
564
  parseMathNode(e) {
557
565
  if (!e) return "";
558
- const s = e.localName;
559
- if (s === "apply")
566
+ const t = e.localName;
567
+ if (t === "apply")
560
568
  return this.parseApply(e);
561
- if (s === "ci")
569
+ if (t === "ci")
562
570
  return e.textContent?.trim() || "";
563
- if (s === "cn") {
564
- const i = e.textContent?.trim() || "0", t = e.getAttributeNS(g, "units");
565
- return t ? `${i} {units: ${t}}` : i;
571
+ if (t === "cn") {
572
+ let i = e.textContent?.trim() || "0";
573
+ if (e.getAttribute("type") === "e-notation") {
574
+ const a = Array.from(e.childNodes), o = a.findIndex((l) => l.nodeType === 1 && l.localName === "sep");
575
+ if (o !== -1) {
576
+ const l = a.slice(0, o).map((p) => p.textContent).join("").trim(), u = a.slice(o + 1).map((p) => p.textContent).join("").trim();
577
+ i = `${l}e${u}`;
578
+ }
579
+ }
580
+ const r = e.getAttributeNS(C, "units");
581
+ return r ? `${i} {units: ${r}}` : i;
566
582
  } else {
567
- if (s === "piecewise")
583
+ if (t === "piecewise")
568
584
  return this.parsePiecewise(e);
569
- if (s === "pi")
585
+ if (t === "pi")
570
586
  return "pi";
571
- if (s === "bvar")
587
+ if (t === "bvar")
572
588
  return "";
573
589
  }
574
- return console.log(`Unsupported MathML node: ${s}`), `/* Unsupported MathML node: ${s} */`;
590
+ return console.log(`Unsupported MathML node: ${t}`), `/* Unsupported MathML node: ${t} */`;
575
591
  }
576
592
  parseApply(e) {
577
- const s = Array.from(e.children);
578
- if (s.length === 0) return "";
579
- const i = s[0]?.localName, t = s.slice(1).map((r) => this.parseMathNode(r));
593
+ const t = Array.from(e.children);
594
+ if (t.length === 0) return "";
595
+ const i = t[0]?.localName, s = t.slice(1).map((r) => this.parseMathNode(r));
580
596
  switch (i) {
581
597
  case "plus":
582
- return `(${t.join(" + ")})`;
598
+ return `(${s.join(" + ")})`;
583
599
  case "minus":
584
- return t.length === 1 ? `-${t[0]}` : `(${t[0]} - ${t[1]})`;
600
+ return s.length === 1 ? `-${s[0]}` : `(${s[0]} - ${s[1]})`;
585
601
  case "times":
586
- return `(${t.join(" * ")})`;
602
+ return `(${s.join(" * ")})`;
587
603
  case "divide":
588
- return `(${t[0]} / ${t[1]})`;
604
+ return `(${s[0]} / ${s[1]})`;
589
605
  case "eq":
590
- return `${t[0]} == ${t[1]}`;
606
+ return `${s[0]} == ${s[1]}`;
591
607
  case "neq":
592
- return `${t[0]} != ${t[1]}`;
608
+ return `${s[0]} != ${s[1]}`;
593
609
  case "lt":
594
- return `${t[0]} < ${t[1]}`;
610
+ return `${s[0]} < ${s[1]}`;
595
611
  case "leq":
596
- return `${t[0]} <= ${t[1]}`;
612
+ return `${s[0]} <= ${s[1]}`;
597
613
  case "gt":
598
- return `${t[0]} > ${t[1]}`;
614
+ return `${s[0]} > ${s[1]}`;
599
615
  case "geq":
600
- return `${t[0]} >= ${t[1]}`;
616
+ return `${s[0]} >= ${s[1]}`;
601
617
  case "and":
602
- return `${t.join(" and ")}`;
618
+ return `${s.join(" and ")}`;
603
619
  case "or":
604
- return `${t.join(" or ")}`;
620
+ return `${s.join(" or ")}`;
605
621
  case "diff":
606
- const r = s.find((l) => l.localName === "bvar"), c = s.find((l) => l.localName !== "diff" && l.localName !== "bvar"), o = r?.children[0]?.textContent || "t";
607
- return `ode(${c ? this.parseMathNode(c) : "unknown"}, ${o})`;
622
+ const r = t.find((u) => u.localName === "bvar"), a = t.find((u) => u.localName !== "diff" && u.localName !== "bvar"), o = r?.children[0]?.textContent || "t";
623
+ return `ode(${a ? this.parseMathNode(a) : "unknown"}, ${o})`;
608
624
  // Functions
609
625
  case "sin":
610
626
  case "cos":
@@ -612,48 +628,84 @@ class N {
612
628
  case "exp":
613
629
  case "ln":
614
630
  case "log":
615
- return `${i}(${t[0]})`;
631
+ return `${i}(${s[0]})`;
616
632
  case "root":
617
- return `sqrt(${t[0]})`;
633
+ return `sqrt(${s[0]})`;
618
634
  default:
619
- return `${i}(${t.join(", ")})`;
635
+ return `${i}(${s.join(", ")})`;
620
636
  }
621
637
  }
622
638
  parsePiecewise(e) {
623
- let s = [];
624
- return Array.from(e?.children || []).forEach((t) => {
625
- if (t.localName === "piece") {
626
- const r = this.parseMathNode(t.children[0]), c = this.parseMathNode(t.children[1]);
627
- s.push(`${this.standardIndent}case ${c}: ${r};`);
628
- } else if (t.localName === "otherwise") {
629
- const r = this.parseMathNode(t.children[0]);
630
- s.push(`${this.standardIndent}otherwise: ${r};`);
639
+ let t = [];
640
+ return Array.from(e?.children || []).forEach((s) => {
641
+ if (s.localName === "piece") {
642
+ const r = this.parseMathNode(s.children[0]), a = this.parseMathNode(s.children[1]);
643
+ t.push(`${this.standardIndent}case ${a}: ${r};`);
644
+ } else if (s.localName === "otherwise") {
645
+ const r = this.parseMathNode(s.children[0]);
646
+ t.push(`${this.standardIndent}otherwise: ${r};`);
631
647
  }
632
648
  }), `sel
633
- ${this.indent()}${s.join(`
649
+ ${this.indent()}${t.join(`
634
650
  ${this.indent()}`)}
635
651
  ${this.indent()}endsel`;
636
652
  }
637
653
  }
638
- class C {
654
+ const $ = {
655
+ atomic: 100,
656
+ // Identifiers, numbers
657
+ func: 90,
658
+ // sin, cos, exp (visually self-contained)
659
+ power: 80,
660
+ // ^
661
+ times: 70,
662
+ // *
663
+ divide: 70,
664
+ // / (usually self-contained in \frac, but good to have)
665
+ plus: 60,
666
+ // +
667
+ minus: 60,
668
+ // -
669
+ rel: 50,
670
+ // =, <, >
671
+ unknown: 0
672
+ };
673
+ class O {
639
674
  convert(e) {
640
675
  if (!e) return "";
641
676
  if (e.localName === "math")
642
- return Array.from(e.children).map((s) => this.convert(s)).join(`
677
+ return Array.from(e.children).map((t) => this.convert(t)).join(`
643
678
  `);
644
679
  if (e.localName === "apply" && e.firstElementChild?.localName === "eq") {
645
- const s = Array.from(e.children), i = this.parseNode(s[1]), t = this.parseNode(s[2]);
646
- return `${i} = ${t}`;
680
+ const t = Array.from(e.children), i = this.parseNode(t[1]), s = this.parseNode(t[2]);
681
+ return `${i} = ${s}`;
647
682
  }
648
683
  return this.parseNode(e);
649
684
  }
650
685
  ignoreTag(e) {
651
686
  return ["bvar"].includes(e);
652
687
  }
653
- parseNode(e) {
688
+ parseNode(e, t = 0) {
654
689
  if (!e) return "";
655
- const s = e.localName;
656
- return s === "apply" ? this.parseApply(e) : s === "ci" ? this.parseIdentifier(e.textContent || "") : s === "cn" ? e.textContent || "0" : s === "piecewise" ? this.parsePiecewise(e) : s === "pi" ? "\\pi" : (this.ignoreTag(s) || console.warn(`Unsupported MathML node: ${s}`), "");
690
+ const i = e.localName;
691
+ if (i === "apply") return this.parseApply(e, t);
692
+ if (i === "ci") return this.parseIdentifier(e.textContent || "");
693
+ if (i === "cn") {
694
+ if (e.getAttribute("type") === "e-notation") {
695
+ const a = Array.from(e.childNodes), o = a.findIndex((l) => l.nodeType === 1 && l.localName === "sep");
696
+ if (o !== -1) {
697
+ const l = a.slice(0, o).map((p) => p.textContent).join("").trim(), u = a.slice(o + 1).map((p) => p.textContent).join("").trim();
698
+ return `${l} \\times 10^{${u}}`;
699
+ }
700
+ }
701
+ const r = e.textContent?.trim() || "0";
702
+ if (r.match(/^-?[\d.]+[eE][+-]?\d+$/)) {
703
+ const [a, o] = r.split(/[eE]/);
704
+ return `${a} \\times 10^{${o}}`;
705
+ }
706
+ return r;
707
+ }
708
+ return i === "piecewise" ? this.parsePiecewise(e) : i === "pi" ? "\\pi" : (this.ignoreTag(i) || console.warn(`Unsupported MathML node: ${i}`), "");
657
709
  }
658
710
  escapeGreek(e) {
659
711
  return [
@@ -691,62 +743,84 @@ class C {
691
743
  parseIdentifier(e) {
692
744
  if (!e.includes("_"))
693
745
  return this.escapeGreek(e);
694
- const s = e.split("_"), i = this.escapeGreek(s[0] || ""), t = [];
695
- s[1] && t.push(s[1]), s.length > 4 && t.push(...s.slice(4));
746
+ const t = e.split("_"), i = this.escapeGreek(t[0] || ""), s = [];
747
+ t[1] && s.push(t[1]), t.length > 4 && s.push(...t.slice(4));
696
748
  let r = "";
697
- s.length === 3 && (s[2] || []).length === 1 ? t.push(this.escapeGreek(s[2] || "")) : s[2] && (r = this.escapeGreek(s[2]), s[3] && (r += `_{${this.escapeGreek(s[3])}}`)), t.forEach((u, l) => {
698
- t[l] = this.escapeGreek(u);
749
+ t.length === 3 && (t[2] || []).length === 1 ? s.push(this.escapeGreek(t[2] || "")) : t[2] && (r = this.escapeGreek(t[2]), t[3] && (r += `_{${this.escapeGreek(t[3])}}`)), s.forEach((l, u) => {
750
+ s[u] = this.escapeGreek(l);
699
751
  });
700
- const c = t.join(",");
752
+ const a = s.join(",");
701
753
  let o = i;
702
- return c && (o += `_{${c}}`), r && (o += `^{${r}}`), o;
754
+ return a && (o += `_{${a}}`), r && (o += `^{${r}}`), o;
703
755
  }
704
- parseApply(e) {
705
- const s = Array.from(e?.children || []), i = s[0]?.localName, t = s.slice(1).map((r) => this.parseNode(r));
706
- switch (i) {
756
+ parseApply(e, t) {
757
+ const i = Array.from(e?.children || []), s = i[0]?.localName || "unknown", r = $[s] || $.func, a = i.slice(1).map((l, u) => {
758
+ let p = r;
759
+ return ["divide", "diff", "root", "sqrt", "sin", "cos", "tan", "exp", "ln", "log"].includes(s) ? p = 0 : s === "minus" && u === 1 && (p = r + 1), this.parseNode(l, p);
760
+ });
761
+ let o = "";
762
+ switch (s) {
707
763
  case "plus":
708
- return t.join(" + ");
764
+ o = a.join(" + ");
765
+ break;
709
766
  case "minus":
710
- return t.length === 1 ? `-${t[0]}` : `${t[0]} - ${t[1]}`;
767
+ o = a.length === 1 ? `-${a[0]}` : `${a[0]} - ${a[1]}`;
768
+ break;
711
769
  case "times":
712
- return t.join(" \\cdot ");
770
+ o = a.join(" \\cdot ");
771
+ break;
713
772
  case "divide":
714
- return `\\frac{${t[0]}}{${t[1]}}`;
773
+ o = `\\frac{${a[0]}}{${a[1]}}`;
774
+ break;
715
775
  case "eq":
716
- return `${t[0]} == ${t[1]}`;
776
+ o = `${a[0]} == ${a[1]}`;
777
+ break;
717
778
  case "neq":
718
- return `${t[0]} \\neq ${t[1]}`;
779
+ o = `${a[0]} \\neq ${a[1]}`;
780
+ break;
719
781
  case "lt":
720
- return `${t[0]} < ${t[1]}`;
782
+ o = `${a[0]} < ${a[1]}`;
783
+ break;
721
784
  case "leq":
722
- return `${t[0]} \\leq ${t[1]}`;
785
+ o = `${a[0]} \\leq ${a[1]}`;
786
+ break;
723
787
  case "gt":
724
- return `${t[0]} > ${t[1]}`;
788
+ o = `${a[0]} > ${a[1]}`;
789
+ break;
725
790
  case "geq":
726
- return `${t[0]} \\geq ${t[1]}`;
791
+ o = `${a[0]} \\geq ${a[1]}`;
792
+ break;
727
793
  case "and":
728
- return t.join(" \\land ");
794
+ o = a.join(" \\land ");
795
+ break;
729
796
  case "or":
730
- return t.join(" \\lor ");
797
+ o = a.join(" \\lor ");
798
+ break;
731
799
  case "power":
732
- const r = s[1], c = t[0] || "", o = t[1];
733
- return r?.localName === "ci" || r?.localName === "cn" && !c.trim().startsWith("-") ? `{${c}}^{${o}}` : `\\left({${c}}\\right)^{${o}}`;
800
+ const l = i[1], u = a[0] || "", p = a[1];
801
+ o = l?.localName === "ci" || l?.localName === "cn" && !u.trim().startsWith("-") ? `{${u}}^{${p}}` : `\\left({${u}}\\right)^{${p}}`;
802
+ break;
734
803
  case "root":
735
804
  case "sqrt":
736
- return `\\sqrt{${t[0]}}`;
737
- // simple sqrt
805
+ o = `\\sqrt{${a[0]}}`;
806
+ break;
738
807
  case "diff":
739
- const l = s.find((w) => w.localName === "bvar"), p = s.find((w) => w.localName !== "diff" && w.localName !== "bvar"), d = l ? this.parseNode(l.firstElementChild) : "x";
740
- return `\\frac{d${p ? this.parseNode(p) : "y"}}{d${d}}`;
808
+ const f = i.find((x) => x.localName === "bvar"), w = i.find((x) => x.localName !== "diff" && x.localName !== "bvar"), g = f ? this.parseNode(f.firstElementChild) : "x";
809
+ o = `\\frac{d${w ? this.parseNode(w) : "y"}}{d${g}}`;
810
+ break;
741
811
  // Trig & Funcs
742
812
  case "exp":
743
- return `e^{${t[0]}}`;
813
+ o = `e^{${a[0]}}`;
814
+ break;
744
815
  case "abs":
745
- return `\\left|${t[0]}\\right|`;
816
+ o = `\\left|${a[0]}\\right|`;
817
+ break;
746
818
  case "floor":
747
- return `\\lfloor ${t[0]} \\rfloor`;
819
+ o = `\\lfloor ${a[0]} \\rfloor`;
820
+ break;
748
821
  case "ceil":
749
- return `\\lceil ${t[0]} \\rceil`;
822
+ o = `\\lceil ${a[0]} \\rceil`;
823
+ break;
750
824
  case "cos":
751
825
  case "cosh":
752
826
  case "log10":
@@ -758,26 +832,29 @@ class C {
758
832
  case "sinh":
759
833
  case "tan":
760
834
  case "tanh":
761
- return `\\${i}\\left(${t[0]}\\right)`;
835
+ o = `\\${s}\\left(${a[0]}\\right)`;
836
+ break;
762
837
  default:
763
- return console.log(`Unsupported MathML operator: ${i}`), `\\text{${i}}(${t.join(", ")})`;
838
+ console.log(`Unsupported MathML operator: ${s}`), o = `\\text{${s}}(${a.join(", ")})`;
839
+ break;
764
840
  }
841
+ return r < t && (o = `\\left(${o}\\right)`), o;
765
842
  }
766
843
  parsePiecewise(e) {
767
- let s = "";
768
- return Array.from(e.children).forEach((t) => {
769
- if (t.localName === "piece") {
770
- const r = this.parseNode(t.children[0]), c = this.parseNode(t.children[1]);
771
- s += `${r} & \\text{if } ${c} \\\\ `;
772
- } else if (t.localName === "otherwise") {
773
- const r = this.parseNode(t.children[0]);
774
- s += `${r} & \\text{otherwise}`;
844
+ let t = "";
845
+ return Array.from(e.children).forEach((s) => {
846
+ if (s.localName === "piece") {
847
+ const r = this.parseNode(s.children[0]), a = this.parseNode(s.children[1]);
848
+ t += `${r} & \\text{if } ${a} \\\\ `;
849
+ } else if (s.localName === "otherwise") {
850
+ const r = this.parseNode(s.children[0]);
851
+ t += `${r} & \\text{otherwise}`;
775
852
  }
776
- }), `\\begin{cases} ${s} \\end{cases}`;
853
+ }), `\\begin{cases} ${t} \\end{cases}`;
777
854
  }
778
855
  }
779
856
  export {
780
- C as CellMLLatexGenerator,
781
- N as CellMLTextGenerator,
782
- $ as CellMLTextParser
857
+ O as CellMLLatexGenerator,
858
+ k as CellMLTextGenerator,
859
+ E as CellMLTextParser
783
860
  };
@@ -1,11 +1,11 @@
1
- (function(m,n){typeof exports=="object"&&typeof module<"u"?n(exports):typeof define=="function"&&define.amd?define(["exports"],n):(m=typeof globalThis<"u"?globalThis:m||self,n(m.CellMLTextEditor={}))})(this,(function(m){"use strict";var n=(a=>(a[a.Unknown=0]="Unknown",a[a.EOF=1]="EOF",a[a.Identifier=2]="Identifier",a[a.Number=3]="Number",a[a.String=4]="String",a[a.KwDef=5]="KwDef",a[a.KwModel=6]="KwModel",a[a.KwComp=7]="KwComp",a[a.KwEndDef=8]="KwEndDef",a[a.KwAs=9]="KwAs",a[a.KwVar=10]="KwVar",a[a.KwUnit=11]="KwUnit",a[a.KwSel=12]="KwSel",a[a.KwCase=13]="KwCase",a[a.KwOtherwise=14]="KwOtherwise",a[a.KwEndSel=15]="KwEndSel",a[a.OpAss=16]="OpAss",a[a.OpPlus=17]="OpPlus",a[a.OpMinus=18]="OpMinus",a[a.OpTimes=19]="OpTimes",a[a.OpDivide=20]="OpDivide",a[a.OpComma=21]="OpComma",a[a.Colon=22]="Colon",a[a.SemiColon=23]="SemiColon",a[a.LParam=24]="LParam",a[a.RParam=25]="RParam",a[a.LBrace=26]="LBrace",a[a.RBrace=27]="RBrace",a[a.OpEq=28]="OpEq",a[a.OpNe=29]="OpNe",a[a.OpLt=30]="OpLt",a[a.OpLe=31]="OpLe",a[a.OpGt=32]="OpGt",a[a.OpGe=33]="OpGe",a[a.OpAnd=34]="OpAnd",a[a.OpOr=35]="OpOr",a))(n||{});class g{input;pos=0;line=1;length;currentToken=1;currentValue="";constructor(e){this.input=e,this.length=e.length,this.nextToken()}get token(){return this.currentToken}get value(){return this.currentValue}nextToken(){const e=this.skipWhitespace();if(this.line+=e,this.pos>=this.length){this.currentToken=1;return}const s=this.input[this.pos];if(/[a-zA-Z_]/.test(s||"")){let i=this.pos;for(;this.pos<this.length&&/[a-zA-Z0-9_]/.test(this.input[this.pos]||"");)this.pos++;const t=this.input.slice(i,this.pos);this.currentValue=t,this.currentToken=this.getKeywordType(t);return}if(/[0-9]/.test(s||"")||s==="."&&/[0-9]/.test(this.input[this.pos+1]||"")){let i=this.pos;for(;this.pos<this.length&&/[0-9]/.test(this.input[this.pos]||"");)this.pos++;if(this.input[this.pos]===".")for(this.pos++;this.pos<this.length&&/[0-9]/.test(this.input[this.pos]||"");)this.pos++;if(this.input[this.pos]==="e"||this.input[this.pos]==="E")for(this.pos++,(this.input[this.pos]==="+"||this.input[this.pos]==="-")&&this.pos++;this.pos<this.length&&/[0-9]/.test(this.input[this.pos]||"");)this.pos++;this.currentValue=this.input.slice(i,this.pos),this.currentToken=3;return}switch(this.pos++,this.currentValue=s||"",s){case"=":this.input[this.pos]==="="?(this.pos++,this.currentValue="==",this.currentToken=28):this.currentToken=16;break;case"!":this.input[this.pos]==="="?(this.pos++,this.currentValue="!=",this.currentToken=29):(console.warn(`Unexpected character '!' at pos ${this.pos}`),this.currentToken=0);break;case"<":this.input[this.pos]==="="?(this.pos++,this.currentValue="<=",this.currentToken=31):this.currentToken=30;break;case">":this.input[this.pos]==="="?(this.pos++,this.currentValue=">=",this.currentToken=33):this.currentToken=32;break;case"+":this.currentToken=17;break;case"-":this.currentToken=18;break;case"*":this.currentToken=19;break;case"/":this.currentToken=20;break;case"(":this.currentToken=24;break;case")":this.currentToken=25;break;case"{":this.currentToken=26;break;case"}":this.currentToken=27;break;case":":this.currentToken=22;break;case";":this.currentToken=23;break;case",":this.currentToken=21;break;default:console.warn("Unknown char:",s),this.currentToken=0}}getLine(){return this.line}skipWhitespace(){let e=0;for(;this.pos<this.length;){const s=this.input[this.pos];if(/\s/.test(s||""))s===`
2
- `&&e++,this.pos++;else if(s==="/"&&this.input[this.pos+1]==="/")for(this.pos+=2;this.pos<this.length&&this.input[this.pos]!==`
3
- `;)this.pos++;else break}return e}getKeywordType(e){switch(e){case"def":return 5;case"model":return 6;case"comp":return 7;case"enddef":return 8;case"as":return 9;case"var":return 10;case"unit":return 11;case"sel":return 12;case"case":return 13;case"otherwise":return 14;case"endsel":return 15;case"and":return 34;case"or":return 35;default:return 2}}}const f="http://www.cellml.org/cellml/2.0#",o="http://www.w3.org/1998/Math/MathML";class ${scanner;doc;sourceLineAttr;constructor(e={}){this.sourceLineAttr=e.sourceLineAttribute===void 0?"data-source-location":e.sourceLineAttribute}parse(e){this.scanner=new g(e),this.doc=document.implementation.createDocument(f,"model",null);try{const s=this.doc.documentElement;for(this.expect(n.KwDef),this.expect(n.KwModel),this.scanner.token===n.Identifier&&(s.setAttribute("name",this.scanner.value),this.scanner.nextToken()),this.expect(n.KwAs);this.scanner.token!==n.KwEndDef&&this.scanner.token!==n.EOF;)this.scanner.token===n.KwDef?this.parseBlock(s):this.scanner.nextToken();return this.expect(n.KwEndDef),this.expect(n.SemiColon),{xml:`<?xml version="1.0" encoding="UTF-8"?>
4
- `+this.serialize(s),errors:[]}}catch(s){return{xml:null,errors:[{line:this.scanner.getLine(),message:s.message||"Unknown parsing error"}]}}}parseBlock(e){if(this.expect(n.KwDef),this.scanner.token===n.KwComp)this.parseComponent(e);else if(this.scanner.token===n.KwUnit)this.parseUnit(e);else throw new Error("Expected 'comp' or 'unit' after 'def'")}parseComponent(e){this.expect(n.KwComp);const s=this.expectValue(n.Identifier);this.expect(n.KwAs);const i=this.doc.createElementNS(f,"component");for(i.setAttribute("name",s),e.appendChild(i);this.scanner.token!==n.KwEndDef&&this.scanner.token!==n.EOF;)this.scanner.token===n.KwVar?this.parseVariable(i):this.scanner.token===n.Identifier||this.scanner.token===n.KwSel?this.parseMathEquation(i):this.scanner.nextToken();this.expect(n.KwEndDef),this.expect(n.SemiColon)}parseVariable(e){this.expect(n.KwVar);const s=this.expectValue(n.Identifier);this.expect(n.Colon);const i=this.expectValue(n.Identifier),t=this.doc.createElementNS(f,"variable");if(t.setAttribute("name",s),t.setAttribute("units",i),this.scanner.token===n.LBrace){for(this.scanner.nextToken();this.scanner.token!==n.RBrace&&this.scanner.token!==n.EOF;){const r=this.expectValue(n.Identifier);this.expect(n.Colon);let c="";this.scanner.token===n.OpMinus?(this.scanner.nextToken(),c="-"+this.expectValue(n.Number)):this.scanner.token===n.Number?c=this.expectValue(n.Number):c=this.expectValue(n.Identifier),r==="init"?t.setAttribute("initial_value",c):r==="interface"&&t.setAttribute("interface",c),this.scanner.token===n.OpComma&&this.scanner.nextToken()}this.expect(n.RBrace)}this.expect(n.SemiColon),e.appendChild(t)}parseUnit(e){for(this.expect(n.KwUnit);this.scanner.token!==n.KwEndDef&&this.scanner.token!==n.EOF;)this.scanner.nextToken();this.expect(n.KwEndDef),this.expect(n.SemiColon)}parseMathEquation(e){const s=this.scanner.getLine();let i=e.getElementsByTagNameNS(o,"math")[0];i||(i=this.doc.createElementNS(o,"math"),e.appendChild(i));const t=this.doc.createElementNS(o,"apply"),r=this.doc.createElementNS(o,"eq");t.appendChild(r);const c=this.parseExpression();this.expect(n.OpAss);const h=this.parseExpression(),u=this.scanner.getLine();this.sourceLineAttr&&t.setAttribute(this.sourceLineAttr,`${s.toString()}`+(u!==s?`-${u.toString()}`:"")),t.appendChild(c),t.appendChild(h),i.appendChild(t),this.expect(n.SemiColon)}parseCondition(){let e=this.parseComparison();for(;this.scanner.token===n.OpAnd||this.scanner.token===n.OpOr;){const s=this.scanner.token;this.scanner.nextToken();const i=this.parseComparison(),t=this.doc.createElementNS(o,"apply"),r=this.doc.createElementNS(o,s===n.OpAnd?"and":"or");t.appendChild(r),t.appendChild(e),t.appendChild(i),e=t}return e}isComparisonToken(e){return[n.OpEq,n.OpNe,n.OpLt,n.OpLe,n.OpGt,n.OpGe].includes(e)}parseComparison(){let e=this.parseExpression();if(this.isComparisonToken(this.scanner.token)){const s=this.scanner.token;this.scanner.nextToken();const i=this.parseExpression(),t=this.doc.createElementNS(o,"apply");let r="";switch(s){case n.OpEq:r="eq";break;case n.OpNe:r="neq";break;case n.OpLt:r="lt";break;case n.OpLe:r="leq";break;case n.OpGt:r="gt";break;case n.OpGe:r="geq";break;case n.OpAnd:r="and";break}const c=this.doc.createElementNS(o,r);return t.appendChild(c),t.appendChild(e),t.appendChild(i),t}return e}isMathMLApply(e,s){if(e.localName!=="apply")return!1;const i=e.firstElementChild;return i?i.localName===s:!1}parseExpression(){let e=this.parseTerm();for(;this.scanner.token===n.OpPlus||this.scanner.token===n.OpMinus;){const s=this.scanner.token;this.scanner.nextToken();const i=this.parseTerm();if(s===n.OpPlus&&this.isMathMLApply(e,"plus"))e.appendChild(i);else{const t=this.doc.createElementNS(o,"apply"),r=this.doc.createElementNS(o,s===n.OpPlus?"plus":"minus");t.appendChild(r),t.appendChild(e),t.appendChild(i),e=t}}return e}parseTerm(){let e=this.parseFactor();for(;this.scanner.token===n.OpTimes||this.scanner.token===n.OpDivide;){const s=this.scanner.token;this.scanner.nextToken();const i=this.parseFactor();if(s===n.OpTimes&&this.isMathMLApply(e,"times"))e.appendChild(i);else{const t=this.doc.createElementNS(o,"apply"),r=this.doc.createElementNS(o,s===n.OpTimes?"times":"divide");t.appendChild(r),t.appendChild(e),t.appendChild(i),e=t}}return e}createMathMLConstant(e){const s={pi:"pi",e:"exponentiale",inf:"infinity",infinity:"infinity",NaN:"notanumber",true:"true",false:"false"};return s.hasOwnProperty(e)?this.doc.createElementNS(o,s[e]||""):null}parseFactor(){if(this.scanner.token===n.OpMinus){this.scanner.nextToken();const e=this.parseFactor(),s=this.doc.createElementNS(o,"apply"),i=this.doc.createElementNS(o,"minus");return s.appendChild(i),s.appendChild(e),s}if(this.scanner.token===n.Number){const e=this.scanner.value;this.scanner.nextToken();const s=this.doc.createElementNS(o,"cn");if(s.textContent=e,this.scanner.token===n.LBrace){if(this.scanner.nextToken(),this.scanner.value==="units"){this.scanner.nextToken(),this.expect(n.Colon);const i=this.expectValue(n.Identifier);s.setAttributeNS(f,"cellml:units",i)}for(;this.scanner.token!==n.RBrace&&this.scanner.token!==n.EOF;)this.scanner.nextToken();this.expect(n.RBrace)}return s}else if(this.scanner.token===n.Identifier){const e=this.scanner.value;if(this.scanner.nextToken(),this.scanner.token===n.LParam)return this.parseFunctionCall(e);const s=this.createMathMLConstant(e);if(s)return s;const i=this.doc.createElementNS(o,"ci");return i.textContent=e,i}else if(this.scanner.token===n.LParam){this.scanner.nextToken();const e=this.parseExpression();return this.expect(n.RParam),e}else if(this.scanner.token===n.KwSel)return this.parsePiecewise();throw new Error(`Unexpected token in math: ${this.scanner.value}`)}parsePiecewise(){const e=this.doc.createElementNS(o,"piecewise");for(this.expect(n.KwSel);this.scanner.token===n.KwCase;){this.expect(n.KwCase);const s=this.parseCondition();this.expect(n.Colon);const i=this.parseExpression();this.expect(n.SemiColon);const t=this.doc.createElementNS(o,"piece");t.appendChild(i),t.appendChild(s),e.appendChild(t)}if(this.scanner.token===n.KwOtherwise){this.expect(n.KwOtherwise),this.expect(n.Colon);const s=this.parseExpression();this.expect(n.SemiColon);const i=this.doc.createElementNS(o,"otherwise");i.appendChild(s),e.appendChild(i)}return this.expect(n.KwEndSel),e}parseFunctionCall(e){if(this.expect(n.LParam),e==="ode"){const t=this.parseExpression();this.expect(n.OpComma);const r=this.parseExpression();this.expect(n.RParam);const c=this.doc.createElementNS(o,"apply");c.appendChild(this.doc.createElementNS(o,"diff"));const h=this.doc.createElementNS(o,"bvar");return h.appendChild(r),c.appendChild(h),c.appendChild(t),c}const s=this.doc.createElementNS(o,"apply"),i=this.doc.createElementNS(o,e);if(s.appendChild(i),this.scanner.token!==n.RParam)do this.scanner.token===n.OpComma&&this.scanner.nextToken(),s.appendChild(this.parseExpression());while(this.scanner.token===n.OpComma);return this.expect(n.RParam),s}expect(e){if(this.scanner.token!==e)throw new Error(`Syntax Error: Expected ${n[e]} but found '${this.scanner.value}'`);this.scanner.nextToken()}expectValue(e){if(this.scanner.token!==e)throw new Error(`Expected value of type ${n[e]}, got ${this.scanner.token}`);const s=this.scanner.value;return this.scanner.nextToken(),s}usesCellMLNamespace(e){const s=e.getElementsByTagName("*");for(let i=0;i<s.length;i++){const t=s[i];for(let r=0;t&&r<t.attributes.length;r++){const c=t.attributes[r];if(c&&c.namespaceURI===f)return!0}}return!1}getPrefixForNamespace(e,s){const i="http://www.w3.org/2000/xmlns/";for(let t=0;t<e.attributes.length;t++){const r=e.attributes[t];if(r&&r.namespaceURI===i&&r.value===s)return r.localName==="xmlns"?"":r.localName}return null}serialize(e,s=0){const i=" ".repeat(s),t=e.tagName,r=e.localName;let c="";r==="model"&&!e.hasAttribute("xmlns")&&(c+=` xmlns="${f}"`),r==="math"&&!e.hasAttribute("xmlns")&&(c+=` xmlns="${o}"`,this.usesCellMLNamespace(e)&&!e.hasAttribute("xmlns:cellml")&&this.getPrefixForNamespace(e,f)===null&&(c+=` xmlns:cellml="${f}"`));for(let d=0;d<e.attributes.length;d++){const w=e.attributes[d];if(w){if(this.sourceLineAttr&&w.name===this.sourceLineAttr)continue;c+=` ${w.name}="${w.value}"`}}const h=Array.from(e.childNodes),u=h.some(d=>d.nodeType===1),l=e.textContent?.trim();if(h.length===0&&!l)return`${i}<${t}${c}/>`;if(!u)return`${i}<${t}${c}>${l}</${t}>`;let p=`${i}<${t}${c}>
5
- `;return h.forEach(d=>{d.nodeType===1&&(p+=this.serialize(d,s+1)+`
6
- `)}),p+=`${i}</${t}>`,p}}const N="http://www.cellml.org/cellml/2.0#";class C{output="";indentLevel=0;domParser;standardIndent=" ";constructor(){this.domParser=new DOMParser}indent(){return this.standardIndent.repeat(this.indentLevel)}append(e,s=!0){this.output+=(s?this.indent():"")+e+(s?`
7
- `:"")}generate(e){this.output="",this.indentLevel=0;try{const s=this.domParser.parseFromString(e,"application/xml");if(s.querySelector("parsererror"))throw new Error("XML Parsing Error");const t=s.getElementsByTagNameNS("http://www.cellml.org/cellml/2.0#","model")[0];if(!t)throw new Error("No CellML 2.0 Model found");this.processModel(t)}catch(s){return`// Error generating text: ${s.message}`}return this.output}processModel(e){const s=e.getAttribute("name")||"unnamed_model";this.append(`def model ${s} as`),this.indentLevel++;const i=e.getElementsByTagName("units");for(let r=0;r<i.length;r++)i[r]?.parentElement===e&&this.processUnits(i[r]);const t=e.getElementsByTagName("component");for(let r=0;r<t.length;r++)this.processComponent(t[r]);this.indentLevel--,this.append("enddef;")}processUnits(e){const s=e?.getAttribute("name")||"unnamed_units";this.append(`def unit ${s} as`),this.indentLevel++;const i=e?.getElementsByTagName("unit")||[];for(let t=0;t<i.length;t++){const r=i[t];if(!r)continue;const c=r.getAttribute("prefix"),h=r.getAttribute("units"),u=r.getAttribute("exponent"),l=r.getAttribute("multiplier");let p=`unit ${h}`;c&&(p+=` {prefix: ${c}}`),u&&(p+=` {exponent: ${u}}`),l&&(p+=` {multiplier: ${l}}`),p+=";",this.append(p)}this.indentLevel--,this.append("enddef;"),this.append("")}processComponent(e){const s=e?.getAttribute("name")||"unnamed_component";this.append(`def comp ${s} as`),this.indentLevel++;const i=e?.getElementsByTagName("variable")||[];for(let r=0;r<i.length;r++)this.processVariable(i[r]);const t=e?.getElementsByTagNameNS("http://www.w3.org/1998/Math/MathML","math")||[];for(let r=0;r<t.length;r++)this.processMath(t[r]);this.indentLevel--,this.append("enddef;"),this.append("")}processVariable(e){const s=e?.getAttribute("name"),i=e?.getAttribute("units"),t=e?.getAttribute("initial_value"),r=e?.getAttribute("interface");let c=`var ${s}: ${i}`,h=[];t&&h.push(`init: ${t}`),r&&h.push(`interface: ${r}`),h.length>0&&(c+=` {${h.join(", ")}}`),c+=";",this.append(c)}processMath(e){const s=Array.from(e?.children||[]);for(const i of s)if(i.localName==="apply"&&i.firstElementChild?.localName==="eq"){const r=Array.from(i.children).slice(1),c=this.parseMathNode(r[0]),h=this.parseMathNode(r[1]);this.append(`${c} = ${h};`)}else{const r=this.parseMathNode(i);r&&this.append(r+";")}}parseMathNode(e){if(!e)return"";const s=e.localName;if(s==="apply")return this.parseApply(e);if(s==="ci")return e.textContent?.trim()||"";if(s==="cn"){const i=e.textContent?.trim()||"0",t=e.getAttributeNS(N,"units");return t?`${i} {units: ${t}}`:i}else{if(s==="piecewise")return this.parsePiecewise(e);if(s==="pi")return"pi";if(s==="bvar")return""}return console.log(`Unsupported MathML node: ${s}`),`/* Unsupported MathML node: ${s} */`}parseApply(e){const s=Array.from(e.children);if(s.length===0)return"";const i=s[0]?.localName,t=s.slice(1).map(r=>this.parseMathNode(r));switch(i){case"plus":return`(${t.join(" + ")})`;case"minus":return t.length===1?`-${t[0]}`:`(${t[0]} - ${t[1]})`;case"times":return`(${t.join(" * ")})`;case"divide":return`(${t[0]} / ${t[1]})`;case"eq":return`${t[0]} == ${t[1]}`;case"neq":return`${t[0]} != ${t[1]}`;case"lt":return`${t[0]} < ${t[1]}`;case"leq":return`${t[0]} <= ${t[1]}`;case"gt":return`${t[0]} > ${t[1]}`;case"geq":return`${t[0]} >= ${t[1]}`;case"and":return`${t.join(" and ")}`;case"or":return`${t.join(" or ")}`;case"diff":const r=s.find(l=>l.localName==="bvar"),c=s.find(l=>l.localName!=="diff"&&l.localName!=="bvar"),h=r?.children[0]?.textContent||"t";return`ode(${c?this.parseMathNode(c):"unknown"}, ${h})`;case"sin":case"cos":case"tan":case"exp":case"ln":case"log":return`${i}(${t[0]})`;case"root":return`sqrt(${t[0]})`;default:return`${i}(${t.join(", ")})`}}parsePiecewise(e){let s=[];return Array.from(e?.children||[]).forEach(t=>{if(t.localName==="piece"){const r=this.parseMathNode(t.children[0]),c=this.parseMathNode(t.children[1]);s.push(`${this.standardIndent}case ${c}: ${r};`)}else if(t.localName==="otherwise"){const r=this.parseMathNode(t.children[0]);s.push(`${this.standardIndent}otherwise: ${r};`)}}),`sel
8
- ${this.indent()}${s.join(`
1
+ (function(m,n){typeof exports=="object"&&typeof module<"u"?n(exports):typeof define=="function"&&define.amd?define(["exports"],n):(m=typeof globalThis<"u"?globalThis:m||self,n(m.CellMLTextEditor={}))})(this,(function(m){"use strict";var n=(c=>(c[c.Unknown=0]="Unknown",c[c.EOF=1]="EOF",c[c.Identifier=2]="Identifier",c[c.Number=3]="Number",c[c.String=4]="String",c[c.KwDef=5]="KwDef",c[c.KwModel=6]="KwModel",c[c.KwComp=7]="KwComp",c[c.KwEndDef=8]="KwEndDef",c[c.KwAs=9]="KwAs",c[c.KwVar=10]="KwVar",c[c.KwUnit=11]="KwUnit",c[c.KwSel=12]="KwSel",c[c.KwCase=13]="KwCase",c[c.KwOtherwise=14]="KwOtherwise",c[c.KwEndSel=15]="KwEndSel",c[c.OpAss=16]="OpAss",c[c.OpPlus=17]="OpPlus",c[c.OpMinus=18]="OpMinus",c[c.OpTimes=19]="OpTimes",c[c.OpDivide=20]="OpDivide",c[c.OpComma=21]="OpComma",c[c.Colon=22]="Colon",c[c.SemiColon=23]="SemiColon",c[c.LParam=24]="LParam",c[c.RParam=25]="RParam",c[c.LBrace=26]="LBrace",c[c.RBrace=27]="RBrace",c[c.OpEq=28]="OpEq",c[c.OpNe=29]="OpNe",c[c.OpLt=30]="OpLt",c[c.OpLe=31]="OpLe",c[c.OpGt=32]="OpGt",c[c.OpGe=33]="OpGe",c[c.OpAnd=34]="OpAnd",c[c.OpOr=35]="OpOr",c))(n||{});class N{input;pos=0;line=1;length;currentToken=1;currentValue="";constructor(e){this.input=e,this.length=e.length,this.nextToken()}get token(){return this.currentToken}get value(){return this.currentValue}nextToken(){const e=this.skipWhitespace();if(this.line+=e,this.pos>=this.length){this.currentToken=1;return}const t=this.input[this.pos];if(/[a-zA-Z_]/.test(t||"")){let i=this.pos;for(;this.pos<this.length&&/[a-zA-Z0-9_]/.test(this.input[this.pos]||"");)this.pos++;const s=this.input.slice(i,this.pos);this.currentValue=s,this.currentToken=this.getKeywordType(s);return}if(/[0-9]/.test(t||"")||t==="."&&/[0-9]/.test(this.input[this.pos+1]||"")){let i=this.pos;for(;this.pos<this.length&&/[0-9]/.test(this.input[this.pos]||"");)this.pos++;if(this.input[this.pos]===".")for(this.pos++;this.pos<this.length&&/[0-9]/.test(this.input[this.pos]||"");)this.pos++;if(this.input[this.pos]==="e"||this.input[this.pos]==="E")for(this.pos++,(this.input[this.pos]==="+"||this.input[this.pos]==="-")&&this.pos++;this.pos<this.length&&/[0-9]/.test(this.input[this.pos]||"");)this.pos++;this.currentValue=this.input.slice(i,this.pos),this.currentToken=3;return}switch(this.pos++,this.currentValue=t||"",t){case"=":this.input[this.pos]==="="?(this.pos++,this.currentValue="==",this.currentToken=28):this.currentToken=16;break;case"!":this.input[this.pos]==="="?(this.pos++,this.currentValue="!=",this.currentToken=29):(console.warn(`Unexpected character '!' at pos ${this.pos}`),this.currentToken=0);break;case"<":this.input[this.pos]==="="?(this.pos++,this.currentValue="<=",this.currentToken=31):this.currentToken=30;break;case">":this.input[this.pos]==="="?(this.pos++,this.currentValue=">=",this.currentToken=33):this.currentToken=32;break;case"+":this.currentToken=17;break;case"-":this.currentToken=18;break;case"*":this.currentToken=19;break;case"/":this.currentToken=20;break;case"(":this.currentToken=24;break;case")":this.currentToken=25;break;case"{":this.currentToken=26;break;case"}":this.currentToken=27;break;case":":this.currentToken=22;break;case";":this.currentToken=23;break;case",":this.currentToken=21;break;default:console.warn("Unknown char:",t),this.currentToken=0}}getLine(){return this.line}skipWhitespace(){let e=0;for(;this.pos<this.length;){const t=this.input[this.pos];if(/\s/.test(t||""))t===`
2
+ `&&e++,this.pos++;else if(t==="/"&&this.input[this.pos+1]==="/")for(this.pos+=2;this.pos<this.length&&this.input[this.pos]!==`
3
+ `;)this.pos++;else break}return e}getKeywordType(e){switch(e){case"def":return 5;case"model":return 6;case"comp":return 7;case"enddef":return 8;case"as":return 9;case"var":return 10;case"unit":return 11;case"sel":return 12;case"case":return 13;case"otherwise":return 14;case"endsel":return 15;case"and":return 34;case"or":return 35;default:return 2}}}const f="http://www.cellml.org/cellml/2.0#",l="http://www.w3.org/1998/Math/MathML";class C{scanner;doc;sourceLineAttr;constructor(e={}){this.sourceLineAttr=e.sourceLineAttribute===void 0?"data-source-location":e.sourceLineAttribute}parse(e){this.scanner=new N(e),this.doc=document.implementation.createDocument(f,"model",null);try{const t=this.doc.documentElement;for(this.expect(n.KwDef),this.expect(n.KwModel),this.scanner.token===n.Identifier&&(t.setAttribute("name",this.scanner.value),this.scanner.nextToken()),this.expect(n.KwAs);this.scanner.token!==n.KwEndDef&&this.scanner.token!==n.EOF;)this.scanner.token===n.KwDef?this.parseBlock(t):this.scanner.nextToken();return this.expect(n.KwEndDef),this.expect(n.SemiColon),{xml:`<?xml version="1.0" encoding="UTF-8"?>
4
+ `+this.serialize(t),errors:[]}}catch(t){return{xml:null,errors:[{line:this.scanner.getLine(),message:t.message||"Unknown parsing error"}]}}}parseBlock(e){if(this.expect(n.KwDef),this.scanner.token===n.KwComp)this.parseComponent(e);else if(this.scanner.token===n.KwUnit)this.parseUnit(e);else throw new Error("Expected 'comp' or 'unit' after 'def'")}parseComponent(e){this.expect(n.KwComp);const t=this.expectValue(n.Identifier);this.expect(n.KwAs);const i=this.doc.createElementNS(f,"component");for(i.setAttribute("name",t),e.appendChild(i);this.scanner.token!==n.KwEndDef&&this.scanner.token!==n.EOF;)this.scanner.token===n.KwVar?this.parseVariable(i):this.scanner.token===n.Identifier||this.scanner.token===n.KwSel?this.parseMathEquation(i):this.scanner.nextToken();this.expect(n.KwEndDef),this.expect(n.SemiColon)}parseVariable(e){this.expect(n.KwVar);const t=this.expectValue(n.Identifier);this.expect(n.Colon);const i=this.expectValue(n.Identifier),s=this.doc.createElementNS(f,"variable");if(s.setAttribute("name",t),s.setAttribute("units",i),this.scanner.token===n.LBrace){for(this.scanner.nextToken();this.scanner.token!==n.RBrace&&this.scanner.token!==n.EOF;){const r=this.expectValue(n.Identifier);this.expect(n.Colon);let a="";this.scanner.token===n.OpMinus?(this.scanner.nextToken(),a="-"+this.expectValue(n.Number)):this.scanner.token===n.Number?a=this.expectValue(n.Number):a=this.expectValue(n.Identifier),r==="init"?s.setAttribute("initial_value",a):r==="interface"&&s.setAttribute("interface",a),this.scanner.token===n.OpComma&&this.scanner.nextToken()}this.expect(n.RBrace)}this.expect(n.SemiColon),e.appendChild(s)}parseUnit(e){for(this.expect(n.KwUnit);this.scanner.token!==n.KwEndDef&&this.scanner.token!==n.EOF;)this.scanner.nextToken();this.expect(n.KwEndDef),this.expect(n.SemiColon)}parseMathEquation(e){const t=this.scanner.getLine();let i=e.getElementsByTagNameNS(l,"math")[0];i||(i=this.doc.createElementNS(l,"math"),e.appendChild(i));const s=this.doc.createElementNS(l,"apply"),r=this.doc.createElementNS(l,"eq");s.appendChild(r);const a=this.parseExpression();this.expect(n.OpAss);const o=this.parseExpression(),h=this.scanner.getLine();this.sourceLineAttr&&s.setAttribute(this.sourceLineAttr,`${t.toString()}`+(h!==t?`-${h.toString()}`:"")),s.appendChild(a),s.appendChild(o),i.appendChild(s),this.expect(n.SemiColon)}parseCondition(){let e=this.parseComparison();for(;this.scanner.token===n.OpAnd||this.scanner.token===n.OpOr;){const t=this.scanner.token;this.scanner.nextToken();const i=this.parseComparison(),s=this.doc.createElementNS(l,"apply"),r=this.doc.createElementNS(l,t===n.OpAnd?"and":"or");s.appendChild(r),s.appendChild(e),s.appendChild(i),e=s}return e}isComparisonToken(e){return[n.OpEq,n.OpNe,n.OpLt,n.OpLe,n.OpGt,n.OpGe].includes(e)}parseComparison(){let e=this.parseExpression();if(this.isComparisonToken(this.scanner.token)){const t=this.scanner.token;this.scanner.nextToken();const i=this.parseExpression(),s=this.doc.createElementNS(l,"apply");let r="";switch(t){case n.OpEq:r="eq";break;case n.OpNe:r="neq";break;case n.OpLt:r="lt";break;case n.OpLe:r="leq";break;case n.OpGt:r="gt";break;case n.OpGe:r="geq";break;case n.OpAnd:r="and";break}const a=this.doc.createElementNS(l,r);return s.appendChild(a),s.appendChild(e),s.appendChild(i),s}return e}isMathMLApply(e,t){if(e.localName!=="apply")return!1;const i=e.firstElementChild;return i?i.localName===t:!1}parseExpression(){let e=this.parseTerm();for(;this.scanner.token===n.OpPlus||this.scanner.token===n.OpMinus;){const t=this.scanner.token;this.scanner.nextToken();const i=this.parseTerm();if(t===n.OpPlus&&this.isMathMLApply(e,"plus"))e.appendChild(i);else{const s=this.doc.createElementNS(l,"apply"),r=this.doc.createElementNS(l,t===n.OpPlus?"plus":"minus");s.appendChild(r),s.appendChild(e),s.appendChild(i),e=s}}return e}parseTerm(){let e=this.parseFactor();for(;this.scanner.token===n.OpTimes||this.scanner.token===n.OpDivide;){const t=this.scanner.token;this.scanner.nextToken();const i=this.parseFactor();if(t===n.OpTimes&&this.isMathMLApply(e,"times"))e.appendChild(i);else{const s=this.doc.createElementNS(l,"apply"),r=this.doc.createElementNS(l,t===n.OpTimes?"times":"divide");s.appendChild(r),s.appendChild(e),s.appendChild(i),e=s}}return e}createMathMLConstant(e){const t={pi:"pi",e:"exponentiale",inf:"infinity",infinity:"infinity",NaN:"notanumber",true:"true",false:"false"};return t.hasOwnProperty(e)?this.doc.createElementNS(l,t[e]||""):null}parseFactor(){if(this.scanner.token===n.OpMinus){this.scanner.nextToken();const e=this.parseFactor(),t=this.doc.createElementNS(l,"apply"),i=this.doc.createElementNS(l,"minus");return t.appendChild(i),t.appendChild(e),t}if(this.scanner.token===n.Number){const e=this.scanner.value;this.scanner.nextToken();const t=this.doc.createElementNS(l,"cn");if(this.scanner.token===n.LBrace){if(this.scanner.nextToken(),this.scanner.value==="units"){this.scanner.nextToken(),this.expect(n.Colon);const i=this.expectValue(n.Identifier);t.setAttributeNS(f,"cellml:units",i)}for(;this.scanner.token!==n.RBrace&&this.scanner.token!==n.EOF;)this.scanner.nextToken();this.expect(n.RBrace)}if(e.match(/^-?[\d.]+[eE][+-]?\d+$/)){t.setAttribute("type","e-notation");const i=this.doc.createElementNS(l,"sep"),[s,r]=e.split(/[eE]/);t.appendChild(this.doc.createTextNode(s||"1")),t.appendChild(i),t.appendChild(this.doc.createTextNode(r||"0"))}else t.textContent=e;return t}else if(this.scanner.token===n.Identifier){const e=this.scanner.value;if(this.scanner.nextToken(),this.scanner.token===n.LParam)return this.parseFunctionCall(e);const t=this.createMathMLConstant(e);if(t)return t;const i=this.doc.createElementNS(l,"ci");return i.textContent=e,i}else if(this.scanner.token===n.LParam){this.scanner.nextToken();const e=this.parseExpression();return this.expect(n.RParam),e}else if(this.scanner.token===n.KwSel)return this.parsePiecewise();throw new Error(`Unexpected token in math: ${this.scanner.value}`)}parsePiecewise(){const e=this.doc.createElementNS(l,"piecewise");for(this.expect(n.KwSel);this.scanner.token===n.KwCase;){this.expect(n.KwCase);const t=this.parseCondition();this.expect(n.Colon);const i=this.parseExpression();this.expect(n.SemiColon);const s=this.doc.createElementNS(l,"piece");s.appendChild(i),s.appendChild(t),e.appendChild(s)}if(this.scanner.token===n.KwOtherwise){this.expect(n.KwOtherwise),this.expect(n.Colon);const t=this.parseExpression();this.expect(n.SemiColon);const i=this.doc.createElementNS(l,"otherwise");i.appendChild(t),e.appendChild(i)}return this.expect(n.KwEndSel),e}parseFunctionCall(e){if(this.expect(n.LParam),e==="ode"){const s=this.parseExpression();this.expect(n.OpComma);const r=this.parseExpression();this.expect(n.RParam);const a=this.doc.createElementNS(l,"apply");a.appendChild(this.doc.createElementNS(l,"diff"));const o=this.doc.createElementNS(l,"bvar");return o.appendChild(r),a.appendChild(o),a.appendChild(s),a}const t=this.doc.createElementNS(l,"apply"),i=this.doc.createElementNS(l,e);if(t.appendChild(i),this.scanner.token!==n.RParam)do this.scanner.token===n.OpComma&&this.scanner.nextToken(),t.appendChild(this.parseExpression());while(this.scanner.token===n.OpComma);return this.expect(n.RParam),t}expect(e){if(this.scanner.token!==e)throw new Error(`Syntax Error: Expected ${n[e]} but found '${this.scanner.value}'`);this.scanner.nextToken()}expectValue(e){if(this.scanner.token!==e)throw new Error(`Expected value of type ${n[e]}, got ${this.scanner.token}`);const t=this.scanner.value;return this.scanner.nextToken(),t}usesCellMLNamespace(e){const t=e.getElementsByTagName("*");for(let i=0;i<t.length;i++){const s=t[i];for(let r=0;s&&r<s.attributes.length;r++){const a=s.attributes[r];if(a&&a.namespaceURI===f)return!0}}return!1}getPrefixForNamespace(e,t){const i="http://www.w3.org/2000/xmlns/";for(let s=0;s<e.attributes.length;s++){const r=e.attributes[s];if(r&&r.namespaceURI===i&&r.value===t)return r.localName==="xmlns"?"":r.localName}return null}serialize(e,t=0){const i=" ".repeat(t),s=e.tagName,r=e.localName;let a="";r==="model"&&!e.hasAttribute("xmlns")&&(a+=` xmlns="${f}"`),r==="math"&&!e.hasAttribute("xmlns")&&(a+=` xmlns="${l}"`,this.usesCellMLNamespace(e)&&!e.hasAttribute("xmlns:cellml")&&this.getPrefixForNamespace(e,f)===null&&(a+=` xmlns:cellml="${f}"`));for(let d=0;d<e.attributes.length;d++){const x=e.attributes[d];if(x){if(this.sourceLineAttr&&x.name===this.sourceLineAttr)continue;a+=` ${x.name}="${x.value}"`}}const o=Array.from(e.childNodes),h=o.some(d=>d.nodeType===1),u=e.textContent?.trim();if(o.length===0&&!u)return`${i}<${s}${a}/>`;if(h){if(e.tagName==="cn"&&o.length===3)return`${i}<${s}${a}>${o[0]?.textContent}<sep/>${o[2]?.textContent}</${s}>`}else return`${i}<${s}${a}>${u}</${s}>`;let p=`${i}<${s}${a}>
5
+ `;return o.forEach(d=>{d.nodeType===1&&(p+=this.serialize(d,t+1)+`
6
+ `)}),p+=`${i}</${s}>`,p}}const b="http://www.cellml.org/cellml/2.0#";class E{output="";indentLevel=0;domParser;standardIndent=" ";constructor(){this.domParser=new DOMParser}indent(){return this.standardIndent.repeat(this.indentLevel)}append(e,t=!0){this.output+=(t?this.indent():"")+e+(t?`
7
+ `:"")}generate(e){this.output="",this.indentLevel=0;try{const t=this.domParser.parseFromString(e,"application/xml");if(t.querySelector("parsererror"))throw new Error("XML Parsing Error");const s=t.getElementsByTagNameNS("http://www.cellml.org/cellml/2.0#","model")[0];if(!s)throw new Error("No CellML 2.0 Model found");this.processModel(s)}catch(t){return`// Error generating text: ${t.message}`}return this.output}processModel(e){const t=e.getAttribute("name")||"unnamed_model";this.append(`def model ${t} as`),this.indentLevel++;const i=e.getElementsByTagName("units");for(let r=0;r<i.length;r++)i[r]?.parentElement===e&&this.processUnits(i[r]);const s=e.getElementsByTagName("component");for(let r=0;r<s.length;r++)this.processComponent(s[r]);this.indentLevel--,this.append("enddef;")}processUnits(e){const t=e?.getAttribute("name")||"unnamed_units";this.append(`def unit ${t} as`),this.indentLevel++;const i=e?.getElementsByTagName("unit")||[];for(let s=0;s<i.length;s++){const r=i[s];if(!r)continue;const a=r.getAttribute("prefix"),o=r.getAttribute("units"),h=r.getAttribute("exponent"),u=r.getAttribute("multiplier");let p=`unit ${o}`;a&&(p+=` {prefix: ${a}}`),h&&(p+=` {exponent: ${h}}`),u&&(p+=` {multiplier: ${u}}`),p+=";",this.append(p)}this.indentLevel--,this.append("enddef;"),this.append("")}processComponent(e){const t=e?.getAttribute("name")||"unnamed_component";this.append(`def comp ${t} as`),this.indentLevel++;const i=e?.getElementsByTagName("variable")||[];for(let r=0;r<i.length;r++)this.processVariable(i[r]);const s=e?.getElementsByTagNameNS("http://www.w3.org/1998/Math/MathML","math")||[];for(let r=0;r<s.length;r++)this.processMath(s[r]);this.indentLevel--,this.append("enddef;"),this.append("")}processVariable(e){const t=e?.getAttribute("name"),i=e?.getAttribute("units"),s=e?.getAttribute("initial_value"),r=e?.getAttribute("interface");let a=`var ${t}: ${i}`,o=[];s&&o.push(`init: ${s}`),r&&o.push(`interface: ${r}`),o.length>0&&(a+=` {${o.join(", ")}}`),a+=";",this.append(a)}processMath(e){const t=Array.from(e?.children||[]);for(const i of t)if(i.localName==="apply"&&i.firstElementChild?.localName==="eq"){const r=Array.from(i.children).slice(1),a=this.parseMathNode(r[0]),o=this.parseMathNode(r[1]);this.append(`${a} = ${o};`)}else{const r=this.parseMathNode(i);r&&this.append(r+";")}}parseMathNode(e){if(!e)return"";const t=e.localName;if(t==="apply")return this.parseApply(e);if(t==="ci")return e.textContent?.trim()||"";if(t==="cn"){let i=e.textContent?.trim()||"0";if(e.getAttribute("type")==="e-notation"){const a=Array.from(e.childNodes),o=a.findIndex(h=>h.nodeType===1&&h.localName==="sep");if(o!==-1){const h=a.slice(0,o).map(p=>p.textContent).join("").trim(),u=a.slice(o+1).map(p=>p.textContent).join("").trim();i=`${h}e${u}`}}const r=e.getAttributeNS(b,"units");return r?`${i} {units: ${r}}`:i}else{if(t==="piecewise")return this.parsePiecewise(e);if(t==="pi")return"pi";if(t==="bvar")return""}return console.log(`Unsupported MathML node: ${t}`),`/* Unsupported MathML node: ${t} */`}parseApply(e){const t=Array.from(e.children);if(t.length===0)return"";const i=t[0]?.localName,s=t.slice(1).map(r=>this.parseMathNode(r));switch(i){case"plus":return`(${s.join(" + ")})`;case"minus":return s.length===1?`-${s[0]}`:`(${s[0]} - ${s[1]})`;case"times":return`(${s.join(" * ")})`;case"divide":return`(${s[0]} / ${s[1]})`;case"eq":return`${s[0]} == ${s[1]}`;case"neq":return`${s[0]} != ${s[1]}`;case"lt":return`${s[0]} < ${s[1]}`;case"leq":return`${s[0]} <= ${s[1]}`;case"gt":return`${s[0]} > ${s[1]}`;case"geq":return`${s[0]} >= ${s[1]}`;case"and":return`${s.join(" and ")}`;case"or":return`${s.join(" or ")}`;case"diff":const r=t.find(u=>u.localName==="bvar"),a=t.find(u=>u.localName!=="diff"&&u.localName!=="bvar"),o=r?.children[0]?.textContent||"t";return`ode(${a?this.parseMathNode(a):"unknown"}, ${o})`;case"sin":case"cos":case"tan":case"exp":case"ln":case"log":return`${i}(${s[0]})`;case"root":return`sqrt(${s[0]})`;default:return`${i}(${s.join(", ")})`}}parsePiecewise(e){let t=[];return Array.from(e?.children||[]).forEach(s=>{if(s.localName==="piece"){const r=this.parseMathNode(s.children[0]),a=this.parseMathNode(s.children[1]);t.push(`${this.standardIndent}case ${a}: ${r};`)}else if(s.localName==="otherwise"){const r=this.parseMathNode(s.children[0]);t.push(`${this.standardIndent}otherwise: ${r};`)}}),`sel
8
+ ${this.indent()}${t.join(`
9
9
  ${this.indent()}`)}
10
- ${this.indent()}endsel`}}class E{convert(e){if(!e)return"";if(e.localName==="math")return Array.from(e.children).map(s=>this.convert(s)).join(`
11
- `);if(e.localName==="apply"&&e.firstElementChild?.localName==="eq"){const s=Array.from(e.children),i=this.parseNode(s[1]),t=this.parseNode(s[2]);return`${i} = ${t}`}return this.parseNode(e)}ignoreTag(e){return["bvar"].includes(e)}parseNode(e){if(!e)return"";const s=e.localName;return s==="apply"?this.parseApply(e):s==="ci"?this.parseIdentifier(e.textContent||""):s==="cn"?e.textContent||"0":s==="piecewise"?this.parsePiecewise(e):s==="pi"?"\\pi":(this.ignoreTag(s)||console.warn(`Unsupported MathML node: ${s}`),"")}escapeGreek(e){return["alpha","beta","gamma","delta","epsilon","zeta","eta","theta","iota","kappa","lambda","mu","nu","xi","omicron","pi","rho","sigma","tau","upsilon","phi","chi","psi","omega"].includes(e.toLowerCase())?`\\${e}`:e}parseIdentifier(e){if(!e.includes("_"))return this.escapeGreek(e);const s=e.split("_"),i=this.escapeGreek(s[0]||""),t=[];s[1]&&t.push(s[1]),s.length>4&&t.push(...s.slice(4));let r="";s.length===3&&(s[2]||[]).length===1?t.push(this.escapeGreek(s[2]||"")):s[2]&&(r=this.escapeGreek(s[2]),s[3]&&(r+=`_{${this.escapeGreek(s[3])}}`)),t.forEach((u,l)=>{t[l]=this.escapeGreek(u)});const c=t.join(",");let h=i;return c&&(h+=`_{${c}}`),r&&(h+=`^{${r}}`),h}parseApply(e){const s=Array.from(e?.children||[]),i=s[0]?.localName,t=s.slice(1).map(r=>this.parseNode(r));switch(i){case"plus":return t.join(" + ");case"minus":return t.length===1?`-${t[0]}`:`${t[0]} - ${t[1]}`;case"times":return t.join(" \\cdot ");case"divide":return`\\frac{${t[0]}}{${t[1]}}`;case"eq":return`${t[0]} == ${t[1]}`;case"neq":return`${t[0]} \\neq ${t[1]}`;case"lt":return`${t[0]} < ${t[1]}`;case"leq":return`${t[0]} \\leq ${t[1]}`;case"gt":return`${t[0]} > ${t[1]}`;case"geq":return`${t[0]} \\geq ${t[1]}`;case"and":return t.join(" \\land ");case"or":return t.join(" \\lor ");case"power":const r=s[1],c=t[0]||"",h=t[1];return r?.localName==="ci"||r?.localName==="cn"&&!c.trim().startsWith("-")?`{${c}}^{${h}}`:`\\left({${c}}\\right)^{${h}}`;case"root":case"sqrt":return`\\sqrt{${t[0]}}`;case"diff":const l=s.find(x=>x.localName==="bvar"),p=s.find(x=>x.localName!=="diff"&&x.localName!=="bvar"),d=l?this.parseNode(l.firstElementChild):"x";return`\\frac{d${p?this.parseNode(p):"y"}}{d${d}}`;case"exp":return`e^{${t[0]}}`;case"abs":return`\\left|${t[0]}\\right|`;case"floor":return`\\lfloor ${t[0]} \\rfloor`;case"ceil":return`\\lceil ${t[0]} \\rceil`;case"cos":case"cosh":case"log10":case"log":case"ln":case"max":case"min":case"sin":case"sinh":case"tan":case"tanh":return`\\${i}\\left(${t[0]}\\right)`;default:return console.log(`Unsupported MathML operator: ${i}`),`\\text{${i}}(${t.join(", ")})`}}parsePiecewise(e){let s="";return Array.from(e.children).forEach(t=>{if(t.localName==="piece"){const r=this.parseNode(t.children[0]),c=this.parseNode(t.children[1]);s+=`${r} & \\text{if } ${c} \\\\ `}else if(t.localName==="otherwise"){const r=this.parseNode(t.children[0]);s+=`${r} & \\text{otherwise}`}}),`\\begin{cases} ${s} \\end{cases}`}}m.CellMLLatexGenerator=E,m.CellMLTextGenerator=C,m.CellMLTextParser=$,Object.defineProperty(m,Symbol.toStringTag,{value:"Module"})}));
10
+ ${this.indent()}endsel`}}const $={atomic:100,func:90,power:80,times:70,divide:70,plus:60,minus:60,rel:50,unknown:0};class k{convert(e){if(!e)return"";if(e.localName==="math")return Array.from(e.children).map(t=>this.convert(t)).join(`
11
+ `);if(e.localName==="apply"&&e.firstElementChild?.localName==="eq"){const t=Array.from(e.children),i=this.parseNode(t[1]),s=this.parseNode(t[2]);return`${i} = ${s}`}return this.parseNode(e)}ignoreTag(e){return["bvar"].includes(e)}parseNode(e,t=0){if(!e)return"";const i=e.localName;if(i==="apply")return this.parseApply(e,t);if(i==="ci")return this.parseIdentifier(e.textContent||"");if(i==="cn"){if(e.getAttribute("type")==="e-notation"){const a=Array.from(e.childNodes),o=a.findIndex(h=>h.nodeType===1&&h.localName==="sep");if(o!==-1){const h=a.slice(0,o).map(p=>p.textContent).join("").trim(),u=a.slice(o+1).map(p=>p.textContent).join("").trim();return`${h} \\times 10^{${u}}`}}const r=e.textContent?.trim()||"0";if(r.match(/^-?[\d.]+[eE][+-]?\d+$/)){const[a,o]=r.split(/[eE]/);return`${a} \\times 10^{${o}}`}return r}return i==="piecewise"?this.parsePiecewise(e):i==="pi"?"\\pi":(this.ignoreTag(i)||console.warn(`Unsupported MathML node: ${i}`),"")}escapeGreek(e){return["alpha","beta","gamma","delta","epsilon","zeta","eta","theta","iota","kappa","lambda","mu","nu","xi","omicron","pi","rho","sigma","tau","upsilon","phi","chi","psi","omega"].includes(e.toLowerCase())?`\\${e}`:e}parseIdentifier(e){if(!e.includes("_"))return this.escapeGreek(e);const t=e.split("_"),i=this.escapeGreek(t[0]||""),s=[];t[1]&&s.push(t[1]),t.length>4&&s.push(...t.slice(4));let r="";t.length===3&&(t[2]||[]).length===1?s.push(this.escapeGreek(t[2]||"")):t[2]&&(r=this.escapeGreek(t[2]),t[3]&&(r+=`_{${this.escapeGreek(t[3])}}`)),s.forEach((h,u)=>{s[u]=this.escapeGreek(h)});const a=s.join(",");let o=i;return a&&(o+=`_{${a}}`),r&&(o+=`^{${r}}`),o}parseApply(e,t){const i=Array.from(e?.children||[]),s=i[0]?.localName||"unknown",r=$[s]||$.func,a=i.slice(1).map((h,u)=>{let p=r;return["divide","diff","root","sqrt","sin","cos","tan","exp","ln","log"].includes(s)?p=0:s==="minus"&&u===1&&(p=r+1),this.parseNode(h,p)});let o="";switch(s){case"plus":o=a.join(" + ");break;case"minus":o=a.length===1?`-${a[0]}`:`${a[0]} - ${a[1]}`;break;case"times":o=a.join(" \\cdot ");break;case"divide":o=`\\frac{${a[0]}}{${a[1]}}`;break;case"eq":o=`${a[0]} == ${a[1]}`;break;case"neq":o=`${a[0]} \\neq ${a[1]}`;break;case"lt":o=`${a[0]} < ${a[1]}`;break;case"leq":o=`${a[0]} \\leq ${a[1]}`;break;case"gt":o=`${a[0]} > ${a[1]}`;break;case"geq":o=`${a[0]} \\geq ${a[1]}`;break;case"and":o=a.join(" \\land ");break;case"or":o=a.join(" \\lor ");break;case"power":const h=i[1],u=a[0]||"",p=a[1];o=h?.localName==="ci"||h?.localName==="cn"&&!u.trim().startsWith("-")?`{${u}}^{${p}}`:`\\left({${u}}\\right)^{${p}}`;break;case"root":case"sqrt":o=`\\sqrt{${a[0]}}`;break;case"diff":const x=i.find(w=>w.localName==="bvar"),g=i.find(w=>w.localName!=="diff"&&w.localName!=="bvar"),O=x?this.parseNode(x.firstElementChild):"x";o=`\\frac{d${g?this.parseNode(g):"y"}}{d${O}}`;break;case"exp":o=`e^{${a[0]}}`;break;case"abs":o=`\\left|${a[0]}\\right|`;break;case"floor":o=`\\lfloor ${a[0]} \\rfloor`;break;case"ceil":o=`\\lceil ${a[0]} \\rceil`;break;case"cos":case"cosh":case"log10":case"log":case"ln":case"max":case"min":case"sin":case"sinh":case"tan":case"tanh":o=`\\${s}\\left(${a[0]}\\right)`;break;default:console.log(`Unsupported MathML operator: ${s}`),o=`\\text{${s}}(${a.join(", ")})`;break}return r<t&&(o=`\\left(${o}\\right)`),o}parsePiecewise(e){let t="";return Array.from(e.children).forEach(s=>{if(s.localName==="piece"){const r=this.parseNode(s.children[0]),a=this.parseNode(s.children[1]);t+=`${r} & \\text{if } ${a} \\\\ `}else if(s.localName==="otherwise"){const r=this.parseNode(s.children[0]);t+=`${r} & \\text{otherwise}`}}),`\\begin{cases} ${t} \\end{cases}`}}m.CellMLLatexGenerator=k,m.CellMLTextGenerator=E,m.CellMLTextParser=C,Object.defineProperty(m,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cellml-text-editor",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "A CellML text editor library for parsing and generating CellML text representations.",
5
5
  "keywords": [
6
6
  "cellml",