Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/editors/slate/elements/math/index.tsx
1698 views
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import React from "react";
7
import { Element } from "slate";
8
import { register, RenderElementProps, SlateElement } from "../register";
9
import { useFileContext } from "@cocalc/frontend/lib/file-context";
10
import DefaultMath from "@cocalc/frontend/components/math/ssr";
11
12
export interface DisplayMath extends SlateElement {
13
type: "math_block";
14
value: string;
15
isVoid: true;
16
}
17
18
export interface InlineMath extends SlateElement {
19
type: "math_inline";
20
value: string;
21
display?: boolean; // inline but acts as displayed math
22
isVoid: true;
23
isInline: true;
24
}
25
26
export const StaticElement: React.FC<RenderElementProps> = ({
27
attributes,
28
element,
29
}) => {
30
const { MathComponent } = useFileContext();
31
if (element.type != "math_block" && element.type != "math_inline") {
32
// type guard.
33
throw Error("bug");
34
}
35
const C = MathComponent ?? DefaultMath;
36
return (
37
<span {...attributes}>
38
<C
39
data={wrap(
40
element.value,
41
element.type == "math_inline" && !element.display
42
)}
43
inMarkdown
44
/>
45
</span>
46
);
47
};
48
49
function wrap(math, isInline) {
50
math = "$" + math + "$";
51
if (!isInline) {
52
math = "$" + math + "$";
53
}
54
return math;
55
}
56
57
register({
58
slateType: ["math_inline", "math_inline_double"],
59
StaticElement,
60
toSlate: ({ token }) => {
61
return {
62
type: "math_inline",
63
value: stripMathEnvironment(token.content),
64
isVoid: true,
65
isInline: true,
66
children: [{ text: "" }],
67
display: token.type == "math_inline_double",
68
} as Element;
69
},
70
});
71
72
export function toDisplayMath({ token }) {
73
return {
74
type: "math_block",
75
value: stripMathEnvironment(token.content).trim(),
76
isVoid: true,
77
children: [{ text: "" }],
78
} as Element;
79
}
80
81
register({
82
slateType: ["math_block", "math_block_eqno"],
83
StaticElement,
84
toSlate: toDisplayMath,
85
});
86
87
export function stripMathEnvironment(s: string): string {
88
// These environments get detected, but we must remove them, since once in
89
// math mode they make no sense. All the other environments do make sense.
90
for (const env of ["math", "displaymath"]) {
91
if (s.startsWith(`\\begin{${env}}`)) {
92
return s.slice(
93
`\\begin{${env}}`.length,
94
s.length - `\\end{${env}}`.length
95
);
96
}
97
}
98
return s;
99
}
100
101