✨ Basic post viewer
This commit is contained in:
parent
f730579eeb
commit
fc4c884ade
6
.prettierrc
Normal file
6
.prettierrc
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"tabWidth": 2,
|
||||
"singleQuote": true,
|
||||
"semi": false,
|
||||
"trailingComma": "es5"
|
||||
}
|
48
README.md
48
README.md
@ -1,48 +0,0 @@
|
||||
# Astro Starter Kit: Basics
|
||||
|
||||
```sh
|
||||
npm create astro@latest -- --template basics
|
||||
```
|
||||
|
||||
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/basics)
|
||||
[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/basics)
|
||||
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/basics/devcontainer.json)
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
|
||||
![just-the-basics](https://github.com/withastro/astro/assets/2244813/a0a5533c-a856-4198-8470-2d67b1d7c554)
|
||||
|
||||
## 🚀 Project Structure
|
||||
|
||||
Inside of your Astro project, you'll see the following folders and files:
|
||||
|
||||
```text
|
||||
/
|
||||
├── public/
|
||||
│ └── favicon.svg
|
||||
├── src/
|
||||
│ ├── layouts/
|
||||
│ │ └── Layout.astro
|
||||
│ └── pages/
|
||||
│ └── index.astro
|
||||
└── package.json
|
||||
```
|
||||
|
||||
To learn more about the folder structure of an Astro project, refer to [our guide on project structure](https://docs.astro.build/en/basics/project-structure/).
|
||||
|
||||
## 🧞 Commands
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
|
||||
| Command | Action |
|
||||
| :------------------------ | :----------------------------------------------- |
|
||||
| `npm install` | Installs dependencies |
|
||||
| `npm run dev` | Starts local dev server at `localhost:4321` |
|
||||
| `npm run build` | Build your production site to `./dist/` |
|
||||
| `npm run preview` | Preview your build locally, before deploying |
|
||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||
| `npm run astro -- --help` | Get help using the Astro CLI |
|
||||
|
||||
## 👀 Want to learn more?
|
||||
|
||||
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
@ -1,12 +1,14 @@
|
||||
// @ts-check
|
||||
import { defineConfig } from 'astro/config';
|
||||
import { defineConfig } from 'astro/config'
|
||||
|
||||
import tailwind from '@astrojs/tailwind';
|
||||
import tailwind from '@astrojs/tailwind'
|
||||
|
||||
import icon from 'astro-icon';
|
||||
import icon from 'astro-icon'
|
||||
|
||||
import mdx from '@astrojs/mdx';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [tailwind(), icon()],
|
||||
prefetch: true
|
||||
});
|
||||
integrations: [tailwind(), icon(), mdx()],
|
||||
prefetch: true,
|
||||
})
|
@ -9,14 +9,18 @@
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/mdx": "^4.0.2",
|
||||
"@astrojs/tailwind": "^5.1.3",
|
||||
"@iconify-json/material-symbols": "^1.2.10",
|
||||
"astro": "^5.0.5",
|
||||
"astro-icon": "^1.1.4",
|
||||
"marked": "^15.0.4",
|
||||
"sanitize-html": "^2.13.1",
|
||||
"tailwindcss": "^3.4.16"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"@types/sanitize-html": "^2.13.0",
|
||||
"daisyui": "^4.12.22"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,12 @@
|
||||
import { Image } from "astro:assets";
|
||||
|
||||
import CompanyLogo from "../assets/images/company-logo.png";
|
||||
|
||||
interface Props {
|
||||
title?: string;
|
||||
}
|
||||
|
||||
const { title } = Astro.props;
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
@ -10,7 +16,7 @@ import CompanyLogo from "../assets/images/company-logo.png";
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="icon" type="image/png" href="/favicon.png" />
|
||||
<title>Solsynth LLC</title>
|
||||
<title>{title ? `${title} | Solsynth LLC` : "Solsynth LLC"}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar backdrop-blur fixed top-0 left-0 right-0 z-10">
|
||||
@ -20,7 +26,7 @@ import CompanyLogo from "../assets/images/company-logo.png";
|
||||
<Image
|
||||
src={CompanyLogo}
|
||||
alt="company logo"
|
||||
class="h-7 w-7 navbar-company-logo"
|
||||
class="h-8 w-8 p-1 bg-white rounded-lg shadow-sm"
|
||||
/>
|
||||
<span>Solsynth</span>
|
||||
</a>
|
||||
@ -56,17 +62,4 @@ import CompanyLogo from "../assets/images/company-logo.png";
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.navbar-company-logo {
|
||||
-webkit-filter: drop-shadow(1px 1px 0 black) drop-shadow(-1px -1px 0 black);
|
||||
filter: drop-shadow(1px 1px 0 black) drop-shadow(-1px -1px 0 black);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.navbar-company-logo {
|
||||
-webkit-filter: drop-shadow(1px 1px 0 white)
|
||||
drop-shadow(-1px -1px 0 white);
|
||||
filter: drop-shadow(1px 1px 0 white) drop-shadow(-1px -1px 0 white);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -59,7 +59,7 @@ import ProductSnPreviewImage from "../assets/images/product-solar-network.webp";
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<a class="link flex items-center gap-1 mt-3">
|
||||
<a class="link flex items-center gap-1 mt-3" href="/products/solar-network">
|
||||
<span>Learn more about Solar Network</span>
|
||||
<Icon name="material-symbols:arrow-right-alt" />
|
||||
</a>
|
||||
|
108
src/pages/posts/[...slug].astro
Normal file
108
src/pages/posts/[...slug].astro
Normal file
@ -0,0 +1,108 @@
|
||||
---
|
||||
export const prerender = false
|
||||
|
||||
import sanitizeHtml from 'sanitize-html'
|
||||
import { Icon } from 'astro-icon/components'
|
||||
import { marked } from 'marked'
|
||||
|
||||
import Layout from '../../layouts/Layout.astro'
|
||||
import { getAttachmentUrl, fetchAttachmentMeta } from '../../scripts/attachment'
|
||||
|
||||
const { slug } = Astro.params
|
||||
|
||||
const baseUrl = import.meta.env.PUBLIC_SOLAR_NETWORK_URL
|
||||
const resp = await fetch(`${baseUrl}/cgi/co/posts/${slug}`)
|
||||
|
||||
if (resp.status !== 200) {
|
||||
return new Response(null, { status: 404 })
|
||||
}
|
||||
|
||||
const data = await resp.json()
|
||||
|
||||
const rawContent = await marked(data.body.content as string, {
|
||||
breaks: data.type == 'story',
|
||||
})
|
||||
const content = sanitizeHtml(rawContent)
|
||||
|
||||
const attachments = await fetchAttachmentMeta(data.body.attachments)
|
||||
---
|
||||
|
||||
<Layout title={data.body?.title ? data.body.title : `Post #${data.id}`}>
|
||||
<div role="alert" class="alert shadow-lg px-12 m-0 rounded-none mb-5">
|
||||
<Icon
|
||||
name="material-symbols:ungroup"
|
||||
class="stroke-info fill-info h-6 w-6 shrink-0"
|
||||
/>
|
||||
<div>
|
||||
<h3 class="font-bold">Open in the Solian</h3>
|
||||
<div class="text-xs">
|
||||
The most modern, user-friendly, and official Solar Network app.
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<a class="btn btn-sm" href="/products/solar-network">Get</a>
|
||||
<a class="btn btn-sm" href={`https://sn.solsynth.dev/posts/${data.id}`}
|
||||
>Open</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container lg:max-w-[75ch] px-8 mx-auto">
|
||||
<div class="flex gap-4 items-center mb-5">
|
||||
<div class="avatar">
|
||||
<div class="w-12 rounded-full">
|
||||
<img src={getAttachmentUrl(data.publisher.avatar)} alt="avatar" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="userinfo flex flex-col">
|
||||
<span class="flex gap-2 items-baseline">
|
||||
<span class="text-md font-bold">{data.publisher.nick}</span>
|
||||
<span class="text-xs font-mono">@{data.publisher.name}</span>
|
||||
</span>
|
||||
<span class="text-sm line-clamp-2 overflow-ellipsis"
|
||||
>{data.publisher.description}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{
|
||||
data.repost_id && (
|
||||
<div role="alert" class="alert mb-5 py-2 mx-[-4px]">
|
||||
<Icon
|
||||
name="material-symbols:format-quote"
|
||||
class="stroke-info fill-info h-6 w-6 shrink-0"
|
||||
/>
|
||||
<span>
|
||||
This post is reposting post{' '}
|
||||
<span class="font-mono">#{data.repost_id}</span>
|
||||
</span>
|
||||
<div>
|
||||
<a class="btn btn-sm" href={`/posts/${data.repost_id}`}>
|
||||
See reposted post
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
<article class="prose max-w-none max-md:prose-lg" set:html={content} />
|
||||
|
||||
{
|
||||
attachments && (
|
||||
<div class="attachment-list mt-5 gap-4 grid grid-cols-1 md:grid-cols-2">
|
||||
{attachments.map((attachment) => (
|
||||
<div class="attachment">
|
||||
<a href={getAttachmentUrl(attachment.rid)} target="_blank">
|
||||
<img
|
||||
src={getAttachmentUrl(attachment.rid)}
|
||||
alt={attachment.alt}
|
||||
class="rounded-lg"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</Layout>
|
7
src/pages/products/solar-network.astro
Normal file
7
src/pages/products/solar-network.astro
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
import Layout from "../../layouts/Layout.astro";
|
||||
---
|
||||
|
||||
<Layout title="Solar Network">
|
||||
|
||||
</Layout>
|
23
src/scripts/attachment.ts
Normal file
23
src/scripts/attachment.ts
Normal file
@ -0,0 +1,23 @@
|
||||
export function getAttachmentUrl(identifier: string): string {
|
||||
if (identifier.startsWith('http')) {
|
||||
return identifier
|
||||
}
|
||||
const baseUrl = import.meta.env.PUBLIC_SOLAR_NETWORK_URL
|
||||
return `${baseUrl}/cgi/uc/attachments/${identifier}`
|
||||
}
|
||||
|
||||
export async function fetchAttachmentMeta(
|
||||
identifiers: string[]
|
||||
): Promise<any[]> {
|
||||
if (!identifiers) return []
|
||||
|
||||
const baseUrl = import.meta.env.PUBLIC_SOLAR_NETWORK_URL
|
||||
const resp = await fetch(
|
||||
`${baseUrl}/cgi/uc/attachments?take=${identifiers.length}&id=${identifiers.join(',')}`
|
||||
)
|
||||
if (resp.status !== 200) {
|
||||
throw new Error(`Failed to fetch attachment meta: ${await resp.text()}`)
|
||||
}
|
||||
const out = await resp.json()
|
||||
return out['data']
|
||||
}
|
@ -1,38 +1,38 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
|
||||
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [require("@tailwindcss/typography"), require("daisyui")],
|
||||
plugins: [require('@tailwindcss/typography'), require('daisyui')],
|
||||
daisyui: {
|
||||
themes: [
|
||||
{
|
||||
dark: {
|
||||
primary: "#3f51b5",
|
||||
secondary: "#4ba6ee",
|
||||
accent: "#03a9f4",
|
||||
neutral: "#1f2937",
|
||||
"base-100": "#000011",
|
||||
info: "#4994ec",
|
||||
success: "#67ad5b",
|
||||
warning: "#f5c344",
|
||||
error: "#e15241",
|
||||
light: {
|
||||
primary: '#3f51b5',
|
||||
secondary: '#4ba6ee',
|
||||
accent: '#03a9f4',
|
||||
neutral: '#4b5563',
|
||||
'base-100': '#ffffff',
|
||||
info: '#4994ec',
|
||||
success: '#67ad5b',
|
||||
warning: '#f5c344',
|
||||
error: '#e15241',
|
||||
},
|
||||
},
|
||||
{
|
||||
light: {
|
||||
primary: "#3f51b5",
|
||||
secondary: "#4ba6ee",
|
||||
accent: "#03a9f4",
|
||||
neutral: "#4b5563",
|
||||
"base-100": "#ffffff",
|
||||
info: "#4994ec",
|
||||
success: "#67ad5b",
|
||||
warning: "#f5c344",
|
||||
error: "#e15241",
|
||||
dark: {
|
||||
primary: '#3f51b5',
|
||||
secondary: '#4ba6ee',
|
||||
accent: '#03a9f4',
|
||||
neutral: '#1f2937',
|
||||
'base-100': '#000011',
|
||||
info: '#4994ec',
|
||||
success: '#67ad5b',
|
||||
warning: '#f5c344',
|
||||
error: '#e15241',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user