commit 93ff8356ceb22b4681ec1a70135102e5fdf5493a Author: HyunSuk Nam Date: Sat Aug 3 22:23:04 2024 +0900 Init Commit diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..d6c9537 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,18 @@ +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react-hooks/recommended', + ], + ignorePatterns: ['dist', '.eslintrc.cjs'], + parser: '@typescript-eslint/parser', + plugins: ['react-refresh'], + rules: { + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/.gitignore @@ -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? diff --git a/README.md b/README.md new file mode 100644 index 0000000..e1cdc89 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: + +- Configure the top-level `parserOptions` property like this: + +```js +export default { + // other rules... + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + project: ['./tsconfig.json', './tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: __dirname, + }, +} +``` + +- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked` +- Optionally add `plugin:@typescript-eslint/stylistic-type-checked` +- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list diff --git a/bun.lockb b/bun.lockb new file mode 100644 index 0000000..b901f15 Binary files /dev/null and b/bun.lockb differ diff --git a/declarations.d.ts b/declarations.d.ts new file mode 100644 index 0000000..4cabf4f --- /dev/null +++ b/declarations.d.ts @@ -0,0 +1,5 @@ +// declarations.d.ts +declare module '*.md' { + const content: string; + export default content; + } \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..281b711 --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + imnyang with πŸ’• + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..bd5bd6b --- /dev/null +++ b/package.json @@ -0,0 +1,43 @@ +{ + "name": "imnyang-new", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "@nextui-org/kbd": "^2.0.33", + "@nextui-org/react": "^2.4.6", + "autoprefixer": "^10.4.20", + "framer-motion": "^11.3.21", + "highlight.js": "^11.10.0", + "postcss": "^8.4.40", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-draggable": "^4.4.6", + "react-markdown": "^9.0.1", + "react-router-dom": "^6.26.0", + "rehype-highlight": "^7.0.0", + "tailwind": "^4.0.0", + "tailwindcss": "^3.4.7" + }, + "devDependencies": { + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.15.0", + "@typescript-eslint/parser": "^7.15.0", + "@vitejs/plugin-react-swc": "^3.5.0", + "eslint": "^8.57.0", + "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-react-refresh": "^0.4.7", + "typescript": "^5.2.2", + "vite": "^5.3.4" + }, + "trustedDependencies": [ + "core-js" + ] +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..8def97b --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,4 @@ +export const plugins = { + tailwindcss: {}, + autoprefixer: {}, +}; \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..6845de1 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,65 @@ +import Root from './pages/Root'; +import Timeline from './pages/Timeline'; +import { Route, Routes } from 'react-router-dom'; +import { useEffect } from 'react'; + +function App() { + const keySequence: string[] = []; + const targetSequence = 'furry'; + + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + // 단일 ν‚€ μž…λ ₯ 감지 + console.log(`Key: ${event.key} with keycode ${event.keyCode} has been pressed`); + console.log(`KeySquare: ${keySequence.join('')}`); + // νŠΉμ • λ¬Έμžμ—΄ μ‹œν€€μŠ€ 감지 + keySequence.push(event.key); + if (keySequence.length > targetSequence.length) { + keySequence.shift(); + } + + + if (event.key === 'm') { + console.log('Get mail'); + document.location.href = 'mailto:me@imnyang.xyz'; + } + if (event.key === 'g') { + console.log('Get Github'); + document.location.href = 'https://github.com/imnyang'; + } + if (event.key === 'b') { + console.log('Get Github'); + document.location.href = 'https://blog.imnyang.xyz'; + } + if (event.key === 't') { + console.log('Get Timeline'); + document.location.href = 'https://imnyang.xyz/timeline'; + } + if (event.key === 'i') { + console.log('Get isangjeong.today'); + document.location.href = 'https://instagram.com/isangjeong.today'; + } + + if (keySequence.join('') === targetSequence) { + console.log('Furry sequence detected!'); + document.location.href = 'https://ny64.kr'; + } + }; + + document.addEventListener('keydown', handleKeyDown); + + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + }, [keySequence]); + + return ( + <> + + + + + + ); +} +export default App; \ No newline at end of file diff --git a/src/assets/._react.svg b/src/assets/._react.svg new file mode 100644 index 0000000..d89c576 Binary files /dev/null and b/src/assets/._react.svg differ diff --git a/src/assets/react.svg b/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/component/Help.css b/src/component/Help.css new file mode 100644 index 0000000..91f4731 --- /dev/null +++ b/src/component/Help.css @@ -0,0 +1,33 @@ +.Help { + display: none; + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; + width: 50vw; + height: 50vh; + background-color: #141414; + border: 1px solid #fff; + border-radius: 10px; + z-index: 10; + position: fixed; + padding: 50px; +} + +.Help.visible { + display: flex; +} + +.key_container { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + gap: 20px; + margin-bottom: 20px; +} + +.key { + background-color: #000000; + border-radius: 5px; + padding: 10px; +} \ No newline at end of file diff --git a/src/component/help.tsx b/src/component/help.tsx new file mode 100644 index 0000000..407e3b8 --- /dev/null +++ b/src/component/help.tsx @@ -0,0 +1,65 @@ +import { useEffect, useState } from 'react'; +import './Help.css'; +import Draggable from 'react-draggable'; + +export default function Help() { + const [isVisible, setIsVisible] = useState(false); + + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'F1') { + event.preventDefault(); + setIsVisible(!isVisible); + console.log('Help!'); + } + if (event.key === 'Escape') { + setIsVisible(false); + console.log('Help!'); + } + }; + document.addEventListener('keydown', handleKeyDown); + + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + }, [isVisible]); + + return ( + +
+

