Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c373009
runtimeをworkspaceに
na-trium-144 Feb 27, 2026
17b3b73
dependenciesを移動
na-trium-144 Feb 27, 2026
cf26ea9
update dockerfile
na-trium-144 Feb 27, 2026
5ff99e5
update readme (雑)
na-trium-144 Feb 27, 2026
1c2b679
terminalコンポーネントはapp/に戻してみる
na-trium-144 Feb 28, 2026
f5fa9ac
Merge remote-tracking branch 'origin/main' into runtime-workspace
na-trium-144 Feb 28, 2026
76bd878
言語の定義をリファクタ、1箇所に統一
na-trium-144 Feb 28, 2026
db4d038
vitestを導入, ciのセットアップ
na-trium-144 Feb 28, 2026
1ae527e
vitestで全テスト動くようになった
na-trium-144 Feb 28, 2026
e013a56
テスト定義をリファクタ
na-trium-144 Feb 28, 2026
23de989
chaiをruntimeに移動、npm dedupe
na-trium-144 Feb 28, 2026
a0ba779
workerのonOutputをawaitしていなかったのを修正
na-trium-144 Mar 1, 2026
d69b9ef
domいらない
na-trium-144 Mar 1, 2026
8eb5fd9
optimizedepsを追加してみる
na-trium-144 Mar 1, 2026
6290a43
format
na-trium-144 Mar 1, 2026
109eaf0
optimizedep追加
na-trium-144 Mar 1, 2026
bc837f3
ドキュメントをtsdocに移動、useRuntimeAllを追加しテストを修正
na-trium-144 Mar 2, 2026
5836fd9
jsevalのテストも独立したciのファイルに
na-trium-144 Mar 2, 2026
bb14920
Merge branch 'main' into runtime-workspace
na-trium-144 Mar 4, 2026
b3ba0d0
サンプルコードはapp/にもどす
na-trium-144 Mar 5, 2026
d59a856
Merge branch 'main' into runtime-workspace
na-trium-144 Mar 8, 2026
032f1d9
update readme
na-trium-144 Mar 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/workflows/jseval-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: jsEval Tests CI
on:
pull_request:
paths:
- 'packages/jsEval/**'
- '.github/workflows/jseval-tests.yml'
jobs:
test-js-eval:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.x]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm test -w @my-code/js-eval
14 changes: 0 additions & 14 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,3 @@ jobs:
cache: 'npm'
- run: npm ci
- run: npm run checkDocs

test-js-eval:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.x]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm test --workspace=packages/jsEval
20 changes: 20 additions & 0 deletions .github/workflows/runtime-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Runtime Tests CI
on:
pull_request:
paths:
- 'packages/runtime/**'
- '.github/workflows/runtime-tests.yml'
jobs:
test-runtime:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.x]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm test -w @my-code/runtime
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,4 @@ next-env.d.ts

/public/typescript/
/app/m-plus-rounded-1c-nohint/
node_modules
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ WORKDIR /app

COPY package.json package-lock.json ./
COPY packages/jsEval/package.json ./packages/jsEval/
COPY packages/runtime/package.json ./packages/runtime/

RUN --mount=type=cache,target=/root/.npm \
npm ci --no-audit --no-fund
Expand Down
15 changes: 6 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ npm run checkDocs

## markdown仕様

実行環境の説明は ./packages/runtime/README.md を参照

````
```言語名-repl
>>> コマンド
Expand All @@ -181,10 +183,7 @@ npm run checkDocs
````

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

````
```言語名:ファイル名
Expand All @@ -193,13 +192,12 @@ npm run checkDocs
````

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

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

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


## 技術スタック・ドキュメント・メモ
Expand Down
32 changes: 12 additions & 20 deletions app/[lang]/[pageId]/markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,12 @@ import Markdown, { Components, ExtraProps } from "react-markdown";
import remarkGfm from "remark-gfm";
import removeComments from "remark-remove-comments";
import remarkCjkFriendly from "remark-cjk-friendly";
import { EditorComponent, getAceLang } from "@/terminal/editor";
import { EditorComponent } from "@/terminal/editor";
import { ExecFile } from "@/terminal/exec";
import { JSX, ReactNode } from "react";
import { getRuntimeLang } from "@/terminal/runtime";
import { langConstants, MarkdownLang } from "@my-code/runtime/languages";
import { ReplTerminal } from "@/terminal/repl";
import {
getSyntaxHighlighterLang,
MarkdownLang,
StyledSyntaxHighlighter,
} from "./styledSyntaxHighlighter";
import { StyledSyntaxHighlighter } from "./styledSyntaxHighlighter";

