Skip to content

Commit ad343ea

Browse files
authored
Merge pull request #173 from ut-code/runtime-workspace
runtimeをworkspaceに & テストを追加
2 parents 9dfc353 + 032f1d9 commit ad343ea

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+16470
-9407
lines changed

.github/workflows/jseval-tests.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: jsEval Tests CI
2+
on:
3+
pull_request:
4+
paths:
5+
- 'packages/jsEval/**'
6+
- '.github/workflows/jseval-tests.yml'
7+
jobs:
8+
test-js-eval:
9+
runs-on: ubuntu-latest
10+
strategy:
11+
matrix:
12+
node-version: [22.x]
13+
steps:
14+
- uses: actions/checkout@v4
15+
- uses: actions/setup-node@v4
16+
with:
17+
node-version: ${{ matrix.node-version }}
18+
cache: 'npm'
19+
- run: npm ci
20+
- run: npm test -w @my-code/js-eval

.github/workflows/node.js.yml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,3 @@ jobs:
4646
cache: 'npm'
4747
- run: npm ci
4848
- run: npm run checkDocs
49-
50-
test-js-eval:
51-
runs-on: ubuntu-latest
52-
strategy:
53-
matrix:
54-
node-version: [22.x]
55-
steps:
56-
- uses: actions/checkout@v4
57-
- uses: actions/setup-node@v4
58-
with:
59-
node-version: ${{ matrix.node-version }}
60-
cache: 'npm'
61-
- run: npm ci
62-
- run: npm test --workspace=packages/jsEval
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: Runtime Tests CI
2+
on:
3+
pull_request:
4+
paths:
5+
- 'packages/runtime/**'
6+
- '.github/workflows/runtime-tests.yml'
7+
jobs:
8+
test-runtime:
9+
runs-on: ubuntu-latest
10+
strategy:
11+
matrix:
12+
node-version: [22.x]
13+
steps:
14+
- uses: actions/checkout@v4
15+
- uses: actions/setup-node@v4
16+
with:
17+
node-version: ${{ matrix.node-version }}
18+
cache: 'npm'
19+
- run: npm ci
20+
- run: npm test -w @my-code/runtime

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,4 @@ next-env.d.ts
5050

5151
/public/typescript/
5252
/app/m-plus-rounded-1c-nohint/
53+
node_modules

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ WORKDIR /app
66

77
COPY package.json package-lock.json ./
88
COPY packages/jsEval/package.json ./packages/jsEval/
9+
COPY packages/runtime/package.json ./packages/runtime/
910

1011
RUN --mount=type=cache,target=/root/.npm \
1112
npm ci --no-audit --no-fund

README.md

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ npm run checkDocs
173173

174174
## markdown仕様
175175

176+
実行環境の説明は ./packages/runtime/README.md を参照
177+
176178
````
177179
```言語名-repl
178180
>>> コマンド
@@ -181,10 +183,7 @@ npm run checkDocs
181183
````
182184

183185
でターミナルを埋め込む。
184-
* ターミナル表示部は app/terminal/terminal.tsx
185-
* コマンド入力処理は app/terminal/repl.tsx
186-
* 各言語の実行環境は app/terminal/言語名/ 内に書く。
187-
* 実行結果はSectionContextにも送られ、section.tsxからアクセスできる
186+
* 実行結果はEmbedContextにも送られ、チャットフォームが参照できる
188187

189188
````
190189
```言語名:ファイル名
@@ -193,13 +192,12 @@ npm run checkDocs
193192
````
194193

195194
でテキストエディターを埋め込む。
196-
* app/terminal/editor.tsx
197-
* editor.tsx内で `import "ace-builds/src-min-noconflict/mode-言語名";` を追加すればその言語に対応した色付けがされる。
195+
* app/terminal/editor.tsx内で `import "ace-builds/src-min-noconflict/mode-言語名";` を追加し、packages/runtime/src/languages.tsにも追加すればその言語に対応した色付けがされる。
198196
* importできる言語の一覧は https://github.com/ajaxorg/ace-builds/tree/master/src-noconflict
199197
* 編集した内容は app/terminal/file.tsx のFileContextで管理される。
200198
* 編集中のコードはFileContextに即時送られる
201199
* FileContextが書き換えられたら即時すべてのエディターに反映される
202-
* 編集したファイルの一覧はSectionContextにも送られ、section.tsxからアクセスできる
200+
* 編集したファイルの一覧はEmbedContextにも送られ、チャットフォームが参照できる
203201