Help

+
+

+

+

F1

+

Help

+
+
+

l

+

Change nameIndex

+
+ +
+

furry

+

Show Furry

+
+

+

+

+

m

+

Mailto

+
+
+

g

+

Github

+
+
+

b

+

Blog

+
+

+
+
+
+ ); +} \ No newline at end of file diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..8310fc1 --- /dev/null +++ b/src/index.css @@ -0,0 +1,121 @@ +@import url("https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css"); + +* { + font-family: "Pretendard Variable", Pretendard, -apple-system, BlinkMacSystemFont, system-ui, Roboto, "Helvetica Neue", "Segoe UI", "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", sans-serif; +} + +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #101010; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +/* from reset */ + +::-webkit-scrollbar { + width: 10px; + height: 11px; +} + +::-webkit-scrollbar-track { + background: 0 0; +} + +.list:not(.dark)::-webkit-scrollbar-track { + background: rgb(55, 56, 62); +} + +::-webkit-scrollbar-thumb { + background: rgb(65, 66, 68); + border: 1px solid rgb(29, 30, 32); + border-radius: 8px; +} + +.list:not(.dark)::-webkit-scrollbar-thumb { + border: 5px solid rgb(55, 56, 62); +} + +::-webkit-scrollbar-thumb:hover { + background: rgb(155, 156, 157); +} + +::-webkit-scrollbar:not(.highlighttable, .highlight table, .gist .highlight) { + background: rgb(29, 30, 32); +} + +/* from post-single */ +.post-content .highlighttable td .highlight pre code::-webkit-scrollbar { + display: none; +} + +.post-content :not(table) ::-webkit-scrollbar-thumb { + border: 2px solid var(--hljs-bg); + background: rgb(113, 113, 117); +} + +.post-content :not(table) ::-webkit-scrollbar-thumb:hover { + background: rgb(163, 163, 165); +} + +.gist table::-webkit-scrollbar-thumb { + border: 2px solid rgb(255, 255, 255); + background: rgb(173, 173, 173); +} + +.gist table::-webkit-scrollbar-thumb:hover { + background: rgb(112, 112, 112); +} + +.post-content table::-webkit-scrollbar-thumb { + border-width: 2px; +} diff --git a/src/main.tsx b/src/main.tsx new file mode 100644 index 0000000..acf7743 --- /dev/null +++ b/src/main.tsx @@ -0,0 +1,13 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.tsx' +import './index.css' +import { BrowserRouter } from 'react-router-dom'; + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + + + , +) diff --git a/src/pages/Root.css b/src/pages/Root.css new file mode 100644 index 0000000..46e56de --- /dev/null +++ b/src/pages/Root.css @@ -0,0 +1,16 @@ + + +.App { + width: 100vw; + height: 100vh; + + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + + background-color: #101010; + z-index: 9; +} + diff --git a/src/pages/Root.tsx b/src/pages/Root.tsx new file mode 100644 index 0000000..527962c --- /dev/null +++ b/src/pages/Root.tsx @@ -0,0 +1,49 @@ +import { useEffect, useState, useMemo } from 'react'; +import './Root.css'; +import Help from '../component/help'; + +function Root() { + + const name: string[] = useMemo(() => ['imnyang', 'μ•„μž„λƒ₯', 'μ•”λƒ₯', 'μž„λƒ₯', '@not.furry_', '@imnyang', '@mahiro_me'], []); + const [nameIndex, setNameIndex] = useState(0); + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + // 단일 ν‚€ μž…λ ₯ 감지 + console.log(`Key: ${event.key} with keycode ${event.keyCode} has been pressed`); + if (event.key === 'l') { + console.log('Change My Name'); + setNameIndex((prevIndex) => (prevIndex + 1) % name.length); + } + }; + + document.addEventListener('keydown', handleKeyDown); + + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + }, [name.length, name]); + return ( +
+

