diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..bffb357 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "next/core-web-vitals" +} diff --git a/.gitignore b/.gitignore index 5ad6ad7..b8bcb3b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,41 @@ -# build output -dist/ -dist.zip -# generated types -.astro/ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # dependencies -node_modules/ +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz -# logs +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug npm-debug.log* yarn-debug.log* yarn-error.log* -pnpm-debug.log* +# local env files +.env*.local -# environment variables -.env -.env.production +# vercel +.vercel -# macOS-specific files -.DS_Store +# typescript +*.tsbuildinfo +next-env.d.ts + +bun.lockb *.lock -# Development content -public/media +.env \ No newline at end of file diff --git a/.prettierrc b/.prettierrc index de3bd60..ae31b65 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,5 +1,5 @@ { "tabWidth": 2, - "printWidth": 120, - "singleQuote": false + "singleQuote": false, + "printWidth": 120 } diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 22a1505..0000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "recommendations": ["astro-build.astro-vscode"], - "unwantedRecommendations": [] -} diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index d642209..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "command": "./node_modules/.bin/astro dev", - "name": "Development server", - "request": "launch", - "type": "node-terminal" - } - ] -} diff --git a/README.md b/README.md new file mode 100644 index 0000000..c403366 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/app/console/[[...index]]/page.tsx b/app/console/[[...index]]/page.tsx new file mode 100644 index 0000000..01aa0cc --- /dev/null +++ b/app/console/[[...index]]/page.tsx @@ -0,0 +1,17 @@ +'use client' + +/** + * This route is responsible for the built-in authoring environment using Sanity Studio. + * All routes under your studio path is handled by this file using Next.js' catch-all routes: + * https://nextjs.org/docs/routing/dynamic-routes#catch-all-routes + * + * You can learn more about the next-sanity package here: + * https://github.com/sanity-io/next-sanity + */ + +import { NextStudio } from 'next-sanity/studio' +import config from '../../../sanity.config' + +export default function StudioPage() { + return +} \ No newline at end of file diff --git a/app/consts.tsx b/app/consts.tsx new file mode 100644 index 0000000..d84138a --- /dev/null +++ b/app/consts.tsx @@ -0,0 +1,31 @@ +import { ReactNode } from "react"; +import GitHubIcon from "@mui/icons-material/GitHub"; +import TwitterIcon from "@mui/icons-material/Twitter"; +import CoffeeIcon from "@mui/icons-material/Coffee"; + +export interface RelatedAccount { + icon: ReactNode; + platform: string; + accountName: string; + link: string; +} + +export const SITE_NAME = "Goatshed"; +export const SITE_DESCRIPTION = "山羊寒舍,在这里最终智羊工作室的最新动态。"; +export const SITE_URL = "https://smartsheep.studio"; + +export const RELATED_ACCOUNTS: RelatedAccount[] = [ + { icon: , platform: "GitHub", accountName: "@smartsheep-hq", link: "https://github.com/smartsheep-hq" }, + { + icon: , + platform: "Twitter", + accountName: "@littlesheepovo", + link: "https://twitter.com/littlesheepovo", + }, + { + icon: , + platform: "Ko-fi", + accountName: "@littlesheep2code", + link: "https://ko-fi.com/littlesheep2code", + }, +]; diff --git a/app/feed/route.ts b/app/feed/route.ts new file mode 100644 index 0000000..30d79fb --- /dev/null +++ b/app/feed/route.ts @@ -0,0 +1,36 @@ +import { Feed } from "feed"; +import { SITE_DESCRIPTION, SITE_NAME, SITE_URL } from "@/app/consts"; +import { client } from "@/sanity/lib/client"; + +export async function GET() { + const feed = new Feed({ + title: SITE_NAME, + description: SITE_DESCRIPTION, + id: SITE_URL, + link: SITE_URL, + favicon: `${SITE_URL}/favicon.png`, + feedLinks: { atom: `${SITE_URL}/feed` }, + language: "zh-CN", + copyright: `Copyright © ${new Date().getFullYear()} SmartSheep Studio`, + }); + + const posts = await client.fetch(`*[_type == "post"] { + title, description, slug, publishedAt, + }`); + + posts.forEach((item) => { + feed.addItem({ + id: `${SITE_URL}/p/${item.slug.current}`, + link: `${SITE_URL}/p/${item.slug.current}`, + title: item.title, + description: item.description ?? "No description yet.", + date: new Date(item.publishedAt) + }); + }); + + return new Response(feed.rss2(), { + headers: { + "content-type": "application/xml" + } + }); +} diff --git a/app/globals.css b/app/globals.css new file mode 100644 index 0000000..b5c61c9 --- /dev/null +++ b/app/globals.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/public/favicon.svg b/app/icon.svg old mode 100644 new mode 100755 similarity index 100% rename from public/favicon.svg rename to app/icon.svg diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..ad5bdd7 --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,45 @@ +import type { Metadata } from "next"; +import { ReactNode } from "react"; +import { ThemeProvider } from "@mui/material/styles"; +import { AppRouterCacheProvider } from "@mui/material-nextjs/v13-appRouter"; +import { CssBaseline } from "@mui/material"; +import { SITE_DESCRIPTION, SITE_NAME } from "@/app/consts"; +import { theme } from "@/app/theme"; + +import "@fontsource/roboto/300.css"; +import "@fontsource/roboto/400.css"; +import "@fontsource/roboto/500.css"; +import "@fontsource/roboto/700.css"; + +import "./globals.css"; + +import AppShell from "@/components/AppShell"; +import NextTopLoader from "nextjs-toploader"; + +export const runtime = "edge"; + +export const metadata: Metadata = { + title: { + default: SITE_NAME, + template: `${SITE_NAME} | %s` + }, + description: SITE_DESCRIPTION +}; + +export default function RootLayout({ children }: Readonly<{ + children: ReactNode; +}>) { + return ( + + + + + + + {children} + + + + + ); +} diff --git a/app/page.tsx b/app/page.tsx new file mode 100644 index 0000000..314b578 --- /dev/null +++ b/app/page.tsx @@ -0,0 +1,76 @@ +import { + Avatar, + Box, + Button, + Card, + colors, + Container, + Grid, + List, + ListItemAvatar, + ListItemButton, + ListItemText, + Typography, +} from "@mui/material"; +import { RELATED_ACCOUNTS } from "@/app/consts"; +import Image from "next/image"; +import Link from "next/link"; + +export default function Home() { + return ( + + + + + 你好呀 👋 + + + 欢迎来到 SmartSheep Studio 的官方网站!在这里了解,订阅,跟踪我们的最新消息。 + 接触我们最大的官方社区,并且尝试最新产品,参与各种活动,提供反馈,让我们更好的服务您。 + + + + + + Logo + + + + + + + + + {RELATED_ACCOUNTS.map((item, idx) => ( + + + + {item.icon} + + + + + ))} + + + + + + 关于我们 + + + 我们是一群充满活力、对开源充满热情的开发者。成立于 2019 年。自那年起我们一直在开发让人喜欢的开源软件。 + 在我们这里,“取之于开源,用之于开源” 不仅是原则,更是我们信仰的座右铭。 + + + + + ); +} diff --git a/app/posts/[id]/page.tsx b/app/posts/[id]/page.tsx new file mode 100644 index 0000000..7b4e3b0 --- /dev/null +++ b/app/posts/[id]/page.tsx @@ -0,0 +1,55 @@ +import { Box, Card, CardContent, CardMedia, Chip, Divider, Stack, Typography } from "@mui/material"; +import { client } from "@/sanity/lib/client"; +import PostContent from "@/components/posts/PostContent"; +import Image from "next/image"; + +export default async function PostDetailPage({ params }: { params: { id: string } }) { + const post = await client.fetch(`*[_type == "post" && slug.current == $slug][0] { + title, description, slug, body, author, publishedAt, + mainImage { + asset -> { + _id, + url + }, + alt + }, + "categories": categories[]->title, + "author_name": author->name, + "author_image": author->image + }`, { slug: params.id }); + + return ( + + { + post.mainImage && + + {post.mainImage.alt} + + } + + + + + {post.title} + + + + {post.categories.map((category: string, idx: number) => )} + + + {post.description ?? "No description yet."} + + + + + + + + + ); +} diff --git a/app/posts/layout.tsx b/app/posts/layout.tsx new file mode 100644 index 0000000..5b36990 --- /dev/null +++ b/app/posts/layout.tsx @@ -0,0 +1,14 @@ +import { Box, Container } from "@mui/material"; +import { ReactNode } from "react"; + +export default function PostLayout({ + children, +}: Readonly<{ + children: ReactNode; +}>) { + return ( + + {children} + + ); +} diff --git a/app/posts/page.tsx b/app/posts/page.tsx new file mode 100644 index 0000000..c707f49 --- /dev/null +++ b/app/posts/page.tsx @@ -0,0 +1,56 @@ +import { Button, Card, CardActions, CardContent, CardMedia, Chip, Stack, Typography } from "@mui/material"; +import { client } from "@/sanity/lib/client"; +import Image from "next/image"; +import Link from "next/link"; + +export default async function PostList() { + const posts = await client.fetch(`*[_type == "post"] { + title, description, slug, author, publishedAt, + mainImage { + asset -> { + _id, + url + }, + alt + }, + "categories": categories[]->title, + "author_name": author->name, + "author_image": author->image + }`); + + return ( + posts.map((post) => ( + + { + post.mainImage && + + {post.mainImage.alt} + + } + + + + {post.title} + + + + {post.categories.map((category: string, idx: number) => )} + + + {post.description ? post.description : "No description yet."} + + + + + + + + + )) + ); +} \ No newline at end of file diff --git a/app/sitemap.ts b/app/sitemap.ts new file mode 100644 index 0000000..d3d59e4 --- /dev/null +++ b/app/sitemap.ts @@ -0,0 +1,31 @@ +import { MetadataRoute } from "next"; +import { SITE_URL } from "@/app/consts"; +import { client } from "@/sanity/lib/client"; + +export default async function sitemap(): Promise { + const posts = await client.fetch(`*[_type == "post"] { + slug, publishedAt, + }`); + + return [ + { + url: `${SITE_URL}/`, + lastModified: new Date(), + changeFrequency: "weekly", + priority: 1, + }, + { + url: `${SITE_URL}/posts`, + lastModified: new Date(), + changeFrequency: "daily", + priority: 0.8, + }, + + ...posts.map((item: any) => ({ + url: `${SITE_URL}/posts/${item.slug.current}`, + lastModified: new Date(item.publishedAt), + changeFrequency: "daily" as any, + priority: 0.75, + })), + ]; +} diff --git a/app/theme.ts b/app/theme.ts new file mode 100644 index 0000000..699996f --- /dev/null +++ b/app/theme.ts @@ -0,0 +1,22 @@ +"use client"; + +import { createTheme } from "@mui/material/styles"; + +export const theme = createTheme({ + palette: { + primary: { + main: "#49509e", + }, + secondary: { + main: "#d43630", + }, + }, + typography: { + h1: { fontSize: "2.5rem" }, + h2: { fontSize: "2rem" }, + h3: { fontSize: "1.75rem" }, + h4: { fontSize: "1.5rem" }, + h5: { fontSize: "1.25rem" }, + h6: { fontSize: "1.15rem" }, + }, +}); diff --git a/astro.config.mjs b/astro.config.mjs deleted file mode 100644 index fe5635f..0000000 --- a/astro.config.mjs +++ /dev/null @@ -1,17 +0,0 @@ -import { defineConfig } from "astro/config"; - -import react from "@astrojs/react"; -import tailwind from "@astrojs/tailwind"; -import sitemap from "@astrojs/sitemap"; -import cloudflare from "@astrojs/cloudflare"; - -// https://astro.build/config -export default defineConfig({ - output: "hybrid", - site: "https://smartsheep.studio", - integrations: [tailwind(), react(), sitemap()], - adapter: cloudflare(), - redirects: { - "/p/[...slug]": "/posts/[...slug]", - }, -}); diff --git a/components/AppShell.tsx b/components/AppShell.tsx new file mode 100644 index 0000000..427ef99 --- /dev/null +++ b/components/AppShell.tsx @@ -0,0 +1,139 @@ +"use client"; + +import { + Slide, + Toolbar, + Typography, + AppBar as MuiAppBar, + AppBarProps as MuiAppBarProps, + useScrollTrigger, + IconButton, + styled, + Box, + useMediaQuery, +} from "@mui/material"; +import { ReactElement, ReactNode, useEffect, useState } from "react"; +import { SITE_NAME } from "@/app/consts"; +import NavigationDrawer, { DRAWER_WIDTH, AppNavigationHeader, isMobileQuery } from "@/components/NavigationDrawer"; +import MenuIcon from "@mui/icons-material/Menu"; +import Image from "next/image"; +import Link from "next/link"; + +function HideOnScroll(props: { window?: () => Window; children: ReactElement }) { + const { children, window } = props; + const trigger = useScrollTrigger({ + target: window ? window() : undefined, + }); + + return ( + + {children} + + ); +} + +interface AppBarProps extends MuiAppBarProps { + open?: boolean; +} + +const ShellAppBar = styled(MuiAppBar, { + shouldForwardProp: (prop) => prop !== "open", +})(({ theme, open }) => { + const isMobile = useMediaQuery(isMobileQuery); + + return { + transition: theme.transitions.create(["margin", "width"], { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.leavingScreen, + }), + ...(!isMobile && + open && { + width: `calc(100% - ${DRAWER_WIDTH}px)`, + transition: theme.transitions.create(["margin", "width"], { + easing: theme.transitions.easing.easeOut, + duration: theme.transitions.duration.enteringScreen, + }), + marginRight: DRAWER_WIDTH, + }), + }; +}); + +const AppMain = styled("main", { shouldForwardProp: (prop) => prop !== "open" })<{ + open?: boolean; +}>(({ theme, open }) => { + const isMobile = useMediaQuery(isMobileQuery); + + return { + flexGrow: 1, + transition: theme.transitions.create("margin", { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.leavingScreen, + }), + marginRight: -DRAWER_WIDTH, + ...(!isMobile && + open && { + transition: theme.transitions.create("margin", { + easing: theme.transitions.easing.easeOut, + duration: theme.transitions.duration.enteringScreen, + }), + marginRight: 0, + }), + position: "relative", + }; +}); + +export default function AppShell({ children }: { children: ReactNode }) { + let documentWindow: Window; + + const isMobile = useMediaQuery(isMobileQuery); + const [open, setOpen] = useState(false); + + useEffect(() => { + documentWindow = window; + }); + + return ( + <> + documentWindow}> + + + + Logo + + + + {SITE_NAME} + + + setOpen(true)} + sx={{ mr: 1, display: !isMobile && open ? "none" : "block" }} + > + + + + + + + + + + + {children} + + + setOpen(false)} /> + + + ); +} diff --git a/components/NavigationDrawer.tsx b/components/NavigationDrawer.tsx new file mode 100644 index 0000000..5bc2d56 --- /dev/null +++ b/components/NavigationDrawer.tsx @@ -0,0 +1,117 @@ +"use client"; + +import ChevronLeftIcon from "@mui/icons-material/ChevronLeft"; +import ChevronRightIcon from "@mui/icons-material/ChevronRight"; +import { + Box, + Divider, + Drawer, + IconButton, + List, + ListItemButton, + ListItemIcon, + ListItemText, + styled, + useMediaQuery, +} from "@mui/material"; +import { theme } from "@/app/theme"; +import { ReactNode } from "react"; +import HomeIcon from "@mui/icons-material/Home"; +import ArticleIcon from "@mui/icons-material/Article"; +import FeedIcon from "@mui/icons-material/RssFeed"; +import Link from "next/link"; + +export interface NavigationItem { + icon?: ReactNode; + title?: string; + link?: string; + divider?: boolean; +} + +export const DRAWER_WIDTH = 320; +export const NAVIGATION_ITEMS: NavigationItem[] = [ + { icon: , title: "首页", link: "/" }, + { icon: , title: "新闻", link: "/posts" }, + { divider: true }, + { icon: , title: "订阅源", link: "/feed" }, +]; + +export const AppNavigationHeader = styled("div")(({ theme }) => ({ + display: "flex", + alignItems: "center", + padding: theme.spacing(0, 1), + justifyContent: "flex-start", + height: 64, + ...theme.mixins.toolbar, +})); + +export function AppNavigation({ showClose, onClose }: { showClose?: boolean; onClose: () => void }) { + return ( + <> + + {showClose && ( + + {theme.direction === "rtl" ? : } + + )} + + + + {NAVIGATION_ITEMS.map((item, idx) => { + return item.divider ? ( + + ) : ( + + + {item.icon} + + + + ); + })} + + + ); +} + +export const isMobileQuery = theme.breakpoints.down("md"); + +export default function NavigationDrawer({ open, onClose }: { open: boolean; onClose: () => void }) { + const isMobile = useMediaQuery(isMobileQuery); + + return isMobile ? ( + <> + + + + + + ) : ( + + + + ); +} diff --git a/components/posts/PostContent.tsx b/components/posts/PostContent.tsx new file mode 100644 index 0000000..5e847a0 --- /dev/null +++ b/components/posts/PostContent.tsx @@ -0,0 +1,7 @@ +"use client"; + +import { PortableText } from "@portabletext/react"; + +export default function PostContent({ content }: { content: any }) { + return ; +} diff --git a/license b/license deleted file mode 100644 index 0ad25db..0000000 --- a/license +++ /dev/null @@ -1,661 +0,0 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. diff --git a/next.config.mjs b/next.config.mjs new file mode 100644 index 0000000..7cd19ed --- /dev/null +++ b/next.config.mjs @@ -0,0 +1,23 @@ +/** @type {import("next").NextConfig} */ +const nextConfig = { + pageExtensions: ["js", "jsx", "mdx", "ts", "tsx"], + images: { + remotePatterns: [ + { + protocol: "https", + hostname: "**", + }, + ], + }, + async rewrites() { + return [ + { source: "/rss", destination: "/feed" }, + { source: "/rss.xml", destination: "/feed.xml" }, + { source: "/feed.xml", destination: "/feed" }, + + { source: "/p/:id", destination: "/posts/:id" }, + ]; + }, +}; + +export default nextConfig; diff --git a/package.json b/package.json index b53148c..421aa28 100644 --- a/package.json +++ b/package.json @@ -1,46 +1,59 @@ { "name": "capital", - "type": "module", - "version": "0.0.1", + "version": "0.1.0", + "private": true, "scripts": { - "dev": "astro dev", - "start": "astro dev", - "build": "astro check && astro build", - "preview": "astro preview", - "astro": "astro" + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" }, "dependencies": { - "@astrojs/check": "^0.4.1", - "@astrojs/cloudflare": "^9.0.0", - "@astrojs/node": "^8.0.0", - "@astrojs/react": "^3.0.9", - "@astrojs/sitemap": "^3.0.5", - "@astrojs/tailwind": "^5.1.0", - "@fortawesome/fontawesome-free": "^6.5.1", - "@popperjs/core": "^2.11.8", - "@types/react": "^18.2.48", - "@types/react-dom": "^18.2.18", - "aplayer": "^1.10.1", - "artplayer": "^5.1.1", - "astro": "^4.2.1", - "dompurify": "^3.0.8", - "html-react-parser": "^5.1.2", - "marked": "^12.0.0", - "medium-zoom": "^1.1.0", - "nprogress": "^0.2.0", - "react": "^17", - "react-dom": "^17", - "sass": "^1.70.0", - "tailwindcss": "^3.4.1", - "theme-change": "^2.5.0", - "typescript": "^5.3.3" + "@emotion/cache": "^11.11.0", + "@emotion/react": "^11.11.3", + "@emotion/styled": "^11.11.0", + "@fontsource/roboto": "^5.0.8", + "@mdx-js/loader": "^3.0.1", + "@mdx-js/react": "^3.0.1", + "@mui/icons-material": "^5.15.10", + "@mui/material": "^5.15.10", + "@mui/material-nextjs": "^5.15.11", + "@next/mdx": "^14.1.0", + "@portabletext/react": "^3.0.11", + "@sanity/client": "^6.12.4", + "@sanity/icons": "^2.8", + "@sanity/image-url": "1", + "@sanity/types": "^3.25", + "@sanity/ui": "^2.0", + "@sanity/vision": "3", + "@types/mdx": "^2.0.11", + "feed": "^4.2.2", + "gray-matter": "^4.0.3", + "next": "^14.1", + "next-sanity": "7.1.4", + "nextjs-toploader": "^1.6.6", + "react": "^18.2", + "react-dom": "^18", + "react-markdown": "^9.0.1", + "sanity": "^3.25", + "styled-components": "^6.0" }, "devDependencies": { "@tailwindcss/typography": "^0.5.10", - "@types/dompurify": "^3.0.5", - "@types/node": "^20.11.5", + "@types/node": "^20", "@types/nprogress": "^0.2.3", - "daisyui": "^4.6.0", - "prettier": "^3.2.4" + "@types/react": "^18", + "@types/react-dom": "^18", + "@types/rss": "^0.0.32", + "autoprefixer": "^10.0.1", + "eslint": "^8", + "eslint-config-next": "14.1.0", + "postcss": "^8", + "tailwindcss": "^3.3.0", + "typescript": "^5" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" } } diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..12a703d --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/public/next.svg b/public/next.svg new file mode 100644 index 0000000..5174b28 --- /dev/null +++ b/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/smartsheep.svg b/public/smartsheep.svg new file mode 100755 index 0000000..d42a1a1 --- /dev/null +++ b/public/smartsheep.svg @@ -0,0 +1,21 @@ + + SmartSheep Logo + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/vercel.svg b/public/vercel.svg new file mode 100644 index 0000000..d2f8422 --- /dev/null +++ b/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/sanity.cli.ts b/sanity.cli.ts new file mode 100644 index 0000000..b8a1096 --- /dev/null +++ b/sanity.cli.ts @@ -0,0 +1,10 @@ +/** + * This configuration file lets you run `$ sanity [command]` in this folder + * Go to https://www.sanity.io/docs/cli to learn more. + **/ +import { defineCliConfig } from "sanity/cli"; + +const projectId = process.env.NEXT_PUBLIC_SANITY_PROJECT_ID; +const dataset = process.env.NEXT_PUBLIC_SANITY_DATASET; + +export default defineCliConfig({ api: { projectId, dataset } }); diff --git a/sanity.config.ts b/sanity.config.ts new file mode 100644 index 0000000..b27f3c8 --- /dev/null +++ b/sanity.config.ts @@ -0,0 +1,25 @@ +/** + * This configuration is used to for the Sanity Studio that’s mounted on the `/pages/studio/page.tsx` route + */ + +import { visionTool } from "@sanity/vision"; +import { defineConfig } from "sanity"; +import { structureTool } from "sanity/structure"; + +// Go to https://www.sanity.io/docs/api-versioning to learn how API versioning works +import { apiVersion, dataset, projectId } from "./sanity/env"; +import { schema } from "./sanity/schema"; + +export default defineConfig({ + basePath: "/console", + projectId, + dataset, + // Add and edit the content schema in the './sanity/schema' folder + schema, + plugins: [ + structureTool(), + // Vision is a tool that lets you query your content with GROQ in the studio + // https://www.sanity.io/docs/the-vision-plugin + visionTool({ defaultApiVersion: apiVersion }), + ], +}); diff --git a/sanity/env.ts b/sanity/env.ts new file mode 100644 index 0000000..d85f4ba --- /dev/null +++ b/sanity/env.ts @@ -0,0 +1,21 @@ +export const apiVersion = process.env.NEXT_PUBLIC_SANITY_API_VERSION || "2024-02-24"; + +export const dataset = assertValue( + process.env.NEXT_PUBLIC_SANITY_DATASET, + "Missing environment variable: NEXT_PUBLIC_SANITY_DATASET", +); + +export const projectId = assertValue( + process.env.NEXT_PUBLIC_SANITY_PROJECT_ID, + "Missing environment variable: NEXT_PUBLIC_SANITY_PROJECT_ID", +); + +export const useCdn = false; + +function assertValue(v: T | undefined, errorMessage: string): T { + if (v === undefined) { + throw new Error(errorMessage); + } + + return v; +} diff --git a/sanity/lib/client.ts b/sanity/lib/client.ts new file mode 100644 index 0000000..eb84962 --- /dev/null +++ b/sanity/lib/client.ts @@ -0,0 +1,10 @@ +import { createClient } from "next-sanity"; + +import { apiVersion, dataset, projectId, useCdn } from "../env"; + +export const client = createClient({ + apiVersion, + dataset, + projectId, + useCdn, +}); diff --git a/sanity/lib/image.ts b/sanity/lib/image.ts new file mode 100644 index 0000000..79ee2a2 --- /dev/null +++ b/sanity/lib/image.ts @@ -0,0 +1,13 @@ +import createImageUrlBuilder from "@sanity/image-url"; +import type { Image } from "sanity"; + +import { dataset, projectId } from "../env"; + +const imageBuilder = createImageUrlBuilder({ + projectId: projectId || "", + dataset: dataset || "", +}); + +export const urlForImage = (source: Image) => { + return imageBuilder?.image(source).auto("format").fit("max").url(); +}; diff --git a/sanity/schema.ts b/sanity/schema.ts new file mode 100644 index 0000000..0bf6810 --- /dev/null +++ b/sanity/schema.ts @@ -0,0 +1,10 @@ +import { type SchemaTypeDefinition } from "sanity"; + +import blockContent from "./schemaTypes/blockContent"; +import category from "./schemaTypes/category"; +import post from "./schemaTypes/post"; +import author from "./schemaTypes/author"; + +export const schema: { types: SchemaTypeDefinition[] } = { + types: [post, author, category, blockContent], +}; diff --git a/sanity/schemaTypes/author.ts b/sanity/schemaTypes/author.ts new file mode 100644 index 0000000..aca7fe6 --- /dev/null +++ b/sanity/schemaTypes/author.ts @@ -0,0 +1,57 @@ +import { defineField, defineType } from "sanity"; + +export default defineType({ + name: "author", + title: "Author", + type: "document", + fields: [ + defineField({ + name: "name", + title: "Name", + type: "string", + }), + defineField({ + name: "slug", + title: "Slug", + type: "slug", + options: { + source: "name", + maxLength: 96, + }, + }), + defineField({ + name: "image", + title: "Image", + type: "image", + options: { + hotspot: true, + }, + fields: [ + { + name: "alt", + type: "string", + title: "Alternative Text", + }, + ], + }), + defineField({ + name: "bio", + title: "Bio", + type: "array", + of: [ + { + title: "Block", + type: "block", + styles: [{ title: "Normal", value: "normal" }], + lists: [], + }, + ], + }), + ], + preview: { + select: { + title: "name", + media: "image", + }, + }, +}); diff --git a/sanity/schemaTypes/blockContent.ts b/sanity/schemaTypes/blockContent.ts new file mode 100644 index 0000000..23eafa5 --- /dev/null +++ b/sanity/schemaTypes/blockContent.ts @@ -0,0 +1,75 @@ +import { defineType, defineArrayMember } from "sanity"; + +/** + * This is the schema type for block content used in the post document type + * Importing this type into the studio configuration's `schema` property + * lets you reuse it in other document types with: + * { + * name: 'someName', + * title: 'Some title', + * type: 'blockContent' + * } + */ + +export default defineType({ + title: "Block Content", + name: "blockContent", + type: "array", + of: [ + defineArrayMember({ + title: "Block", + type: "block", + // Styles let you define what blocks can be marked up as. The default + // set corresponds with HTML tags, but you can set any title or value + // you want, and decide how you want to deal with it where you want to + // use your content. + styles: [ + { title: "Normal", value: "normal" }, + { title: "H1", value: "h1" }, + { title: "H2", value: "h2" }, + { title: "H3", value: "h3" }, + { title: "H4", value: "h4" }, + { title: "Quote", value: "blockquote" }, + ], + lists: [{ title: "Bullet", value: "bullet" }], + // Marks let you mark up inline text in the Portable Text Editor + marks: { + // Decorators usually describe a single property – e.g. a typographic + // preference or highlighting + decorators: [ + { title: "Strong", value: "strong" }, + { title: "Emphasis", value: "em" }, + ], + // Annotations can be any object structure – e.g. a link or a footnote. + annotations: [ + { + title: "URL", + name: "link", + type: "object", + fields: [ + { + title: "URL", + name: "href", + type: "url", + }, + ], + }, + ], + }, + }), + // You can add additional types here. Note that you can't use + // primitive types such as 'string' and 'number' in the same array + // as a block type. + defineArrayMember({ + type: "image", + options: { hotspot: true }, + fields: [ + { + name: "alt", + type: "string", + title: "Alternative Text", + }, + ], + }), + ], +}); diff --git a/sanity/schemaTypes/category.ts b/sanity/schemaTypes/category.ts new file mode 100644 index 0000000..d1f4c57 --- /dev/null +++ b/sanity/schemaTypes/category.ts @@ -0,0 +1,19 @@ +import { defineField, defineType } from "sanity"; + +export default defineType({ + name: "category", + title: "Category", + type: "document", + fields: [ + defineField({ + name: "title", + title: "Title", + type: "string", + }), + defineField({ + name: "description", + title: "Description", + type: "text", + }), + ], +}); diff --git a/sanity/schemaTypes/post.ts b/sanity/schemaTypes/post.ts new file mode 100644 index 0000000..e5c813c --- /dev/null +++ b/sanity/schemaTypes/post.ts @@ -0,0 +1,77 @@ +import { defineField, defineType } from "sanity"; + +export default defineType({ + name: "post", + title: "Post", + type: "document", + fields: [ + defineField({ + name: "title", + title: "Title", + type: "string", + }), + defineField({ + name: "description", + title: "Description", + type: "string", + }), + defineField({ + name: "slug", + title: "Slug", + type: "slug", + options: { + source: "title", + maxLength: 96, + }, + }), + defineField({ + name: "author", + title: "Author", + type: "reference", + to: { type: "author" }, + }), + defineField({ + name: "mainImage", + title: "Main image", + type: "image", + options: { + hotspot: true, + }, + fields: [ + { + name: "alt", + type: "string", + title: "Alternative Text", + }, + ], + }), + defineField({ + name: "categories", + title: "Categories", + type: "array", + of: [{ type: "reference", to: { type: "category" } }], + }), + defineField({ + name: "publishedAt", + title: "Published at", + type: "datetime", + }), + defineField({ + name: "body", + title: "Body", + type: "blockContent", + }), + ], + + preview: { + select: { + title: "title", + author: "author.name", + media: "mainImage", + }, + prepare(selection) { + const { author } = selection; + return { ...selection, subtitle: author && `by ${author}` }; + }, + }, +}); diff --git a/semantic.json b/semantic.json deleted file mode 100644 index ed8ba82..0000000 --- a/semantic.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "base": "libs/fomantic", - "paths": { - "source": { - "config": "src/theme.config", - "definitions": "src/definitions/", - "site": "src/site/", - "themes": "src/themes/" - }, - "output": { - "packaged": "dist/", - "uncompressed": "dist/components/", - "compressed": "dist/components/", - "themes": "dist/themes/" - }, - "clean": "dist/" - }, - "permission": false, - "autoInstall": false, - "rtl": false, - "version": "2.9.3" -} diff --git a/src/assets/fonts/fonts.css b/src/assets/fonts/fonts.css deleted file mode 100644 index 4f7f941..0000000 --- a/src/assets/fonts/fonts.css +++ /dev/null @@ -1,197 +0,0 @@ -:root { - --bs-body-font-family: "IBM Plex Sans", "Noto Serif SC", sans-serif !important; -} - -html, -body { - font-family: var(--bs-body-font-family); -} - -/* ibm-plex-sans-100 - latin */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "IBM Plex Sans"; - font-style: normal; - font-weight: 100; - src: url("./ibm-plex-sans-v19-latin-100.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* ibm-plex-sans-100italic - latin */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "IBM Plex Sans"; - font-style: italic; - font-weight: 100; - src: url("./ibm-plex-sans-v19-latin-100italic.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* ibm-plex-sans-200 - latin */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "IBM Plex Sans"; - font-style: normal; - font-weight: 200; - src: url("./ibm-plex-sans-v19-latin-200.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* ibm-plex-sans-200italic - latin */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "IBM Plex Sans"; - font-style: italic; - font-weight: 200; - src: url("./ibm-plex-sans-v19-latin-200italic.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* ibm-plex-sans-300 - latin */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "IBM Plex Sans"; - font-style: normal; - font-weight: 300; - src: url("./ibm-plex-sans-v19-latin-300.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* ibm-plex-sans-300italic - latin */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "IBM Plex Sans"; - font-style: italic; - font-weight: 300; - src: url("./ibm-plex-sans-v19-latin-300italic.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* ibm-plex-sans-regular - latin */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "IBM Plex Sans"; - font-style: normal; - font-weight: 400; - src: url("./ibm-plex-sans-v19-latin-regular.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* ibm-plex-sans-italic - latin */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "IBM Plex Sans"; - font-style: italic; - font-weight: 400; - src: url("./ibm-plex-sans-v19-latin-italic.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* ibm-plex-sans-500 - latin */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "IBM Plex Sans"; - font-style: normal; - font-weight: 500; - src: url("./ibm-plex-sans-v19-latin-500.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* ibm-plex-sans-500italic - latin */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "IBM Plex Sans"; - font-style: italic; - font-weight: 500; - src: url("./ibm-plex-sans-v19-latin-500italic.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* ibm-plex-sans-600 - latin */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "IBM Plex Sans"; - font-style: normal; - font-weight: 600; - src: url("./ibm-plex-sans-v19-latin-600.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* ibm-plex-sans-600italic - latin */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "IBM Plex Sans"; - font-style: italic; - font-weight: 600; - src: url("./ibm-plex-sans-v19-latin-600italic.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* ibm-plex-sans-700 - latin */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "IBM Plex Sans"; - font-style: normal; - font-weight: 700; - src: url("./ibm-plex-sans-v19-latin-700.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* ibm-plex-sans-700italic - latin */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "IBM Plex Sans"; - font-style: italic; - font-weight: 700; - src: url("./ibm-plex-sans-v19-latin-700italic.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* noto-serif-sc-200 - chinese-simplified */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "Noto Serif SC"; - font-style: normal; - font-weight: 200; - src: url("./noto-serif-sc-v22-chinese-simplified-200.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* noto-serif-sc-300 - chinese-simplified */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "Noto Serif SC"; - font-style: normal; - font-weight: 300; - src: url("./noto-serif-sc-v22-chinese-simplified-300.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* noto-serif-sc-regular - chinese-simplified */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "Noto Serif SC"; - font-style: normal; - font-weight: 400; - src: url("./noto-serif-sc-v22-chinese-simplified-regular.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* noto-serif-sc-500 - chinese-simplified */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "Noto Serif SC"; - font-style: normal; - font-weight: 500; - src: url("./noto-serif-sc-v22-chinese-simplified-500.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* noto-serif-sc-600 - chinese-simplified */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "Noto Serif SC"; - font-style: normal; - font-weight: 600; - src: url("./noto-serif-sc-v22-chinese-simplified-600.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* noto-serif-sc-700 - chinese-simplified */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "Noto Serif SC"; - font-style: normal; - font-weight: 700; - src: url("./noto-serif-sc-v22-chinese-simplified-700.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} - -/* noto-serif-sc-900 - chinese-simplified */ -@font-face { - font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */ - font-family: "Noto Serif SC"; - font-style: normal; - font-weight: 900; - src: url("./noto-serif-sc-v22-chinese-simplified-900.woff2") format("woff2"); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */ -} diff --git a/src/assets/fonts/ibm-plex-sans-v19-latin-100.woff2 b/src/assets/fonts/ibm-plex-sans-v19-latin-100.woff2 deleted file mode 100755 index bbe5a8b..0000000 Binary files a/src/assets/fonts/ibm-plex-sans-v19-latin-100.woff2 and /dev/null differ diff --git a/src/assets/fonts/ibm-plex-sans-v19-latin-100italic.woff2 b/src/assets/fonts/ibm-plex-sans-v19-latin-100italic.woff2 deleted file mode 100755 index 075d1c8..0000000 Binary files a/src/assets/fonts/ibm-plex-sans-v19-latin-100italic.woff2 and /dev/null differ diff --git a/src/assets/fonts/ibm-plex-sans-v19-latin-200.woff2 b/src/assets/fonts/ibm-plex-sans-v19-latin-200.woff2 deleted file mode 100755 index 13e9069..0000000 Binary files a/src/assets/fonts/ibm-plex-sans-v19-latin-200.woff2 and /dev/null differ diff --git a/src/assets/fonts/ibm-plex-sans-v19-latin-200italic.woff2 b/src/assets/fonts/ibm-plex-sans-v19-latin-200italic.woff2 deleted file mode 100755 index 0947013..0000000 Binary files a/src/assets/fonts/ibm-plex-sans-v19-latin-200italic.woff2 and /dev/null differ diff --git a/src/assets/fonts/ibm-plex-sans-v19-latin-300.woff2 b/src/assets/fonts/ibm-plex-sans-v19-latin-300.woff2 deleted file mode 100755 index 8737b6b..0000000 Binary files a/src/assets/fonts/ibm-plex-sans-v19-latin-300.woff2 and /dev/null differ diff --git a/src/assets/fonts/ibm-plex-sans-v19-latin-300italic.woff2 b/src/assets/fonts/ibm-plex-sans-v19-latin-300italic.woff2 deleted file mode 100755 index a5f9f4c..0000000 Binary files a/src/assets/fonts/ibm-plex-sans-v19-latin-300italic.woff2 and /dev/null differ diff --git a/src/assets/fonts/ibm-plex-sans-v19-latin-500.woff2 b/src/assets/fonts/ibm-plex-sans-v19-latin-500.woff2 deleted file mode 100755 index adbbd4c..0000000 Binary files a/src/assets/fonts/ibm-plex-sans-v19-latin-500.woff2 and /dev/null differ diff --git a/src/assets/fonts/ibm-plex-sans-v19-latin-500italic.woff2 b/src/assets/fonts/ibm-plex-sans-v19-latin-500italic.woff2 deleted file mode 100755 index 6d6a9b1..0000000 Binary files a/src/assets/fonts/ibm-plex-sans-v19-latin-500italic.woff2 and /dev/null differ diff --git a/src/assets/fonts/ibm-plex-sans-v19-latin-600.woff2 b/src/assets/fonts/ibm-plex-sans-v19-latin-600.woff2 deleted file mode 100755 index 0ac91d6..0000000 Binary files a/src/assets/fonts/ibm-plex-sans-v19-latin-600.woff2 and /dev/null differ diff --git a/src/assets/fonts/ibm-plex-sans-v19-latin-600italic.woff2 b/src/assets/fonts/ibm-plex-sans-v19-latin-600italic.woff2 deleted file mode 100755 index c71f94c..0000000 Binary files a/src/assets/fonts/ibm-plex-sans-v19-latin-600italic.woff2 and /dev/null differ diff --git a/src/assets/fonts/ibm-plex-sans-v19-latin-700.woff2 b/src/assets/fonts/ibm-plex-sans-v19-latin-700.woff2 deleted file mode 100755 index da7d57f..0000000 Binary files a/src/assets/fonts/ibm-plex-sans-v19-latin-700.woff2 and /dev/null differ diff --git a/src/assets/fonts/ibm-plex-sans-v19-latin-700italic.woff2 b/src/assets/fonts/ibm-plex-sans-v19-latin-700italic.woff2 deleted file mode 100755 index 9cd1838..0000000 Binary files a/src/assets/fonts/ibm-plex-sans-v19-latin-700italic.woff2 and /dev/null differ diff --git a/src/assets/fonts/ibm-plex-sans-v19-latin-italic.woff2 b/src/assets/fonts/ibm-plex-sans-v19-latin-italic.woff2 deleted file mode 100755 index eea1618..0000000 Binary files a/src/assets/fonts/ibm-plex-sans-v19-latin-italic.woff2 and /dev/null differ diff --git a/src/assets/fonts/ibm-plex-sans-v19-latin-regular.woff2 b/src/assets/fonts/ibm-plex-sans-v19-latin-regular.woff2 deleted file mode 100755 index 93bcd64..0000000 Binary files a/src/assets/fonts/ibm-plex-sans-v19-latin-regular.woff2 and /dev/null differ diff --git a/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-200.woff2 b/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-200.woff2 deleted file mode 100755 index d90173a..0000000 Binary files a/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-200.woff2 and /dev/null differ diff --git a/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-300.woff2 b/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-300.woff2 deleted file mode 100755 index 385e4f8..0000000 Binary files a/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-300.woff2 and /dev/null differ diff --git a/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-500.woff2 b/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-500.woff2 deleted file mode 100755 index 9699234..0000000 Binary files a/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-500.woff2 and /dev/null differ diff --git a/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-600.woff2 b/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-600.woff2 deleted file mode 100755 index ee418fd..0000000 Binary files a/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-600.woff2 and /dev/null differ diff --git a/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-700.woff2 b/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-700.woff2 deleted file mode 100755 index 03494a8..0000000 Binary files a/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-700.woff2 and /dev/null differ diff --git a/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-900.woff2 b/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-900.woff2 deleted file mode 100755 index 149b461..0000000 Binary files a/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-900.woff2 and /dev/null differ diff --git a/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-regular.woff2 b/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-regular.woff2 deleted file mode 100755 index 6c638af..0000000 Binary files a/src/assets/fonts/noto-serif-sc-v22-chinese-simplified-regular.woff2 and /dev/null differ diff --git a/src/components/Footer.astro b/src/components/Footer.astro deleted file mode 100644 index f9f1007..0000000 --- a/src/components/Footer.astro +++ /dev/null @@ -1,51 +0,0 @@ - - -
- -
diff --git a/src/components/Navbar.astro b/src/components/Navbar.astro deleted file mode 100644 index 8622abb..0000000 --- a/src/components/Navbar.astro +++ /dev/null @@ -1,73 +0,0 @@ ---- -interface MenuItem { - href?: string; - label: string; - children?: MenuItem[]; -} - -const items: MenuItem[] = [ - { - label: "情报", children: [ - { href: "/posts", label: "记录" }, - { href: "/moments", label: "回忆" } - ] - } -]; ---- - - diff --git a/src/components/PostList.astro b/src/components/PostList.astro deleted file mode 100644 index 606bfed..0000000 --- a/src/components/PostList.astro +++ /dev/null @@ -1,53 +0,0 @@ ---- -interface Props { - posts: any[]; -} - -const { posts } = Astro.props; - -function getThumbnail(item: any): string | null { - for (const attachment of item?.attachments ?? []) { - if (attachment.mimetype.startsWith("image")) { - return attachment.external_url - ? attachment.external_url - : `https://feed.smartsheep.studio/api/attachments/o/${attachment.file_id}`; - } - } - return null; -} ---- - - diff --git a/src/components/posts/Content.tsx b/src/components/posts/Content.tsx deleted file mode 100644 index ca78f43..0000000 --- a/src/components/posts/Content.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import parse from "html-react-parser"; -import mediumZoom from "medium-zoom"; -import DOMPurify from "dompurify"; -import * as marked from "marked"; -import { useEffect } from "react"; - -export default function Content({ content }: { content: string }) { - useEffect(() => { - mediumZoom(document.querySelectorAll(".post img"), { - background: "var(--fallback-b1,oklch(var(--b1)/1))", - }); - }); - - return
{parse(DOMPurify.sanitize(marked.parse(content) as string))}
; -} diff --git a/src/components/posts/Media.tsx b/src/components/posts/Media.tsx deleted file mode 100644 index 4d3bcb3..0000000 --- a/src/components/posts/Media.tsx +++ /dev/null @@ -1,111 +0,0 @@ -// @ts-ignore -import APlayer from "aplayer"; -import Artplayer from "artplayer"; -import { useState, Fragment, useRef, useEffect } from "react"; - -import "aplayer/dist/APlayer.min.css"; - -function Video({ url, mimetype, ...rest }: { url: string; mimetype: string; className?: string }) { - const container = useRef(null); - - useEffect(() => { - new Artplayer({ - container: container.current as HTMLDivElement, - url: url, - setting: true, - flip: true, - loop: true, - playbackRate: true, - aspectRatio: true, - subtitleOffset: true, - fullscreen: true, - fullscreenWeb: true, - screenshot: true, - autoPlayback: true, - airplay: true, - theme: "#49509e", - }); - }); - - return
; -} - -function Audio({ - url, - artist, - caption, - ...rest -}: { - url: string; - artist: string; - caption: string; - className?: string; -}) { - const container = useRef(null); - - useEffect(() => { - new APlayer({ - container: container.current, - audio: [ - { - name: caption, - artist: artist, - url: url, - theme: "#49509e", - }, - ], - }); - }); - - return
; -} - -export default function Media({ - sources, - author, -}: { - sources: { id: number; filename: string; mimetype: string }[]; - author?: { name: string }; -}) { - const items = sources.sort((a, b) => (a.id > b.id ? 1 : -1)); - console.log(items); - const [focus, setFocus] = useState(items.map((_, idx) => idx === 0)); - - function changeFocus(idx: number) { - setFocus(focus.map((_, i) => i === idx)); - } - - function getUrl(item: any) { - return item.external_url ? item.external_url : `https://feed.smartsheep.studio/api/attachments/o/${item.file_id}`; - } - - return ( -
- {items.map((item, idx) => ( - - changeFocus(idx)} - /> -
- {item.mimetype.startsWith("video") && ( -
-
- )} - {item.mimetype.startsWith("audio") && ( -
-
- )} -
-
- ))} -
- ); -} diff --git a/src/env.d.ts b/src/env.d.ts deleted file mode 100644 index f964fe0..0000000 --- a/src/env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/src/layouts/PageLayout.astro b/src/layouts/PageLayout.astro deleted file mode 100644 index 842b894..0000000 --- a/src/layouts/PageLayout.astro +++ /dev/null @@ -1,11 +0,0 @@ ---- -import RootLayout from "./RootLayout.astro"; - -const { title } = Astro.props; ---- - - -
- -
-
diff --git a/src/layouts/RootLayout.astro b/src/layouts/RootLayout.astro deleted file mode 100644 index c75df1b..0000000 --- a/src/layouts/RootLayout.astro +++ /dev/null @@ -1,96 +0,0 @@ ---- -import "../assets/fonts/fonts.css"; - -import "@fortawesome/fontawesome-free/css/all.min.css"; -import "nprogress/nprogress.css"; - -import Navbar from "../components/Navbar.astro"; -import Footer from "../components/Footer.astro"; -import { ViewTransitions } from "astro:transitions"; - -const { title } = Astro.props; ---- - - - - - - - - {title && 山羊寒舍 | {title}} - {!title && 山羊寒舍} - - - - - - - - - - - - -
- -
- - -