first commit

This commit is contained in:
2024-01-21 20:48:03 +08:00
commit c4bdcac452
28 changed files with 7707 additions and 0 deletions

24
.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

1
.prettierrc.toml Normal file
View File

@@ -0,0 +1 @@
semi=false

3
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
}

18
README.md Normal file
View File

@@ -0,0 +1,18 @@
# Vue 3 + TypeScript + Vite
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
## Recommended IDE Setup
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
## Type Support For `.vue` Imports in TS
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
1. Disable the built-in TypeScript Extension
1. Run `Extensions: Show Built-in Extensions` from VSCode's command palette
2. Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.

16
index.html Normal file
View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>徐越的自测猫</title>
<script>
this.globalThis || (this.globalThis = window)
</script>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

6821
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

33
package.json Normal file
View File

@@ -0,0 +1,33 @@
{
"name": "code-next",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"start": "vite",
"build": "vue-tsc && vite build",
"fmt": "prettier --write src"
},
"dependencies": {
"@codemirror/lang-cpp": "^6.0.2",
"@codemirror/lang-python": "^6.1.3",
"@vueuse/core": "^10.7.2",
"axios": "^1.6.5",
"codemirror": "^6.0.1",
"copy-text-to-clipboard": "^3.2.0",
"naive-ui": "^2.37.3",
"normalize.css": "^8.0.1",
"query-string": "^8.1.0",
"vue": "^3.4.15",
"vue-codemirror": "^6.1.1"
},
"devDependencies": {
"@vitejs/plugin-legacy": "^5.2.0",
"@vitejs/plugin-vue": "^5.0.3",
"prettier": "^3.2.4",
"terser": "^5.27.0",
"typescript": "^5.3.3",
"vite": "^5.0.12",
"vue-tsc": "^1.8.27"
}
}

1
public/vite.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

22
src/App.vue Normal file
View File

@@ -0,0 +1,22 @@
<script setup lang="ts">
import { zhCN, dateZhCN, darkTheme } from "naive-ui"
import Desktop from "./desktop/index.vue"
import Mobile from "./mobile/index.vue"
import { isDesktop, isMobile } from "./composables/breakpoints"
import { useDark } from "@vueuse/core"
const isDark = useDark()
</script>
<template>
<n-config-provider
inline-theme-disabled
:locale="zhCN"
:date-locale="dateZhCN"
:theme="isDark ? darkTheme : null"
>
<n-layout>
<Desktop v-if="isDesktop" />
<Mobile v-if="isMobile" />
</n-layout>
</n-config-provider>
</template>

56
src/api.ts Normal file
View File

@@ -0,0 +1,56 @@
import axios from "axios"
import { Code } from "./types"
import { deadResults, languageToId } from "./templates"
function getChromeVersion() {
var raw = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)
return raw ? parseInt(raw[2], 10) : 0
}
const isLowVersion = getChromeVersion() < 80
const protocol = isLowVersion ? "http" : "https"
function encode(string?: string) {
return btoa(String.fromCharCode(...new TextEncoder().encode(string ?? "")))
}
function decode(bytes?: string) {
const latin = atob(bytes ?? "")
return new TextDecoder("utf-8").decode(
Uint8Array.from({ length: latin.length }, (_, index) =>
latin.charCodeAt(index),
),
)
}
const http = axios.create({ baseURL: `${protocol}://judge0api.xuyue.cc` })
export async function submit(code: Code, input: string) {
const encodedCode = encode(code.value)
if (encodedCode === deadResults[code.language].encoded) {
return deadResults[code.language].result
} else {
const id = languageToId[code.language]
let compilerOptions = ""
if (id === 50) compilerOptions = "-lm" // 解决 GCC 的链接问题
const payload = {
source_code: encodedCode,
language_id: id,
stdin: encode(input),
redirect_stderr_to_stdout: true,
compiler_options: compilerOptions,
}
const response = await http.post("/submissions", payload, {
params: { base64_encoded: true, wait: true },
})
const data = response.data
return {
status: data.status && data.status.id,
output: [decode(data.compile_output), decode(data.stdout)]
.join("\n")
.trim(),
}
}
}

View File

