Skip to content
This repository has been archived by the owner on Jan 17, 2025. It is now read-only.

Commit

Permalink
Fix Python result console
Browse files Browse the repository at this point in the history
  • Loading branch information
bclswl0827 committed Feb 4, 2024
1 parent 890d94d commit 6e744e7
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 20 deletions.
26 changes: 24 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "chatgemini",
"version": "0.5.1",
"version": "0.5.2",
"homepage": ".",
"private": true,
"dependencies": {
Expand All @@ -12,6 +12,7 @@
"crypto-js": "^4.2.0",
"file-saver": "^2.0.5",
"localforage": "^1.10.0",
"lodash.isequal": "^4.5.0",
"node-fetch": "^2.7.0",
"pyodide": "^0.23.4",
"react": "^18.2.0",
Expand Down Expand Up @@ -53,6 +54,7 @@
"@tailwindcss/typography": "^0.5.10",
"@types/crypto-js": "^4.2.2",
"@types/file-saver": "^2.0.7",
"@types/lodash.isequal": "^4.5.8",
"@types/node": "^16.18.76",
"@types/react": "^18.2.48",
"@types/react-dom": "^18.2.18",
Expand Down
57 changes: 40 additions & 17 deletions src/components/Markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import userThrottle from "../helpers/userThrottle";
import { useEffect, useState } from "react";
import { loadPyodide } from "pyodide";
import userDebounce from "../helpers/userDebounce";
import { Position } from "unist";
import isEqual from "lodash.isequal";

interface MarkdownProps {
readonly className?: string;
Expand All @@ -21,7 +23,10 @@ interface MarkdownProps {
export const Markdown = (props: MarkdownProps) => {
const { className, typingEffect, children } = props;

const [executeResult, setExecuteResult] = useState("");
const [executeResult, setExecuteResult] = useState<{
result: string;
position: Position | null;
}>({ result: "", position: null });

const handleCopyCode = userThrottle(
async (code: string, currentTarget: EventTarget) => {
Expand All @@ -38,27 +43,39 @@ export const Markdown = (props: MarkdownProps) => {
);

const handleExecuteCode = userDebounce(
async (code: string, currentTarget: EventTarget) => {
async (
position: Position | null,
code: string,
currentTarget: EventTarget
) => {
const innerText = (currentTarget as HTMLButtonElement).innerText;
try {
(currentTarget as HTMLButtonElement).innerText = "正在执行";
(currentTarget as HTMLButtonElement).disabled = true;
setExecuteResult("# 正在加载资源");
setExecuteResult({ result: "# 正在加载资源", position });
const pyodide = await loadPyodide({
indexURL: `${window.location.pathname}pyodide/`,
stdout: (x: string) => setExecuteResult(`# stdout\n${x}`),
stderr: (x: string) => setExecuteResult(`# stderr\n${x}`),
stdout: (x: string) =>
setExecuteResult({
result: `# stdout\n${x}`,
position,
}),
stderr: (x: string) =>
setExecuteResult({
result: `# stderr\n${x}`,
position,
}),
});
await pyodide.runPythonAsync(`
from js import prompt
def input(p):
return prompt(p)
__builtins__.input = input
`);
setExecuteResult("# 正在执行代码");
setExecuteResult({ result: "# 正在执行代码", position });
await pyodide.runPythonAsync(code);
} catch (e) {
setExecuteResult(`# 运行失败\n${e}`);
setExecuteResult({ result: `# 执行失败\n${e}`, position });
}
(currentTarget as HTMLButtonElement).innerText = innerText;
(currentTarget as HTMLButtonElement).disabled = false;
Expand All @@ -67,7 +84,7 @@ __builtins__.input = input
);

useEffect(() => {
setExecuteResult("");
setExecuteResult({ result: "", position: null });
}, [children]);

return (
Expand All @@ -90,13 +107,14 @@ __builtins__.input = input
pre: ({ node, ...props }) => (
<pre className="bg-transparent p-2" {...props} />
),
code: ({ className, children }) => {
code: ({ className, children, node }) => {
const typeEffectPlaceholder = "❚";
const match = /language-(\w+)/.exec(className ?? "");
const lang = match !== null ? match[1] : "";
const code = (
!!children ? String(children) : typeEffectPlaceholder
).replace(typingEffect, typeEffectPlaceholder);
const position = node?.position ?? null;
return match ? (
<>
<Prism
Expand All @@ -120,6 +138,7 @@ __builtins__.input = input
className="text-gray-700/100 text-xs hover:opacity-50"
onClick={({ currentTarget }) =>
handleExecuteCode(
position,
code,
currentTarget
)
Expand All @@ -129,14 +148,18 @@ __builtins__.input = input
</button>
)}
</div>
{!!executeResult.length && (
<Prism
PreTag={"div"}
style={style}
language={"python"}
children={executeResult.replace(/\n$/, "")}
/>
)}
{isEqual(executeResult.position, position) &&
!!executeResult.result.length && (
<Prism
PreTag={"div"}
style={style}
language={"python"}
children={executeResult.result.replace(
/\n$/,
""
)}
/>
)}
</>
) : (
<code className="text-gray-700">
Expand Down

0 comments on commit 6e744e7

Please sign in to comment.