Skip to content

Commit ce6dff9

Browse files
committed
Update index.html to disable submit button by default and load mathlive from CDN; refactor fetch method in index.ts for improved error handling and response structure
1 parent f7f2656 commit ce6dff9

File tree

3 files changed

+91
-164
lines changed

3 files changed

+91
-164
lines changed

public/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@ <h3>Math solver</h3>
3333
<option value="en">English</option>
3434
<option value="zh">Chinese</option>
3535
</select>
36-
<button type="button" id="SubmitButton" class="btn btn-sm btn-primary">Submit</button>
36+
<button type="button" id="SubmitButton" class="btn btn-sm btn-primary" disabled>Submit</button>
3737
</div>
3838
</div>
3939
</div>
4040
<div id="SimpleResult"></div>
4141
<div id="FullResult" class="accordion"></div>
4242
</div>
4343
<script src="index.js"></script>
44-
<script src="mathlive/dist/mathlive.min.js"></script>
44+
<script src="https://unpkg.com/mathlive"></script>
4545
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/js/bootstrap.min.js"
4646
integrity="sha512-ykZ1QQr0Jy/4ZkvKuqWn4iF3lqPZyij9iRv6sGqLRdTPkY69YX6+7wvVGmsdBbiIfN/8OdsI7HABjvEok6ZopQ=="
4747
crossorigin="anonymous" referrerpolicy="no-referrer"></script>

public/index.js

Lines changed: 65 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,6 @@ const SubmitButton = document.getElementById("SubmitButton");
44
const SimpleResult = document.getElementById("SimpleResult");
55
const FullResult = document.getElementById("FullResult");
66