@@ -0,0 +1,81 @@
<script lang="ts" setup>
import { computed, ref, watch } from "vue"
import { useDark } from "@vueuse/core"
import { Codemirror } from "vue-codemirror"
import { cpp } from "@codemirror/lang-cpp"
import { python } from "@codemirror/lang-python"
import { EditorView } from "@codemirror/view"
import { LANGUAGE } from "../types"
import { oneDark } from "../themes/oneDark"
import { smoothy } from "../themes/smoothy"
interface Props {
label: string
modelValue: string
language?: LANGUAGE
fontSize?: number
readonly?: boolean
placeholder?: string
}
const props = withDefaults(defineProps<Props>(), {
language: "c",
fontSize: 24,
readonly: false,
placeholder: "",
})
const code = ref(props.modelValue)
const isDark = useDark()
const styleTheme = EditorView.baseTheme({
"& .cm-scroller": {
"font-family": "Consolas",
},
"&.cm-editor.cm-focused": {
outline: "none",
},
})
const emit = defineEmits(["update:modelValue"])
watch(
() => props.modelValue,
(v) => {
code.value = v
},
)
const lang = computed(() => {
if (props.language === "c") {
return cpp()
}
return python()
})
function onChange(v: string) {
emit("update:modelValue", v)
}
</script>
<template>
<div class="container">
<div class="title">{{ label }}</div>
<Codemirror
v-model="code"
indentWithTab
:extensions="[styleTheme, lang, isDark ? oneDark : smoothy]"
:disabled="props.readonly"
:tabSize="4"
:placeholder="props.placeholder"
:style="{ height: '100%', fontSize: props.fontSize + 'px' }"
@change="onChange"
/>
</div>
</template>
<style scoped>
.container {
height: 100%;
}
.title {
padding: 12px 20px;
font-size: 16px;
}
</style>

View File

@@ -0,0 +1,6 @@
import { breakpointsTailwind, useBreakpoints } from "@vueuse/core"
const breakpoints = useBreakpoints(breakpointsTailwind)
export const isMobile = breakpoints.smallerOrEqual("md")
export const isDesktop = breakpoints.greater("md")

35
src/composables/code.ts Normal file
View File

@@ -0,0 +1,35 @@
import { ref } from "vue"
import copyTextToClipboard from "copy-text-to-clipboard"
import { Code } from "../types"
import { sources } from "../templates"
import { submit } from "../api"
export const code = ref<Code>({
value: sources["python"],
language: "python",
})
export const input = ref("")
export const output = ref("")
export const loading = ref(false)
export function copy() {
copyTextToClipboard(code.value.value)
}
export function reset() {
code.value.value = sources["python"]
output.value = ""
}
export async function run() {
loading.value = true
const cleanCode = code.value.value.trim()
if (!cleanCode) return
output.value = ""
const result = await submit(
{ value: cleanCode, language: code.value.language },
input.value.trim(),
)
output.value = result.output || ""
loading.value = false
}

37
src/desktop/Content.vue Normal file
View File

@@ -0,0 +1,37 @@
<template>
<n-layout-content class="container">
<n-split direction="horizontal" :min="1 / 3" :max="4 / 5">
<template #1>
<CodeEditor
label="代码区"
v-model="code.value"
:language="code.language"
/>
</template>
<template #2>
<n-split
direction="vertical"
:default-size="1 / 3"
:min="1 / 5"
:max="3 / 5"
>
<template #1>
<CodeEditor label="输入框" v-model="input" />
</template>
<template #2>
<CodeEditor label="输出框" v-model="output" readonly />
</template>
</n-split>
</template>
</n-split>
</n-layout-content>
</template>
<script lang="ts" setup>
import { code, input, output } from "../composables/code"
import CodeEditor from "../components/CodeEditor.vue"
</script>
<style scoped>
.container {
height: calc(100vh - 60px);
}
</style>

53
src/desktop/Header.vue Normal file
View File

@@ -0,0 +1,53 @@
<script setup lang="ts">
import type { SelectOption } from "naive-ui"
import { useDark, useToggle } from "@vueuse/core"
import Play from "../icons/Play.vue"
import { copy, reset, run, loading } from "../composables/code"
const isDark = useDark()
const toggleDark = useToggle(isDark)
const languages: SelectOption[] = [
{ value: "c", label: "C" },
{ value: "python", label: "Python" },
{ value: "cpp", label: "C++" },
{ value: "java", label: "Java" },
]
</script>
<template>
<n-layout-header bordered class="header">
<n-flex justify="space-between" align="center">
<div class="title">徐越的自测猫</div>
<n-flex>
<n-button @click="toggleDark()">
{{ isDark ? "浅色" : "深色" }}
</n-button>
<n-button @click="reset">重置</n-button>
<n-button @click="copy">复制</n-button>
<n-select class="select" :options="languages"></n-select>
<n-button type="primary" @click="run" :loading="loading">
<template #icon>
<n-icon>
<Play />
</n-icon>
</template>
运行 (F5)
</n-button>
</n-flex>
</n-flex>
</n-layout-header>
</template>
<style scoped>
.header {
height: 60px;
padding: 12px;
}
.title {
font-size: 20px;
}
.select {
width: 100px;
}
</style>