204202
````
205203
```言語名-readonly:ファイル名
@@ -217,8 +215,7 @@ npm run checkDocs
217215

218216
で実行ボタンを表示する
219217
* 実行ボタンを押した際にFileContextからファイルを読み、実行し、結果を表示する
220-
* app/terminal/exec.tsx に各言語ごとの実装を書く (それぞれ app/terminal/言語名/ 内に定義した関数を呼び出す)
221-
* 実行結果はSectionContextにも送られ、section.tsxからアクセスできる
218+
* 実行結果はEmbedContextにも送られ、チャットフォームが参照できる
222219

223220

224221
## 技術スタック・ドキュメント・メモ

app/[lang]/[pageId]/markdown.tsx

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,12 @@ import Markdown, { Components, ExtraProps } from "react-markdown";
22
import remarkGfm from "remark-gfm";
33
import removeComments from "remark-remove-comments";
44
import remarkCjkFriendly from "remark-cjk-friendly";
5-
import { EditorComponent, getAceLang } from "@/terminal/editor";
5+
import { EditorComponent } from "@/terminal/editor";
66
import { ExecFile } from "@/terminal/exec";
77
import { JSX, ReactNode } from "react";
8-
import { getRuntimeLang } from "@/terminal/runtime";
8+
import { langConstants, MarkdownLang } from "@my-code/runtime/languages";
99
import { ReplTerminal } from "@/terminal/repl";
10-
import {
11-
getSyntaxHighlighterLang,
12-
MarkdownLang,
13-
StyledSyntaxHighlighter,
14-
} from "./styledSyntaxHighlighter";
10+
import { StyledSyntaxHighlighter } from "./styledSyntaxHighlighter";
1511

1612
export function StyledMarkdown({ content }: { content: string }) {
1713
return (
@@ -93,7 +89,7 @@ function CodeComponent({
9389
className || ""
9490
);
9591
if (match) {
96-
const runtimeLang = getRuntimeLang(match[1] as MarkdownLang | undefined);
92+
const language = langConstants(match[1] as MarkdownLang | undefined);
9793
if (match[2] === "-exec" && match[3]) {
9894
/*
9995
```python-exec:main.py
@@ -105,10 +101,10 @@ function CodeComponent({
105101
hello, world!
106102
---------------------------
107103
*/
108-
if (runtimeLang) {
104+
if (language.runtime) {
109105
return (
110106
<ExecFile
111-
language={runtimeLang}
107+
language={language}
112108
filenames={match[3].split(",")}
113109
content={String(props.children || "").replace(/\n$/, "")}
114110
/>
@@ -121,39 +117,35 @@ function CodeComponent({
121117
`${match[1]}-repl without terminal id! content: ${String(props.children).slice(0, 20)}...`
122118
);
123119
}
124-
if (runtimeLang) {
120+
if (language.runtime) {
125121
return (
126122
<ReplTerminal
127123
terminalId={match[3]}
128-
language={runtimeLang}
124+
language={language}
129125
initContent={String(props.children || "").replace(/\n$/, "")}
130126
/>
131127
);
132128
}
133129
} else if (match[3]) {
134130
// ファイル名指定がある場合、ファイルエディター
135-
const aceLang = getAceLang(match[1] as MarkdownLang | undefined);
136131
return (
137132
<EditorComponent
138-
language={aceLang}
133+
language={language}
139134
filename={match[3]}
140135
readonly={match[2] === "-readonly"}
141136
initContent={String(props.children || "").replace(/\n$/, "")}
142137
/>
143138
);
144139
}
145-
const syntaxHighlighterLang = getSyntaxHighlighterLang(
146-
match[1] as MarkdownLang | undefined
147-
);
148140
return (
149-
<StyledSyntaxHighlighter language={syntaxHighlighterLang}>
141+
<StyledSyntaxHighlighter language={language}>
150142
{String(props.children || "").replace(/\n$/, "")}
151143
</StyledSyntaxHighlighter>
152144
);
153145
} else if (String(props.children).includes("\n")) {
154146
// 言語指定なしコードブロック
155147
return (
156-
<StyledSyntaxHighlighter language={undefined}>
148+
<StyledSyntaxHighlighter language={langConstants(undefined)}>
157149
{String(props.children || "").replace(/\n$/, "")}
158150
</StyledSyntaxHighlighter>
159151
);
@@ -171,4 +163,4 @@ export function InlineCode({ children }: { children: ReactNode }) {
171163
{children}
172164
</code>
173165
);
174-
}
166+
}

app/[lang]/[pageId]/styledSyntaxHighlighter.tsx

Lines changed: 3 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
tomorrowNight,
77
} from "react-syntax-highlighter/dist/esm/styles/hljs";
88
import { lazy, Suspense, useEffect, useState } from "react";
9+
import { LangConstants } from "@my-code/runtime/languages";
910
import clsx from "clsx";
1011

1112
// SyntaxHighlighterはファイルサイズがでかいので & HydrationErrorを起こすので、SSRを無効化する
@@ -17,102 +18,9 @@ const SyntaxHighlighter = lazy(() => {
1718
}
1819
});
1920

20-
// Markdownで指定される可能性のある言語名を列挙
21-
export type MarkdownLang =
22-
| "python"
23-
| "py"
24-
| "ruby"
25-
| "rb"
26-
| "cpp"
27-
| "c++"
28-
| "rust"
29-
| "rs"
30-
| "javascript"
31-
| "js"
32-
| "typescript"
33-
| "ts"
34-
| "bash"
35-
| "sh"
36-
| "powershell"
37-
| "json"
38-
| "toml"
39-
| "csv"
40-
| "html"
41-
| "makefile"
42-
| "cmake"
43-
| "text"
44-
| "txt";
45-
46-
// react-syntax-highliter (hljs版) が対応している言語
47-
// https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/AVAILABLE_LANGUAGES_HLJS.MD を参照
48-
export type SyntaxHighlighterLang =
49-
| "python"
50-
| "ruby"
51-
| "c"
52-
| "cpp"
53-
| "rust"
54-
| "javascript"
55-
| "typescript"
56-
| "bash"
57-
| "powershell"
58-
| "html"
59-
| "json"
60-
| "ini"
61-
| "makefile"
62-
| "cmake";
63-
export function getSyntaxHighlighterLang(
64-
lang: MarkdownLang | undefined
65-
): SyntaxHighlighterLang | undefined {
66-
switch (lang) {
67-
case "python":
68-
case "py":
69-
return "python";
70-
case "ruby":
71-
case "rb":
72-
return "ruby";
73-
case "cpp":
74-
case "c++":
75-
return "cpp";
76-
case "rust":
77-
case "rs":
78-
return "rust";
79-
case "javascript":
80-
case "js":
81-
return "javascript";
82-
case "typescript":
83-
case "ts":
84-
return "typescript";
85-
case "bash":
86-
case "sh":
87-
return "bash";
88-
case "powershell":
89-
return "powershell";
90-
case "json":
91-
return "json";
92-
case "toml":
93-
return "ini";
94-
case "html":
95-
return "html";
96-
case "makefile":
97-
return "makefile";
98-
case "cmake":
99-
return "cmake";
100-
case "csv": // not supported
101-
case "text":
102-
case "txt":
103-
case undefined:
104-
return undefined;
105-
default:
106-
lang satisfies never;
107-
console.error(
108-
`getSyntaxHighlighterLang() does not handle language ${lang}`
109-
);
110-
return undefined;
111-
}
112-
}
11321
export function StyledSyntaxHighlighter(props: {
11422
children: string;
115-
language: SyntaxHighlighterLang | undefined;
23+
language: LangConstants;
11624
}) {
11725
const theme = useChangeTheme();
11826
const codetheme = theme === "tomorrow" ? tomorrow : tomorrowNight;
@@ -123,7 +31,7 @@ export function StyledSyntaxHighlighter(props: {
12331
return initHighlighter ? (
12432
<Suspense fallback={<FallbackPre>{props.children}</FallbackPre>}>
12533
<SyntaxHighlighter
126-
language={props.language}
34+
language={props.language.rsh}
12735
PreTag="div"
12836
className="border-2 border-current/20 mx-2 my-2 rounded-box p-4! bg-base-300! text-base-content!"
12937
style={codetheme}

app/actions/chatActions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// import { z } from "zod";
44
import { generateContent } from "./gemini";
55
import { DynamicMarkdownSection } from "../[lang]/[pageId]/pageContent";
6-
import { ReplCommand, ReplOutput } from "../terminal/repl";
6+
import { ReplCommand, ReplOutput } from "@my-code/runtime/interface";
77
import { addChat, ChatWithMessages } from "@/lib/chatHistory";
88
import { getPagesList, introSectionId, PagePath, SectionId } from "@/lib/docs";
99

app/layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import "./globals.css";
88
import { Navbar } from "./navbar";
99
import { Sidebar } from "./sidebar";
1010
import { ReactNode } from "react";
11-
import { EmbedContextProvider } from "./terminal/embedContext";
11+
import { EmbedContextProvider } from "@/terminal/embedContext";
1212
import { AutoAnonymousLogin } from "./accountMenu";
1313
import { SidebarMdProvider } from "./sidebar";
14-
import { RuntimeProvider } from "./terminal/runtime";
14+
import { RuntimeProvider } from "@my-code/runtime/context";
1515
import { getPagesList } from "@/lib/docs";
1616

1717
export const metadata: Metadata = {

0 commit comments

Comments
 (0)