+ {name[nameIndex]} +

+
+

Press

+

F1

+

and Check Help

+
+
+ πŸ“¬ Mail + πŸˆβ€β¬› Github + πŸ“ Blog +
+
+ 🌈 Timeline + πŸ₯• isangjeong.today +
+ +
+ ) +} + +export default Root; \ No newline at end of file diff --git a/src/pages/Timeline.css b/src/pages/Timeline.css new file mode 100644 index 0000000..36db20b --- /dev/null +++ b/src/pages/Timeline.css @@ -0,0 +1,33 @@ +@import url('https://fonts.googleapis.com/css2?family=Nanum+Gothic+Coding&display=swap'); + +.App { + width: 100vw; + height: 100vh; + + text-align: center; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + + background-color: #101010; + z-index: 9; +} + +.inner { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: center; + text-align: left; +} +.scroll { + height: 60vh; + overflow-y: auto; + padding: 0 20px; +} + +code { + color: #fff; + font-family: "Nanum Gothic Coding", monospace; +} \ No newline at end of file diff --git a/src/pages/Timeline.md b/src/pages/Timeline.md new file mode 100644 index 0000000..5c2958c --- /dev/null +++ b/src/pages/Timeline.md @@ -0,0 +1,31 @@ +# 🌈 Timeline + +- `2024-05-16` [κΈ€λ‘œλ²Œ μŠ€νƒ€νŠΈμ—… 학ꡐ λ² νŠΈλ‚¨ ν•΄μ™Έ μ—°μˆ˜ 데λͺ¨λ°μ΄ λŒ€μƒ (1μœ„)](http://ncf.or.kr) +- `2024-05-11` [κΈ€λ‘œλ²Œ μŠ€νƒ€νŠΈμ—… 학ꡐ 2κΈ° 합격](http://ncf.or.kr) +- `2024-05-11` [LG AI μ²­μ†Œλ…„ μΊ ν”„ 1κΈ° LG 탐색상 μˆ˜μƒ](https://lgaiyouthcamp.or.kr/) +- `2024-05-11` [LG AI μ²­μ†Œλ…„ μΊ ν”„ 1κΈ° 수료](https://lgaiyouthcamp.or.kr/) +- `2024-04-22` [@isangjeong.today (μΈμ²œμƒμ •μ€‘ν•™κ΅μ˜ 였늘 급식)](https://www.instagram.com/isangjeong.today/) +- `2024-04-06` [TimeTable (Sekai 개쑰판 배포) [API μœ μ‹€]](https://timeline.imnyang.xyz) +- `2024-03-24` [Dreamhack #133](https://dreamhack.io/users/40116/wargame) +- `2024-03-24` [Ubuntu Mirror](https://launchpad.net/ubuntu/+mirror/mirror.imnyang.xyz-release) +- `2024-03-24` [λ‚΄ λͺ©μ†Œλ¦¬λ‘œ AI Cover λ§Œλ“€κΈ°](https://colab.research.google.com/drive/1a4G4hD9huBeGRZhEL2HNDMpqSuf4y61k?usp=sharing) +- `2024-01-26` [Fastapiλ₯Ό 톡해 API μ œμž‘](https://github.com/imnyang/api) +- `2023-12-20` LG AI μ²­μ†Œλ…„ μΊ ν”„ 1κΈ° 합격 +- `2023-11-14` μΈμ²œμƒμ •μ€‘ν•™κ΅ 2023학년도 SW 문제 ν•΄κ²° ν™œλ™ μš°μˆ˜μƒ(2μœ„) μˆ˜μ—¬ +- `2023-11-01` [λΈ”λ‘œκ·Έ μ‹œμž‘](https://blog.imnyang.xyz) +- `2023-10-12` [λ‚˜λŠ” 둜컬 μ‹œκ°„μ„ μ•Œκ³  μ‹Άλ‹€](https://time.imnyang.xyz/) +- `2023-09-24` [sqlr.kr 기획 및 초기 개발](https://github.com/sqlare/sqlr.kr/tree/main) +- `2023-09-02` 선린인터넷고등학ꡐ 제6회 μ†Œν”„νŠΈμ›¨μ–΄λ‚˜λŠ μΆ•μ œ Layer7 λΆ€μ„œ κ³Όμ • 이수 +- `2023-08-26` [μ»΄μ‹œκ°„ μ‹œκ°„ν‘œλ₯Ό 더 λ‚˜μ•„λ³΄μ΄κ²Œ Sekai](https://github.com/imnyang/Sekai) +- `2023-08-23` [λ””μŠ€μ½”λ“œ 톡화방 λ…ΉμŒ](https://github.com/imnyang/discord-voice-rec) +- `2023-07-24` ν•œκ΅­μ •λ³΄κΈ°μˆ μ—°κ΅¬μ›μ΄ μ£Όλ„ν•˜λŠ” 사이버 κ°€λ””μ–Έμ¦ˆ λ³΄μ•ˆμΊ ν”„ 수료 +- `2023-03-20` [λ””μŠ€μ½”λ“œμ—μ„œ λŒ€ν™”ν˜• 인곡지λŠ₯ Siru μ œμž‘](https://github.com/imnyang/siru) +- `2023-05-15` ν•œκ΅­ μ½”λ“œνŽ˜μ–΄ μ˜ˆμ„  μ§„μΆœ +- `2023-03-14` [타이머](https://github.com/imnyang/imnyang-timer) +- `2022-12-20` 2022 SW영재 μ°½μž‘λŒ€νšŒ 은상 μˆ˜μƒ +- `2022-09-27` 2022 μ‚Όμ„± μ£Όλ‹ˆμ–΄ SW μ°½μž‘λŒ€νšŒ λ³Έμ„  μ§„μΆœ +- `2022-05-23` 2022학년도 μ„μ •μ΄ˆSWμ˜μž¬ν•™κΈ‰ 첫 μˆ˜μ—… +- `2022-07-26` 제 14회 λ§‘μ€ν•˜λŠ˜ λ§‘μ€μ›ƒμŒ 곡λͺ¨μ „μ—μ„œ λ§‘μ€μ›ƒμŒμƒ μˆ˜μ—¬ +- `2021-11-14` Become a ZEPETO Creator 이수 +- `2021-05-19` μ†Œν”„νŠΈμ›¨μ–΄μ™€ μ „μžμ‹ λ¬Έμ΄ μ£Όκ΄€ν•œ μ†Œν”„νŠΈμ›¨μ–΄μž¬λ‹¨ 꿈찾기 μΊ ν”„ 이수 +- `2018-01-27` 제4회 λ§‘μ€ν•˜λŠ˜ λ§‘μ€μ›ƒμŒ 어린이 문예곡λͺ¨μ „μ—μ„œ μœ„λ‹‰μŠ€μƒ(2μœ„) μˆ˜μ—¬ \ No newline at end of file diff --git a/src/pages/Timeline.tsx b/src/pages/Timeline.tsx new file mode 100644 index 0000000..df08065 --- /dev/null +++ b/src/pages/Timeline.tsx @@ -0,0 +1,21 @@ +import Markdown from "react-markdown"; +import Help from '../component/help'; +import './Timeline.css'; +import markdown from './Timeline.md'; + +import "highlight.js/styles/a11y-dark.css"; +import rehypeHighlight from "rehype-highlight"; + +export default function Timeline() { + return ( +
+
+ ⬅️ Back +
+ +
+
+ +
+ ); +} \ No newline at end of file diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..e85d7c5 --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1,3 @@ +/// + +declare module "*.md"; diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..c189a4a --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,9 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: [], + theme: { + extend: {}, + }, + plugins: [], +} + diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..d739292 --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..ea9d0cd --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..3afdd6e --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "strict": true, + "noEmit": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..3396d37 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,19 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react-swc' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + react(), + // Custom plugin to load markdown files + { + name: "markdown-loader", + transform(code, id) { + if (id.slice(-3) === ".md") { + // For .md files, get the raw content + return `export default ${JSON.stringify(code)};`; + } + } + } + ], +})