8
src/desktop/index.vue Normal file
View File

@@ -0,0 +1,8 @@
<template>
<Header />
<Content />
</template>
<script lang="ts" setup>
import Header from "./Header.vue"
import Content from "./Content.vue"
</script>

15
src/icons/Play.vue Normal file
View File

@@ -0,0 +1,15 @@
<template>
<svg
viewBox="0 0 1024 1024"
focusable="false"
data-icon="caret-right"
width="18px"
height="18px"
fill="currentColor"
aria-hidden="true"
>
<path
d="M715.8 493.5L335 165.1c-14.2-12.2-35-1.2-35 18.5v656.8c0 19.7 20.8 30.7 35 18.5l380.8-328.4c10.9-9.4 10.9-27.6 0-37z"
></path>
</svg>
</template>

37
src/main.ts Normal file
View File

@@ -0,0 +1,37 @@
import { createApp } from "vue"
import {
create,
NButton,
NConfigProvider,
NInput,
NLayout,
NLayoutContent,
NLayoutHeader,
NSelect,
NSpace,
NSplit,
NFlex,
NIcon,
} from "naive-ui"
import App from "./App.vue"
import "normalize.css"
const naive = create({
components: [
NButton,
NConfigProvider,
NLayout,
NLayoutHeader,
NLayoutContent,
NSpace,
NInput,
NSelect,
NSplit,
NFlex,
NIcon,
],
})
const app = createApp(App)
app.use(naive)
app.mount("#app")

1
src/mobile/index.vue Normal file
View File

@@ -0,0 +1 @@
<template></template>

55
src/templates.ts Normal file
View File

@@ -0,0 +1,55 @@
const cSource =
'#include<stdio.h>\r\n\r\nint main()\r\n{\r\n printf("黄岩一职");\r\n return 0;\r\n}'
const cppSource =
'#include<iostream>\r\n\r\nusing namespace std;\r\n\r\nint main()\r\n{\r\n cout<<"黄岩一职"<<endl;\r\n return 0;\r\n}'
const pythonSource = 'print("黄岩一职")'
const javaSource =
'public class Main {\r\n public static void main(String[] args) {\r\n System.out.println("黄岩一职");\r\n }\r\n}'
export const languageToId = {
c: 50,
cpp: 54,
java: 62,
python: 71,
}
export const sources = {
c: cSource,
cpp: cppSource,
java: javaSource,
python: pythonSource,
}
export const deadResults = {
c: {
encoded:
"I2luY2x1ZGU8c3RkaW8uaD4NCg0KaW50IG1haW4oKQ0Kew0KICAgIHByaW50Zigi6buE5bKp5LiA6IGMIik7DQogICAgcmV0dXJuIDA7DQp9",
result: {
status: 3,
output: "黄岩一职",
},
},
cpp: {
encoded:
"I2luY2x1ZGU8aW9zdHJlYW0+DQoNCnVzaW5nIG5hbWVzcGFjZSBzdGQ7DQoNCmludCBtYWluKCkNCnsNCiAgICBjb3V0PDwi6buE5bKp5LiA6IGMIjw8ZW5kbDsNCiAgICByZXR1cm4gMDsNCn0=",
result: {
status: 3,
output: "黄岩一职",
},
},
python: {
encoded: "cHJpbnQoIum7hOWyqeS4gOiBjCIp",
result: {
status: 3,
output: "黄岩一职",
},
},
java: {
encoded:
"cHVibGljIGNsYXNzIE1haW4gew0KICAgIHB1YmxpYyBzdGF0aWMgdm9pZCBtYWluKFN0cmluZ1tdIGFyZ3MpIHsNCiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCLpu4TlsqnkuIDogYwiKTsNCiAgICB9DQp9",
result: {
status: 3,
output: "黄岩一职",
},
},
}

110
src/themes/createTheme.ts Normal file
View File

