diff --git a/package.json b/package.json index 1295b9f..d688990 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ }, "dependencies": { "@icons-pack/react-simple-icons": "^9.4.1", + "@monaco-editor/react": "^4.6.0", "@uidotdev/usehooks": "^2.4.1", "client-only": "^0.0.1", "clsx": "^2.1.0", @@ -21,7 +22,6 @@ "react": "^18", "react-dom": "^18", "server-only": "^0.0.1", - "shiki": "^1.3.0", "tailwind-merge": "^2.3.0" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 00470d9..76c1d9f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ dependencies: '@icons-pack/react-simple-icons': specifier: ^9.4.1 version: 9.4.1(react@18.2.0) + '@monaco-editor/react': + specifier: ^4.6.0 + version: 4.6.0(monaco-editor@0.48.0)(react-dom@18.2.0)(react@18.2.0) '@uidotdev/usehooks': specifier: ^2.4.1 version: 2.4.1(react-dom@18.2.0)(react@18.2.0) @@ -32,9 +35,6 @@ dependencies: server-only: specifier: ^0.0.1 version: 0.0.1 - shiki: - specifier: ^1.3.0 - version: 1.3.0 tailwind-merge: specifier: ^2.3.0 version: 2.3.0 @@ -207,6 +207,28 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /@monaco-editor/loader@1.4.0(monaco-editor@0.48.0): + resolution: {integrity: sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==} + peerDependencies: + monaco-editor: '>= 0.21.0 < 1' + dependencies: + monaco-editor: 0.48.0 + state-local: 1.0.7 + dev: false + + /@monaco-editor/react@4.6.0(monaco-editor@0.48.0)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==} + peerDependencies: + monaco-editor: '>= 0.25.0 < 1' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@monaco-editor/loader': 1.4.0(monaco-editor@0.48.0) + monaco-editor: 0.48.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@next/env@14.2.2: resolution: {integrity: sha512-sk72qRfM1Q90XZWYRoJKu/UWlTgihrASiYw/scb15u+tyzcze3bOuJ/UV6TBOQEeUaxOkRqGeuGUdiiuxc5oqw==} dev: false @@ -330,10 +352,6 @@ packages: resolution: {integrity: sha512-hw437iINopmQuxWPSUEvqE56NCPsiU8N4AYtfHmJFckclktzK9YQJieD3XkDCDH4OjL+C7zgPUh73R/nrcHrqw==} dev: true - /@shikijs/core@1.3.0: - resolution: {integrity: sha512-7fedsBfuILDTBmrYZNFI8B6ATTxhQAasUHllHmjvSZPnoq4bULWoTpHwmuQvZ8Aq03/tAa2IGo6RXqWtHdWaCA==} - dev: false - /@swc/counter@0.1.3: resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} dev: false @@ -1975,6 +1993,10 @@ packages: engines: {node: '>=16 || 14 >=14.17'} dev: true + /monaco-editor@0.48.0: + resolution: {integrity: sha512-goSDElNqFfw7iDHMg8WDATkfcyeLTNpBHQpO8incK6p5qZt5G/1j41X0xdGzpIkGojGXM+QiRQyLjnfDVvrpwA==} + dev: false + /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true @@ -2559,12 +2581,6 @@ packages: engines: {node: '>=8'} dev: true - /shiki@1.3.0: - resolution: {integrity: sha512-9aNdQy/etMXctnPzsje1h1XIGm9YfRcSksKOGqZWXA/qP9G18/8fpz5Bjpma8bOgz3tqIpjERAd6/lLjFyzoww==} - dependencies: - '@shikijs/core': 1.3.0 - dev: false - /side-channel@1.0.6: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} engines: {node: '>= 0.4'} @@ -2589,6 +2605,10 @@ packages: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} + /state-local@1.0.7: + resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==} + dev: false + /streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} diff --git a/src/app/globals.css b/src/app/globals.css index c60e306..b5c61c9 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,39 +1,3 @@ @tailwind base; @tailwind components; @tailwind utilities; - -html .shiki { - background-color: transparent !important; -} - -html .shiki, -html .shiki > * { - font-family: inherit; -} - -html .shiki .line { - counter-increment: line-numbering; -} - -html .shiki .line::before { - content: counter(line-numbering); - display: inline-block; - width: 2em; - margin-right: 1em; - color: var(--shiki-line-number-color); - text-align: right; - user-select: none; - - @apply text-neutral-400; -} - -@media (prefers-color-scheme: dark) { - html .shiki, - html .shiki span { - color: var(--shiki-dark) !important; - /* Optional, if you also want font styles */ - font-style: var(--shiki-dark-font-style) !important; - font-weight: var(--shiki-dark-font-weight) !important; - text-decoration: var(--shiki-dark-text-decoration) !important; - } -} diff --git a/src/app/inner.tsx b/src/app/inner.tsx index 6c7ce46..0901b92 100644 --- a/src/app/inner.tsx +++ b/src/app/inner.tsx @@ -4,13 +4,13 @@ import { Header } from "@/lib/ui/header"; import { TabSelector } from "@/lib/ui/tabs/selector"; import { TabController } from "@/lib/ui/tabs/controller"; import { useBreakpoint } from "@/lib/ui/tailwindcss/client/hooks/breakpoint"; -import { Highlight } from "@/lib/ui/highlight"; import { cn } from "@/lib/ui/utils/cn"; -import { TabContent } from "@/lib/ui/tabs/content"; import { OutputTabContents } from "@/lib/ui/protocol/OutputTabContents"; import { OutputTabSelectors } from "@/lib/ui/protocol/OutputTabSelectors"; import { OutputTabController } from "@/lib/ui/protocol/OutputTabController"; import { CompilerProvider } from "@/lib/hooks/compiler"; +import CodeEditor from "@/lib/ui/editor/codeEditor"; +import { TabContent } from "@/lib/ui/tabs/content"; const defaultCode = `// Insert your code here @@ -64,9 +64,7 @@ export function Inner({ initialCode }: { initialCode: string | null }) { -
- -
+
{!lg.loading && !lg.active && } diff --git a/src/lib/ui/editor/codeEditor.tsx b/src/lib/ui/editor/codeEditor.tsx new file mode 100644 index 0000000..435c634 --- /dev/null +++ b/src/lib/ui/editor/codeEditor.tsx @@ -0,0 +1,24 @@ +import { useCompilerContext } from "@/lib/hooks/compiler" +import { Editor } from "@monaco-editor/react" + + +export type CodeEditorProps = { + initialCode: string +} + +export default function CodeEditor({initialCode}: CodeEditorProps){ + const compilerContext = useCompilerContext() + + return ( + <> + { + if (value != undefined) compilerContext.setCode(value) + }} + /> + + ) +} \ No newline at end of file diff --git a/src/lib/ui/editor/use-editor.ts b/src/lib/ui/editor/use-editor.ts deleted file mode 100644 index dc2d1f1..0000000 --- a/src/lib/ui/editor/use-editor.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { useEffect, useMemo, useState } from "react"; -import { createLifetime } from "../utils/lifetime"; - -type Highlighter = Awaited>; - -/** - * Imports the relevant libraries necessary for highlighting code. - */ -async function createHighlighter() { - const { getHighlighterCore } = await import("shiki/core"); - const getWasm = await import("shiki/wasm"); - - return getHighlighterCore({ - langs: [() => import("shiki/langs/java.mjs")], - themes: [ - () => import("shiki/themes/github-dark-default.mjs"), - () => import("shiki/themes/github-light-default.mjs"), - ], - loadWasm: getWasm, - }); -} - -function useHighlighter() { - const [highlighter, setHighlighter] = useState(null); - - useEffect(() => { - const lifetime = createLifetime(); - - async function initializeHighlighter() { - const awaitedHighlighter = await createHighlighter(); - lifetime.runIfMounted(() => setHighlighter(awaitedHighlighter)); - } - - initializeHighlighter(); - return lifetime.createCleanup(); - }, []); - - return !!highlighter - ? { - codeToHtml: (code: string, { lang }: { lang: string }) => - highlighter.codeToHtml(code, { - lang, - themes: { - light: "github-light-default", - dark: "github-dark-default", - }, - }), - } - : null; -} - -export function useEditor(content: string) { - const highlighter = useHighlighter(); - - const html = useMemo(() => { - if (!highlighter) return ""; - return highlighter.codeToHtml(content, { - lang: "java", - }); - }, [highlighter, content]); - - return { - isLoading: highlighter === null, - html, - content, - }; -} diff --git a/src/lib/ui/highlight.tsx b/src/lib/ui/highlight.tsx deleted file mode 100644 index 5765bbc..0000000 --- a/src/lib/ui/highlight.tsx +++ /dev/null @@ -1,58 +0,0 @@ -"use client"; - -import { useEditor } from "./editor/use-editor"; -import { useCompilerContext } from "../hooks/compiler"; - -export function Highlight() { - const { code, setCode } = useCompilerContext(); - const { isLoading, html } = useEditor(code); - - return ( -
- {isLoading ? ( -

- Loading... -

- ) : ( - <> -