math-core 0.5.3__tar.gz → 0.6.0__tar.gz
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.
- {math_core-0.5.3 → math_core-0.6.0}/Cargo.lock +52 -38
- {math_core-0.5.3 → math_core-0.6.0}/Cargo.toml +1 -1
- math_core-0.6.0/LICENSE +9 -0
- {math_core-0.5.3 → math_core-0.6.0}/PKG-INFO +1 -1
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/Cargo.toml +3 -3
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/README.md +30 -9
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/examples/browser_test.rs +3 -1
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/examples/equations.rs +2 -2
- math_core-0.6.0/crates/math-core/src/character_class.rs +194 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/src/commands.rs +82 -32
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/src/environments.rs +37 -32
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/src/lexer.rs +16 -1
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/src/lib.rs +9 -7
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/src/parser.rs +181 -94
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/src/predefined.rs +2 -1
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/src/token.rs +8 -11
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/tests/conversion_test.rs +6 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core-python/Cargo.toml +1 -1
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core-python/src/lib.rs +11 -1
- {math_core-0.5.3 → math_core-0.6.0}/crates/mathml-renderer/src/arena.rs +4 -4
- {math_core-0.5.3 → math_core-0.6.0}/crates/mathml-renderer/src/ast.rs +58 -105
- {math_core-0.5.3 → math_core-0.6.0}/crates/mathml-renderer/src/attribute.rs +6 -43
- {math_core-0.5.3 → math_core-0.6.0}/crates/mathml-renderer/src/length.rs +2 -2
- {math_core-0.5.3 → math_core-0.6.0}/crates/mathml-renderer/src/lib.rs +1 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/mathml-renderer/src/symbol.rs +41 -122
- {math_core-0.5.3 → math_core-0.6.0}/pyproject.toml +1 -1
- {math_core-0.5.3 → math_core-0.6.0}/python/math_core/_math_core_rust.pyi +1 -0
- math_core-0.5.3/crates/math-core/src/character_class.rs +0 -22
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/examples/minijinja.rs +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/src/atof.rs +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/src/color_defs.rs +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/src/error.rs +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/src/html_utils.rs +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/src/specifications.rs +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/src/text_parser.rs +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/src/token_queue.rs +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/tests/custom_cmd_test.rs +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/tests/error_test.rs +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core/tests/wiki_test.rs +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/math-core-python/README.md +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/mathml-renderer/Cargo.toml +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/mathml-renderer/README.md +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/mathml-renderer/src/fmt.rs +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/mathml-renderer/src/itoa.rs +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/crates/mathml-renderer/src/table.rs +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/python/math_core/__init__.py +0 -0
- {math_core-0.5.3 → math_core-0.6.0}/python/math_core/py.typed +0 -0
|
@@ -13,9 +13,9 @@ dependencies = [
|
|
|
13
13
|
|
|
14
14
|
[[package]]
|
|
15
15
|
name = "anstream"
|
|
16
|
-
version = "0.
|
|
16
|
+
version = "1.0.0"
|
|
17
17
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
18
|
-
checksum = "
|
|
18
|
+
checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
|
|
19
19
|
dependencies = [
|
|
20
20
|
"anstyle",
|
|
21
21
|
"anstyle-parse",
|
|
@@ -28,15 +28,15 @@ dependencies = [
|
|
|
28
28
|
|
|
29
29
|
[[package]]
|
|
30
30
|
name = "anstyle"
|
|
31
|
-
version = "1.0.
|
|
31
|
+
version = "1.0.14"
|
|
32
32
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
33
|
-
checksum = "
|
|
33
|
+
checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
|
|
34
34
|
|
|
35
35
|
[[package]]
|
|
36
36
|
name = "anstyle-parse"
|
|
37
|
-
version = "0.
|
|
37
|
+
version = "1.0.0"
|
|
38
38
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
39
|
-
checksum = "
|
|
39
|
+
checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
|
|
40
40
|
dependencies = [
|
|
41
41
|
"utf8parse",
|
|
42
42
|
]
|
|
@@ -52,12 +52,13 @@ dependencies = [
|
|
|
52
52
|
|
|
53
53
|
[[package]]
|
|
54
54
|
name = "anstyle-wincon"
|
|
55
|
-
version = "3.0.
|
|
55
|
+
version = "3.0.11"
|
|
56
56
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
57
|
-
checksum = "
|
|
57
|
+
checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
|
|
58
58
|
dependencies = [
|
|
59
59
|
"anstyle",
|
|
60
|
-
"
|
|
60
|
+
"once_cell_polyfill",
|
|
61
|
+
"windows-sys 0.61.2",
|
|
61
62
|
]
|
|
62
63
|
|
|
63
64
|
[[package]]
|
|
@@ -126,9 +127,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|
|
126
127
|
|
|
127
128
|
[[package]]
|
|
128
129
|
name = "clap"
|
|
129
|
-
version = "4.
|
|
130
|
+
version = "4.6.0"
|
|
130
131
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
131
|
-
checksum = "
|
|
132
|
+
checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351"
|
|
132
133
|
dependencies = [
|
|
133
134
|
"clap_builder",
|
|
134
135
|
"clap_derive",
|
|
@@ -136,9 +137,9 @@ dependencies = [
|
|
|
136
137
|
|
|
137
138
|
[[package]]
|
|
138
139
|
name = "clap_builder"
|
|
139
|
-
version = "4.
|
|
140
|
+
version = "4.6.0"
|
|
140
141
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
141
|
-
checksum = "
|
|
142
|
+
checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
|
|
142
143
|
dependencies = [
|
|
143
144
|
"anstream",
|
|
144
145
|
"anstyle",
|
|
@@ -148,9 +149,9 @@ dependencies = [
|
|
|
148
149
|
|
|
149
150
|
[[package]]
|
|
150
151
|
name = "clap_derive"
|
|
151
|
-
version = "4.
|
|
152
|
+
version = "4.6.0"
|
|
152
153
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
153
|
-
checksum = "
|
|
154
|
+
checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a"
|
|
154
155
|
dependencies = [
|
|
155
156
|
"heck",
|
|
156
157
|
"proc-macro2",
|
|
@@ -362,7 +363,7 @@ dependencies = [
|
|
|
362
363
|
|
|
363
364
|
[[package]]
|
|
364
365
|
name = "math-core"
|
|
365
|
-
version = "0.
|
|
366
|
+
version = "0.6.0"
|
|
366
367
|
dependencies = [
|
|
367
368
|
"ariadne",
|
|
368
369
|
"insta",
|
|
@@ -382,7 +383,7 @@ dependencies = [
|
|
|
382
383
|
|
|
383
384
|
[[package]]
|
|
384
385
|
name = "math-core-cli"
|
|
385
|
-
version = "0.
|
|
386
|
+
version = "0.6.0"
|
|
386
387
|
dependencies = [
|
|
387
388
|
"ariadne",
|
|
388
389
|
"clap",
|
|
@@ -395,7 +396,7 @@ dependencies = [
|
|
|
395
396
|
|
|
396
397
|
[[package]]
|
|
397
398
|
name = "math-core-python"
|
|
398
|
-
version = "0.
|
|
399
|
+
version = "0.6.0"
|
|
399
400
|
dependencies = [
|
|
400
401
|
"ariadne",
|
|
401
402
|
"math-core",
|
|
@@ -405,7 +406,7 @@ dependencies = [
|
|
|
405
406
|
|
|
406
407
|
[[package]]
|
|
407
408
|
name = "math-core-renderer-internal"
|
|
408
|
-
version = "0.
|
|
409
|
+
version = "0.6.0"
|
|
409
410
|
dependencies = [
|
|
410
411
|
"bitflags",
|
|
411
412
|
"dtoa",
|
|
@@ -418,7 +419,7 @@ dependencies = [
|
|
|
418
419
|
|
|
419
420
|
[[package]]
|
|
420
421
|
name = "math-core-wasm"
|
|
421
|
-
version = "0.
|
|
422
|
+
version = "0.6.0"
|
|
422
423
|
dependencies = [
|
|
423
424
|
"ariadne",
|
|
424
425
|
"js-sys",
|
|
@@ -435,6 +436,12 @@ version = "2.8.0"
|
|
|
435
436
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
436
437
|
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
|
437
438
|
|
|
439
|
+
[[package]]
|
|
440
|
+
name = "memo-map"
|
|
441
|
+
version = "0.3.3"
|
|
442
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
443
|
+
checksum = "38d1115007560874e373613744c6fba374c17688327a71c1476d1a5954cc857b"
|
|
444
|
+
|
|
438
445
|
[[package]]
|
|
439
446
|
name = "minicov"
|
|
440
447
|
version = "0.3.8"
|
|
@@ -447,10 +454,11 @@ dependencies = [
|
|
|
447
454
|
|
|
448
455
|
[[package]]
|
|
449
456
|
name = "minijinja"
|
|
450
|
-
version = "2.
|
|
457
|
+
version = "2.18.0"
|
|
451
458
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
452
|
-
checksum = "
|
|
459
|
+
checksum = "328251e58ad8e415be6198888fc207502727dc77945806421ab34f35bf012e7d"
|
|
453
460
|
dependencies = [
|
|
461
|
+
"memo-map",
|
|
454
462
|
"serde",
|
|
455
463
|
]
|
|
456
464
|
|
|
@@ -479,6 +487,12 @@ version = "1.21.3"
|
|
|
479
487
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
480
488
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
|
481
489
|
|
|
490
|
+
[[package]]
|
|
491
|
+
name = "once_cell_polyfill"
|
|
492
|
+
version = "1.70.2"
|
|
493
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
494
|
+
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
|
495
|
+
|
|
482
496
|
[[package]]
|
|
483
497
|
name = "oorandom"
|
|
484
498
|
version = "11.1.5"
|
|
@@ -548,9 +562,9 @@ checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
|
|
|
548
562
|
|
|
549
563
|
[[package]]
|
|
550
564
|
name = "proc-macro2"
|
|
551
|
-
version = "1.0.
|
|
565
|
+
version = "1.0.106"
|
|
552
566
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
553
|
-
checksum = "
|
|
567
|
+
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
|
554
568
|
dependencies = [
|
|
555
569
|
"unicode-ident",
|
|
556
570
|
]
|
|
@@ -615,9 +629,9 @@ dependencies = [
|
|
|
615
629
|
|
|
616
630
|
[[package]]
|
|
617
631
|
name = "quote"
|
|
618
|
-
version = "1.0.
|
|
632
|
+
version = "1.0.45"
|
|
619
633
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
620
|
-
checksum = "
|
|
634
|
+
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
|
621
635
|
dependencies = [
|
|
622
636
|
"proc-macro2",
|
|
623
637
|
]
|
|
@@ -843,9 +857,9 @@ dependencies = [
|
|
|
843
857
|
|
|
844
858
|
[[package]]
|
|
845
859
|
name = "syn"
|
|
846
|
-
version = "2.0.
|
|
860
|
+
version = "2.0.117"
|
|
847
861
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
848
|
-
checksum = "
|
|
862
|
+
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
|
849
863
|
dependencies = [
|
|
850
864
|
"proc-macro2",
|
|
851
865
|
"quote",
|
|
@@ -873,9 +887,9 @@ dependencies = [
|
|
|
873
887
|
|
|
874
888
|
[[package]]
|
|
875
889
|
name = "toml"
|
|
876
|
-
version = "1.0.
|
|
890
|
+
version = "1.0.7+spec-1.1.0"
|
|
877
891
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
878
|
-
checksum = "
|
|
892
|
+
checksum = "dd28d57d8a6f6e458bc0b8784f8fdcc4b99a437936056fa122cb234f18656a96"
|
|
879
893
|
dependencies = [
|
|
880
894
|
"indexmap",
|
|
881
895
|
"serde_core",
|
|
@@ -888,27 +902,27 @@ dependencies = [
|
|
|
888
902
|
|
|
889
903
|
[[package]]
|
|
890
904
|
name = "toml_datetime"
|
|
891
|
-
version = "1.0.
|
|
905
|
+
version = "1.0.1+spec-1.1.0"
|
|
892
906
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
893
|
-
checksum = "
|
|
907
|
+
checksum = "9b320e741db58cac564e26c607d3cc1fdc4a88fd36c879568c07856ed83ff3e9"
|
|
894
908
|
dependencies = [
|
|
895
909
|
"serde_core",
|
|
896
910
|
]
|
|
897
911
|
|
|
898
912
|
[[package]]
|
|
899
913
|
name = "toml_parser"
|
|
900
|
-
version = "1.0.
|
|
914
|
+
version = "1.0.10+spec-1.1.0"
|
|
901
915
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
902
|
-
checksum = "
|
|
916
|
+
checksum = "7df25b4befd31c4816df190124375d5a20c6b6921e2cad937316de3fccd63420"
|
|
903
917
|
dependencies = [
|
|
904
918
|
"winnow",
|
|
905
919
|
]
|
|
906
920
|
|
|
907
921
|
[[package]]
|
|
908
922
|
name = "toml_writer"
|
|
909
|
-
version = "1.0.
|
|
923
|
+
version = "1.0.7+spec-1.1.0"
|
|
910
924
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
911
|
-
checksum = "
|
|
925
|
+
checksum = "f17aaa1c6e3dc22b1da4b6bba97d066e354c7945cac2f7852d4e4e7ca7a6b56d"
|
|
912
926
|
|
|
913
927
|
[[package]]
|
|
914
928
|
name = "typeid"
|
|
@@ -1160,9 +1174,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
|
|
1160
1174
|
|
|
1161
1175
|
[[package]]
|
|
1162
1176
|
name = "winnow"
|
|
1163
|
-
version = "0.
|
|
1177
|
+
version = "1.0.0"
|
|
1164
1178
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1165
|
-
checksum = "
|
|
1179
|
+
checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8"
|
|
1166
1180
|
|
|
1167
1181
|
[[package]]
|
|
1168
1182
|
name = "wit-bindgen"
|
math_core-0.6.0/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright 2020 Hiromu Sugiura
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -19,7 +19,7 @@ categories = ["science"]
|
|
|
19
19
|
exclude = ["/src/snapshots", "/tests/snapshots"]
|
|
20
20
|
|
|
21
21
|
[dependencies]
|
|
22
|
-
mathml-renderer = { path = "../mathml-renderer", package = "math-core-renderer-internal", version = "0.
|
|
22
|
+
mathml-renderer = { path = "../mathml-renderer", package = "math-core-renderer-internal", version = "0.6.0" }
|
|
23
23
|
serde = { workspace = true, optional = true }
|
|
24
24
|
serde-tuple-vec-map = { version = "1.0.1", optional = true }
|
|
25
25
|
phf = { version = "0.13.1", features = ["macros"] }
|
|
@@ -32,10 +32,10 @@ ariadne = { workspace = true, optional = true }
|
|
|
32
32
|
|
|
33
33
|
[dev-dependencies]
|
|
34
34
|
math-core = { path = ".", features = ["serde", "ariadne"] }
|
|
35
|
-
mathml-renderer = { path = "../mathml-renderer", package = "math-core-renderer-internal", version = "0.
|
|
35
|
+
mathml-renderer = { path = "../mathml-renderer", package = "math-core-renderer-internal", version = "0.6.0", features = ["serde"] }
|
|
36
36
|
insta = { version = "1.46.3", features = ["default", "ron"] }
|
|
37
37
|
regex = "1.12.3"
|
|
38
|
-
minijinja = "2.
|
|
38
|
+
minijinja = "2.18.0"
|
|
39
39
|
|
|
40
40
|
[features]
|
|
41
41
|
serde = ["dep:serde", "dep:serde-tuple-vec-map"]
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Convert LaTeX to MathML Core
|
|
4
4
|
|
|
5
|
-
[Try it out on the playground
|
|
5
|
+
[Try it out on the playground](https://tmke8.github.io/math-core/) or [take a look at the comparison table with KaTeX](https://tmke8.github.io/math-core/comparison.html).
|
|
6
6
|
|
|
7
7
|
`math-core` allows you to convert LaTeX math to [MathML Core](https://www.w3.org/TR/mathml-core/), the MathML specification that is being implemented by web browsers. For example, this LaTeX code:
|
|
8
8
|
|
|
@@ -51,13 +51,13 @@ There are 4 ways to use the code in this project:
|
|
|
51
51
|
1. As a CLI binary
|
|
52
52
|
2. As a Python package
|
|
53
53
|
3. As a Rust library
|
|
54
|
-
4. As a
|
|
54
|
+
4. As a Node.js package
|
|
55
55
|
|
|
56
56
|
### CLI
|
|
57
57
|
You can download precompiled binaries from the GitHub Release page. Alternatively, you can build the CLI binary from source:
|
|
58
58
|
|
|
59
59
|
```sh
|
|
60
|
-
cargo
|
|
60
|
+
cargo install math-core-cli
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
You can see an explanation of the CLI interface with
|
|
@@ -86,12 +86,16 @@ cargo add math-core
|
|
|
86
86
|
|
|
87
87
|
The documentation for the library can be found on docs.rs: https://docs.rs/math-core/latest/math_core/
|
|
88
88
|
|
|
89
|
-
###
|
|
90
|
-
|
|
89
|
+
### Node.js package
|
|
90
|
+
Install the package with
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
npm i math-core
|
|
94
|
+
```
|
|
91
95
|
|
|
92
96
|
## Required CSS
|
|
93
97
|
### CSS for math font
|
|
94
|
-
The MathML
|
|
98
|
+
The MathML markup generated by this project is intended to be very portable and work *almost* without a CSS style sheet. However, in order to really get LaTeX-like rendering, one unfortunately needs custom math fonts.
|
|
95
99
|
|
|
96
100
|
To specify the font, include something like this in your CSS:
|
|
97
101
|
|
|
@@ -106,15 +110,17 @@ math {
|
|
|
106
110
|
}
|
|
107
111
|
```
|
|
108
112
|
|
|
109
|
-
Some day, perhaps, any font with a MATH table will be supported, but right now fonts require some tweaks.
|
|
113
|
+
Some day, perhaps, any font with a MATH table will be supported, but right now fonts require some tweaks due to browser shortcomings.
|
|
110
114
|
|
|
111
|
-
|
|
115
|
+
One problem is that Chromium does not look at `ssty` variants when deciding on a glyph for super- and subscript (resulting in incorrectly rendered primes). Another problem is that Safari displays accents with incorrect vertical space. Additionally, both Chromium and Safari do not horizontally center certain accents. These problems have been manually fixed for the three fonts selectable on the playground:
|
|
112
116
|
|
|
113
117
|
- *New Computer Modern Math Book* ([original repo](https://git.gnu.org.ua/newcm.git/about/)): a maintained continuation of LaTeX’s classic *Computer Modern Math*
|
|
114
118
|
- *Libertinus Math* ([original repo](https://github.com/alerque/libertinus)): a maintained continuation of *Linux Libertine*
|
|
115
119
|
- *Noto Sans Math* ([original repo](https://github.com/notofonts/math)): a sans-serif math font
|
|
116
120
|
|
|
117
|
-
The fixes applied to the font files do not change the shape of any glyphs; they merely rearrange some glyphs or
|
|
121
|
+
The fixes applied to the font files do not change the shape of any glyphs; they merely rearrange some glyphs or position them differently within glyph space.
|
|
122
|
+
|
|
123
|
+
The patching of these fonts is tracked in a separate repository: [math-core-fonts](https://github.com/tmke8/math-core-fonts). To use them on your website, download them from there.
|
|
118
124
|
|
|
119
125
|
#### Font subsetting
|
|
120
126
|
The math fonts all have quite large font files. Especially *New Computer Modern Math Book* is enormous with an almost 700kB `.woff2` file. Therefore, if possible, you should use *font subsetting* where the font file only includes those glyphs that are actually used on your website. Existing tools should work fine for this.
|
|
@@ -184,6 +190,20 @@ Chromium does not support the `<menclose>` element, which is used for `\sout{...
|
|
|
184
190
|
}
|
|
185
191
|
```
|
|
186
192
|
|
|
193
|
+
### Accent gap
|
|
194
|
+
We also recommend (though it is not necessary) to add the following CSS:
|
|
195
|
+
|
|
196
|
+
```css
|
|
197
|
+
/* Styles for Chromium and Safari */
|
|
198
|
+
@supports (not (-moz-appearance: none)) {
|
|
199
|
+
mover[accent="true" i] > mo:nth-child(2) {
|
|
200
|
+
margin-bottom: 0.15ex;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
This slightly increases the gap between letter and accent on Chromium and Safari. One risk with such a CSS rule is that if Chromium or Safari ever increases that gap to match Firefox, then this CSS will produce an overlarge gap. However, it's not clear that this will ever happen and we think the present-day benefits of this CSS rule outweigh the future risks.
|
|
206
|
+
|
|
187
207
|
#### Dealing with other rendering problems
|
|
188
208
|
The above CSS unfortunately does not fix all rendering bugs found in the current versions of browsers. There is a tracking issue for other known rendering bugs: https://github.com/tmke8/math-core/issues/209
|
|
189
209
|
|
|
@@ -218,6 +238,7 @@ There is no Unicode range for this, so the only way to implement this would be w
|
|
|
218
238
|
- This also applies to things like `:=`. Consider using `\coloneqq` instead, which will result in the semantically correct Unicode symbol.
|
|
219
239
|
- Don’t worry about having unnecessary curly braces, like, say, `x_{2}` vs `x_2`. Both result in the same MathML because unnecessary groups are stripped away by this library.
|
|
220
240
|
- Try to avoid using absolute length units like `\hspace{1cm}`. It’s difficult to render them correctly. Instead, use relative length units like `\hspace{2.8em}`.
|
|
241
|
+
- Use `\text{...}` only for prose and not for, e.g., subscripted textual labels as in `D_\text{test}`. In the latter case, use `\mathrm{...}` instead.
|
|
221
242
|
|
|
222
243
|
## Alternatives to this library
|
|
223
244
|
|
|
@@ -4,9 +4,10 @@ fn main() {
|
|
|
4
4
|
let inputs = vec![
|
|
5
5
|
// Safari bugs:
|
|
6
6
|
r#"\bar x, \hat x, \check x, \grave x, \breve x, \acute x"#,
|
|
7
|
-
r#"\vec x, \dot x, \ddot x, \dddot x, \ddddot x"#,
|
|
7
|
+
r#"\vec x, \mathring x, \tilde x, \dot x, \ddot x, \dddot x, \ddddot x"#,
|
|
8
8
|
r#"x^*"#,
|
|
9
9
|
// Chrome bugs:
|
|
10
|
+
r#"\widehat x, \widehat{xxxx}"#,
|
|
10
11
|
r#"\widetilde x, \widetilde{xxxx}"#,
|
|
11
12
|
r#"\widecheck x, \widecheck{xxxx}"#,
|
|
12
13
|
r#"\overline x, \overline{xxxx}"#,
|
|
@@ -21,6 +22,7 @@ fn main() {
|
|
|
21
22
|
|
|
22
23
|
let converter = LatexToMathML::new(MathCoreConfig {
|
|
23
24
|
pretty_print: PrettyPrint::Always,
|
|
25
|
+
allow_unreliable_rendering: true,
|
|
24
26
|
..Default::default()
|
|
25
27
|
})
|
|
26
28
|
.unwrap();
|
|
@@ -18,7 +18,7 @@ fn main() {
|
|
|
18
18
|
r#"\overparen{x\times\cdots\times x}, \overparen{x\times\cdots\times x}^{n}, \underparen{x\times\cdots\times x}, \underparen{x\times\cdots\times x}_{n} ,
|
|
19
19
|
\overbracket{x\times\cdots\times x}, \overbracket{x\times\cdots\times x}^{n}, \underbracket{x\times\cdots\times x}, \underbracket{x\times\cdots\times x}_{n}"#,
|
|
20
20
|
r#"X \overset{f}{\rightarrow} Y \underset{g}{\rightarrow} Z , \ h \eqdef g \circ f"#,
|
|
21
|
-
r#"\overline{x + y} , \underline{x + y}, \widehat{x + y}, \
|
|
21
|
+
r#"\overline{x + y} , \underline{x + y}, \widehat{x + y}, \overrightarrow{A + B} , \overleftarrow{A + B}"#,
|
|
22
22
|
r#"\left. \frac{\pi}{2} \right\} \, \left( x \right) \, \left\{ \frac12 \right."#,
|
|
23
23
|
r#"\Biggl( \biggl( \Bigl( \bigl( ( ) \bigr) \Bigr) \biggr) \Biggr)"#,
|
|
24
24
|
r#"\mu \left( \bigcup_i E_i \right) = \sum_i \mu ( E_i )"#,
|
|
@@ -60,7 +60,7 @@ fn main() {
|
|
|
60
60
|
r#"\mathcal{C} \times \mathcal{Y}\times\mathcal{P}"#,
|
|
61
61
|
r"a := 2 \land b :\equiv 3 \land f : X\to Y",
|
|
62
62
|
r"f(x):=\begin{cases}0 &\text{if }x\geq 0\\1 &\text{otherwise}\end{cases}",
|
|
63
|
-
r"\oint_C \vec{B}\circ \mathrm{d}\vec{
|
|
63
|
+
r"\oint_C \vec{B}\circ \mathrm{d}\vec{\ell} = \mu_0 \left( I_{\mathrm{enc}} + \varepsilon_0 \frac{\mathrm{d}}{\mathrm{d}t} \int_S {\vec{E} \circ \hat{n}}\; \mathrm{d}a \right)",
|
|
64
64
|
];
|
|
65
65
|
|
|
66
66
|
let converter = LatexToMathML::new(MathCoreConfig {
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
use mathml_renderer::{
|
|
2
|
+
arena::Arena,
|
|
3
|
+
ast::Node,
|
|
4
|
+
attribute::{MathSpacing, OpAttrs, RowAttr, Style, TextTransform},
|
|
5
|
+
symbol::{self, MathMLOperator, OrdCategory, OrdLike, Rel, RelCategory},
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
|
9
|
+
pub enum Class {
|
|
10
|
+
/// `mathord`
|
|
11
|
+
#[default]
|
|
12
|
+
Default = 0,
|
|
13
|
+
/// `mathop`
|
|
14
|
+
Operator,
|
|
15
|
+
/// `mathbin`
|
|
16
|
+
BinaryOp,
|
|
17
|
+
/// `mathrel`
|
|
18
|
+
Relation,
|
|
19
|
+
/// `mathopen`
|
|
20
|
+
Open,
|
|
21
|
+
/// `mathclose`
|
|
22
|
+
Close,
|
|
23
|
+
/// `mathpunct`
|
|
24
|
+
Punctuation,
|
|
25
|
+
/// `mathinner`
|
|
26
|
+
Inner,
|
|
27
|
+
/// A class indicating the end of the current formula.
|
|
28
|
+
End,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
#[derive(Debug, Clone, Copy)]
|
|
32
|
+
pub enum ParenType {
|
|
33
|
+
Left = 1,
|
|
34
|
+
Right,
|
|
35
|
+
Middle,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/// <mi> mathvariant attribute
|
|
39
|
+
#[derive(Debug, Clone, Copy)]
|
|
40
|
+
pub enum MathVariant {
|
|
41
|
+
/// This is enforced by setting `mathvariant="normal"`.
|
|
42
|
+
Normal,
|
|
43
|
+
/// This is enforced by transforming the characters themselves.
|
|
44
|
+
Transform(TextTransform),
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
48
|
+
pub enum Stretchy {
|
|
49
|
+
/// The operator is always stretchy (e.g. `(`, `)`).
|
|
50
|
+
Always = 1,
|
|
51
|
+
/// The operator is only stretchy as a pre- or postfix operator (e.g. `|`).
|
|
52
|
+
PrePostfix,
|
|
53
|
+
/// The operator is never stretchy (e.g. `/`).
|
|
54
|
+
Never,
|
|
55
|
+
/// The operator is always stretchy but isn't symmetric (e.g. `↑`).
|
|
56
|
+
AlwaysAsymmetric,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
60
|
+
pub enum DelimiterSpacing {
|
|
61
|
+
/// Never has any spacing, even when used as an infix operator (e.g. `(`, `)`).
|
|
62
|
+
Zero,
|
|
63
|
+
/// Has relation spacing when used as an infix operator, but not when used as a prefix or
|
|
64
|
+
/// postfix operator (e.g. `|`).
|
|
65
|
+
InfixRelation,
|
|
66
|
+
/// Always has relation spacing, even when used as a prefix or postfix operator (e.g. `↑`).
|
|
67
|
+
Relation,
|
|
68
|
+
/// Always has some spacing, even when used as a prefix or postfix operator (e.g. `/`).
|
|
69
|
+
Other,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/// A stretchable operator.
|
|
73
|
+
///
|
|
74
|
+
/// It can be created from an `OrdLike` or a `Rel` if the operator is stretchable. This struct
|
|
75
|
+
/// carries all the information needed to know how to make the operator stretchy and how to set
|
|
76
|
+
/// spacing around it.
|
|
77
|
+
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
|
|
78
|
+
pub struct StretchableOp {
|
|
79
|
+
op: MathMLOperator,
|
|
80
|
+
pub stretchy: Stretchy,
|
|
81
|
+
pub spacing: DelimiterSpacing,
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
impl StretchableOp {
|
|
85
|
+
#[inline]
|
|
86
|
+
pub const fn as_op(self) -> MathMLOperator {
|
|
87
|
+
self.op
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/// Creates a `StretchableOp` from an `OrdLike` if it's stretchable. Returns `None` if the
|
|
91
|
+
/// operator isn't stretchable.
|
|
92
|
+
pub const fn from_ord(ord: OrdLike) -> Option<Self> {
|
|
93
|
+
let (stretchy, spacing) = match ord.category() {
|
|
94
|
+
OrdCategory::F | OrdCategory::G => (Stretchy::Always, DelimiterSpacing::Zero),
|
|
95
|
+
OrdCategory::FGandForceDefault => {
|
|
96
|
+
(Stretchy::PrePostfix, DelimiterSpacing::InfixRelation)
|
|
97
|
+
}
|
|
98
|
+
OrdCategory::K => (Stretchy::Never, DelimiterSpacing::Zero),
|
|
99
|
+
OrdCategory::KButUsedToBeB => (Stretchy::Never, DelimiterSpacing::Other),
|
|
100
|
+
OrdCategory::D | OrdCategory::E | OrdCategory::I | OrdCategory::IK => {
|
|
101
|
+
return None;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
Some(StretchableOp {
|
|
105
|
+
op: ord.as_op(),
|
|
106
|
+
stretchy,
|
|
107
|
+
spacing,
|
|
108
|
+
})
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/// Creates a `StretchableOp` from a `Rel` if it's stretchable. Returns `None` if the operator
|
|
112
|
+
/// isn't stretchable.
|
|
113
|
+
pub const fn from_rel(rel: Rel) -> Option<Self> {
|
|
114
|
+
match rel.category() {
|
|
115
|
+
RelCategory::A => Some(StretchableOp {
|
|
116
|
+
op: rel.as_op(),
|
|
117
|
+
stretchy: Stretchy::AlwaysAsymmetric,
|
|
118
|
+
spacing: DelimiterSpacing::Relation,
|
|
119
|
+
}),
|
|
120
|
+
RelCategory::Default => None,
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/// Creates a fenced expression where opening and closing delimiters are stretched to fit the height
|
|
126
|
+
/// of the content. If `open` or `close` is `None`, no delimiter will be rendered on that side.
|
|
127
|
+
pub fn fenced<'arena>(
|
|
128
|
+
arena: &'arena Arena,
|
|
129
|
+
mut content: Vec<&'arena Node<'arena>>,
|
|
130
|
+
open: Option<StretchableOp>,
|
|
131
|
+
close: Option<StretchableOp>,
|
|
132
|
+
style: Option<Style>,
|
|
133
|
+
) -> Node<'arena> {
|
|
134
|
+
fn to_operator(delim: Option<StretchableOp>) -> Node<'static> {
|
|
135
|
+
if let Some(op) = delim {
|
|
136
|
+
let attrs = if matches!(op.stretchy, Stretchy::Never) {
|
|
137
|
+
OpAttrs::STRETCHY_TRUE
|
|
138
|
+
} else {
|
|
139
|
+
OpAttrs::empty()
|
|
140
|
+
};
|
|
141
|
+
let (left, right) = if matches!(
|
|
142
|
+
op.spacing,
|
|
143
|
+
DelimiterSpacing::Relation | DelimiterSpacing::Other
|
|
144
|
+
) {
|
|
145
|
+
(Some(MathSpacing::Zero), Some(MathSpacing::Zero))
|
|
146
|
+
} else {
|
|
147
|
+
(None, None)
|
|
148
|
+
};
|
|
149
|
+
Node::Operator {
|
|
150
|
+
op: op.as_op(),
|
|
151
|
+
attrs,
|
|
152
|
+
size: None,
|
|
153
|
+
left,
|
|
154
|
+
right,
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
// An empty `<mo></mo>` produces weird spacing in some browsers.
|
|
158
|
+
// Use U+2063 (INVISIBLE SEPARATOR) to work around this. It's in Category K in MathML Core.
|
|
159
|
+
Node::Operator {
|
|
160
|
+
op: const { symbol::INVISIBLE_SEPARATOR.as_op() },
|
|
161
|
+
attrs: OpAttrs::empty(),
|
|
162
|
+
size: None,
|
|
163
|
+
left: None,
|
|
164
|
+
right: None,
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
let open = arena.push(to_operator(open));
|
|
169
|
+
let close = arena.push(to_operator(close));
|
|
170
|
+
content.insert(0, open);
|
|
171
|
+
content.push(close);
|
|
172
|
+
let nodes = arena.push_slice(&content);
|
|
173
|
+
Node::Row {
|
|
174
|
+
nodes,
|
|
175
|
+
attr: style.map(RowAttr::Style),
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
#[cfg(test)]
|
|
180
|
+
mod tests {
|
|
181
|
+
use super::{MathVariant, TextTransform};
|
|
182
|
+
|
|
183
|
+
#[test]
|
|
184
|
+
fn size_test() {
|
|
185
|
+
assert_eq!(
|
|
186
|
+
std::mem::size_of::<MathVariant>(),
|
|
187
|
+
std::mem::size_of::<TextTransform>()
|
|
188
|
+
);
|
|
189
|
+
assert_eq!(
|
|
190
|
+
std::mem::size_of::<Option<MathVariant>>(),
|
|
191
|
+
std::mem::size_of::<TextTransform>()
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
}
|