@barocss/math-editor 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/ADAPTERS.md +31 -2
  2. package/API-JAVASCRIPT.md +157 -0
  3. package/API-REACT.md +202 -0
  4. package/API-SESSION.md +163 -0
  5. package/API-SOLID.md +90 -0
  6. package/API-SVELTE.md +83 -0
  7. package/API-VUE.md +104 -0
  8. package/API-WEB-COMPONENT.md +128 -0
  9. package/CHANGELOG.md +16 -0
  10. package/EMBEDDING.md +7 -0
  11. package/IMPLEMENTATION.md +132 -1
  12. package/JSON-MODEL.md +441 -0
  13. package/LATEX-GUIDE.md +248 -0
  14. package/LATEX-MODEL.md +290 -0
  15. package/LATEX-SCOPE.md +260 -4
  16. package/LOCALIZATION.md +7 -1
  17. package/README.md +91 -4
  18. package/RELEASING.md +1 -1
  19. package/ROADMAP.md +107 -16
  20. package/SUPPORT.md +128 -13
  21. package/SYMBOLS.md +33 -1
  22. package/VALIDATION.md +171 -0
  23. package/dist/core.d.ts +2 -0
  24. package/dist/core.d.ts.map +1 -1
  25. package/dist/core.js +2 -0
  26. package/dist/core.js.map +1 -1
  27. package/dist/document-codec.d.ts +4 -0
  28. package/dist/document-codec.d.ts.map +1 -0
  29. package/dist/document-codec.js +37 -0
  30. package/dist/document-codec.js.map +1 -0
  31. package/dist/dom/menu-position.d.ts +3 -0
  32. package/dist/dom/menu-position.d.ts.map +1 -0
  33. package/dist/dom/menu-position.js +44 -0
  34. package/dist/dom/menu-position.js.map +1 -0
  35. package/dist/dom/toolbar.d.ts +2 -0
  36. package/dist/dom/toolbar.d.ts.map +1 -1
  37. package/dist/dom/toolbar.js +16 -1
  38. package/dist/dom/toolbar.js.map +1 -1
  39. package/dist/dom.d.ts +1 -0
  40. package/dist/dom.d.ts.map +1 -1
  41. package/dist/dom.js +134 -24
  42. package/dist/dom.js.map +1 -1
  43. package/dist/editor-labels.d.ts.map +1 -1
  44. package/dist/editor-labels.js +42 -0
  45. package/dist/editor-labels.js.map +1 -1
  46. package/dist/fences.d.ts +11 -0
  47. package/dist/fences.d.ts.map +1 -0
  48. package/dist/fences.js +21 -0
  49. package/dist/fences.js.map +1 -0
  50. package/dist/index.d.ts +3 -1
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +2 -0
  53. package/dist/index.js.map +1 -1
  54. package/dist/latex.d.ts +26 -0
  55. package/dist/latex.d.ts.map +1 -0
  56. package/dist/latex.js +689 -0
  57. package/dist/latex.js.map +1 -0
  58. package/dist/locales/en.js +108 -1
  59. package/dist/locales/en.json +108 -1
  60. package/dist/locales/ko.js +120 -2
  61. package/dist/locales/ko.json +120 -2
  62. package/dist/math-editor-toolbar.d.ts +5 -2
  63. package/dist/math-editor-toolbar.d.ts.map +1 -1
  64. package/dist/math-editor-toolbar.js +10 -6
  65. package/dist/math-editor-toolbar.js.map +1 -1
  66. package/dist/math-editor.d.ts +24 -4
  67. package/dist/math-editor.d.ts.map +1 -1
  68. package/dist/math-editor.js +218 -39
  69. package/dist/math-editor.js.map +1 -1
  70. package/dist/model.d.ts +10 -2
  71. package/dist/model.d.ts.map +1 -1
  72. package/dist/model.js +262 -9
  73. package/dist/model.js.map +1 -1
  74. package/dist/range.d.ts +1 -1
  75. package/dist/range.d.ts.map +1 -1
  76. package/dist/range.js +116 -6
  77. package/dist/range.js.map +1 -1
  78. package/dist/react.d.ts +1 -1
  79. package/dist/react.d.ts.map +1 -1
  80. package/dist/session.d.ts +3 -0
  81. package/dist/session.d.ts.map +1 -1
  82. package/dist/session.js +9 -1
  83. package/dist/session.js.map +1 -1
  84. package/dist/suggestions.d.ts +4 -0
  85. package/dist/suggestions.d.ts.map +1 -1
  86. package/dist/suggestions.js +158 -21
  87. package/dist/suggestions.js.map +1 -1
  88. package/dist/symbols.d.ts +1 -1
  89. package/dist/symbols.d.ts.map +1 -1
  90. package/dist/symbols.js +56 -5
  91. package/dist/symbols.js.map +1 -1
  92. package/package.json +3 -2
  93. package/src/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  94. package/src/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  95. package/src/fonts/KaTeX_Main-Bold.woff2 +0 -0
  96. package/src/fonts/KaTeX_Main-Regular.woff2 +0 -0
  97. package/src/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  98. package/src/fonts/LICENSE-KaTeX.txt +21 -0
  99. package/src/style.css +868 -45
package/src/style.css CHANGED
@@ -1,3 +1,10 @@
1
+ /* Use lining numerals for mathematical baselines and a clear similarity sign.
2
+ Georgia's text numerals have uneven heights and its U+223C is unusually curled. */
3
+ @font-face {
4
+ font-family: 'Barocss Math Glyphs';
5
+ src: url('./fonts/KaTeX_Main-Regular.woff2') format('woff2');
6
+ unicode-range: U+0030-0039, U+223C;
7
+ }
1
8
  .me-editor {
2
9
  --me-accent: #236957;
3
10
  --me-line: #d9e1dd;
@@ -25,7 +32,7 @@
25
32
  font: 12px system-ui;
26
33
  }
27
34
  .me-tools button span {
28
- font: 20px Georgia, serif;
35
+ font: 20px 'Barocss Math Glyphs', Georgia, serif;
29
36
  }
30
37
  .me-tools button:hover {
31
38
  background: #edf3ef;
@@ -63,7 +70,7 @@
63
70
  }
64
71
  .me-input,
