diff --git a/package-lock.json b/package-lock.json index bb88d1d..2718723 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-navigation-menu": "^1.2.14", "@radix-ui/react-slot": "^1.2.3", + "@tanstack/react-query": "^5.90.12", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "lucide-react": "^0.548.0", @@ -1734,13 +1735,38 @@ "vite": "^5.2.0 || ^6 || ^7" } }, + "node_modules/@tanstack/query-core": { + "version": "5.90.12", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.12.tgz", + "integrity": "sha512-T1/8t5DhV/SisWjDnaiU2drl6ySvsHj1bHBCWNXd+/T+Hh1cf6JodyEYMd5sgwm+b/mETT4EV3H+zCVczCU5hg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.90.12", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.12.tgz", + "integrity": "sha512-graRZspg7EoEaw0a8faiUASCyJrqjKPdqJ9EwuDRUF9mEYJ1YPczI9H+/agJ0mOJkPCJDk0lsz5QTrLZ/jQ2rg==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "5.90.12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, "node_modules/@trivago/prettier-plugin-sort-imports": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-5.2.2.tgz", "integrity": "sha512-fYDQA9e6yTNmA13TLVSA+WMQRc5Bn/c0EUBditUHNfMMxN7M82c38b1kEggVE3pLpZ0FwkwJkUEKMiOi52JXFA==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "@babel/generator": "^7.26.5", "@babel/parser": "^7.26.7", @@ -1811,7 +1837,6 @@ "integrity": "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -1820,7 +1845,8 @@ "version": "1.26.5", "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.5.tgz", "integrity": "sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/react": { "version": "19.2.2", @@ -1828,7 +1854,6 @@ "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -1839,7 +1864,6 @@ "integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==", "devOptional": true, "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -3291,7 +3315,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -3334,7 +3357,6 @@ "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -3443,7 +3465,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -3464,7 +3485,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -3825,7 +3845,6 @@ "integrity": "sha512-J1QRxf8zlYNvjAY1fB6zW+FLr0K26/IpKFrGM+Za0Ko6meJUMlHBk+LV19gAb8sfSluH4/6dyWKVS2dvNU4RLQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@oxc-project/runtime": "0.96.0", "fdir": "^6.5.0", diff --git a/package.json b/package.json index 7f3ae47..81f3b57 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-navigation-menu": "^1.2.14", "@radix-ui/react-slot": "^1.2.3", + "@tanstack/react-query": "^5.90.12", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "lucide-react": "^0.548.0", diff --git a/src/app/auto-splitters.tsx b/src/app/auto-splitters.tsx new file mode 100644 index 0000000..4c96d8a --- /dev/null +++ b/src/app/auto-splitters.tsx @@ -0,0 +1,9 @@ +import { AppGitHubGenericMarkdown } from "@/components/libresplit/AppGitHubGenericMarkdown"; + +export function AutoSplitters() { + return ( +
+ +
+ ); +} diff --git a/src/app/home.tsx b/src/app/home.tsx index c11e654..af5fdcc 100644 --- a/src/app/home.tsx +++ b/src/app/home.tsx @@ -1,11 +1,11 @@ -import { AppGitHubReadme } from "@/components/libresplit/AppGitHubReadme"; +import { AppGitHubGenericMarkdown } from "@/components/libresplit/AppGitHubGenericMarkdown"; import { AppHero } from "@/components/libresplit/AppHero"; export function Home() { return (
- +
); } diff --git a/src/app/settings-keybinds.tsx b/src/app/settings-keybinds.tsx new file mode 100644 index 0000000..9bda018 --- /dev/null +++ b/src/app/settings-keybinds.tsx @@ -0,0 +1,9 @@ +import { AppGitHubGenericMarkdown } from "@/components/libresplit/AppGitHubGenericMarkdown"; + +export function SettingsKeybinds() { + return ( +
+ +
+ ); +} diff --git a/src/app/split-files.tsx b/src/app/split-files.tsx new file mode 100644 index 0000000..ced460a --- /dev/null +++ b/src/app/split-files.tsx @@ -0,0 +1,9 @@ +import { AppGitHubGenericMarkdown } from "@/components/libresplit/AppGitHubGenericMarkdown"; + +export function SplitFiles() { + return ( +
+ +
+ ); +} diff --git a/src/app/themes.tsx b/src/app/themes.tsx new file mode 100644 index 0000000..3d06a38 --- /dev/null +++ b/src/app/themes.tsx @@ -0,0 +1,9 @@ +import { AppGitHubGenericMarkdown } from "@/components/libresplit/AppGitHubGenericMarkdown"; + +export function Themes() { + return ( +
+ +
+ ); +} diff --git a/src/app/troubleshooting.tsx b/src/app/troubleshooting.tsx new file mode 100644 index 0000000..284ba03 --- /dev/null +++ b/src/app/troubleshooting.tsx @@ -0,0 +1,9 @@ +import { AppGitHubGenericMarkdown } from "@/components/libresplit/AppGitHubGenericMarkdown"; + +export function Troubleshooting() { + return ( +
+ +
+ ); +} diff --git a/src/components/libresplit/AppGitHubGenericMarkdown.tsx b/src/components/libresplit/AppGitHubGenericMarkdown.tsx new file mode 100644 index 0000000..edb6179 --- /dev/null +++ b/src/components/libresplit/AppGitHubGenericMarkdown.tsx @@ -0,0 +1,37 @@ +import { AppLoading } from "./AppLoading"; +import { Markdown } from "@/lib/markdown"; +import { useQuery } from "@tanstack/react-query"; + +async function fetchMarkdown(url: string): Promise { + const res = await fetch(url); + + if (!res.ok) { + throw new Error("Failed to fetch markdown from GitHub."); + } + + return res.text(); +} + +type AppGitHubGenericMarkdownProps = { + url: string; +}; + +export function AppGitHubGenericMarkdown({ + url, +}: AppGitHubGenericMarkdownProps) { + const { data, isLoading, error } = useQuery({ + queryKey: ["markdown-text"], + queryFn: () => fetchMarkdown(url), + enabled: !!url, + }); + + if (isLoading) return ; + if (error) return
Failed to fetch markdown from GitHub.
; + if (!data) return
Failed to fetch markdown from GitHub.
; + + return ( +
+ +
+ ); +} diff --git a/src/components/libresplit/AppGitHubReadme.tsx b/src/components/libresplit/AppGitHubReadme.tsx deleted file mode 100644 index 464b0f6..0000000 --- a/src/components/libresplit/AppGitHubReadme.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { useEffect, useState } from "react"; - -import { AppLoading } from "./AppLoading"; -import { Markdown } from "@/lib/markdown"; - -export function AppGitHubReadme() { - const [readme, setReadme] = useState("Loading..."); - const [isLoading, setIsLoading] = useState(true); - - const urlReadme = - "https://raw.githubusercontent.com/LibreSplit/LibreSplit/refs/heads/main/README.md"; - - // Fetch markdown from GitHub page for LibreSplit, place into the readme state. - useEffect(() => { - fetch(urlReadme) - .then((res) => { - if (!res.ok) throw new Error(`HTTP Error! Status: ${res.status}`); - return res.text(); - }) - .then((text) => setReadme(text)) - .catch(() => setReadme("Failed to load README from GitHub.")) - .finally(() => setIsLoading(false)); - }, []); - - if (isLoading) { - return ; - } - - return ( -
- -
- ); -} diff --git a/src/main.tsx b/src/main.tsx index 8610034..6609c20 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -2,21 +2,26 @@ import { StrictMode } from "react"; import App from "./app"; import "./index.css"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { ThemeProvider } from "next-themes"; import { createRoot } from "react-dom/client"; import { BrowserRouter } from "react-router"; +const queryClient = new QueryClient(); + createRoot(document.getElementById("root")!).render( - - - - - + + + + + + + , ); diff --git a/src/router.tsx b/src/router.tsx index fcf97aa..3b96332 100644 --- a/src/router.tsx +++ b/src/router.tsx @@ -1,6 +1,11 @@ +import { AutoSplitters } from "./app/auto-splitters"; import { Converter } from "./app/converter"; import { Home } from "./app/home"; import { NotFound } from "./app/not-found"; +import { SettingsKeybinds } from "./app/settings-keybinds"; +import { SplitFiles } from "./app/split-files"; +import { Themes } from "./app/themes"; +import { Troubleshooting } from "./app/troubleshooting"; import { Route, Routes } from "react-router"; export default function AppRouter() { @@ -9,6 +14,13 @@ export default function AppRouter() { } /> } /> + {/* Documentation pages pulled from GitHub. */} + } /> + } /> + } /> + } /> + } /> + {/* Fall back on app's 404 page. This is because of the SPA routing trick with 404.html used in GitHub Pages. */} } /> diff --git a/vite.config.ts b/vite.config.ts index 4ea20f7..5c8d2c1 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -13,7 +13,14 @@ export default defineConfig({ copyIndexTo404(), sitemap({ hostname: "https://libresplit.org", - dynamicRoutes: ["/converter"], + dynamicRoutes: [ + "/converter", + "/docs/auto-splitters.md", + "/docs/settings-keybinds.md", + "/docs/split-files.md", + "/docs/themes.md", + "/docs/troubleshooting.md", + ], exclude: ["/404"], }), ],