@@ -0,0 +1,110 @@
import { EditorView } from "@codemirror/view"
import { Extension } from "@codemirror/state"
import {
HighlightStyle,
TagStyle,
syntaxHighlighting,
} from "@codemirror/language"
interface Options {
/**
* Theme variant. Determines which styles CodeMirror will apply by default.
*/
variant: Variant
/**
* Settings to customize the look of the editor, like background, gutter, selection and others.
*/
settings: Settings
/**
* Syntax highlighting styles.
*/
styles: TagStyle[]
}
type Variant = "light" | "dark"
interface Settings {
/**
* Editor background.
*/
background: string
/**
* Default text color.
*/
foreground: string
/**
* Caret color.
*/
caret: string
/**
* Selection background.
*/
selection: string
/**
* Background of highlighted lines.
*/
lineHighlight: string
/**
* Gutter background.
*/
gutterBackground: string
/**
* Text color inside gutter.
*/
gutterForeground: string
gutterBorderRight: string
}
export const createTheme = ({
variant,
settings,
styles,
}: Options): Extension => {
const theme = EditorView.theme(
{
// eslint-disable-next-line @typescript-eslint/naming-convention
"&": {
backgroundColor: settings.background,
color: settings.foreground,
},
".cm-content": {
caretColor: settings.caret,
},
".cm-cursor, .cm-dropCursor": {
borderLeftColor: settings.caret,
},
"&.cm-focused .cm-selectionBackgroundm .cm-selectionBackground, .cm-content ::selection":
{
backgroundColor: settings.selection,
},
".cm-activeLine": {
backgroundColor: settings.lineHighlight,
},
".cm-gutters": {
backgroundColor: settings.gutterBackground,
borderRight: settings.gutterBorderRight,
color: settings.gutterForeground,
},
".cm-activeLineGutter": {
backgroundColor: settings.lineHighlight,
},
},
{
dark: variant === "dark",
},
)
const highlightStyle = HighlightStyle.define(styles)
const extension = [theme, syntaxHighlighting(highlightStyle)]
return extension
}

149
src/themes/oneDark.ts Normal file
View File

@@ -0,0 +1,149 @@
import { EditorView } from "@codemirror/view"
import { Extension } from "@codemirror/state"
import { HighlightStyle, syntaxHighlighting } from "@codemirror/language"
import { tags as t } from "@lezer/highlight"
// Using https://github.com/one-dark/vscode-one-dark-theme/ as reference for the colors
const chalky = "#e5c07b",
coral = "#e06c75",
cyan = "#56b6c2",
invalid = "#ffffff",
ivory = "#abb2bf",
stone = "#7d8799", // Brightened compared to original to increase contrast
malibu = "#61afef",
sage = "#98c379",
whiskey = "#d19a66",
violet = "#c678dd",
darkBackground = "#26262a",
highlightBackground = "#2c313a",
background = "#101014", // naive-ui
tooltipBackground = "#353a42",
selection = "#3E4451",
cursor = "#528bff"
/// The editor theme styles for One Dark.
const oneDarkTheme = EditorView.theme(
{
"&": {
color: ivory,
backgroundColor: background,
},
".cm-content": {
caretColor: cursor,
},
".cm-cursor, .cm-dropCursor": { borderLeftColor: cursor },
"&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection":
{ backgroundColor: selection },
".cm-panels": { backgroundColor: darkBackground, color: ivory },
".cm-panels.cm-panels-top": { borderBottom: "2px solid black" },
".cm-panels.cm-panels-bottom": { borderTop: "2px solid black" },
".cm-searchMatch": {
backgroundColor: "#72a1ff59",
outline: "1px solid #457dff",
},
".cm-searchMatch.cm-searchMatch-selected": {
backgroundColor: "#6199ff2f",
},
".cm-activeLine": { backgroundColor: "#6699ff0b" },
".cm-selectionMatch": { backgroundColor: "#aafe661a" },
"&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket": {
backgroundColor: "#bad0f847",
},
".cm-gutters": {
backgroundColor: background,
color: stone,
border: "none",
},
".cm-activeLineGutter": {
backgroundColor: highlightBackground,
},
".cm-foldPlaceholder": {
backgroundColor: "transparent",
border: "none",
color: "#ddd",
},
".cm-tooltip": {
border: "none",
backgroundColor: tooltipBackground,
},
".cm-tooltip .cm-tooltip-arrow:before": {
borderTopColor: "transparent",
borderBottomColor: "transparent",
},
".cm-tooltip .cm-tooltip-arrow:after": {
borderTopColor: tooltipBackground,
borderBottomColor: tooltipBackground,
},
".cm-tooltip-autocomplete": {
"& > ul > li[aria-selected]": {
backgroundColor: highlightBackground,
color: ivory,
},
},
},
{ dark: true },
)
/// The highlighting style for code in the One Dark theme.
const oneDarkHighlightStyle = HighlightStyle.define([
{ tag: t.keyword, color: violet },
{
tag: [t.name, t.deleted, t.character, t.propertyName, t.macroName],
color: coral,
},
{ tag: [t.function(t.variableName), t.labelName], color: malibu },
{ tag: [t.color, t.constant(t.name), t.standard(t.name)], color: whiskey },
{ tag: [t.definition(t.name), t.separator], color: ivory },
{
tag: [
t.typeName,
t.className,
t.number,
t.changed,
t.annotation,
t.modifier,
t.self,
t.namespace,
],
color: chalky,
},
{
tag: [
t.operator,
t.operatorKeyword,
t.url,
t.escape,
t.regexp,
t.link,
t.special(t.string),
],
color: cyan,
},
{ tag: [t.meta, t.comment], color: stone },
{ tag: t.strong, fontWeight: "bold" },
{ tag: t.emphasis, fontStyle: "italic" },
{ tag: t.strikethrough, textDecoration: "line-through" },
{ tag: t.link, color: stone, textDecoration: "underline" },
{ tag: t.heading, fontWeight: "bold", color: coral },
{ tag: [t.atom, t.bool, t.special(t.variableName)], color: whiskey },
{ tag: [t.processingInstruction, t.string, t.inserted], color: sage },
{ tag: t.invalid, color: invalid },
])
/// Extension to enable the One Dark theme (both the editor theme and
/// the highlight style).
export const oneDark: Extension = [
oneDarkTheme,
syntaxHighlighting(oneDarkHighlightStyle),
]