65
72
  .me-measure {
66
- font: italic 22px Georgia, 'Times New Roman', serif;
73
+ font: italic var(--me-font-size, 22px) 'Barocss Math Glyphs', Georgia, 'Times New Roman', serif;
67
74
  line-height: 1.35;
68
75
  min-width: 1ch;
69
76
  border: 0;
@@ -102,12 +109,17 @@
102
109
  margin-top: 4px;
103
110
  }
104
111
  .me-radical {
105
- font: 33px Georgia, serif;
112
+ font: 33px 'Barocss Math Glyphs', Georgia, serif;
106
113
  }
107
114
  .me-superscript > .me-slot:last-child {
108
115
  align-self: flex-start;
109
116
  transform: translateY(-0.3em);
110
117
  }
118
+ .me-superscript > .me-slot,
119
+ .me-subscript > .me-slot {
120
+ /* Avoid the inline line-box descent below the base's flex row. */
121
+ display: inline-flex;
122
+ }
111
123
  .me-subscript > .me-slot:last-child {
112
124
  align-self: flex-end;
113
125
  transform: translateY(0.3em);
@@ -116,7 +128,7 @@
116
128
  .me-subscript > .me-slot:last-child .me-input,
117
129
  .me-superscript > .me-slot:last-child .me-measure,
118
130
  .me-subscript > .me-slot:last-child .me-measure {
119
- font-size: 16px;
131
+ font-size: calc(var(--me-font-size, 22px) * 16 / 22);
120
132
  }
121
133
  .me-suggestions {
122
134
  position: absolute;
@@ -220,7 +232,7 @@
220
232
  box-shadow: none;
221
233
  border: 0;
222
234
  border-radius: 0;
223
- flex: 1;
235
+ flex: 1 1 auto;
224
236
  }
225
237
  .me-suggestion-panel .me-suggestions button {
226
238
  justify-content: flex-start;
@@ -230,7 +242,7 @@
230
242
  min-height: 54px;
231
243
  }
232
244
  .me-candidate-glyph {
233
- font: 26px Georgia, serif;
245
+ font: 26px 'Barocss Math Glyphs', Georgia, serif;
234
246
  min-width: 42px;
235
247
  text-align: center;
236
248
  }
@@ -251,16 +263,16 @@
251
263
  }
252
264
  .me-limit .me-input,
253
265
  .me-limit .me-measure {
254
- font-size: 14px;
266
+ font-size: calc(var(--me-font-size, 22px) * 14 / 22);
255
267
  }
256
268
  .me-operator-glyph {
257
- font: 35px/1 Georgia, serif;
269
+ font: 35px/1 'Barocss Math Glyphs', Georgia, serif;
258
270
  }
259
271
  .me-large-operator {
260
272
  gap: 8px;
261
273
  }
262
274
  .me-delimiter {
263
- font: 28px/1 Georgia, serif;
275
+ font: 28px/1 'Barocss Math Glyphs', Georgia, serif;
264
276
  }
265
277
 
266
278
  /* Slot roles are presentation metadata, not a claim that text is a variable or constant. */
@@ -316,9 +328,8 @@
316
328
  }
317
329
  .me-input:focus {
318
330
  background: var(--me-focus);
319
- outline: 2px solid var(--me-ring);
320
- outline-offset: 1px;
321
- box-shadow: 0 0 0 5px var(--me-tint);
331
+ outline: none;
332
+ box-shadow: none;
322
333
  }
323
334
  .me-input::selection {
324
335
  color: white;
@@ -354,8 +365,8 @@
354
365
  display: grid;
355
366
  align-items: center;
356
367
  justify-items: center;
357
- gap: 12px 18px;
358
- padding: 9px 7px;
368
+ gap: 4px 12px;
369
+ padding: 3px 5px;
359
370
  }
360
371
  .me-matrix-cell {
361
372
  min-width: 1.4ch;
@@ -559,7 +570,8 @@
559
570
  align-items: center;
560
571
  justify-content: center;
561
572
  white-space: pre;
562
- font: italic 22px/1.35 Georgia, 'Times New Roman', serif;
573
+ font: italic var(--me-font-size, 22px) / 1.35 'Barocss Math Glyphs', Georgia, 'Times New Roman',
574
+ serif;
563
575
  color: var(--me-ink);
564
576
  border-radius: 4px;
565
577
  cursor: text;
@@ -581,10 +593,10 @@
581
593
  }
582
594
  .me-superscript > .me-slot:last-child .me-preview-token,
583
595
  .me-subscript > .me-slot:last-child .me-preview-token {
584
- font-size: 16px;
596
+ font-size: calc(var(--me-font-size, 22px) * 16 / 22);
585
597
  }
586
598
  .me-limit .me-preview-token {
587
- font-size: 14px;
599
+ font-size: calc(var(--me-font-size, 22px) * 14 / 22);
588
600
  }
589
601
  .me-range-highlight,
590
602
  .me-empty[data-range-selected='true'] {
@@ -599,33 +611,6 @@
599
611
  outline: 2px solid #3676d3;
600
612
  outline-offset: -2px;
601
613
  }
602
- .me-wrap-tools {
603
- display: flex;
604
- flex-wrap: wrap;
605
- gap: 8px;
606
- align-items: center;
607
- padding: 8px 16px;
608
- background: #eef5ff;
609
- color: #245da1;
610
- font: 12px system-ui;
611
- border-bottom: 1px solid var(--me-line);
612
- }
613
- .me-wrap-tools button {
614
- font: inherit;
615
- color: inherit;
616
- border: 1px solid #b9cee7;
617
- background: white;
618
- border-radius: 5px;
619
- padding: 6px 10px;
620
- cursor: pointer;
621
- }
622
- .me-wrap-tools button:hover {
623
- background: #dbeaff;
624
- }
625
- .me-wrap-tools button:disabled {
626
- opacity: 0.4;
627
- cursor: default;
628
- }
629
614
  .me-line-number {
630
615
  flex: 0 0 2.5ch;
631
616
  margin-right: 16px;
@@ -711,7 +696,7 @@
711
696
  border-color: #9cbbac;
712
697
  }
