add: solid.js powered frontend
This commit is contained in:
parent
92c3c8eefe
commit
edbae956ca
28
packages/solid/.gitignore
vendored
Normal file
28
packages/solid/.gitignore
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
dist
|
||||||
|
.wrangler
|
||||||
|
.output
|
||||||
|
.vercel
|
||||||
|
.netlify
|
||||||
|
.vinxi
|
||||||
|
app.config.timestamp_*.js
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
.env
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
|
||||||
|
# IDEs and editors
|
||||||
|
/.idea
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
*.launch
|
||||||
|
.settings/
|
||||||
|
|
||||||
|
# Temp
|
||||||
|
gitignore
|
||||||
|
|
||||||
|
# System Files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
32
packages/solid/README.md
Normal file
32
packages/solid/README.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# SolidStart
|
||||||
|
|
||||||
|
Everything you need to build a Solid project, powered by [`solid-start`](https://start.solidjs.com);
|
||||||
|
|
||||||
|
## Creating a project
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# create a new project in the current directory
|
||||||
|
npm init solid@latest
|
||||||
|
|
||||||
|
# create a new project in my-app
|
||||||
|
npm init solid@latest my-app
|
||||||
|
```
|
||||||
|
|
||||||
|
## Developing
|
||||||
|
|
||||||
|
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# or start the server and open the app in a new browser tab
|
||||||
|
npm run dev -- --open
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
Solid apps are built with _presets_, which optimise your project for deployment to different environments.
|
||||||
|
|
||||||
|
By default, `npm run build` will generate a Node app that you can run with `npm start`. To use a different preset, add it to the `devDependencies` in `package.json` and specify in your `app.config.js`.
|
||||||
|
|
||||||
|
## This project was created with the [Solid CLI](https://github.com/solidjs-community/solid-cli)
|
8
packages/solid/app.config.ts
Normal file
8
packages/solid/app.config.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { defineConfig } from "@solidjs/start/config";
|
||||||
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
vite: {
|
||||||
|
plugins: [tailwindcss()]
|
||||||
|
}
|
||||||
|
});
|
1648
packages/solid/bun.lock
Normal file
1648
packages/solid/bun.lock
Normal file
File diff suppressed because it is too large
Load Diff
28
packages/solid/package.json
Normal file
28
packages/solid/package.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "example-basic",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vinxi dev --port 9200",
|
||||||
|
"build": "vinxi build",
|
||||||
|
"start": "vinxi start",
|
||||||
|
"version": "vinxi version"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@solidjs/meta": "^0.29.4",
|
||||||
|
"@solidjs/router": "^0.15.0",
|
||||||
|
"@solidjs/start": "^1.1.0",
|
||||||
|
"@tailwindcss/vite": "^4.1.10",
|
||||||
|
"@types/luxon": "^3.6.2",
|
||||||
|
"luxon": "^3.6.1",
|
||||||
|
"solid-js": "^1.9.5",
|
||||||
|
"tailwindcss": "^4.1.10",
|
||||||
|
"vinxi": "^0.5.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=22"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tailwindcss/postcss": "^4.1.10",
|
||||||
|
"postcss": "^8.5.6"
|
||||||
|
}
|
||||||
|
}
|
5
packages/solid/postcss.config.mjs
Normal file
5
packages/solid/postcss.config.mjs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export default {
|
||||||
|
plugins: {
|
||||||
|
"@tailwindcss/postcss": {}
|
||||||
|
}
|
||||||
|
};
|
106
packages/solid/src/app.css
Normal file
106
packages/solid/src/app.css
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
@import url("./fonts/InterFont/Inter.css");
|
||||||
|
@import url("./fonts/MiSans/MiSans.css");
|
||||||
|
|
||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
@theme {
|
||||||
|
--color-background: #fff8f6;
|
||||||
|
--color-on-background: #2a1613;
|
||||||
|
--color-surface: #fff8f6;
|
||||||
|
--color-surface-dim: #f7d2cc;
|
||||||
|
--color-surface-bright: #fff8f6;
|
||||||
|
--color-surface-container-lowest: #ffffff;
|
||||||
|
--color-surface-container-low: #fff0ee;
|
||||||
|
--color-surface-container: #ffe9e6;
|
||||||
|
--color-surface-container-high: #ffe2dd;
|
||||||
|
--color-surface-container-highest: #ffdad4;
|
||||||
|
--color-on-surface: #2a1613;
|
||||||
|
--color-surface-variant: #ffdad4;
|
||||||
|
--color-on-surface-variant: #5f3e39;
|
||||||
|
--color-inverse-surface: #422b27;
|
||||||
|
--color-inverse-on-surface: #ffedea;
|
||||||
|
--color-outline: #946e68;
|
||||||
|
--color-outline-variant: #eabcb4;
|
||||||
|
--color-shadow: #000000;
|
||||||
|
--color-scrim: #000000;
|
||||||
|
--color-surface-tint: #c00100;
|
||||||
|
--color-primary: #a50100;
|
||||||
|
--color-on-primary: #ffffff;
|
||||||
|
--color-primary-container: #eb0000;
|
||||||
|
--color-on-primary-container: #ffffff;
|
||||||
|
--color-inverse-primary: #ffb4a8;
|
||||||
|
--color-secondary: #b4271a;
|
||||||
|
--color-on-secondary: #ffffff;
|
||||||
|
--color-secondary-container: #ff7460;
|
||||||
|
--color-on-secondary-container: #2f0000;
|
||||||
|
--color-tertiary: #6f4800;
|
||||||
|
--color-on-tertiary: #ffffff;
|
||||||
|
--color-tertiary-container: #9f6900;
|
||||||
|
--color-on-tertiary-container: #ffffff;
|
||||||
|
--color-error: #ba1a1a;
|
||||||
|
--color-on-error: #ffffff;
|
||||||
|
--color-error-container: #ffdad6;
|
||||||
|
--color-on-error-container: #410002;
|
||||||
|
|
||||||
|
--color-dark-background: #210e0b;
|
||||||
|
--color-dark-on-background: #ffdad4;
|
||||||
|
--color-dark-surface: #210e0b;
|
||||||
|
--color-dark-surface-dim: #210e0b;
|
||||||
|
--color-dark-surface-bright: #4b332f;
|
||||||
|
--color-dark-surface-container-lowest: #1b0907;
|
||||||
|
--color-dark-surface-container-low: #2a1613;
|
||||||
|
--color-dark-surface-container: #2f1a17;
|
||||||
|
--color-dark-surface-container-high: #3a2421;
|
||||||
|
--color-dark-surface-container-highest: #462f2b;
|
||||||
|
--color-dark-on-surface: #ffdad4;
|
||||||
|
--color-dark-surface-variant: #5f3e39;
|
||||||
|
--color-dark-on-surface-variant: #eabcb4;
|
||||||
|
--color-dark-inverse-surface: #ffdad4;
|
||||||
|
--color-dark-inverse-on-surface: #422b27;
|
||||||
|
--color-dark-outline: #b08780;
|
||||||
|
--color-dark-outline-variant: #5f3e39;
|
||||||
|
--color-dark-shadow: #000000;
|
||||||
|
--color-dark-scrim: #000000;
|
||||||
|
--color-dark-surface-tint: #ffb4a8;
|
||||||
|
--color-dark-primary: #ffb4a8;
|
||||||
|
--color-dark-on-primary: #690000;
|
||||||
|
--color-dark-primary-container: #de0000;
|
||||||
|
--color-dark-on-primary-container: #ffffff;
|
||||||
|
--color-dark-inverse-primary: #c00100;
|
||||||
|
--color-dark-secondary: #ffb4a8;
|
||||||
|
--color-dark-on-secondary: #690000;
|
||||||
|
--color-dark-secondary-container: #870100;
|
||||||
|
--color-dark-on-secondary-container: #ffc9c0;
|
||||||
|
--color-dark-tertiary: #feba54;
|
||||||
|
--color-dark-on-tertiary: #452b00;
|
||||||
|
--color-dark-tertiary-container: #966300;
|
||||||
|
--color-dark-on-tertiary-container: #ffffff;
|
||||||
|
--color-dark-error: #ffb4ab;
|
||||||
|
--color-dark-on-error: #690005;
|
||||||
|
--color-dark-error-container: #93000a;
|
||||||
|
--color-dark-on-error-container: #ffdad6;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
@apply text-primary dark:text-dark-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
font-family: "Inter", "MiSans", sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
@apply bg-surface dark:bg-dark-surface text-on-surface dark:text-dark-on-surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type="search"]::-webkit-search-cancel-button,
|
||||||
|
[type="search"]::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@supports (font-variation-settings: normal) {
|
||||||
|
:root {
|
||||||
|
font-family: "Inter Variable", "MiSans VF", sans-serif;
|
||||||
|
font-optical-sizing: auto;
|
||||||
|
font-weight: 330;
|
||||||
|
}
|
||||||
|
}
|
19
packages/solid/src/app.tsx
Normal file
19
packages/solid/src/app.tsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { MetaProvider } from "@solidjs/meta";
|
||||||
|
import { Router } from "@solidjs/router";
|
||||||
|
import { FileRoutes } from "@solidjs/start/router";
|
||||||
|
import { Suspense } from "solid-js";
|
||||||
|
import "./app.css";
|
||||||
|
|
||||||
|
export default function App() {
|
||||||
|
return (
|
||||||
|
<Router
|
||||||
|
root={(props) => (
|
||||||
|
<MetaProvider>
|
||||||
|
<Suspense>{props.children}</Suspense>
|
||||||
|
</MetaProvider>
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<FileRoutes />
|
||||||
|
</Router>
|
||||||
|
);
|
||||||
|
}
|
21
packages/solid/src/components/Counter.css
Normal file
21
packages/solid/src/components/Counter.css
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
.increment {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
padding: 1em 2em;
|
||||||
|
color: #335d92;
|
||||||
|
background-color: rgba(68, 107, 158, 0.1);
|
||||||
|
border-radius: 2em;
|
||||||
|
border: 2px solid rgba(68, 107, 158, 0);
|
||||||
|
outline: none;
|
||||||
|
width: 200px;
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.increment:focus {
|
||||||
|
border: 2px solid #335d92;
|
||||||
|
}
|
||||||
|
|
||||||
|
.increment:active {
|
||||||
|
background-color: rgba(68, 107, 158, 0.2);
|
||||||
|
}
|
11
packages/solid/src/components/Counter.tsx
Normal file
11
packages/solid/src/components/Counter.tsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { createSignal } from "solid-js";
|
||||||
|
import "./Counter.css";
|
||||||
|
|
||||||
|
export default function Counter() {
|
||||||
|
const [count, setCount] = createSignal(0);
|
||||||
|
return (
|
||||||
|
<button class="increment" onClick={() => setCount(count() + 1)} type="button">
|
||||||
|
Clicks: {count()}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
4
packages/solid/src/entry-client.tsx
Normal file
4
packages/solid/src/entry-client.tsx
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
// @refresh reload
|
||||||
|
import { mount, StartClient } from "@solidjs/start/client";
|
||||||
|
|
||||||
|
mount(() => <StartClient />, document.getElementById("app")!);
|
23
packages/solid/src/entry-server.tsx
Normal file
23
packages/solid/src/entry-server.tsx
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// @refresh reload
|
||||||
|
import { createHandler, StartServer } from "@solidjs/start/server";
|
||||||
|
import { MetaProvider } from "@solidjs/meta";
|
||||||
|
|
||||||
|
export default createHandler(() => (
|
||||||
|
<StartServer
|
||||||
|
document={({ assets, children, scripts }) => (
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<MetaProvider></MetaProvider>
|
||||||
|
{assets}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app">{children}</div>
|
||||||
|
{scripts}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
));
|
BIN
packages/solid/src/fonts/InterFont/Inter-Black.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-Black.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/Inter-BlackItalic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-BlackItalic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/Inter-Bold.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-Bold.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/Inter-BoldItalic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-BoldItalic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/Inter-ExtraBold.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-ExtraBold.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/Inter-ExtraBoldItalic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-ExtraBoldItalic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/Inter-ExtraLight.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-ExtraLight.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/Inter-ExtraLightItalic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-ExtraLightItalic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/Inter-Italic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-Italic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/Inter-Light.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-Light.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/Inter-LightItalic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-LightItalic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/Inter-Medium.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-Medium.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/Inter-MediumItalic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-MediumItalic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/Inter-Regular.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-Regular.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/Inter-SemiBold.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-SemiBold.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/Inter-SemiBoldItalic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-SemiBoldItalic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/Inter-Thin.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-Thin.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/Inter-ThinItalic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/Inter-ThinItalic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
449
packages/solid/src/fonts/InterFont/Inter.css
Normal file
449
packages/solid/src/fonts/InterFont/Inter.css
Normal file
@ -0,0 +1,449 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: "Inter Variable";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 100 900;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterVariable.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter Variable";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 100 900;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterVariable-Italic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static fonts */
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 100;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-Thin.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 100;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-ThinItalic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 200;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-ExtraLight.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 200;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-ExtraLightItalic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 300;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-Light.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 300;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-LightItalic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-Regular.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 400;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-Italic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-Medium.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 500;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-MediumItalic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-SemiBold.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 600;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-SemiBoldItalic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-Bold.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 700;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-BoldItalic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 800;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-ExtraBold.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 800;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-ExtraBoldItalic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 900;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-Black.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Inter";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 900;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("Inter-BlackItalic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 100;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-Thin.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 100;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-ThinItalic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 200;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-ExtraLight.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 200;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-ExtraLightItalic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 300;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-Light.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 300;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-LightItalic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-Regular.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 400;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-Italic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-Medium.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 500;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-MediumItalic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-SemiBold.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 600;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-SemiBoldItalic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-Bold.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 700;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-BoldItalic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 800;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-ExtraBold.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 800;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-ExtraBoldItalic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 900;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-Black.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "InterDisplay";
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: 900;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("InterDisplay-BlackItalic.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-feature-values InterVariable {
|
||||||
|
@character-variant {
|
||||||
|
cv01: 1;
|
||||||
|
cv02: 2;
|
||||||
|
cv03: 3;
|
||||||
|
cv04: 4;
|
||||||
|
cv05: 5;
|
||||||
|
cv06: 6;
|
||||||
|
cv07: 7;
|
||||||
|
cv08: 8;
|
||||||
|
cv09: 9;
|
||||||
|
cv10: 10;
|
||||||
|
cv11: 11;
|
||||||
|
cv12: 12;
|
||||||
|
cv13: 13;
|
||||||
|
alt-1: 1; /* Alternate one */
|
||||||
|
alt-3: 9; /* Flat-top three */
|
||||||
|
open-4: 2; /* Open four */
|
||||||
|
open-6: 3; /* Open six */
|
||||||
|
open-9: 4; /* Open nine */
|
||||||
|
lc-l-with-tail: 5; /* Lower-case L with tail */
|
||||||
|
simplified-u: 6; /* Simplified u */
|
||||||
|
alt-double-s: 7; /* Alternate German double s */
|
||||||
|
uc-i-with-serif: 8; /* Upper-case i with serif */
|
||||||
|
uc-g-with-spur: 10; /* Capital G with spur */
|
||||||
|
single-story-a: 11; /* Single-story a */
|
||||||
|
compact-lc-f: 12; /* Compact f */
|
||||||
|
compact-lc-t: 13; /* Compact t */
|
||||||
|
}
|
||||||
|
@styleset {
|
||||||
|
ss01: 1;
|
||||||
|
ss02: 2;
|
||||||
|
ss03: 3;
|
||||||
|
ss04: 4;
|
||||||
|
ss05: 5;
|
||||||
|
ss06: 6;
|
||||||
|
ss07: 7;
|
||||||
|
ss08: 8;
|
||||||
|
open-digits: 1; /* Open digits */
|
||||||
|
disambiguation: 2; /* Disambiguation (with zero) */
|
||||||
|
disambiguation-except-zero: 4; /* Disambiguation (no zero) */
|
||||||
|
round-quotes-and-commas: 3; /* Round quotes & commas */
|
||||||
|
square-punctuation: 7; /* Square punctuation */
|
||||||
|
square-quotes: 8; /* Square quotes */
|
||||||
|
circled-characters: 5; /* Circled characters */
|
||||||
|
squared-characters: 6; /* Squared characters */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@font-feature-values Inter {
|
||||||
|
@character-variant {
|
||||||
|
cv01: 1;
|
||||||
|
cv02: 2;
|
||||||
|
cv03: 3;
|
||||||
|
cv04: 4;
|
||||||
|
cv05: 5;
|
||||||
|
cv06: 6;
|
||||||
|
cv07: 7;
|
||||||
|
cv08: 8;
|
||||||
|
cv09: 9;
|
||||||
|
cv10: 10;
|
||||||
|
cv11: 11;
|
||||||
|
cv12: 12;
|
||||||
|
cv13: 13;
|
||||||
|
alt-1: 1; /* Alternate one */
|
||||||
|
alt-3: 9; /* Flat-top three */
|
||||||
|
open-4: 2; /* Open four */
|
||||||
|
open-6: 3; /* Open six */
|
||||||
|
open-9: 4; /* Open nine */
|
||||||
|
lc-l-with-tail: 5; /* Lower-case L with tail */
|
||||||
|
simplified-u: 6; /* Simplified u */
|
||||||
|
alt-double-s: 7; /* Alternate German double s */
|
||||||
|
uc-i-with-serif: 8; /* Upper-case i with serif */
|
||||||
|
uc-g-with-spur: 10; /* Capital G with spur */
|
||||||
|
single-story-a: 11; /* Single-story a */
|
||||||
|
compact-lc-f: 12; /* Compact f */
|
||||||
|
compact-lc-t: 13; /* Compact t */
|
||||||
|
}
|
||||||
|
@styleset {
|
||||||
|
ss01: 1;
|
||||||
|
ss02: 2;
|
||||||
|
ss03: 3;
|
||||||
|
ss04: 4;
|
||||||
|
ss05: 5;
|
||||||
|
ss06: 6;
|
||||||
|
ss07: 7;
|
||||||
|
ss08: 8;
|
||||||
|
open-digits: 1; /* Open digits */
|
||||||
|
disambiguation: 2; /* Disambiguation (with zero) */
|
||||||
|
disambiguation-except-zero: 4; /* Disambiguation (no zero) */
|
||||||
|
round-quotes-and-commas: 3; /* Round quotes & commas */
|
||||||
|
square-punctuation: 7; /* Square punctuation */
|
||||||
|
square-quotes: 8; /* Square quotes */
|
||||||
|
circled-characters: 5; /* Circled characters */
|
||||||
|
squared-characters: 6; /* Squared characters */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@font-feature-values InterDisplay {
|
||||||
|
@character-variant {
|
||||||
|
cv01: 1;
|
||||||
|
cv02: 2;
|
||||||
|
cv03: 3;
|
||||||
|
cv04: 4;
|
||||||
|
cv05: 5;
|
||||||
|
cv06: 6;
|
||||||
|
cv07: 7;
|
||||||
|
cv08: 8;
|
||||||
|
cv09: 9;
|
||||||
|
cv10: 10;
|
||||||
|
cv11: 11;
|
||||||
|
cv12: 12;
|
||||||
|
cv13: 13;
|
||||||
|
alt-1: 1; /* Alternate one */
|
||||||
|
alt-3: 9; /* Flat-top three */
|
||||||
|
open-4: 2; /* Open four */
|
||||||
|
open-6: 3; /* Open six */
|
||||||
|
open-9: 4; /* Open nine */
|
||||||
|
lc-l-with-tail: 5; /* Lower-case L with tail */
|
||||||
|
simplified-u: 6; /* Simplified u */
|
||||||
|
alt-double-s: 7; /* Alternate German double s */
|
||||||
|
uc-i-with-serif: 8; /* Upper-case i with serif */
|
||||||
|
uc-g-with-spur: 10; /* Capital G with spur */
|
||||||
|
single-story-a: 11; /* Single-story a */
|
||||||
|
compact-lc-f: 12; /* Compact f */
|
||||||
|
compact-lc-t: 13; /* Compact t */
|
||||||
|
}
|
||||||
|
@styleset {
|
||||||
|
ss01: 1;
|
||||||
|
ss02: 2;
|
||||||
|
ss03: 3;
|
||||||
|
ss04: 4;
|
||||||
|
ss05: 5;
|
||||||
|
ss06: 6;
|
||||||
|
ss07: 7;
|
||||||
|
ss08: 8;
|
||||||
|
open-digits: 1; /* Open digits */
|
||||||
|
disambiguation: 2; /* Disambiguation (with zero) */
|
||||||
|
disambiguation-except-zero: 4; /* Disambiguation (no zero) */
|
||||||
|
round-quotes-and-commas: 3; /* Round quotes & commas */
|
||||||
|
square-punctuation: 7; /* Square punctuation */
|
||||||
|
square-quotes: 8; /* Square quotes */
|
||||||
|
circled-characters: 5; /* Circled characters */
|
||||||
|
squared-characters: 6; /* Squared characters */
|
||||||
|
}
|
||||||
|
}
|
BIN
packages/solid/src/fonts/InterFont/InterDisplay-Black.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-Black.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterDisplay-BlackItalic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-BlackItalic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterDisplay-Bold.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-Bold.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterDisplay-BoldItalic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-BoldItalic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterDisplay-ExtraBold.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-ExtraBold.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterDisplay-ExtraBoldItalic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-ExtraBoldItalic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterDisplay-ExtraLight.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-ExtraLight.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterDisplay-ExtraLightItalic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-ExtraLightItalic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterDisplay-Italic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-Italic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterDisplay-Light.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-Light.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterDisplay-LightItalic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-LightItalic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterDisplay-Medium.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-Medium.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterDisplay-MediumItalic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-MediumItalic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterDisplay-Regular.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-Regular.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterDisplay-SemiBold.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-SemiBold.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterDisplay-SemiBoldItalic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-SemiBoldItalic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterDisplay-Thin.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-Thin.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterDisplay-ThinItalic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterDisplay-ThinItalic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterVariable-Italic.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterVariable-Italic.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/InterFont/InterVariable.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/InterFont/InterVariable.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/MiSans/MiSans VF.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/MiSans/MiSans VF.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/MiSans/MiSans-Bold.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/MiSans/MiSans-Bold.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/MiSans/MiSans-Demibold.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/MiSans/MiSans-Demibold.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/MiSans/MiSans-ExtraLight.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/MiSans/MiSans-ExtraLight.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/MiSans/MiSans-Heavy.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/MiSans/MiSans-Heavy.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/MiSans/MiSans-Light.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/MiSans/MiSans-Light.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/MiSans/MiSans-Medium.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/MiSans/MiSans-Medium.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/MiSans/MiSans-Normal.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/MiSans/MiSans-Normal.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/MiSans/MiSans-Regular.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/MiSans/MiSans-Regular.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/MiSans/MiSans-Semibold.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/MiSans/MiSans-Semibold.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
packages/solid/src/fonts/MiSans/MiSans-Thin.woff2
(Stored with Git LFS)
Normal file
BIN
packages/solid/src/fonts/MiSans/MiSans-Thin.woff2
(Stored with Git LFS)
Normal file
Binary file not shown.
87
packages/solid/src/fonts/MiSans/MiSans.css
Normal file
87
packages/solid/src/fonts/MiSans/MiSans.css
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: "MiSans VF";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 150 700;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("MiSans VF.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "MiSans";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 100;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("MiSans-Thin.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "MiSans";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 200;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("MiSans-ExtraLight.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "MiSans";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 300;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("MiSans-Light.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "MiSans";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 360;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("MiSans-Normal.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "MiSans";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("MiSans-Regular.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "MiSans";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("MiSans-Medium.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "MiSans";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("MiSans-Demibold.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "MiSans";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("MiSans-Semibold.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "MiSans";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 800;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("MiSans-Bold.woff2") format("woff2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "MiSans";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 900;
|
||||||
|
font-display: fallback;
|
||||||
|
src: url("MiSans-Heavy.woff2") format("woff2");
|
||||||
|
}
|
1
packages/solid/src/global.d.ts
vendored
Normal file
1
packages/solid/src/global.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/// <reference types="@solidjs/start/env" />
|
25
packages/solid/src/lib/const.ts
Normal file
25
packages/solid/src/lib/const.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
const N_1024 = BigInt(
|
||||||
|
"129023318876534346704360951712586568674758913224876821534686030409476129469193481910786173836188085930974906857867802234113909470848523288588793477904039083513378341278558405407018889387577114155572311708428733260891448259786041525189132461448841652472631435226032063278124857443496954605482776113964107326943"
|
||||||
|
);
|
||||||
|
|
||||||
|
const N_2048 = BigInt(
|
||||||
|
"23987552118069940970878653610463005981599204778388399885550631951871084945075866571231062435627294546200946516668493107358732376187241747090707087544153108117326163500579370560400058549184722138636116585329496684877258304519458316233517215780035360354808658620079068489084797380781488445517430961701007542207001544091884001098497324624368085682074645221148086075871342544591022944384890014176612259729018968864426602901247715051556212559854689574013699665035317257438297910516976812428036717668766321871780963854649899276251822244719887233041422346429752896925499321431273560130952088238625622570366815755926694833109"
|
||||||
|
);
|
||||||
|
|
||||||
|
const N_1792 = BigInt(
|
||||||
|
"23987552118069940970878653610463005981599204778388399885550631951871084945075866571231062435627294546200946516668493107358732376187241747090707087544153108117326163500579370560400058549184722138636116585329496684877258304519458316233517215780035360354808658620079068489084797380781488445517430961701007542207001544091884001098497324624368085682074645221148086075871342544591022944384890014176612259729018968864426602901247715051556212559854689574013699665035317257438297910516976812428036717668766321871780963854649899276251822244719887233041422346429752896925499321431273560130952088238625622570366815755926694833109"
|
||||||
|
);
|
||||||
|
|
||||||
|
const N_1536 = BigInt(
|
||||||
|
"1694330250214463438908848400950857073137355630337290254958754184668036770489801447652464038218330711288158361242955860326168191830448553710492926795708495297280933502917598985378231124113971732841791156356676046934277122699383776036675381503510992810963611269045078440132744168908318454891211962146563551929591147663448816841024591820348784855441153716551049843185172472891407933214238000452095646085222944171689449292644270516031799660928056315886939284985905227"
|
||||||
|
);
|
||||||
|
|
||||||
|
const N_3072 = BigInt(
|
||||||
|
"4432919939296042464443862503456460073874727648022810391370558006281079088795179408238989283371442564716849343712703672836423961818025813387453469700639513190304802553045342607888612037304066433501317127429264242784608682213025490491212489901736408833027611579294436675682774458141490718959615677971745638214649336218217578937534746160749039668886450447773018369168258067682196337978245372237157696236362344796867228581553446331915147012787367438751646936429739232247148712001806846526947508445039707404287951727838234648917450736371192435665040644040487427986702098273581288935278964444790007953559851323281510927332862225214878776790605026472021669614552481167977412450477230442015077669503312683966631454347169703030544483487968842349634064181183599641180349414682042575010303056241481622837185325228233789954078775053744988023738762706404546546146837242590884760044438874357295029411988267287001033032827035809135092270843"
|
||||||
|
);
|
||||||
|
|
||||||
|
const N_4096 = BigInt(
|
||||||
|
"703671044356805218391078271512201582198770553281951369783674142891088501340774249238173262580562112786670043634665390581120113644316651934154746357220932310140476300088580654571796404198410555061275065442553506658401183560336140989074165998202690496991174269748740565700402715364422506782445179963440819952745241176450402011121226863984008975377353558155910994380700267903933205531681076494639818328879475919332604951949178075254600102192323286738973253864238076198710173840170988339024438220034106150475640983877458155141500313471699516670799821379238743709125064098477109094533426340852518505385314780319279862586851512004686798362431227795743253799490998475141728082088984359237540124375439664236138519644100625154580910233437864328111620708697941949936338367445851449766581651338876219676721272448769082914348242483068204896479076062102236087066428603930888978596966798402915747531679758905013008059396214343112694563043918465373870648649652122703709658068801764236979191262744515840224548957285182453209028157886219424802426566456408109642062498413592155064289314088837031184200671561102160059065729282902863248815224399131391716503171191977463328439766546574118092303414702384104112719959325482439604572518549918705623086363111"
|
||||||
|
);
|
||||||
|
|
||||||
|
export const N_ARRAY = [N_1024, N_1536, N_1792, N_2048, N_3072, N_4096];
|
8
packages/solid/src/lib/db/bilibili_metadata/aidExists.ts
Normal file
8
packages/solid/src/lib/db/bilibili_metadata/aidExists.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { sql } from "@cvsa/core";
|
||||||
|
|
||||||
|
export async function aidExists(aid: number) {
|
||||||
|
const res = await sql`
|
||||||
|
SELECT 1 FROM bilibili_metadata WHERE aid = ${aid}
|
||||||
|
`;
|
||||||
|
return res.length > 0;
|
||||||
|
}
|
15
packages/solid/src/lib/db/bilibili_metadata/getAidFromBV.ts
Normal file
15
packages/solid/src/lib/db/bilibili_metadata/getAidFromBV.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { sql } from "@cvsa/core";
|
||||||
|
|
||||||
|
export async function getAidFromBV(bv: string) {
|
||||||
|
const res = await sql`
|
||||||
|
SELECT aid FROM bilibili_metadata WHERE bvid = ${bv}
|
||||||
|
`;
|
||||||
|
if (res.length <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const row = res[0];
|
||||||
|
if (row && row.aid) {
|
||||||
|
return Number(row.aid);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
import { BiliVideoMetadataType, sql } from "@cvsa/core";
|
||||||
|
|
||||||
|
export async function getVideoMetadata(aid: number) {
|
||||||
|
const res = await sql<BiliVideoMetadataType[]>`
|
||||||
|
SELECT * FROM bilibili_metadata WHERE aid = ${aid}
|
||||||
|
`;
|
||||||
|
if (res.length <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const row = res[0];
|
||||||
|
if (row) {
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
11
packages/solid/src/lib/db/snapshots/getAllSnapshots.ts
Normal file
11
packages/solid/src/lib/db/snapshots/getAllSnapshots.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { VideoSnapshotType, sql } from "@cvsa/core";
|
||||||
|
|
||||||
|
export async function getAllSnapshots(aid: number) {
|
||||||
|
const res = await sql<VideoSnapshotType[]>`
|
||||||
|
SELECT * FROM video_snapshot WHERE aid = ${aid} ORDER BY created_at DESC
|
||||||
|
`;
|
||||||
|
if (res.length <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
56
packages/solid/src/lib/db/user.ts
Normal file
56
packages/solid/src/lib/db/user.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { UserType, sqlCred } from "@cvsa/core";
|
||||||
|
import { UserProfile } from "../userAuth";
|
||||||
|
|
||||||
|
export const getUserBySession = async (sessionID: string) => {
|
||||||
|
const users = await sqlCred<UserType[]>`
|
||||||
|
SELECT user_id as id, username, nickname, "role", user_created_at as created_at
|
||||||
|
FROM get_user_by_session_func(${sessionID});
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (users.length === 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = users[0];
|
||||||
|
return {
|
||||||
|
uid: user.id,
|
||||||
|
username: user.username,
|
||||||
|
nickname: user.nickname,
|
||||||
|
role: user.role,
|
||||||
|
createdAt: user.created_at
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const queryUserProfile = async (uid: number, sessionID?: string): Promise<UserProfile | null> => {
|
||||||
|
interface Result extends UserType {
|
||||||
|
logged_in: boolean;
|
||||||
|
}
|
||||||
|
const users = await sqlCred<Result[]>`
|
||||||
|
SELECT
|
||||||
|
u.id, u.username, u.nickname, u."role", u.created_at,
|
||||||
|
CASE
|
||||||
|
WHEN (ls.uid IS NOT NULL AND ls.deactivated_at IS NULL AND ls.expire_at > NOW()) THEN TRUE
|
||||||
|
ELSE FALSE
|
||||||
|
END AS logged_in
|
||||||
|
FROM
|
||||||
|
users u
|
||||||
|
LEFT JOIN
|
||||||
|
login_sessions ls ON ls.uid = u.id AND ls.id = ${sessionID || ""}
|
||||||
|
WHERE
|
||||||
|
u.id = ${uid};
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (users.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = users[0];
|
||||||
|
return {
|
||||||
|
uid: user.id,
|
||||||
|
username: user.username,
|
||||||
|
nickname: user.nickname,
|
||||||
|
role: user.role,
|
||||||
|
createdAt: user.created_at,
|
||||||
|
isLoggedIn: user.logged_in
|
||||||
|
};
|
||||||
|
};
|
70
packages/solid/src/lib/net.ts
Normal file
70
packages/solid/src/lib/net.ts
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import axios, { AxiosRequestConfig, AxiosError, Method, AxiosResponse } from "axios";
|
||||||
|
|
||||||
|
export class ApiRequestError extends Error {
|
||||||
|
public code: number | undefined;
|
||||||
|
public response: unknown | undefined;
|
||||||
|
constructor(message: string, res?: unknown, code?: number) {
|
||||||
|
super(message);
|
||||||
|
this.name = "ApiRequestError";
|
||||||
|
this.code = code;
|
||||||
|
this.response = res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type HttpMethod = Extract<Method, "GET" | "POST" | "PUT" | "DELETE" | "PATCH">;
|
||||||
|
|
||||||
|
const httpMethods = {
|
||||||
|
get: axios.get,
|
||||||
|
post: axios.post,
|
||||||
|
put: axios.put,
|
||||||
|
delete: axios.delete,
|
||||||
|
patch: axios.patch
|
||||||
|
};
|
||||||
|
|
||||||
|
export function fetcher(url: string): Promise<unknown>;
|
||||||
|
export function fetcher<JSON = unknown>(
|
||||||
|
url: string,
|
||||||
|
init?: Omit<AxiosRequestConfig, "method"> & { method?: Exclude<HttpMethod, "DELETE"> }
|
||||||
|
): Promise<JSON>;
|
||||||
|
export function fetcher(
|
||||||
|
url: string,
|
||||||
|
init: Omit<AxiosRequestConfig, "method"> & { method: "DELETE" }
|
||||||
|
): Promise<AxiosResponse>;
|
||||||
|
|
||||||
|
export async function fetcher<JSON = unknown>(
|
||||||
|
url: string,
|
||||||
|
init?: Omit<AxiosRequestConfig, "method"> & { method?: HttpMethod }
|
||||||
|
): Promise<JSON | AxiosResponse<any, any>> {
|
||||||
|
const { method = "get", data, ...config } = init || {};
|
||||||
|
|
||||||
|
const fullConfig: AxiosRequestConfig = {
|
||||||
|
method,
|
||||||
|
...config,
|
||||||
|
timeout: 10000
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const m = method.toLowerCase() as keyof typeof httpMethods;
|
||||||
|
if (["post", "patch", "put"].includes(m)) {
|
||||||
|
const response = await httpMethods[m](url, data, fullConfig);
|
||||||
|
return response.data;
|
||||||
|
} else if (m === "delete") {
|
||||||
|
const response = await axios.delete(url, fullConfig);
|
||||||
|
return response;
|
||||||
|
} else {
|
||||||
|
const response = await httpMethods[m](url, fullConfig);
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
const axiosError = error as AxiosError;
|
||||||
|
|
||||||
|
if (axiosError.response) {
|
||||||
|
const { status, data } = axiosError.response;
|
||||||
|
throw new ApiRequestError(`HTTP error! status: ${status}`, data, status);
|
||||||
|
} else if (axiosError.request) {
|
||||||
|
throw new ApiRequestError("No response received", undefined, -1);
|
||||||
|
} else {
|
||||||
|
throw new ApiRequestError(axiosError.message || "Unknown error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
packages/solid/src/lib/userAuth.ts
Normal file
43
packages/solid/src/lib/userAuth.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { cookies } from "next/headers";
|
||||||
|
import { getUserBySession, queryUserProfile } from "@/lib/db/user";
|
||||||
|
|
||||||
|
export interface User {
|
||||||
|
uid: number;
|
||||||
|
username: string;
|
||||||
|
nickname: string | null;
|
||||||
|
role: string;
|
||||||
|
createdAt: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserProfile extends User {
|
||||||
|
isLoggedIn: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getCurrentUser(): Promise<User | null> {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
const sessionID = cookieStore.get("session_id");
|
||||||
|
if (!sessionID) return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const user = await getUserBySession(sessionID.value);
|
||||||
|
|
||||||
|
return user ?? null;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getUserProfile(uid: number): Promise<UserProfile | null> {
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
const sessionID = cookieStore.get("session_id");
|
||||||
|
|
||||||
|
try {
|
||||||
|
const user = await queryUserProfile(uid, sessionID?.value);
|
||||||
|
|
||||||
|
return user ?? null;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
117
packages/solid/src/lib/vdf.ts
Normal file
117
packages/solid/src/lib/vdf.ts
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
// Define interfaces for input and output
|
||||||
|
interface VdfProgressCallback {
|
||||||
|
(progress: number): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface VdfResult {
|
||||||
|
result: bigint;
|
||||||
|
time: number; // Time taken in milliseconds
|
||||||
|
}
|
||||||
|
|
||||||
|
// The content of the Web Worker script
|
||||||
|
const workerContent = `addEventListener("message", async (event) => {
|
||||||
|
const { g, N, difficulty } = event.data;
|
||||||
|
|
||||||
|
// Although pow is not used in the iterative VDF, it's good to keep the original worker code structure.
|
||||||
|
// The iterative computeVDFWithProgress is better for progress reporting.
|
||||||
|
function pow(base, exponent, mod) {
|
||||||
|
let result = 1n;
|
||||||
|
base = base % mod;
|
||||||
|
while (exponent > 0n) {
|
||||||
|
if (exponent % 2n === 1n) {
|
||||||
|
result = (result * base) % mod;
|
||||||
|
}
|
||||||
|
base = (base * base) % mod;
|
||||||
|
exponent = exponent / 2n;
|
||||||
|
// Using BigInt division (/) which performs integer division
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute VDF iteratively to report progress
|
||||||
|
function computeVDFWithProgress(g, N, T, postProgress) {
|
||||||
|
let result = g;
|
||||||
|
let latestTime = performance.now();
|
||||||
|
const totalSteps = T; // T is the difficulty, representing 2^T squaring steps
|
||||||
|
|
||||||
|
for (let i = 0n; i < totalSteps; i++) {
|
||||||
|
result = (result * result) % N;
|
||||||
|
// Report progress periodically (approx. every 16ms to match typical frame rate)
|
||||||
|
if (performance.now() - latestTime > 16) {
|
||||||
|
// Calculate progress as a percentage
|
||||||
|
const progress = Number((i + 1n) * 10000n / totalSteps) / 100; // Using 10000 for better precision before dividing by 100
|
||||||
|
postProgress(progress);
|
||||||
|
latestTime = performance.now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Ensure final progress is reported
|
||||||
|
postProgress(100);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const startTime = performance.now();
|
||||||
|
// The worker computes g^(2^difficulty) mod N. The loop runs 'difficulty' times, performing squaring.
|
||||||
|
const result = computeVDFWithProgress(g, N, difficulty, (progress) => {
|
||||||
|
// Post progress back to the main thread
|
||||||
|
postMessage({ type: "progress", progress: progress });
|
||||||
|
});
|
||||||
|
const endTime = performance.now();
|
||||||
|
const timeTaken = endTime - startTime;
|
||||||
|
|
||||||
|
// Post the final result and time taken back to the main thread
|
||||||
|
postMessage({ type: "result", result: result.toString(), time: timeTaken });
|
||||||
|
});
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the Verifiable Delay Function (VDF) result g^(2^difficulty) mod N
|
||||||
|
* in a Web Worker and reports progress.
|
||||||
|
* @param g - The base (bigint).
|
||||||
|
* @param N - The modulus (bigint).
|
||||||
|
* @param difficulty - The number of squaring steps (T) (bigint).
|
||||||
|
* @param onProgress - Optional callback function to receive progress updates (0-100).
|
||||||
|
* @returns A Promise that resolves with the VDF result and time taken.
|
||||||
|
*/
|
||||||
|
export function computeVdfInWorker(
|
||||||
|
g: bigint,
|
||||||
|
N: bigint,
|
||||||
|
difficulty: bigint,
|
||||||
|
onProgress?: VdfProgressCallback
|
||||||
|
): Promise<VdfResult> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// Create a Blob containing the worker script
|
||||||
|
const blob = new Blob([workerContent], { type: "text/javascript" });
|
||||||
|
// Create a URL for the Blob
|
||||||
|
const workerUrl = URL.createObjectURL(blob);
|
||||||
|
// Create a new Web Worker
|
||||||
|
const worker = new window.Worker(workerUrl);
|
||||||
|
|
||||||
|
// Handle messages from the worker
|
||||||
|
worker.onmessage = (event) => {
|
||||||
|
const { type, progress, result, time } = event.data;
|
||||||
|
|
||||||
|
if (type === "progress") {
|
||||||
|
if (onProgress) {
|
||||||
|
onProgress(progress);
|
||||||
|
}
|
||||||
|
} else if (type === "result") {
|
||||||
|
// Resolve the promise with the result and time
|
||||||
|
resolve({ result: BigInt(result), time });
|
||||||
|
// Terminate the worker and revoke the URL
|
||||||
|
worker.terminate();
|
||||||
|
URL.revokeObjectURL(workerUrl);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle potential errors in the worker
|
||||||
|
worker.onerror = (error) => {
|
||||||
|
reject(error);
|
||||||
|
// Terminate the worker and revoke the URL in case of error
|
||||||
|
worker.terminate();
|
||||||
|
URL.revokeObjectURL(workerUrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Post the data to the worker to start the computation
|
||||||
|
worker.postMessage({ g, N, difficulty });
|
||||||
|
});
|
||||||
|
}
|
19
packages/solid/src/routes/[...404].tsx
Normal file
19
packages/solid/src/routes/[...404].tsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { Title } from "@solidjs/meta";
|
||||||
|
import { HttpStatusCode } from "@solidjs/start";
|
||||||
|
|
||||||
|
export default function NotFound() {
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<Title>Not Found</Title>
|
||||||
|
<HttpStatusCode code={404} />
|
||||||
|
<h1>Page Not Found</h1>
|
||||||
|
<p>
|
||||||
|
Visit{" "}
|
||||||
|
<a href="https://start.solidjs.com" target="_blank">
|
||||||
|
start.solidjs.com
|
||||||
|
</a>{" "}
|
||||||
|
to learn how to build SolidStart apps.
|
||||||
|
</p>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
19
packages/solid/src/routes/index.tsx
Normal file
19
packages/solid/src/routes/index.tsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { Title } from "@solidjs/meta";
|
||||||
|
import Counter from "~/components/Counter";
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<Title>Hello World</Title>
|
||||||
|
<h1>Hello world!</h1>
|
||||||
|
<Counter />
|
||||||
|
<p>
|
||||||
|
Visit{" "}
|
||||||
|
<a href="https://start.solidjs.com" target="_blank">
|
||||||
|
start.solidjs.com
|
||||||
|
</a>{" "}
|
||||||
|
to learn how to build SolidStart apps.
|
||||||
|
</p>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
5
packages/solid/src/routes/song.tsx
Normal file
5
packages/solid/src/routes/song.tsx
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { RouteSectionProps } from "@solidjs/router";
|
||||||
|
|
||||||
|
export default function SongLayout(props: RouteSectionProps) {
|
||||||
|
return <div>{props.children}</div>;
|
||||||
|
}
|
188
packages/solid/src/routes/song/[id]/info.tsx
Normal file
188
packages/solid/src/routes/song/[id]/info.tsx
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
import { getAllSnapshots } from "~/lib/db/snapshots/getAllSnapshots";
|
||||||
|
import { getAidFromBV } from "~/lib/db/bilibili_metadata/getAidFromBV";
|
||||||
|
import { getVideoMetadata } from "~/lib/db/bilibili_metadata/getVideoMetadata";
|
||||||
|
import { aidExists as idExists } from "~/lib/db/bilibili_metadata/aidExists";
|
||||||
|
import { BiliVideoMetadataType, VideoSnapshotType } from "@cvsa/core";
|
||||||
|
import { DateTime } from "luxon";
|
||||||
|
import { useParams } from "@solidjs/router";
|
||||||
|
import { createResource } from "solid-js";
|
||||||
|
import { Title } from "@solidjs/meta";
|
||||||
|
import { Suspense } from "solid-js";
|
||||||
|
import { For } from "solid-js";
|
||||||
|
|
||||||
|
const MetadataRow = ({ title, desc }: { title: string; desc: string | number | undefined | null }) => {
|
||||||
|
if (!desc) return <></>;
|
||||||
|
return (
|
||||||
|
<tr>
|
||||||
|
<td class="max-w-14 min-w-14 md:max-w-24 md:min-w-24 border dark:border-zinc-500 px-2 md:px-3 py-2 font-semibold">
|
||||||
|
{title}
|
||||||
|
</td>
|
||||||
|
<td class="break-all max-w-[calc(100vw-4.5rem)] border dark:border-zinc-500 px-4 py-2">{desc}</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
function sleep(ms: number) {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function VideoInfoPage() {
|
||||||
|
const params = useParams();
|
||||||
|
const { id } = params;
|
||||||
|
const [data] = createResource(async () => {
|
||||||
|
let videoInfo: BiliVideoMetadataType | null = null;
|
||||||
|
let snapshots: VideoSnapshotType[] = [];
|
||||||
|
await sleep(1000);
|
||||||
|
|
||||||
|
async function getVideoAid(videoId: string | string[] | undefined) {
|
||||||
|
if (!videoId) return null;
|
||||||
|
const videoIdStr = Array.isArray(videoId) ? videoId[0] : videoId;
|
||||||
|
if (videoIdStr?.startsWith("av")) {
|
||||||
|
return parseInt(videoIdStr.slice(2));
|
||||||
|
} else if (videoIdStr?.startsWith("BV")) {
|
||||||
|
return getAidFromBV(videoIdStr);
|
||||||
|
}
|
||||||
|
return parseInt(videoIdStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
const aid = await getVideoAid(id);
|
||||||
|
|
||||||
|
if (!aid) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const exists = await idExists(aid);
|
||||||
|
|
||||||
|
if (!exists) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const videoData = await getVideoMetadata(aid);
|
||||||
|
const snapshotsData = await getAllSnapshots(aid);
|
||||||
|
videoInfo = videoData;
|
||||||
|
if (snapshotsData) {
|
||||||
|
snapshots = snapshotsData;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!videoInfo) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let title = "";
|
||||||
|
const backendURL = process.env.BACKEND_URL;
|
||||||
|
const res = await fetch(`${backendURL}/video/${id}/info`);
|
||||||
|
if (!res.ok) {
|
||||||
|
title = "页面未找到 - 中 V 档案馆";
|
||||||
|
}
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
title = `${data.title} - 歌曲信息 - 中 V 档案馆`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
v: videoInfo,
|
||||||
|
s: snapshots,
|
||||||
|
t: title
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<main class="flex flex-col items-center min-h-screen gap-8 mt-10 md:mt-6 relative z-0 overflow-x-auto pb-8">
|
||||||
|
<div>hi</div>
|
||||||
|
<div class="w-full lg:max-w-4xl lg:mx-auto lg:p-6">
|
||||||
|
<Suspense fallback={<div>loading</div>}>
|
||||||
|
<Title>{data()?.t}</Title>
|
||||||
|
<h1 class="text-2xl font-medium ml-2 mb-4">
|
||||||
|
视频信息:{" "}
|
||||||
|
<a href={`https://www.bilibili.com/video/av${data()?.v.aid}`} class="underline">
|
||||||
|
av{data()?.v.aid}
|
||||||
|
</a>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<div class="mb-6">
|
||||||
|
<h2 class="px-2 mb-2 text-xl font-medium">基本信息</h2>
|
||||||
|
<div class="overflow-x-auto max-w-full px-2">
|
||||||
|
<table class="table-fixed">
|
||||||
|
<tbody>
|
||||||
|
<MetadataRow title="ID" desc={data()?.v.id} />
|
||||||
|
<MetadataRow title="av 号" desc={data()?.v.aid} />
|
||||||
|
<MetadataRow title="BV 号" desc={data()?.v.bvid} />
|
||||||
|
<MetadataRow title="标题" desc={data()?.v.title} />
|
||||||
|
<MetadataRow title="描述" desc={data()?.v.description} />
|
||||||
|
<MetadataRow title="UID" desc={data()?.v.uid} />
|
||||||
|
<MetadataRow title="标签" desc={data()?.v.tags} />
|
||||||
|
<MetadataRow
|
||||||
|
title="发布时间"
|
||||||
|
desc={
|
||||||
|
data()?.v.published_at
|
||||||
|
? DateTime.fromJSDate(new Date(data()?.v.published_at || "")).toFormat(
|
||||||
|
"yyyy-MM-dd HH:mm:ss"
|
||||||
|
)
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<MetadataRow title="时长 (秒)" desc={data()?.v.duration} />
|
||||||
|
<MetadataRow
|
||||||
|
title="创建时间"
|
||||||
|
desc={DateTime.fromJSDate(new Date(data()?.v.created_at || "")).toFormat(
|
||||||
|
"yyyy-MM-dd HH:mm:ss"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<MetadataRow title="封面" desc={data()?.v?.cover_url} />
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h2 class="px-2 mb-2 text-xl font-medium">播放量历史数据</h2>
|
||||||
|
|
||||||
|
<div class="overflow-x-auto px-2">
|
||||||
|
<table class="table-auto w-full">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="border dark:border-zinc-500 px-4 py-2 font-medium">创建时间</th>
|
||||||
|
<th class="border dark:border-zinc-500 px-4 py-2 font-medium">观看</th>
|
||||||
|
<th class="border dark:border-zinc-500 px-4 py-2 font-medium">硬币</th>
|
||||||
|
<th class="border dark:border-zinc-500 px-4 py-2 font-medium">点赞</th>
|
||||||
|
<th class="border dark:border-zinc-500 px-4 py-2 font-medium">收藏</th>
|
||||||
|
<th class="border dark:border-zinc-500 px-4 py-2 font-medium">分享</th>
|
||||||
|
<th class="border dark:border-zinc-500 px-4 py-2 font-medium">弹幕</th>
|
||||||
|
<th class="border dark:border-zinc-500 px-4 py-2 font-medium">评论</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<For each={data()?.s}>
|
||||||
|
{(snapshot) => (
|
||||||
|
<tr>
|
||||||
|
<td class="border dark:border-zinc-500 px-4 py-2">
|
||||||
|
{DateTime.fromJSDate(snapshot.created_at).toFormat(
|
||||||
|
"yyyy-MM-dd HH:mm:ss"
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td class="border dark:border-zinc-500 px-4 py-2">{snapshot.views}</td>
|
||||||
|
<td class="border dark:border-zinc-500 px-4 py-2">{snapshot.coins}</td>
|
||||||
|
<td class="border dark:border-zinc-500 px-4 py-2">{snapshot.likes}</td>
|
||||||
|
<td class="border dark:border-zinc-500 px-4 py-2">
|
||||||
|
{snapshot.favorites}
|
||||||
|
</td>
|
||||||
|
<td class="border dark:border-zinc-500 px-4 py-2">{snapshot.shares}</td>
|
||||||
|
<td class="border dark:border-zinc-500 px-4 py-2">
|
||||||
|
{snapshot.danmakus}
|
||||||
|
</td>
|
||||||
|
<td class="border dark:border-zinc-500 px-4 py-2">
|
||||||
|
{snapshot.replies}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Suspense>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
19
packages/solid/tsconfig.json
Normal file
19
packages/solid/tsconfig.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"jsxImportSource": "solid-js",
|
||||||
|
"allowJs": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"types": ["vinxi/types/client"],
|
||||||
|
"isolatedModules": true,
|
||||||
|
"paths": {
|
||||||
|
"~/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user