83
src/themes/smoothy.ts Normal file
View File

@@ -0,0 +1,83 @@
import { tags as t } from "@lezer/highlight"
import { createTheme } from "./createTheme"
// Author: Kenneth Reitz
export const smoothy = createTheme({
variant: "light",
settings: {
background: "#FFFFFF",
foreground: "#000000",
caret: "#000000",
selection: "#FFFD0054",
gutterBackground: "#FFFFFF",
gutterForeground: "#00000070",
gutterBorderRight: "none",
lineHighlight: "#00000008",
},
styles: [
{
tag: t.comment,
color: "#CFCFCF",
},
{
tag: [t.number, t.bool, t.null],
color: "#E66C29",
},
{
tag: [
t.className,
t.definition(t.propertyName),
t.function(t.variableName),
t.labelName,
t.definition(t.typeName),
],
color: "#2EB43B",
},
{
tag: t.keyword,
color: "#D8B229",
},
{
tag: t.operator,
color: "#4EA44E",
fontWeight: "bold",
},
{
tag: [t.definitionKeyword, t.modifier],
color: "#925A47",
},
{
tag: t.string,
color: "#704D3D",
},
{
tag: t.typeName,
color: "#2F8996",
},
{
tag: [t.variableName, t.propertyName],
color: "#77ACB0",
},
{
tag: t.self,
color: "#77ACB0",
fontWeight: "bold",
},
{
tag: t.regexp,
color: "#E3965E",
},
{
tag: [t.tagName, t.angleBracket],
color: "#BAA827",
},
{
tag: t.attributeName,
color: "#B06520",
},
{
tag: t.derefOperator,
color: "#000",
},
],
})

6
src/types.ts Normal file
View File

@@ -0,0 +1,6 @@
export type LANGUAGE = "c" | "cpp" | "python" | "java"
export interface Code {
value: string
language: LANGUAGE
}

1
src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />

19
tsconfig.json Normal file
View File

@@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
"noEmit": true,
"types": ["naive-ui/volar"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}

9
tsconfig.node.json Normal file
View File

@@ -0,0 +1,9 @@
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}

7
vite.config.ts Normal file
View File

@@ -0,0 +1,7 @@
import { defineConfig } from "vite"
import vue from "@vitejs/plugin-vue"
import legacy from "@vitejs/plugin-legacy"
export default defineConfig({
plugins: [vue(), legacy({ targets: ["chrome 66", "not IE 11"] })],
})