xmmath 1.0.7 → 1.0.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.
package/src/main.ts CHANGED
@@ -24,10 +24,10 @@ function createMath<K extends keyof MathMLElementTagNameMap>(
24
24
 
25
25
  const mathvariant = "mathvariant";
26
26
 
27
- import GraphemeSplitter from "grapheme-splitter";
28
- var splitter = new GraphemeSplitter();
27
+ const Segmenter = Intl.Segmenter;
28
+ const segmenter = new Segmenter("emoji", { granularity: "grapheme" });
29
29
 
30
- type vtype = "" | "str" | "v" | "f" | "blank" | "group" | "group1"; // group1组合基本类型,提高优先级
30
+ type vtype = "" | "str" | "v" | "f" | "blank" | "group" | "group1" | "sharp"; // group1组合基本类型,提高优先级
31
31
  type tree = { type: vtype; value: string; children?: tree; esc?: boolean }[];
32
32
 
33
33
  function ast(str: string) {
@@ -74,7 +74,11 @@ function ast(str: string) {
74
74
  }
75
75
  }
76
76
 
77
- let strl = init_c.emoji ? splitter.splitGraphemes(str) : [...str];
77
+ let strl = init_c.emoji
78
+ ? typeof init_c.emoji === "boolean"
79
+ ? Array.from(segmenter.segment(str)).map((w) => w.segment)
80
+ : init_c.emoji(str)
81
+ : [...str];
78
82
  for (let i = 0; i < strl.length; i++) {
79
83
  const t = strl[i];
80
84
  // 字符
@@ -102,6 +106,11 @@ function ast(str: string) {
102
106
  type = "";
103
107
  }
104
108
 
109
+ if (t === "#") {
110
+ now_tree.push({ type: "sharp", value: t });
111
+ continue;
112
+ }
113
+
105
114
  // 原始值(字母变量、数字、符号)
106
115
  if (
107
116
  type == "" &&
@@ -159,7 +168,7 @@ function ast(str: string) {
159
168
  }
160
169
 
161
170
  import symbols from "./symbols.json?raw";
162
- /** @see https://github.com/typst/typst/blob/v0.6.0/library/src/symbols/sym.rs */
171
+ /** @see https://github.com/typst/typst/blob/v0.11.1/crates/typst/src/symbols/sym.rs */
163
172
  let s = JSON.parse(symbols);
164
173
 
165
174
  // symbols路径简写
@@ -242,6 +251,8 @@ for (let i in shorthand) {
242
251
  }
243
252
  }
244
253
 
254
+ const delimPair = { "(": ["(", ")"], "[": ["[", "]"], "{": ["{", "}"], "|": ["|", "|"], "||": ["‖", "‖"] };
255
+
245
256
  let f: {
246
257
  [name: string]: (attr?: tree[], dic?: fdic, array?: tree[][], e?: fonts) => MathMLElement | DocumentFragment;
247
258
  } = {
@@ -309,7 +320,9 @@ let f: {
309
320
  let a = createMath("mrow");
310
321
  a.append(render(attr[0]));
311
322
  let b = createMath("mrow");
312
- b.append(render(attr[1]));
323
+ const s: tree = [];
324
+ for (let x of attr.slice(1)) s.push(...x, dh);
325
+ b.append(render(s.slice(0, -1)));
313
326
  let f = createMath("mfrac", null, { linethickness: "0" });
314
327
  f.append(a, b);
315
328
  let l = createMath("mo", "(");
@@ -337,9 +350,17 @@ let f: {
337
350
  },
338
351
  cases: (attr: tree[], dic: fdic) => {
339
352
  let r = createMath("mrow");
340
- let l = createMath("mo", dic?.delim?.[0]?.value || "{");
341
- let t = f.x_table(attr, { cases: [] });
342
- r.append(l, t);
353
+ const d = dic?.delim?.[0]?.value || "{";
354
+ let t = f.x_table(attr, { cases: [] }) as MathMLElement;
355
+ const gap = dic?.gap?.[0]?.value || "0.5em";
356
+ t.setAttribute("rowspacing", gap);
357
+ if (is_true(dic?.reverse)) {
358
+ const l = createMath("mo", delimPair[d][1]);
359
+ r.append(t, l);
360
+ } else {
361
+ const l = createMath("mo", d);
362
+ r.append(l, t);
363
+ }
343
364
  return r;
344
365
  },
345
366
  frac: (attr: tree[], dic: fdic) => {
@@ -368,16 +389,26 @@ let f: {
368
389
  end = { c: [el], n: i };
369
390
  break;
370
391
  }
371
- let l = document.createDocumentFragment();
372
- l.append(render(start.c));
373
- let r = document.createDocumentFragment();
374
- r.append(render(end.c));
375
- let c = document.createDocumentFragment();
376
- c.append(render(list.slice(start.n + 1, end.n)));
377
- let row = createMath("mrow");
392
+ const size = dic?.size?.[0]?.value;
393
+ const l = render(start.c);
394
+ const r = render(end.c);
395
+ if (size && size != "auto") {
396
+ const lm = l.querySelector("mo");
397
+ const rm = r.querySelector("mo");
398
+ lm.setAttribute("maxsize", size);
399
+ lm.setAttribute("minsize", size);
400
+ rm.setAttribute("maxsize", size);
401
+ rm.setAttribute("minsize", size);
402
+ }
403
+ const c = render(list.slice(start.n + 1, end.n));
404
+ const row = createMath("mrow");
378
405
  row.append(l, c, r);
379
406
  return row;
380
407
  },
408
+ mid: (attr: tree[], dic: fdic) => {
409
+ const o = createMath("mo", attr?.[0]?.[0]?.value, { stretchy: "true" });
410
+ return o;
411
+ },
381
412
  mat: (attr: tree[], dic: fdic, array: tree[][]) => {
382
413
  let d = dic?.delim?.[0]?.value || "(";
383
414
  let o = { "(": ["(", ")"], "[": ["[", "]"], "{": ["{", "}"], "|": ["|", "|"], "||": ["‖", "‖"] };
@@ -385,8 +416,38 @@ let f: {
385
416
  let l = createMath("mo", o[d][0]);
386
417
  let r = createMath("mo", o[d][1]);
387
418
  let t = createMath("mtable");
419
+ let augment = lan_dic(dic?.augment?.[0].children);
420
+ if (augment) {
421
+ let xa = NaN;
422
+ let ya = NaN;
423
+ if (Array.isArray(augment)) {
424
+ xa = Number((augment as tree).map((i) => i.value).join(""));
425
+ } else {
426
+ ya = Number((augment["hline"] as tree).map((i) => i.value).join(""));
427
+ }
428
+ if (xa < 0) xa = array[0].length + xa;
429
+ if (ya < 0) ya = array.length + ya;
430
+
431
+ if (ya) {
432
+ let l: boolean[] = [];
433
+ for (let i = 1; i < array.length; i++) l.push(i === ya);
434
+ t.setAttribute("rowlines", l.map((i) => (i ? "solid" : "none")).join(" "));
435
+ }
436
+ if (xa) {
437
+ let l: boolean[] = [];
438
+ for (let i = 1; i < array[0].length; i++) l.push(i === xa);
439
+ t.setAttribute("columnlines", l.map((i) => (i ? "solid" : "none")).join(" "));
440
+ }
441
+ }
442
+ const gap = dic?.gap?.[0]?.value;
443
+ const rowgap = dic?.["row-gap"]?.[0]?.value;
444
+ const colgap = dic?.["column-gap"]?.[0]?.value;
445
+ t.setAttribute("columnspacing", colgap || gap || "0.5em");
446
+ t.setAttribute("rowspacing", rowgap || gap || "0.5em");
447
+
388
448
  for (let i of array) {
389
449
  let tr = createMath("mtr");
450
+ if (!i.length) continue;
390
451
  for (let j of i) {
391
452
  let td = createMath("mtd");
392
453
  td.append(render(j));
@@ -459,7 +520,8 @@ let f: {
459
520
  },
460
521
  op: (attr: tree[], dic: fdic, a, e) => {
461
522
  let f = createMath("mrow");
462
- let str = createMath("ms", font(attr[0][0].value, e));
523
+ let str = createMath("ms");
524
+ str.append(render(attr[0], e));
463
525
  f.append(str);
464
526
  return f;
465
527
  },
@@ -501,11 +563,13 @@ let f: {
501
563
  },
502
564
  vec: (attr: tree[], dic: fdic) => {
503
565
  let d = dic?.delim?.[0]?.value || "(";
504
- let o = { "(": ["(", ")"], "[": ["[", "]"], "{": ["{", "}"], "|": ["|", "|"], "||": ["‖", "‖"] };
566
+ let o = delimPair;
505
567
  let row = createMath("mrow");
506
568
  let l = createMath("mo", o[d][0]);
507
569
  let r = createMath("mo", o[d][1]);
508
570
  let t = createMath("mtable");
571
+ const gap = dic?.gap?.[0]?.value || "0.5em";
572
+ t.setAttribute("rowspacing", gap);
509
573
  for (let i of attr) {
510
574
  let tr = createMath("mtr");
511
575
  tr.append(render(i));
@@ -514,6 +578,9 @@ let f: {
514
578
  row.append(l, t, r);
515
579
  return row;
516
580
  },
581
+ h: (attr: tree[], dic: fdic) => {
582
+ return createMath("mspace", "", { width: attr[0][0].value });
583
+ },
517
584
  // 额外
518
585
  //
519
586
  x_table: (attr: tree[], dic: fdic) => {
@@ -579,6 +646,7 @@ let opl: { id: string; str?: string; limits?: boolean }[] = [
579
646
  { id: "ctg" },
580
647
  { id: "coth" },
581
648
  { id: "csc" },
649
+ { id: "csch" },
582
650
  { id: "deg" },
583
651
  { id: "det", limits: true },
584
652
  { id: "dim" },
@@ -586,6 +654,8 @@ let opl: { id: string; str?: string; limits?: boolean }[] = [
586
654
  { id: "gcd", limits: true },
587
655
  { id: "hom" },
588
656
  { id: "mod" },
657
+ { id: "id" },
658
+ { id: "im" },
589
659
  { id: "inf", limits: true },
590
660
  { id: "ker" },
591
661
  { id: "lg" },
@@ -596,12 +666,14 @@ let opl: { id: string; str?: string; limits?: boolean }[] = [
596
666
  { id: "min", limits: true },
597
667
  { id: "Pr", limits: true },
598
668
  { id: "sec" },
669
+ { id: "sech" },
599
670
  { id: "sin" },
600
671
  { id: "sinc" },
601
672
  { id: "sinh" },
602
673
  { id: "sup", limits: true },
603
674
  { id: "tan" },
604
675
  { id: "tg" },
676
+ { id: "tr" },
605
677
  { id: "tanh" },
606
678
  { id: "liminf", str: "lim inf", limits: true },
607
679
  { id: "limsup", str: "lim sup", limits: true },
@@ -622,6 +694,20 @@ function op_f() {
622
694
  }
623
695
  op_f();
624
696
 
697
+ const spaceConst = {
698
+ quad: "1em",
699
+ med: "0.222em",
700
+ thin: "0.17em",
701
+ thick: "0.28em",
702
+ wide: "2em",
703
+ };
704
+
705
+ for (let i in spaceConst) {
706
+ f[i] = () => {
707
+ return f.h([[{ type: "str", value: spaceConst[i] }]]);
708
+ };
709
+ }
710
+
625
711
  let limits_f = [];
626
712
  let limits_sy = ["∏", "∐", "∑", "⋀", "⋁", "⋂", "⋃", "⨀", "⨁", "⨂", "⨃", "⨄", "⨅", "⨆"];
627
713
  for (let i in ss) {
@@ -648,7 +734,13 @@ function accent_f() {
648
734
  "diaer",
649
735
  "circle",
650
736
  "arrow",
737
+ "arrow.r",
651
738
  "arrow.l",
739
+ "arrow.l.r",
740
+ "caron",
741
+ "harpoon",
742
+ "harpoon.rt",
743
+ "harpoon.lt",
652
744
  ];
653
745
  for (let i of l) {
654
746
  f[i] = (attr: tree[]) => {
@@ -668,8 +760,8 @@ function lr_f() {
668
760
  { name: "round", l: v_f("⌊"), r: v_f("⌉") },
669
761
  ];
670
762
  for (let i of l) {
671
- f[i.name] = (attr: tree[]) => {
672
- let s = f.lr([[i.l, ...attr[0], i.r]], {});
763
+ f[i.name] = (attr: tree[], dic) => {
764
+ let s = f.lr([[i.l, ...attr[0], i.r]], dic);
673
765
  return s;
674
766
  };
675
767
  }
@@ -722,15 +814,15 @@ function in_kh(x: tree) {
722
814
  }
723
815
 
724
816
  function is_sup(x: tree[0]) {
725
- return x && x.type == "v" && x.value == "^" && !x.esc;
817
+ return eqq(x, { type: "v", value: "^" });
726
818
  }
727
819
 
728
820
  function is_sub(x: tree[0]) {
729
- return x && x.type == "v" && x.value == "_" && !x.esc;
821
+ return eqq(x, { type: "v", value: "_" });
730
822
  }
731
823
 
732
824
  function is_frac(x: tree[0]) {
733
- return x && x.type == "v" && x.value == "/" && !x.esc;
825
+ return eqq(x, { type: "v", value: "/" });
734
826
  }
735
827
 
736
828
  function is_br(x: tree[0]) {
@@ -744,6 +836,7 @@ function is_limit(tree: tree) {
744
836
  if (limits_f.includes(x.value)) {
745
837
  return true;
746
838
  }
839
+ if (x.value.split(".").at(0) === "arrow") return true;
747
840
  for (let i of opl) {
748
841
  if (i.limits && x.value == i.id) {
749
842
  return true;
@@ -752,12 +845,7 @@ function is_limit(tree: tree) {
752
845
  if (x.value == "scripts") return false;
753
846
  if (x.value == "op") {
754
847
  let { dic } = f_attr(x);
755
- let t = "";
756
- if (dic.limits)
757
- for (let i of dic.limits) {
758
- t += i.value;
759
- }
760
- return t == "#true";
848
+ return is_true(dic.limits);
761
849
  }
762
850
  }
763
851
  if (x.type == "v" && limits_sy.includes(x.value)) {
@@ -773,7 +861,7 @@ function is_f_mark(x: tree[0], str: string) {
773
861
  }
774
862
 
775
863
  function is_dot(x: tree[0]) {
776
- return x && x.type == "v" && x.value == ".";
864
+ return eq(x, { type: "v", value: "." });
777
865
  }
778
866
 
779
867
  function is_dot_f(x: tree[0]) {
@@ -790,6 +878,27 @@ function v_f(str: string): tree[0] {
790
878
  return { type: "v", value: str };
791
879
  }
792
880
 
881
+ function eq(x0: tree[0], x1: tree[0]) {
882
+ if (!x0 || !x1) return false;
883
+ return x0.type === x1.type && x0.value === x1.value;
884
+ }
885
+
886
+ function eqq(x0: tree[0], x1: tree[0]) {
887
+ if (!x0 || !x1) return false;
888
+ return x0.type === x1.type && x0.value === x1.value && x0?.esc === x1?.esc;
889
+ }
890
+
891
+ function trim(tree: tree) {
892
+ if (!tree) return [];
893
+ while (tree.length > 0 && tree[0].type === "blank") {
894
+ tree.shift();
895
+ }
896
+ while (tree.length > 0 && tree.at(-1).type === "blank") {
897
+ tree.pop();
898
+ }
899
+ return tree;
900
+ }
901
+
793
902
  type fdic = { [id: string]: tree };
794
903
 
795
904
  function dic_to_ast(dic: { [id: string]: tree }) {
@@ -798,7 +907,7 @@ function dic_to_ast(dic: { [id: string]: tree }) {
798
907
  l.push({ type: "f", value: i });
799
908
  l.push({ type: "v", value: ":" });
800
909
  for (let x of dic[i]) {
801
- if (x.type == "v" && x.value == ",") x.esc = true;
910
+ if (eq(x, dh)) x.esc = true;
802
911
  }
803
912
  l.push(...dic[i]);
804
913
  if (Number(i) + 1 != Object.keys(dic).length) {
@@ -808,17 +917,35 @@ function dic_to_ast(dic: { [id: string]: tree }) {
808
917
  return l;
809
918
  }
810
919
 
811
- function is_true(t: tree) {
812
- let n = 0;
813
- if (t) {
814
- if (t[0].type == "blank") n++;
815
- if (t[n] && t[n].type == "v" && t[n].value == "#") {
816
- if (t[n + 1] && t[n + 1].type == "f" && t[n + 1].value == "true") {
817
- return true;
920
+ function lan_dic(tree: tree) {
921
+ tree = trim(tree);
922
+ if (!tree.find((v) => eqq(v, v_f(":")))) return tree;
923
+ const o = new Object();
924
+ let key = "";
925
+ let value: tree = [];
926
+ tree.push(dh);
927
+ for (let i = 0; i < tree.length; i++) {
928
+ if (!key && tree[i].type != "blank") {
929
+ key = tree[i].value;
930
+ } else {
931
+ if (value.length) {
932
+ if (eqq(tree[i], dh)) {
933
+ o[key] = trim(value);
934
+ key = "";
935
+ value = [];
936
+ } else value.push(tree[i]);
937
+ } else {
938
+ if (eqq(tree[i], v_f(":"))) {
939
+ value.push(tree[i + 1]);
940
+ }
818
941
  }
819
942
  }
820
943
  }
821
- return false;
944
+ return o;
945
+ }
946
+
947
+ function is_true(t: tree) {
948
+ return eqq(trim(t)?.[0], { type: "sharp", value: "true" });
822
949
  }
823
950
 
824
951
  function ast2(tree: tree) {
@@ -846,13 +973,88 @@ function ast2(tree: tree) {
846
973
  tree = t;
847
974
  }
848
975
 
976
+ // 处理\转义
977
+ {
978
+ let t: tree = [];
979
+ for (let n = 0; n < tree.length; n++) {
980
+ let x = tree[n];
981
+
982
+ if (x.value == "\\" && x.type == "v") {
983
+ if (tree?.[n + 1]) {
984
+ let next = tree[n + 1];
985
+ if (next.value == "\\" && next.type == "v") {
986
+ t.push({ type: "v", value: "\\" });
987
+ n++;
988
+ } else if (next.type == "blank") {
989
+ t.push({ type: "v", value: "br", esc: true });
990
+ n++;
991
+ } else if (next.type == "f") {
992
+ let v = next.value;
993
+ t.push({ type: "v", value: v[0] });
994
+ t.push({ type: v.length == 2 ? "v" : "f", value: v.slice(1) });
995
+ n++;
996
+ } else if (next.type === "sharp") {
997
+ t.push({ type: "v", value: "#" });
998
+ n++;
999
+ } else {
1000
+ let v = next;
1001
+ v.esc = true;
1002
+ t.push(v);
1003
+ n++;
1004
+ }
1005
+ }
1006
+ } else {
1007
+ t.push(x);
1008
+ }
1009
+ }
1010
+ tree = t;
1011
+ }
1012
+
1013
+ // 处理#
1014
+ {
1015
+ const t: tree = [];
1016
+ for (let n = 0; n < tree.length; n++) {
1017
+ const x = tree[n];
1018
+ if (x.type === "sharp") {
1019
+ if (tree[n + 1]?.type === "group") {
1020
+ x.children = tree[n + 1].children;
1021
+ for (let i in x.children) {
1022
+ if (x.children[i].value === "\\" && x.children[i].type === "v") {
1023
+ if (x.children[Number(i) + 1]) {
1024
+ x.children[Number(i) + 1]["esc"] = true;
1025
+ }
1026
+ }
1027
+ }
1028
+ const v = x.children.map((i) => i.value).join("");
1029
+ if (v.match(/^[0-9\+\-\*\/()]+$/)) {
1030
+ x.value = v; // todo 数学运算
1031
+ } else {
1032
+ x.value = v;
1033
+ }
1034
+ } else {
1035
+ x.value = tree[n + 1]?.value;
1036
+ if (tree[n + 2]?.type === "f") {
1037
+ x.value += tree[n + 2].value;
1038
+ n++;
1039
+ }
1040
+ }
1041
+ t.push(x);
1042
+ n++;
1043
+ continue;
1044
+ } else {
1045
+ t.push(x);
1046
+ }
1047
+ }
1048
+ tree = t;
1049
+ }
1050
+
849
1051
  // 处理符号简写(shorthand)
850
1052
  {
851
1053
  let t: tree = [];
852
1054
  for (let n = 0; n < tree.length; n++) {
853
1055
  let x = tree[n];
854
1056
 
855
- if (tree?.[n - 1]?.value != "\\") {
1057
+ if (!x.esc) {
856
1058
  if (x.type == "v") {
857
1059
  let nn = n;
858
1060
  let shortkey = x.value;
@@ -883,40 +1085,6 @@ function ast2(tree: tree) {
883
1085
  tree = t;
884
1086
  }
885
1087
 
886
- // 处理\转义
887
- {
888
- let t: tree = [];
889
- for (let n = 0; n < tree.length; n++) {
890
- let x = tree[n];
891
-
892
- if (x.value == "\\" && x.type == "v") {
893
- if (tree?.[n + 1]) {
894
- let next = tree[n + 1];
895
- if (next.value == "\\" && next.type == "v") {
896
- t.push({ type: "v", value: "\\" });
897
- n++;
898
- } else if (next.type == "blank") {
899
- t.push({ type: "v", value: "br", esc: true });
900
- n++;
901
- } else if (next.type == "f") {
902
- let v = next.value;
903
- t.push({ type: "v", value: v[0] });
904
- t.push({ type: v.length == 2 ? "v" : "f", value: v.slice(1) });
905
- n++;
906
- } else {
907
- let v = next;
908
- v.esc = true;
909
- t.push(v);
910
- n++;
911
- }
912
- }
913
- } else {
914
- t.push(x);
915
- }
916
- }
917
- tree = t;
918
- }
919
-
920
1088
  // 处理字符与v之间空格
921
1089
  {
922
1090
  let t: tree = [];
@@ -1014,6 +1182,35 @@ function ast2(tree: tree) {
1014
1182
  tree = t;
1015
1183
  }
1016
1184
 
1185
+ // '->^'
1186
+ {
1187
+ let t: tree = [];
1188
+ for (let n = 0; n < tree.length; n++) {
1189
+ let x = tree[n];
1190
+ let nn = n;
1191
+ if (eqq(x, { type: "f", value: "prime" })) {
1192
+ while (tree[nn] && eqq(tree[nn], { type: "f", value: "prime" })) {
1193
+ nn++;
1194
+ }
1195
+ const primes = nn - n;
1196
+ if (
1197
+ tree[n - 1] &&
1198
+ !is_sup(tree[n - 1]) &&
1199
+ !is_sub(tree[n - 1]) &&
1200
+ !eq(tree[n - 1], { type: "f", value: "prime" }) &&
1201
+ tree[n - 1].type != "blank"
1202
+ ) {
1203
+ t.push({ type: "v", value: "^" });
1204
+ }
1205
+ t.push({ type: "v", value: "'".repeat(primes), children: [{ type: "v", value: String(primes) }] });
1206
+ n += primes - 1;
1207
+ continue;
1208
+ }
1209
+ t.push(x);
1210
+ }
1211
+ tree = t;
1212
+ }
1213
+
1017
1214
  // 移除blank
1018
1215
  {
1019
1216
  let t: tree = [];
@@ -1207,16 +1404,21 @@ function f_attr(x: tree[0]) {
1207
1404
  // 将dicl的tree转为键对
1208
1405
  let dic: fdic = {};
1209
1406
  for (let i of dicl) {
1407
+ let x = false;
1210
1408
  let n = "";
1211
1409
  let t: tree = [];
1212
1410
  for (let el of i) {
1213
- if (!n) {
1214
- n = el.value;
1411
+ if (el.value === ":") {
1412
+ x = true;
1413
+ continue;
1414
+ }
1415
+ if (!x) {
1416
+ n += el.value;
1215
1417
  } else {
1216
- if (el.value != ":") t.push(el);
1418
+ t.push(el);
1217
1419
  }
1218
1420
  }
1219
- dic[n] = t;
1421
+ dic[n] = ast2(t);
1220
1422
  }
1221
1423
  return { attr, dic, array };
1222
1424
  }
@@ -1355,7 +1557,7 @@ function render(tree: tree, e?: fonts) {
1355
1557
  let el = f[x.value](attr, dic, array, e);
1356
1558
  fragment.append(el);
1357
1559
  } else if (ss[x.value]) {
1358
- let el = createMath("mo", ss[x.value]);
1560
+ let el = createMath("mi", ss[x.value]);
1359
1561
  fragment.append(el, render(in_kh(x.children)));
1360
1562
  }
1361
1563
  }
@@ -1366,16 +1568,16 @@ function render(tree: tree, e?: fonts) {
1366
1568
  let space_w = null;
1367
1569
  const space_width = {
1368
1570
  " ": "0.36em",
1369
- " ": "0.5em",
1370
- " ": "3.75em",
1371
- " ": "0.333em",
1372
- " ": "0.25em",
1373
- " ": "0.166em",
1374
- " ": "0.222em",
1375
- " ": "1ch",
1376
- " ": "0.27em",
1377
- " ": "0.2em",
1378
- " ": "0.09em",
1571
+ "\u2002": "0.5em",
1572
+ "\u2003": "1em",
1573
+ "\u2004": "0.333em",
1574
+ "\u2005": "0.25em",
1575
+ "\u2006": "0.166em",
1576
+ "\u205f": "0.222em",
1577
+ "\u2007": "1ch",
1578
+ "\u2008": "0.27em",
1579
+ "\u2009": "0.17em",
1580
+ "\u200a": "0.09em",
1379
1581
  };
1380
1582
  if (ss[x.value].match(/[a-zA-Z\u0391-\u03C9]/)) {
1381
1583
  tag = "mi";
@@ -1400,12 +1602,15 @@ function render(tree: tree, e?: fonts) {
1400
1602
  fragment.append(el);
1401
1603
  }
1402
1604
 
1403
- if (x.type == "v") {
1605
+ if (x.type === "v" || x.type === "sharp") {
1404
1606
  let tag: keyof MathMLElementTagNameMap;
1405
1607
  if (x.value.match(/[0-9.]+/)) {
1406
1608
  tag = "mn";
1407
1609
  } else if (x.value.match(/[a-zA-Z\u0391-\u03C9]/)) {
1408
1610
  tag = "mi";
1611
+ } else if (x.value.match(/^'+$/)) {
1612
+ if (x.value.length > 1) x.value = x.value.replaceAll("'", ss["prime"]);
1613
+ tag = "mo";
1409
1614
  } else {
1410
1615
  tag = "mo";
1411
1616
  }
@@ -1421,7 +1626,7 @@ function render(tree: tree, e?: fonts) {
1421
1626
  return fragment;
1422
1627
  }
1423
1628
 
1424
- var init_c = {
1629
+ var init_c: { emoji: boolean | ((str: string) => string) } = {
1425
1630
  emoji: false,
1426
1631
  };
1427
1632
 
@@ -1446,4 +1651,9 @@ function toMMLHTML(str: string) {
1446
1651
  return toMML(str).outerHTML;
1447
1652
  }
1448
1653
 
1449
- export { init, toMML, toMMLHTML };
1654
+ const version = {
1655
+ lan: "0.11.1",
1656
+ symbol: "0.11.1",
1657
+ };
1658
+
1659
+ export { init, toMML, toMMLHTML, version };