7-
const UTF8ToBase64 = (UTF8String) => {
8-
return btoa(unescape(encodeURIComponent(UTF8String)));
9-
}
10-
const SetTheme = (Theme) => {
11-
if (Theme === "dark") {
12-
document.body.dataset.bsTheme = "dark";
13-
}
14-
else if (Theme === "light") {
15-
document.body.dataset.bsTheme = "light";
16-
}
17-
localStorage.setItem("Theme", Theme);
18-
};
197
const SetLanguage = (Language) => {
208
LanguageSelect.value = Language;
219
localStorage.setItem("Language", Language);
@@ -35,110 +23,29 @@ const RemoveLoadingSpinner = (Element) => {
3523
const RequestAPI = async (Endpoint, Data) => {
3624
const Result = await fetch("/" + Endpoint, {
3725
method: "POST",
38-
headers: {
39-
"Content-Type": "application/json",
40-
},
26+
headers: { "Content-Type": "application/json", },
4127
body: JSON.stringify(Data),
4228
});
4329
const JSONResult = await Result.json();
44-
if (!JSONResult.Success) {
45-
console.log(JSONResult.Error);
46-
alert(JSONResult.Error);
47-
}
30+
if (!JSONResult.Success) { throw new Error(JSONResult.Error); }
4831
return JSONResult.Data;
4932
};
50-
const SolveSimpleLatex = (LatexExpression, Language) => {
51-
AddLoadingSpinner(SimpleResult);
52-
RequestAPI("SolveSimpleLatex", { LatexExpression, Language })
53-
.then(Result => {
54-
RemoveLoadingSpinner(SimpleResult);
55-
SimpleResult.innerHTML = "$$" + Result + "$$";
56-
MathJax.typesetPromise();
57-
});
58-
};
59-
const SolveLatex = (LatexExpression, Language) => {
60-
SimpleResult.innerHTML = "";
61-
AddLoadingSpinner(FullResult);
62-
RequestAPI("SolveLatex", { LatexExpression, Language })
63-
.then(Result => {
64-
RemoveLoadingSpinner(FullResult);
65-
FullResult.innerHTML = "";
66-
Result.forEach(Item => {
67-
const AccordionItem = document.createElement("div");
68-
AccordionItem.className = "accordion-item";
69-
const AccordionHeader = document.createElement("h2");
70-
AccordionHeader.className = "accordion-header";
71-
const AccordionButton = document.createElement("button");
72-
AccordionButton.className = "accordion-button";
73-
AccordionButton.type = "button";
74-
AccordionButton.setAttribute("data-bs-toggle", "collapse");
75-
AccordionButton.setAttribute("data-bs-target", `#collapse${UTF8ToBase64(Item.Name)}`);
76-
AccordionButton.innerHTML = Item.Name;
77-
const AccordionCollapse = document.createElement("div");
78-
AccordionCollapse.id = `collapse${UTF8ToBase64(Item.Name)}`;
79-
AccordionCollapse.className = "accordion-collapse collapse show";
80-
const AccordionBody = document.createElement("div");
81-
AccordionBody.className = "accordion-body";
82-
const AccordionBodyText = document.createElement("p");
83-
AccordionBodyText.classList.add("mb-2");
84-
AccordionBodyText.innerHTML = Item.Answer;
85-
AccordionBody.appendChild(AccordionBodyText);
86-
const TemplateAccordion = document.createElement("div");
87-
TemplateAccordion.className = "accordion";
88-
Item.TemplateSteps.forEach(TemplateSteps => {
89-
const TemplateAccordionItem = document.createElement("div");
90-
TemplateAccordionItem.className = "accordion-item";
91-
const TemplateStepsHeader = document.createElement("div");
92-
TemplateStepsHeader.className = "accordion-header";
93-
const TemplateStepsButton = document.createElement("button");
94-
TemplateStepsButton.className = "accordion-button collapsed";
95-
TemplateStepsButton.type = "button";
96-
TemplateStepsButton.setAttribute("data-bs-toggle", "collapse");
97-
TemplateStepsButton.setAttribute("data-bs-target", `#collapse${UTF8ToBase64(TemplateSteps.Name)}`);
98-
TemplateStepsButton.innerHTML = TemplateSteps.Name;
99-
TemplateStepsHeader.appendChild(TemplateStepsButton);
100-
const TemplateStepsCollapse = document.createElement("div");
101-
TemplateStepsCollapse.id = `collapse${UTF8ToBase64(TemplateSteps.Name)}`;
102-
TemplateStepsCollapse.className = "accordion-collapse collapse";
103-
const TemplateStepsBody = document.createElement("div");
104-
TemplateStepsBody.className = "accordion-body";
105-
TemplateSteps.Steps.forEach(Step => {
106-
const Card = document.createElement("div");
107-
Card.className = "card mb-2";
108-
const CardBody = document.createElement("div");
109-
CardBody.className = "card-body";
110-
const CardTitle = document.createElement("h5");
111-
CardTitle.className = "card-title";
112-
CardTitle.innerHTML = Step.Hint;
113-
const CardText = document.createElement("p");
114-
CardText.className = "card-text";
115-
CardText.innerHTML = Step.Step;
116-
const CardFooter = document.createElement("div");
117-
CardFooter.className = "card-footer";
118-
const CardFooterText = document.createElement("small");
119-
CardFooterText.className = "text-muted";
120-
CardFooterText.innerHTML = Step.Expression;
121-
CardBody.appendChild(CardTitle);
122-
CardBody.appendChild(CardText);
123-
CardFooter.appendChild(CardFooterText);
124-
Card.appendChild(CardBody);
125-
Card.appendChild(CardFooter);
126-
TemplateStepsBody.appendChild(Card);
127-
});
128-
TemplateStepsCollapse.appendChild(TemplateStepsBody);
129-
TemplateAccordionItem.appendChild(TemplateStepsHeader);
130-
TemplateAccordionItem.appendChild(TemplateStepsCollapse);
131-
TemplateAccordion.appendChild(TemplateAccordionItem);
132-
});
133-
AccordionBody.appendChild(TemplateAccordion);
134-
AccordionCollapse.appendChild(AccordionBody);
135-
AccordionHeader.appendChild(AccordionButton);
136-
AccordionItem.appendChild(AccordionHeader);
137-
AccordionItem.appendChild(AccordionCollapse);
138-
FullResult.appendChild(AccordionItem);
139-
});
140-
MathJax.typesetPromise();
141-
});
33+
const createAccordionItem = (name, content, isCollapsed = false) => {
34+
const UTF8ToBase64 = (UTF8String) => { return btoa(unescape(encodeURIComponent(UTF8String))); }
35+
return `
36+
<div class="accordion-item">
37+
<h2 class="accordion-header">
38+
<button class="accordion-button ${isCollapsed ? "collapsed" : ""}" type="button" data-bs-toggle="collapse" data-bs-target="#collapse${UTF8ToBase64(name)}">
39+
${name}
40+
</button>
41+
</h2>
42+
<div id="collapse${UTF8ToBase64(name)}" class="accordion-collapse collapse ${isCollapsed ? "" : "show"}">
43+
<div class="accordion-body">
44+
${content}
45+
</div>
46+
</div>
47+
</div>
48+
`;
14249
};
14350

14451
MathJax = {
@@ -161,26 +68,58 @@ MathJax = {
16168
},
16269
};
16370

164-
LanguageSelect.addEventListener("change", () => {
165-
SetLanguage(LanguageSelect.value);
166-
});
71+
LanguageSelect.addEventListener("change", () => { SetLanguage(LanguageSelect.value); });
16772
LatexInput.addEventListener("input", () => {
168-
SimpleResult.innerHTML = "";
169-
FullResult.innerHTML = "";
73+
SubmitButton.disabled = LatexInput.value == "";
17074
if (LatexInput.value != "") {
171-
SolveSimpleLatex(LatexInput.value, LanguageSelect.value);
75+
SimpleResult.innerHTML = FullResult.innerHTML = "";
76+
AddLoadingSpinner(SimpleResult);
77+
RequestAPI("SolveSimpleLatex", {
78+
LatexExpression: LatexInput.value,
79+
Language: LanguageSelect.value
80+
}).then(Result => {
81+
SimpleResult.innerHTML = "$$" + Result + "$$";
82+
MathJax.typesetPromise();
83+
}).catch(error => {
84+
SimpleResult.innerHTML = error;
85+
}).finally(() => {
86+
RemoveLoadingSpinner(SimpleResult);
87+
});
17288
}
17389
});
17490
SubmitButton.addEventListener("click", () => {
175-
SimpleResult.innerHTML = "";
176-
FullResult.innerHTML = "";
177-
SubmitButton.disabled = true;
178-
AddLoadingSpinner(SubmitButton);
179-
SolveSimpleLatex(LatexInput.value, LanguageSelect.value);
180-
SolveLatex(LatexInput.value, LanguageSelect.value);
181-
SubmitButton.disabled = false;
182-
RemoveLoadingSpinner(SubmitButton);
91+
SimpleResult.innerHTML = FullResult.innerHTML = "";
92+
AddLoadingSpinner(FullResult);
93+
RequestAPI("SolveLatex", {
94+
LatexExpression: LatexInput.value,
95+
Language: LanguageSelect.value
96+
}).then(Result => {
97+
FullResult.innerHTML = Result.map(Item =>
98+
createAccordionItem(Item.Name, `<p class="mb-2">${Item.Answer}</p>` +
99+
Item.TemplateSteps.map(templateStep =>
100+
createAccordionItem(templateStep.Name, templateStep.Steps.map((step) =>
101+
`
102+
<div class="card mb-2">
103+
<div class="card-body">
104+
<h5 class="card-title">${step.Hint}</h5>
105+
<div>${step.Expression}</div>
106+
</div>
107+
<div class="card-footer">
108+
${step.Step}
109+
</div>
110+
</div>
111+
`
112+
).join(""), true)
113+
).join("")
114+
)
115+
).join("");
116+
MathJax.typesetPromise();
117+
}).catch(error => {
118+
FullResult.innerHTML = error;
119+
}).finally(() => {
120+
RemoveLoadingSpinner(FullResult);
121+
});
183122
});
184123

185-
SetTheme(localStorage.getItem("Theme") || (window.matchMedia("(prefers-color-scheme: dark)").matches) ? "dark" : "light");
124+
document.body.dataset.bsTheme = ((window.matchMedia("(prefers-color-scheme: dark)").matches) ? "dark" : "light");
186125
SetLanguage(localStorage.getItem("Language") || navigator.language.split("-")[0] || "en");

src/index.ts

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -85,46 +85,34 @@ export default {
8585
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
8686
const { method } = request;
8787
const path = new URL(request.url).pathname;
88-
if (method === "GET") {
89-
if (path.startsWith("/mathlive/")) {
90-
const url = new URL(request.url);
91-
url.host = "unpkg.com";
92-
url.port = "80";
93-
console.log(url.toString());
94-
return fetch(url.toString());
95-
} else {
96-
return new Response("Not found", { status: 404 });
88+
if (method !== "POST") { return new Response("Method not allowed", { status: 405 }); }
89+
var Result = {
90+
Success: true,
91+
Error: "",
92+
Data: {},
93+
};
94+
try {
95+
const { LatexExpression, Language } = await request.json();
96+
if (!LatexExpression) {
97+
Result.Success = false;
98+
Result.Error = "Please provide a latex expression";
9799
}
98-
} else if (method === "POST") {
99-
var Result = {
100-
"Success": true,
101-
"Error": "",
102-
"Data": {},
103-
};
104-
try {
105-
const { LatexExpression, Language } = await request.json();
106-
if (!LatexExpression) {
107-
Result.Success = false;
108-
Result.Error = "Please provide a latex expression";
109-
}
110-
if (path === "/SolveLatex") {
111-
Result.Data = await SolveMathProblem(LatexExpression, Language || "en");
112-
}
113-
else if (path === "/SolveSimpleLatex") {
114-
Result.Data = await SolveSimple(LatexExpression, Language || "en");
115-
}
116-
else {
117-
Result.Success = false;
118-
Result.Error = "Not found";
119-
}
120-
console.log(Result);
100+
if (path === "/SolveLatex") {
101+
Result.Data = await SolveMathProblem(LatexExpression, Language || "en");
121102
}
122-
catch (ErrorDetail) {
103+
else if (path === "/SolveSimpleLatex") {
104+
Result.Data = await SolveSimple(LatexExpression, Language || "en");
105+
}
106+
else {
123107
Result.Success = false;
124-
Result.Error = ErrorDetail;
108+
Result.Error = "Not found";
125109
}
126-
return new Response(JSON.stringify(Result), { status: 200, headers: { "Content-Type": "application/json" } });
110+
console.log(Result);
111+
}
112+
catch (ErrorDetail) {
113+
Result.Success = false;
114+
Result.Error = (ErrorDetail as Error).message;
127115
}
128-
return new Response("Method not allowed", { status: 405 });
116+
return new Response(JSON.stringify(Result), { headers: { "Content-Type": "application/json" } });
129117
},
130118
};

0 commit comments

Comments
 (0)