713
698
  .me-symbol-glyph {
714
- font: 25px/1.2 Georgia, 'Times New Roman', serif;
699
+ font: 25px/1.2 'Barocss Math Glyphs', Georgia, 'Times New Roman', serif;
715
700
  }
716
701
  .me-symbol-browser button:focus-visible,
717
702
  .me-symbol-search input:focus-visible {
@@ -779,3 +764,841 @@
779
764
  .me-dom-editor[data-mode='inline'] .me-document-line {
780
765
  min-height: 0;
781
766
  }
767
+
768
+ /* Combined scripts share a column, while the base spans both script rows. */
769
+ .me-scripts {
770
+ display: inline-grid;
771
+ grid-template-columns: auto auto;
772
+ grid-template-rows: auto auto;
773
+ vertical-align: middle;
774
+ gap: 0;
775
+ }
776
+ .me-scripts > .me-slot:nth-child(1) {
777
+ grid-column: 1;
778
+ grid-row: 1 / 3;
779
+ align-self: center;
780
+ }
781
+ .me-scripts > .me-slot:nth-child(2) {
782
+ grid-column: 2;
783
+ grid-row: 2;
784
+ }
785
+ .me-scripts > .me-slot:nth-child(3) {
786
+ grid-column: 2;
787
+ grid-row: 1;
788
+ }
789
+ .me-scripts > .me-slot:not(:first-child) :is(.me-input, .me-measure, .me-preview-token) {
790
+ font-size: calc(var(--me-font-size, 22px) * 16 / 22);
791
+ }
792
+
793
+ .me-textGroup,
794
+ .me-operatorName {
795
+ font-style: normal;
796
+ }
797
+ .me-operatorName {
798
+ margin-inline-end: 0.16em;
799
+ }
800
+ .me-textGroup :is(.me-input, .me-preview-token, .me-measure),
801
+ .me-operatorName :is(.me-input, .me-preview-token, .me-measure) {
802
+ font-family: 'Barocss Math Glyphs', Georgia, serif;
803
+ font-style: normal;
804
+ white-space: pre;
805
+ color: #263b32;
806
+ }
807
+ .me-textGroup .me-preview-token *,
808
+ .me-operatorName .me-preview-token * {
809
+ color: inherit;
810
+ }
811
+
812
+ .me-indexedRoot {
813
+ display: inline-grid;
814
+ grid-template-columns: auto auto auto;
815
+ align-items: center;
816
+ gap: 0;
817
+ }
818
+ .me-indexedRoot > .me-radical {
819
+ grid-column: 2;
820
+ grid-row: 1;
821
+ }
822
+ .me-indexedRoot > .me-slot:nth-last-child(2) {
823
+ grid-column: 1;
824
+ grid-row: 1;
825
+ align-self: start;
826
+ margin-right: -3px;
827
+ z-index: 1;
828
+ }
829
+ .me-indexedRoot > .me-slot:last-child {
830
+ grid-column: 3;
831
+ grid-row: 1;
832
+ border-top: 1.5px solid currentColor;
833
+ margin-top: 4px;
834
+ }
835
+ .me-indexedRoot > .me-slot:nth-last-child(2) :is(.me-input, .me-measure, .me-preview-token) {
836
+ font-size: calc(var(--me-font-size, 22px) * 14 / 22);
837
+ }
838
+
839
+ /* Accents follow the editable body's width, including nested structures. */
840
+ .me-vec,
841
+ .me-hat,
842
+ .me-overline {
843
+ position: relative;
844
+ padding-top: 0.3em;
845
+ }
846
+ .me-vec::before,
847
+ .me-overline::before {
848
+ content: '';
849
+ position: absolute;
850
+ top: 0.16em;
851
+ left: 0;
852
+ right: 0;
853
+ border-top: 1.5px solid currentColor;
854
+ pointer-events: none;
855
+ }
856
+ .me-vec::after {
857
+ content: '';
858
+ position: absolute;
859
+ right: 1px;
860
+ top: calc(0.16em - 2px);
861
+ width: 4px;
862
+ height: 4px;
863
+ border-top: 1.5px solid currentColor;
864
+ border-right: 1.5px solid currentColor;
865
+ transform: rotate(45deg);
866
+ pointer-events: none;
867
+ }
868
+ .me-hat::before {
869
+ content: '';
870
+ position: absolute;
871
+ left: 0;
872
+ right: 0;
873
+ top: 0;
874
+ height: 0.28em;
875
+ background: currentColor;
876
+ clip-path: polygon(0 100%, 50% 0, 100% 100%, 90% 100%, 50% 32%, 10% 100%);
877
+ pointer-events: none;
878
+ }
879
+
880
+ /* A binomial stacks two editable terms; curved sides grow with nested content. */
881
+ .me-binomial {
882
+ display: inline-flex;
883
+ flex-direction: column;
884
+ padding: 2px 7px;
885
+ border-left: 1.5px solid currentColor;
886
+ border-right: 1.5px solid currentColor;
887
+ border-radius: 45% / 50%;
888
+ }
889
+ .me-binomial > .me-slot {
890
+ padding: 1px 3px;
891
+ }
892
+
893
+ /* Model boundary nodes are caret targets, not mathematical whitespace.
894
+ Expand only the target being edited; real empty slots retain their hit area. */
895
+ .me-empty-boundary:not(:focus-within) > .me-measure {
896
+ min-width: 4px;
897
+ width: 4px;
898
+ padding-inline: 0;
899
+ }
900
+ .me-operatorName {
901
+ margin-inline-start: 0;
902
+ }
903
+ .me-textGroup,
904
+ .me-subscript,
905
+ .me-superscript {
906
+ margin-inline: 0;
907
+ }
908
+ /* Structural caret boundaries must not detach a script from its base.
909
+ The active boundary still expands to its normal editable width. */
910
+ :is(.me-subscript, .me-superscript, .me-scripts)
911
+ > .me-slot:first-child
912
+ > .me-row
913
+ > .me-empty-boundary:not(:focus-within)
914
+ > .me-measure {
915
+ min-width: 1px;
916
+ width: 1px;
917
+ }
918
+ .me-subscript > .me-slot:first-child .me-operatorName,
919
+ .me-superscript > .me-slot:first-child .me-operatorName,
920
+ .me-scripts > .me-slot:first-child .me-operatorName {
921
+ margin-inline-end: 0;
922
+ }
923
+
924
+ .me-limit-operator {
925
+ align-items: flex-start;
926
+ gap: 4px;
927
+ }
928
+ .me-limit-glyph {
929
+ font: normal var(--me-font-size, 22px) / 1.1 'Barocss Math Glyphs', Georgia, serif;
930
+ }
931
+ .me-limit-operator > .me-limits {
932
+ align-self: baseline;
933
+ }
934
+ .me-limit-operator .me-limit :is(.me-input, .me-measure, .me-preview-token) {
935
+ font-size: calc(var(--me-font-size, 22px) * 14 / 22);
936
+ line-height: 1.1;
937
+ padding-block: 1px;
938
+ }
939
+ /* Keep the condition close to lim without an inherited text-line strut.
940
+ Nested structures still determine their own required height. */
941
+ .me-limit-operator > .me-limits > .me-limit {
942
+ display: inline-flex;
943
+ }
944
+ .me-limit-operator > .me-limits > .me-limit > .me-row {
945
+ min-height: 0;
946
+ }
947
+
948
+ /* Functions are semantic operator nodes, distinct from ordinary variables. */
949
+ .me-editor {
950
+ --me-function: #087b78;
951
+ }
952
+ .me-operatorName :is(.me-input, .me-preview-token, .me-measure),
953
+ .me-limit-glyph,
954
+ .me-token-legend [data-kind='function'] {
955
+ color: var(--me-function);
956
+ }
957
+
958
+ /* Explicit LaTeX spacing is content, independent of empty caret hit areas. */
959
+ .me-quad,
960
+ .me-qquad {
961
+ flex: 0 0 auto;
962
+ width: 1em;
963
+ min-height: 1.35em;
964
+ margin: 0;
965
+ font-size: 22px;
966
+ }
967
+ .me-qquad {
968
+ width: 2em;
969
+ }
970
+ .me-quad:hover,
971
+ .me-qquad:hover {
972
+ background: var(--me-focus);
973
+ }
974
+
975
+ .me-roman :is(.me-input, .me-measure, .me-preview-token) {
976
+ font-style: normal;
977
+ }
978
+ .me-roman .me-preview-token * {
979
+ font-style: normal;
980
+ }
981
+ .me-superscript > .me-slot:last-child :is(.me-quad, .me-qquad),
982
+ .me-subscript > .me-slot:last-child :is(.me-quad, .me-qquad),
983
+ .me-scripts > .me-slot:not(:first-child) :is(.me-quad, .me-qquad) {
984
+ font-size: calc(var(--me-font-size, 22px) * 16 / 22);
985
+ }
986
+ .me-limit :is(.me-quad, .me-qquad) {
987
+ font-size: calc(var(--me-font-size, 22px) * 14 / 22);
988
+ }
989
+
990
+ /* Structured delimiters export as \left/\right and stretch with their body. */
991
+ :is(.me-parentheses, .me-brackets, .me-absolute) > .me-delimiter {
992
+ align-self: stretch;
993
+ flex: 0 0 7px;
994
+ box-sizing: border-box;
995
+ min-height: 26px;
996
+ font-size: 0;
997
+ }
998
+ :is(.me-parentheses, .me-brackets, .me-absolute) > .me-delimiter:first-child {
999
+ border-left: 1.5px solid currentColor;
1000
+ }
1001
+ :is(.me-parentheses, .me-brackets, .me-absolute) > .me-delimiter:last-child {
1002
+ border-right: 1.5px solid currentColor;
1003
+ }
1004
+ /* A tapered curve keeps its bow at tall sizes; an elliptical border flattens. */
1005
+ .me-parentheses > .me-delimiter:first-child,
1006
+ .me-parentheses > .me-delimiter:last-child {
1007
+ flex-basis: 8px;
1008
+ border: 0;
1009
+ background: currentColor;
1010
+ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 100' preserveAspectRatio='none'%3E%3Cpath d='M14 0C4 16 0 32 0 50C0 68 4 84 14 100L14 97C7 80 3 65 3 50C3 35 7 20 14 3Z'/%3E%3C/svg%3E")
1011
+ center / 100% 100% no-repeat;
1012
+ }
1013
+ .me-parentheses > .me-delimiter:last-child {
1014
+ transform: scaleX(-1);
1015
+ }
1016
+ .me-parentheses:has(> .me-slot .me-structure) > .me-delimiter {
1017
+ flex-basis: 14px;
1018
+ }
1019
+ .me-brackets > .me-delimiter {
1020
+ border-top: 1.5px solid currentColor;
1021
+ border-bottom: 1.5px solid currentColor;
1022
+ }
1023
+ /* Leave room between the editable operand and each absolute-value bar. */
1024
+ .me-absolute > .me-delimiter {
1025
+ flex-basis: 7px;
1026
+ position: relative;
1027
+ z-index: 1;
1028
+ }
1029
+
1030
+ /* Additional fences have independent ends, including invisible ends. */
1031
+ :is(.me-braces, .me-angle, .me-openClosed, .me-closedOpen, .me-fenced) > .me-delimiter {
1032
+ align-self: stretch;
1033
+ flex: 0 0 12px;
1034
+ min-height: 26px;
1035
+ box-sizing: border-box;
1036
+ font-size: 0;
1037
+ }
1038
+ :is(.me-openClosed, .me-closedOpen, .me-fenced) > :is([data-fence='('], [data-fence=')']),
1039
+ .me-matrix[data-environment='pmatrix'] > .me-matrix-delimiter {
1040
+ background: currentColor;
1041
+ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 100' preserveAspectRatio='none'%3E%3Cpath d='M14 0C4 16 0 32 0 50C0 68 4 84 14 100L14 97C7 80 3 65 3 50C3 35 7 20 14 3Z'/%3E%3C/svg%3E")
1042
+ center / 100% 100% no-repeat;
1043
+ }
1044
+ .me-delimiter[data-fence=')'] {
1045
+ transform: scaleX(-1);
1046
+ }
1047
+ :is(.me-openClosed, .me-closedOpen, .me-fenced) > :is([data-fence='['], [data-fence=']']) {
1048
+ flex-basis: 7px;
1049
+ border-block: 1.5px solid currentColor;
1050
+ }
1051
+ .me-delimiter[data-fence='['] {
1052
+ border-left: 1.5px solid currentColor;
1053
+ }
1054
+ .me-delimiter[data-fence=']'] {
1055
+ border-right: 1.5px solid currentColor;
1056
+ }
1057
+ .me-delimiter:is([data-fence='⟨'], [data-fence='⟩']) {
1058
+ background: currentColor;
1059
+ clip-path: polygon(100% 0, 18% 50%, 100% 100%, 82% 100%, 0 50%, 82% 0);
1060
+ }
1061
+ .me-delimiter[data-fence='⟩'] {
1062
+ transform: scaleX(-1);
1063
+ }
1064
+ .me-delimiter:is([data-fence='{'], [data-fence='}']),
1065
+ .me-matrix[data-environment='Bmatrix'] > .me-matrix-delimiter,
1066
+ .me-matrix[data-structure='cases'] > .me-matrix-left {
1067
+ background: currentColor;
1068
+ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 100' preserveAspectRatio='none'%3E%3Cpath d='M14 0Q6 0 6 15L6 35Q6 47 0 50Q6 53 6 65L6 85Q6 100 14 100L14 97Q9 96 9 85L9 65Q9 53 4 50Q9 47 9 35L9 15Q9 4 14 3Z'/%3E%3C/svg%3E")
1069
+ center / 100% 100% no-repeat;
1070
+ }
1071
+ .me-delimiter[data-fence='}'] {
1072
+ transform: scaleX(-1);
1073
+ }
1074
+ .me-fenced > [data-fence='|'] {
1075
+ flex-basis: 3px;
1076
+ border-left: 1.5px solid currentColor;
1077
+ }
1078
+ .me-fenced > [data-fence='.'] {
1079
+ flex-basis: 0;
1080
+ width: 0;
1081
+ }
1082
+ .me-overset,
1083
+ .me-underset {
1084
+ flex-direction: column;
1085
+ gap: 0;
1086
+ }
1087
+ .me-underset {
1088
+ flex-direction: column-reverse;
1089
+ }
1090
+ :is(.me-overset, .me-underset)
1091
+ > .me-slot:first-child
1092
+ :is(.me-input, .me-preview-token, .me-measure) {
1093
+ font-size: calc(var(--me-font-size, 22px) * 14 / 22);
1094
+ }
1095
+ /* Square and indexed roots share a radical joined to the radicand's overbar. */
1096
+ .me-root > .me-radical,
1097
+ .me-indexedRoot > .me-radical {
1098
+ align-self: stretch;
1099
+ flex-shrink: 0;
1100
+ width: 24px;
1101
+ min-height: 30px;
1102
+ margin-top: 4px;
1103
+ font-size: 0;
1104
+ background: currentColor;
1105
+ clip-path: polygon(
1106
+ 0 55%,
1107
+ 6px 50%,
1108
+ 12px 88%,
1109
+ 21px 0,
1110
+ 100% 0,
1111
+ 14px 100%,
1112
+ 11px 100%,
1113
+ 5px 58%,
1114
+ 1px 61%
1115
+ );
1116
+ }
1117
+ .me-indexedRoot > .me-slot:nth-last-child(2) {
1118
+ margin-right: -9px;
1119
+ margin-top: -2px;
1120
+ }
1121
+
1122
+ /* Match the right-leaning integral form without tilting bounds or the integrand. */
1123
+ :is(
1124
+ [data-structure='integral'],
1125
+ [data-structure='doubleIntegral'],
1126
+ [data-structure='tripleIntegral'],
1127
+ [data-structure='contourIntegral']
1128
+ )
1129
+ > .me-limits
1130
+ > .me-operator-glyph {
1131
+ transform: skewX(-12deg);
1132
+ transform-origin: center;
1133
+ }
1134
+
1135
+ /* Integral bounds sit beside the slanted glyph unless LaTeX requests limits. */
1136
+ :is(
1137
+ [data-structure='integral'],
1138
+ [data-structure='doubleIntegral'],
1139
+ [data-structure='tripleIntegral'],
1140
+ [data-structure='contourIntegral']
1141
+ )[data-limit-placement='auto']
1142
+ > .me-limits {
1143
+ display: inline-grid;
1144
+ grid-template-columns: max-content max-content;
1145
+ grid-template-rows: auto auto;
1146
+ align-items: center;
1147
+ }
1148
+ :is(
1149
+ [data-structure='integral'],
1150
+ [data-structure='doubleIntegral'],
1151
+ [data-structure='tripleIntegral'],
1152
+ [data-structure='contourIntegral']
1153
+ )[data-limit-placement='auto']
1154
+ > .me-limits
1155
+ > .me-operator-glyph {
1156
+ grid-column: 1;
1157
+ grid-row: 1 / 3;
1158
+ font-size: 44px;
1159
+ }
1160
+ :is(
1161
+ [data-structure='integral'],
1162
+ [data-structure='doubleIntegral'],
1163
+ [data-structure='tripleIntegral'],
1164
+ [data-structure='contourIntegral']
1165
+ )[data-limit-placement='auto']
1166
+ > .me-limits
1167
+ > .me-limit:first-child {
1168
+ grid-column: 2;
1169
+ grid-row: 1;
1170
+ justify-self: start;
1171
+ margin-left: 5px;
1172
+ }
1173
+ :is(
1174
+ [data-structure='integral'],
1175
+ [data-structure='doubleIntegral'],
1176
+ [data-structure='tripleIntegral'],
1177
+ [data-structure='contourIntegral']
1178
+ )[data-limit-placement='auto']
1179
+ > .me-limits
1180
+ > .me-limit:last-child {
1181
+ grid-column: 2;
1182
+ grid-row: 2;
1183
+ justify-self: start;
1184
+ margin-left: -3px;
1185
+ }
1186
+
1187
+ /* Grid fences share the scalable glyphs used by ordinary grouped expressions. */
1188
+ .me-matrix:is([data-environment='pmatrix'], [data-environment='Bmatrix'], [data-structure='cases'])
1189
+ > .me-matrix-delimiter {
1190
+ border: 0;
1191
+ border-radius: 0;
1192
+ width: 10px;
1193
+ flex-shrink: 0;
1194
+ }
1195
+ .me-matrix[data-environment='pmatrix'] > .me-matrix-right {
1196
+ transform: scaleX(-1);
1197
+ }
1198
+ .me-matrix[data-environment='Bmatrix'] > .me-matrix-delimiter::before,
1199
+ .me-matrix[data-environment='Bmatrix'] > .me-matrix-delimiter::after {
1200
+ content: none;
1201
+ }
1202
+
1203
+ /* Eliminate inline line-box descent around vertically stacked math rows. */
1204
+ :is(.me-fraction, .me-scripts, .me-vec, .me-hat, .me-overline) > .me-slot {
1205
+ display: inline-flex;
1206
+ justify-content: center;
1207
+ }
1208
+ .me-scripts > .me-slot:not(:first-child) > .me-row {
1209
+ min-height: 0;
1210
+ }
1211
+ .me-scripts > .me-slot:not(:first-child) :is(.me-input, .me-measure, .me-preview-token) {
1212
+ line-height: 1.1;
1213
+ padding-block: 1px;
1214
+ }
1215
+ /* Keep nested fractions readable while avoiding full-size recursive stacks.
1216
+ Apply the same size to the input, passive glyph and measuring twin. */
1217
+ .me-fraction .me-fraction :is(.me-input, .me-measure, .me-preview-token) {
1218
+ font-size: calc(var(--me-font-size, 22px) * 16 / 22);
1219
+ line-height: 1.2;
1220
+ }
1221
+ .me-fraction .me-fraction .me-fraction :is(.me-input, .me-measure, .me-preview-token) {
1222
+ font-size: 12px;
1223
+ }
1224
+ .me-fraction .me-fraction .me-row {
1225
+ min-height: 0;
1226
+ }
1227
+ .me-fraction > .me-slot {
1228
+ padding: 0 3px;
1229
+ }
1230
+
1231
+ .me-vec,
1232
+ .me-hat,
1233
+ .me-overline {
1234
+ padding-top: 0.1em;
1235
+ }
1236
+ .me-vec::before,
1237
+ .me-overline::before {
1238
+ top: 0.32em;
1239
+ }
1240
+ .me-vec::after {
1241
+ top: calc(0.32em - 2px);
1242
+ }
1243
+ .me-hat::before {
1244
+ top: 0.18em;
1245
+ }
1246
+ .me-large-operator {
1247
+ gap: 4px;
1248
+ }
1249
+ /* Only structural boundaries shrink; genuinely empty expression slots stay roomy. */
1250
+ .me-empty-boundary:focus-within > .me-measure {
1251
+ min-width: 12px;
1252
+ padding-inline: 0;
1253
+ }
1254
+
1255
+ /* Norm fences stay outside the editable body and stretch with nested content. */
1256
+ .me-norm > .me-delimiter,
1257
+ .me-fenced > .me-delimiter[data-fence='‖'] {
1258
+ align-self: stretch;
1259
+ flex: 0 0 9px;
1260
+ min-height: 26px;
1261
+ box-sizing: border-box;
1262
+ font-size: 0;
1263
+ border-left: 4px double currentColor;
1264
+ }
1265
+ .me-norm > .me-delimiter:last-child {
1266
+ border-left: 0;
1267
+ border-right: 4px double currentColor;
1268
+ }
1269
+
1270
+ /* KaTeX's display-size contour glyph already contains its ring and slant. */
1271
+ @font-face {
1272
+ font-family: 'Barocss Contour';
1273
+ src: url('./fonts/KaTeX_Size2-Regular.woff2') format('woff2');
1274
+ unicode-range: U+222E;
1275
+ }
1276
+ [data-structure='contourIntegral'][data-limit-placement] > .me-limits > .me-operator-glyph {
1277
+ font: normal var(--me-font-size, 22px) / 2.3 'Barocss Contour', serif;
1278
+ width: 25px;
1279
+ height: 51px;
1280
+ transform: none;
1281
+ }
1282
+
1283
+ /* Brace annotations share annotation/body slot order with overset/underset. */
1284
+ .me-overbrace,
1285
+ .me-underbrace {
1286
+ display: inline-flex;
1287
+ flex-direction: column;
1288
+ gap: 1px;
1289
+ }
1290
+ .me-underbrace {
1291
+ flex-direction: column-reverse;
1292
+ }
1293
+ :is(.me-overbrace, .me-underbrace) > .me-slot {
1294
+ display: inline-flex;
1295
+ justify-content: center;
1296
+ }
1297
+ :is(.me-overbrace, .me-underbrace) > .me-slot:first-child > .me-row {
1298
+ min-height: 0;
1299
+ }
1300
+ :is(.me-overbrace, .me-underbrace)
1301
+ > .me-slot:first-child
1302
+ :is(.me-input, .me-measure, .me-preview-token) {
1303
+ font-size: calc(var(--me-font-size, 22px) * 14 / 22);
1304
+ line-height: 1.1;
1305
+ }
1306
+ :is(.me-overbrace, .me-underbrace) > .me-slot:last-child {
1307
+ position: relative;
1308
+ width: 100%;
1309
+ box-sizing: border-box;
1310
+ }
1311
+ .me-overbrace > .me-slot:last-child {
1312
+ padding-top: 9px;
1313
+ }
1314
+ .me-underbrace > .me-slot:last-child {
1315
+ padding-bottom: 9px;
1316
+ }
1317
+ :is(.me-overbrace, .me-underbrace) > .me-slot:last-child::before {
1318
+ content: '';
1319
+ position: absolute;
1320
+ inset-inline: 0;
1321
+ top: 0;
1322
+ height: 8px;
1323
+ background: currentColor;
1324
+ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 12Q0 5 12 5L38 5Q48 5 50 0Q52 5 62 5L88 5Q100 5 100 12L98 12Q98 8 88 8L62 8Q53 8 50 4Q47 8 38 8L12 8Q2 8 2 12Z'/%3E%3C/svg%3E")
1325
+ center / 100% 100% no-repeat;
1326
+ pointer-events: none;
1327
+ }
1328
+ .me-underbrace > .me-slot:last-child::before {
1329
+ top: auto;
1330
+ bottom: 0;
1331
+ transform: scaleY(-1);
1332
+ }
1333
+
1334
+ /* Toolbar overflow is a control, visually distinct from notation commands. */
1335
+ .me-tools .me-toolbar-toggle {
1336
+ min-height: 32px;
1337
+ padding: 7px 12px;
1338
+ gap: 9px;
1339
+ border: 1px solid #b8cec3;
1340
+ border-radius: 7px;
1341
+ background: #edf4ef;
1342
+ color: #245443;
1343
+ font-weight: 600;
1344
+ white-space: nowrap;
1345
+ }
1346
+ .me-tools .me-toolbar-toggle::after {
1347
+ content: '';
1348
+ width: 6px;
1349
+ height: 6px;
1350
+ border-right: 1.5px solid currentColor;
1351
+ border-bottom: 1.5px solid currentColor;
1352
+ transform: translateY(-2px) rotate(45deg);
1353
+ }
1354
+ .me-tools .me-toolbar-toggle[aria-expanded='true']::after {
1355
+ transform: translateY(2px) rotate(225deg);
1356
+ }
1357
+ .me-tools .me-toolbar-toggle:hover {
1358
+ background: #dfece4;
1359
+ border-color: #8fac9c;
1360
+ }
1361
+ .me-tools .me-toolbar-toggle[aria-expanded='true'] {
1362
+ background: #dfece4;
1363
+ }
1364
+ .me-tools .me-toolbar-toggle:focus-visible {
1365
+ outline-offset: 2px;
1366
+ }
1367
+
1368
+ /* Fixed accents stay centered; wide variants follow the editable body. */
1369
+ :is(.me-tilde, .me-bar, .me-dot, .me-ddot, .me-widehat, .me-widetilde) {
1370
+ position: relative;
1371
+ padding-top: 5px;
1372
+ }
1373
+ :is(.me-tilde, .me-bar, .me-dot, .me-ddot, .me-widehat, .me-widetilde) > .me-slot {
1374
+ display: inline-flex;
1375
+ }
1376
+ :is(.me-tilde, .me-bar, .me-dot, .me-ddot, .me-widehat, .me-widetilde)::before {
1377
+ content: '';
1378
+ position: absolute;
1379
+ top: 6px;
1380
+ left: 50%;
1381
+ transform: translateX(-50%);
1382
+ height: 5px;
1383
+ width: 14px;
1384
+ background: currentColor;
1385
+ pointer-events: none;
1386
+ }
1387
+ .me-bar::before {
1388
+ height: 1.5px;
1389
+ top: 9px;
1390
+ }
1391
+ .me-dot::before {
1392
+ width: 3px;
1393
+ height: 3px;
1394
+ border-radius: 50%;
1395
+ top: 8px;
1396
+ }
1397
+ .me-ddot::before {
1398
+ width: 3px;
1399
+ height: 3px;
1400
+ border-radius: 50%;
1401
+ top: 8px;
1402
+ margin-left: -3px;
1403
+ box-shadow: 6px 0 currentColor;
1404
+ }
1405
+ .me-widehat::before {
1406
+ width: 100%;
1407
+ clip-path: polygon(0 100%, 50% 0, 100% 100%, 90% 100%, 50% 32%, 10% 100%);
1408
+ }
1409
+ .me-widetilde::before {
1410
+ width: 100%;
1411
+ }
1412
+ :is(.me-tilde, .me-widetilde)::before {
1413
+ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 12' preserveAspectRatio='none'%3E%3Cpath d='M0 9C20 -8 35 0 50 5S80 15 100 0L100 4C80 21 65 13 50 9S20 -1 0 12Z'/%3E%3C/svg%3E")
1414
+ center / 100% 100% no-repeat;
1415
+ }
1416
+
1417
+ /* Explicit nolimits places scripts beside every supported large operator. */
1418
+ .me-large-operator[data-limit-placement='nolimits'] > .me-limits {
1419
+ display: inline-grid;
1420
+ grid-template-columns: max-content max-content;
1421
+ grid-template-rows: auto auto;
1422
+ align-items: center;
1423
+ }
1424
+ .me-large-operator[data-limit-placement='nolimits'] > .me-limits > .me-operator-glyph {
1425
+ grid-column: 1;
1426
+ grid-row: 1 / 3;
1427
+ }
1428
+ .me-large-operator[data-limit-placement='nolimits'] > .me-limits > .me-limit:first-child {
1429
+ grid-column: 2;
1430
+ grid-row: 1;
1431
+ margin-left: 5px;
1432
+ }
1433
+ .me-large-operator[data-limit-placement='nolimits'] > .me-limits > .me-limit:last-child {
1434
+ grid-column: 2;
1435
+ grid-row: 2;
1436
+ margin-left: 0;
1437
+ }
1438
+ .me-limit-operator[data-limit-placement='nolimits'] > .me-limits {
1439
+ flex-direction: row;
1440
+ align-items: baseline;
1441
+ gap: 2px;
1442
+ }
1443
+ .me-limit-operator[data-limit-placement='nolimits'] > .me-limits > .me-limit {
1444
+ transform: translateY(0.3em);
1445
+ }
1446
+ :is(
1447
+ [data-structure='integral'],
1448
+ [data-structure='doubleIntegral'],
1449
+ [data-structure='tripleIntegral']
1450
+ )[data-limit-placement='nolimits']
1451
+ > .me-limits
1452
+ > .me-operator-glyph {
1453
+ font-size: 44px;
1454
+ }
1455
+
1456
+ /* TeX math units: 18mu = 1em. Negative spacing has no painted hit box. */
1457
+ :is(.me-thinSpace, .me-mediumSpace, .me-thickSpace, .me-negativeThinSpace) {
1458
+ flex: 0 0 auto;
1459
+ margin: 0;
1460
+ min-height: 1em;
1461
+ font-size: 22px;
1462
+ }
1463
+ .me-thinSpace {
1464
+ width: calc(1em / 6);
1465
+ }
1466
+ .me-mediumSpace {
1467
+ width: calc(2em / 9);
1468
+ }
1469
+ .me-thickSpace {
1470
+ width: calc(5em / 18);
1471
+ }
1472
+ .me-negativeThinSpace {
1473
+ width: 0;
1474
+ margin-inline-end: calc(-1em / 6);
1475
+ }
1476
+ :is(.me-superscript, .me-subscript, .me-scripts)
1477
+ > .me-slot:not(:first-child)
1478
+ :is(.me-thinSpace, .me-mediumSpace, .me-thickSpace, .me-negativeThinSpace) {
1479
+ font-size: 16px;
1480
+ }
1481
+ .me-limit :is(.me-thinSpace, .me-mediumSpace, .me-thickSpace, .me-negativeThinSpace) {
1482
+ font-size: 14px;
1483
+ }
1484
+
1485
+ /* Explicit fraction/binomial styles override the surrounding default size.
1486
+ Nested explicit styles use the nearest style container's inherited value. */
1487
+ .me-structure[data-math-style='display'] {
1488
+ --me-explicit-size: 22px;
1489
+ }
1490
+ .me-structure[data-math-style='text'] {
1491
+ --me-explicit-size: 16px;
1492
+ }
1493
+ .me-structure[data-math-style] :is(.me-input, .me-measure, .me-preview-token) {
1494
+ font-size: var(--me-explicit-size);
1495
+ }
1496
+ .me-structure[data-math-style='text'] > .me-slot > .me-row {
1497
+ min-height: 0;
1498
+ }
1499
+ .me-structure[data-math-style='text'] > .me-slot {
1500
+ padding-block: 0;
1501
+ }
1502
+ .me-structure[data-math-style]
1503
+ :is(.me-superscript, .me-subscript, .me-scripts)
1504
+ > .me-slot:not(:first-child)
1505
+ :is(.me-input, .me-measure, .me-preview-token) {
1506
+ font-size: calc(var(--me-explicit-size) * 0.7273);
1507
+ }
1508
+
1509
+ /* Alphabet fonts are scoped to editable runs, never delimiter/operator glyphs.
1510
+ Restrict decorative faces to their supported Latin capitals. */
1511
+ @font-face {
1512
+ font-family: 'Barocss Bold';
1513
+ src: url('./fonts/KaTeX_Main-Bold.woff2') format('woff2');
1514
+ font-weight: 700;
1515
+ font-display: swap;
1516
+ }
1517
+ @font-face {
1518
+ font-family: 'Barocss Calligraphic';
1519
+ src: url('./fonts/KaTeX_Caligraphic-Regular.woff2') format('woff2');
1520
+ unicode-range: U+0041-005A;
1521
+ font-display: swap;
1522
+ }
1523
+ @font-face {
1524
+ font-family: 'Barocss Blackboard';
1525
+ src: url('./fonts/KaTeX_AMS-Regular.woff2') format('woff2');
1526
+ unicode-range: U+0041-005A;
1527
+ font-display: swap;
1528
+ }
1529
+ .me-bold {
1530
+ --me-alphabet: 'Barocss Bold', Georgia, serif;
1531
+ --me-alphabet-weight: 700;
1532
+ }
1533
+ .me-calligraphic {
1534
+ --me-alphabet: 'Barocss Calligraphic', Georgia, serif;
1535
+ --me-alphabet-weight: 400;
1536
+ }
1537
+ .me-blackboard {
1538
+ --me-alphabet: 'Barocss Blackboard', Georgia, serif;
1539
+ --me-alphabet-weight: 400;
1540
+ }
1541
+ .me-roman {
1542
+ --me-alphabet: Georgia, serif;
1543
+ --me-alphabet-weight: 400;
1544
+ }
1545
+ :is(.me-bold, .me-calligraphic, .me-blackboard, .me-roman)
1546
+ :is(.me-input, .me-measure, .me-preview-token, .me-preview-token *) {
1547
+ font-family: var(--me-alphabet);
1548
+ font-weight: var(--me-alphabet-weight);
1549
+ font-style: normal;
1550
+ }
1551
+ :is(.me-bold, .me-calligraphic, .me-blackboard, .me-roman) {
1552
+ margin-inline: 0;
1553
+ }
1554
+
1555
+ /* Labels determine the shaft width; the arrow itself occupies the middle row. */
1556
+ :is(.me-xrightarrow, .me-xleftarrow) {
1557
+ display: inline-grid;
1558
+ grid-template-columns: minmax(36px, auto);
1559
+ grid-template-rows: auto 9px auto;
1560
+ align-items: center;
1561
+ vertical-align: middle;
1562
+ }
1563
+ :is(.me-xrightarrow, .me-xleftarrow) > .me-slot {
1564
+ display: inline-flex;
1565
+ justify-content: center;
1566
+ padding-inline: 7px;
1567
+ }
1568
+ :is(.me-xrightarrow, .me-xleftarrow) > .me-slot:first-child {
1569
+ grid-area: 1 / 1;
1570
+ }
1571
+ :is(.me-xrightarrow, .me-xleftarrow) > .me-slot:last-child {
1572
+ grid-area: 3 / 1;
1573
+ }
1574
+ :is(.me-xrightarrow, .me-xleftarrow) > .me-slot > .me-row {
1575
+ min-height: 0;
1576
+ }
1577
+ :is(.me-xrightarrow, .me-xleftarrow) > .me-slot :is(.me-input, .me-measure, .me-preview-token) {
1578
+ font-size: 14px;
1579
+ line-height: 1.1;
1580
+ }
1581
+ :is(.me-xrightarrow, .me-xleftarrow)::before {
1582
+ content: '';
1583
+ grid-area: 2 / 1;
1584
+ width: 100%;
1585
+ height: 9px;
1586
+ background: currentColor;
1587
+ height: 1.2px;
1588
+ pointer-events: none;
1589
+ }
1590
+ /* Keep the head a fixed size even when a label makes the shaft much longer. */
1591
+ :is(.me-xrightarrow, .me-xleftarrow)::after {
1592
+ content: '';
1593
+ grid-area: 2 / 1;
1594
+ justify-self: end;
1595
+ width: 7px;
1596
+ height: 9px;
1597
+ background: currentColor;
1598
+ clip-path: polygon(0 0, 100% 50%, 0 100%, 32% 50%);
1599
+ pointer-events: none;
1600
+ }
1601
+ .me-xleftarrow::after {
1602
+ justify-self: start;
1603
+ transform: scaleX(-1);
1604
+ }