export function StyledMarkdown({ content }: { content: string }) {
return (
Expand Down Expand Up @@ -93,7 +89,7 @@ function CodeComponent({
className || ""
);
if (match) {
const runtimeLang = getRuntimeLang(match[1] as MarkdownLang | undefined);
const language = langConstants(match[1] as MarkdownLang | undefined);
if (match[2] === "-exec" && match[3]) {
/*
```python-exec:main.py
Expand All @@ -105,10 +101,10 @@ function CodeComponent({
hello, world!
---------------------------
*/
if (runtimeLang) {
if (language.runtime) {
return (
<ExecFile
language={runtimeLang}
language={language}
filenames={match[3].split(",")}
content={String(props.children || "").replace(/\n$/, "")}
/>
Expand All @@ -121,39 +117,35 @@ function CodeComponent({
`${match[1]}-repl without terminal id! content: ${String(props.children).slice(0, 20)}...`
);
}
if (runtimeLang) {
if (language.runtime) {
return (
<ReplTerminal
terminalId={match[3]}
language={runtimeLang}
language={language}
initContent={String(props.children || "").replace(/\n$/, "")}
/>
);
}
} else if (match[3]) {
// ファイル名指定がある場合、ファイルエディター
const aceLang = getAceLang(match[1] as MarkdownLang | undefined);
return (
<EditorComponent
language={aceLang}
language={language}
filename={match[3]}
readonly={match[2] === "-readonly"}
initContent={String(props.children || "").replace(/\n$/, "")}
/>
);
}
const syntaxHighlighterLang = getSyntaxHighlighterLang(
match[1] as MarkdownLang | undefined
);
return (
<StyledSyntaxHighlighter language={syntaxHighlighterLang}>
<StyledSyntaxHighlighter language={language}>
{String(props.children || "").replace(/\n$/, "")}
</StyledSyntaxHighlighter>
);
} else if (String(props.children).includes("\n")) {
// 言語指定なしコードブロック
return (
<StyledSyntaxHighlighter language={undefined}>
<StyledSyntaxHighlighter language={langConstants(undefined)}>
{String(props.children || "").replace(/\n$/, "")}
</StyledSyntaxHighlighter>
);
Expand All @@ -171,4 +163,4 @@ export function InlineCode({ children }: { children: ReactNode }) {
{children}
</code>
);
}
}
98 changes: 3 additions & 95 deletions app/[lang]/[pageId]/styledSyntaxHighlighter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
tomorrowNight,
} from "react-syntax-highlighter/dist/esm/styles/hljs";
import { lazy, Suspense, useEffect, useState } from "react";
import { LangConstants } from "@my-code/runtime/languages";
import clsx from "clsx";

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

// Markdownで指定される可能性のある言語名を列挙
export type MarkdownLang =
| "python"
| "py"
| "ruby"
| "rb"
| "cpp"
| "c++"
| "rust"
| "rs"
| "javascript"
| "js"
| "typescript"
| "ts"
| "bash"
| "sh"
| "powershell"
| "json"
| "toml"
| "csv"
| "html"
| "makefile"
| "cmake"
| "text"
| "txt";

// react-syntax-highliter (hljs版) が対応している言語
// https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/AVAILABLE_LANGUAGES_HLJS.MD を参照
export type SyntaxHighlighterLang =
| "python"
| "ruby"
| "c"
| "cpp"
| "rust"
| "javascript"
| "typescript"
| "bash"
| "powershell"
| "html"
| "json"
| "ini"
| "makefile"
| "cmake";
export function getSyntaxHighlighterLang(
lang: MarkdownLang | undefined
): SyntaxHighlighterLang | undefined {
switch (lang) {
case "python":
case "py":
return "python";
case "ruby":
case "rb":
return "ruby";
case "cpp":
case "c++":
return "cpp";
case "rust":
case "rs":
return "rust";
case "javascript":
case "js":
return "javascript";
case "typescript":
case "ts":
return "typescript";
case "bash":
case "sh":
return "bash";
case "powershell":
return "powershell";
case "json":
return "json";
case "toml":
return "ini";
case "html":
return "html";
case "makefile":
return "makefile";
case "cmake":
return "cmake";
case "csv": // not supported
case "text":
case "txt":
case undefined:
return undefined;
default:
lang satisfies never;
console.error(
`getSyntaxHighlighterLang() does not handle language ${lang}`
);
return undefined;
}
}
export function StyledSyntaxHighlighter(props: {
children: string;
language: SyntaxHighlighterLang | undefined;
language: LangConstants;
}) {
const theme = useChangeTheme();
const codetheme = theme === "tomorrow" ? tomorrow : tomorrowNight;
Expand All @@ -123,7 +31,7 @@ export function StyledSyntaxHighlighter(props: {
return initHighlighter ? (
<Suspense fallback={<FallbackPre>{props.children}</FallbackPre>}>
<SyntaxHighlighter
language={props.language}
language={props.language.rsh}
PreTag="div"
className="border-2 border-current/20 mx-2 my-2 rounded-box p-4! bg-base-300! text-base-content!"
style={codetheme}
Expand Down
2 changes: 1 addition & 1 deletion app/actions/chatActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// import { z } from "zod";
import { generateContent } from "./gemini";
import { DynamicMarkdownSection } from "../[lang]/[pageId]/pageContent";
import { ReplCommand, ReplOutput } from "../terminal/repl";
import { ReplCommand, ReplOutput } from "@my-code/runtime/interface";
import { addChat, ChatWithMessages } from "@/lib/chatHistory";
import { getPagesList, introSectionId, PagePath, SectionId } from "@/lib/docs";

Expand Down
4 changes: 2 additions & 2 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import "./globals.css";
import { Navbar } from "./navbar";
import { Sidebar } from "./sidebar";
import { ReactNode } from "react";
import { EmbedContextProvider } from "./terminal/embedContext";
import { EmbedContextProvider } from "@/terminal/embedContext";
import { AutoAnonymousLogin } from "./accountMenu";
import { SidebarMdProvider } from "./sidebar";
import { RuntimeProvider } from "./terminal/runtime";
import { RuntimeProvider } from "@my-code/runtime/context";
import { getPagesList } from "@/lib/docs";

export const metadata: Metadata = {
Expand Down
4 changes: 2 additions & 2 deletions app/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import {
} from "react";
import { DynamicMarkdownSection } from "./[lang]/[pageId]/pageContent";
import clsx from "clsx";
import { LanguageIcon } from "./terminal/icons";
import { RuntimeLang } from "./terminal/runtime";
import { LanguageIcon } from "@/terminal/icons";
import { RuntimeLang } from "@my-code/runtime/languages";

export interface ISidebarMdContext {
loadedPath: PagePath | null;
Expand Down
Loading