Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/util/latex-envs.ts
5878 views
1
/*
2
Limited support for some latex environments, only for rendering (not editing).
3
*/
4
5
export default function latexEnvs(value: string): string {
6
value = transformFigures(value);
7
value = transformItemEnvironments(value);
8
return value;
9
}
10
11
/*
12
transformFigures -- simple parser to turn this:
13
14
---
15
16
...
17
18
\begin{figure}
19
\centering
20
\centerline{\includegraphics[width=WIDTH]{URL}}
21
\caption{\label{foo}CAPTION}
22
\end{figure}
23
24
...
25
26
---
27
28
into this:
29
30
---
31
32
...
33
34
<div style="text-align:center"><img src="URL" style="width:WIDTH"/><br/><br/>\figlabel{foo}CAPTION</div>
35
36
37
...
38
39
---
40
41
There can be lots of figures.
42
*/
43
44
function transformFigures(content: string): string {
45
while (true) {
46
const i = content.indexOf("\\begin{figure}");
47
if (i == -1) {
48
return content;
49
}
50
const j = content.indexOf("\\end{figure}");
51
if (j == -1) {
52
return content;
53
}
54
const k = content.indexOf("\\includegraphics");
55
if (k == -1) {
56
return content;
57
}
58
const c = content.indexOf("\\caption{");
59
if (c == -1) {
60
return content;
61
}
62
const c2 = content.lastIndexOf("}", j);
63
if (c2 == -1) {
64
return content;
65
}
66
67
const w = content.indexOf("width=");
68
const w2 = content.indexOf("{", k);
69
const w3 = content.indexOf("}", k);
70
if (w2 == -1 || w3 == -1) {
71
return content;
72
}
73
let style = "";
74
if (w != -1) {
75
style = `width:${content.slice(w + "width=".length, w2 - 1)}`;
76
}
77
const url = content.slice(w2 + 1, w3);
78
let caption = content.slice(c + "\\caption{".length, c2);
79
const x = caption.indexOf("\\label{");
80
let figlabel;
81
if (x != -1) {
82
const y = caption.indexOf("}", x);
83
figlabel = `\\figlabel{${caption.slice(x + "\\label{".length, y)}}`;
84
caption = caption.slice(0, x) + caption.slice(y + 1);
85
} else {
86
figlabel = "";
87
}
88
89
const md = `\n\n<div style="text-align:center;margin:20px auto;max-width:750px"><img src="${url}" style="${style}"/><br/><br/><b>Figure${figlabel}:</b> ${caption}</div>\n\n`;
90
//const md = `\n\n<img src="${url}" style="${style}"/>\n\n**Figure${figlabel}:** ${caption}\n\n`;
91
content =
92
content.slice(0, i) + md + content.slice(j + "\\end{figure}".length);
93
}
94
}
95
96
/*
97
transformEnumerate -- dumb parser to turn this:
98
99
---
100
101
...
102
103
\begin{enumerate}
104
\item ITEM1
105
\item ITEM2
106
...
107
\end{enumerate}
108
109
...
110
111
---
112
113
into this:
114
115
---
116
117
...
118
119
1. ITEM1
120
121
1. ITEM2
122
123
...
124
125
---
126
127
and
128
129
---
130
131
\begin{itemize}
132
\item ITEM1
133
\item ITEM2
134
...
135
\end{itemize}
136
137
into
138
139
- ITEM1
140
141
- ITEM2
142
143
*/
144
145
function transformItemEnvironments(content: string) {
146
for (const type of ["itemize", "enumerate"]) {
147
content = transformItemsType(content, type as "itemize" | "enumerate");
148
}
149
return content;
150
}
151
152
function transformItemsType(
153
content: string,
154
type: "itemize" | "enumerate",
155
): string {
156
while (true) {
157
const BEGIN = `\\begin{${type}}`;
158
const i = content.indexOf(BEGIN);
159
if (i == -1) {
160
return content;
161
}
162
const END = `\\end{${type}}`;
163
const j = content.indexOf(END);
164
if (j == -1) {
165
return content;
166
}
167
168
const body = content.slice(i + BEGIN.length + 1, j);
169
const items = body
170
.split("\\item")
171
.filter((x) => x.trim())
172
.map((x) => (type == "itemize" ? "- " : "1. ") + x)
173
.join("\n\n");
174
content =
175
content.slice(0, i) +
176
"\n\n" +
177
items +
178
"\n\n" +
179
content.slice(j + END.length + 1);
180
}
181
return content;
182
}
183
184