Compare commits
89 commits
chris/soci
...
main
Author | SHA1 | Date | |
---|---|---|---|
993c085952 | |||
|
3f231cefed | ||
|
a8b979ef40 | ||
|
bd5aa1cd35 | ||
|
03e6979c28 | ||
|
75781643a2 | ||
|
9cd6a6657b | ||
|
c071458257 | ||
|
0ab6bad7df | ||
|
90d70eb7c4 | ||
|
054c5c6447 | ||
|
7ea27f6319 | ||
|
c4a7ec4255 | ||
|
a0dc79b946 | ||
|
160d1cd755 | ||
|
29cdfa0248 | ||
|
c24f70d916 | ||
|
33d0be50be | ||
|
93b092266f | ||
|
eaed844ea8 | ||
|
30de324361 | ||
|
2262814a92 | ||
|
f9131003d7 | ||
|
d51cf5e707 | ||
|
e5e6cf16eb | ||
|
41f93e0ccb | ||
|
4e5cafa5d2 | ||
|
ec82e73efa | ||
|
584d6f0680 | ||
|
78adbc4433 | ||
|
d78806dfe0 | ||
|
aa265d7302 | ||
|
b18d4bf3b1 | ||
|
21e0757ea2 | ||
|
272ad45958 | ||
|
21f4826576 | ||
|
71618f4074 | ||
|
240d8ff7c9 | ||
|
357270f2a3 | ||
|
f277ba8b70 | ||
|
6f60da805e | ||
|
d1c75fe158 | ||
|
f9477aade1 | ||
|
78fda5c3ec | ||
|
455af3235b | ||
|
6db2687ef0 | ||
|
5fb6a266f8 | ||
|
3dd65bf889 | ||
|
22fae5211a | ||
|
4c2bec681b | ||
|
a067c2a2c7 | ||
|
0b22bb9af4 | ||
|
47ea310f01 | ||
|
db83237dd3 | ||
|
148b5b8769 | ||
|
345808170f | ||
|
31c59ad8b6 | ||
|
c3572fd5e0 | ||
|
77d37853cb | ||
|
eb530e9b61 | ||
|
2d33b9362d | ||
|
2167ffd72f | ||
|
0ba32e4402 | ||
|
c4c616c0a5 | ||
|
cfd895d877 | ||
|
eada8ab8fa | ||
|
3c93476078 | ||
|
824dd4670a | ||
|
0e35457c0f | ||
|
f6ba533df6 | ||
|
23e7b259eb | ||
|
8617259fc9 | ||
|
ec249f7a98 | ||
|
0ab19ba615 | ||
|
e9b77cbf19 | ||
|
f5c617e3a3 | ||
|
c0708c921c | ||
|
408b50c5ea | ||
|
e797b68160 | ||
|
87d5b841af | ||
|
4ed410db50 | ||
|
a10a798c18 | ||
|
e6be2d8146 | ||
|
5121740de7 | ||
|
9b0114c7d3 | ||
|
e8495c853b | ||
|
aad756297c | ||
|
63bc37f2b6 | ||
|
9fe4b95969 |
|
@ -1,8 +0,0 @@
|
|||
FROM gitpod/workspace-node
|
||||
|
||||
# Install latest pnpm
|
||||
RUN curl -fsSL https://get.pnpm.io/install.sh | SHELL=`which bash` bash -
|
||||
|
||||
# Install deno in gitpod
|
||||
RUN curl -fsSL https://deno.land/x/install/install.sh | sh
|
||||
RUN /home/gitpod/.deno/bin/deno completions bash > /home/gitpod/.bashrc.d/90-deno && echo 'export DENO_INSTALL="/home/gitpod/.deno"' >> /home/gitpod/.bashrc.d/90-deno && echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> /home/gitpod/.bashrc.d/90-deno
|
5
.changeset/forty-singers-ring.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fixed an issue where the transitions router did not work within framework components.
|
5
.changeset/unlucky-avocados-brake.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@astrojs/cloudflare': patch
|
||||
---
|
||||
|
||||
fixes `AdvancedRuntime` & `DirectoryRuntime` types to work woth Cloudflare caches
|
|
@ -6,10 +6,6 @@ RUN npm install -g @playwright/test
|
|||
# Install latest pnpm
|
||||
RUN npm install -g pnpm
|
||||
|
||||
# Install deno
|
||||
ENV DENO_INSTALL=/usr/local
|
||||
RUN curl -fsSL https://deno.land/x/install/install.sh | sh
|
||||
|
||||
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
&& curl -sSL https://dl.google.com/linux/direct/google-chrome-stable_current_$(dpkg --print-architecture).deb -o /tmp/chrome.deb \
|
||||
&& apt-get -y install /tmp/chrome.deb
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"name": "Deno",
|
||||
"build": {
|
||||
"dockerfile": "../examples.deno.Dockerfile"
|
||||
},
|
||||
|
||||
"workspaceFolder": "/workspaces/astro/examples/deno",
|
||||
|
||||
"portsAttributes": {
|
||||
"4321": {
|
||||
"label": "Application",
|
||||
"onAutoForward": "openPreview"
|
||||
}
|
||||
},
|
||||
|
||||
"forwardPorts": [4321],
|
||||
|
||||
"postCreateCommand": "pnpm install && cd /workspaces/astro && pnpm run build",
|
||||
|
||||
"waitFor": "postCreateCommand",
|
||||
|
||||
"postAttachCommand": {
|
||||
"Server": "pnpm start --host"
|
||||
},
|
||||
|
||||
"customizations": {
|
||||
"codespaces": {
|
||||
"openFiles": ["src/pages/index.astro"]
|
||||
},
|
||||
"vscode": {
|
||||
"extensions": ["astro-build.astro-vscode", "esbenp.prettier-vscode"]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
FROM mcr.microsoft.com/devcontainers/javascript-node:0-18
|
||||
|
||||
# Install latest pnpm
|
||||
RUN npm install -g pnpm
|
||||
|
||||
# Install deno
|
||||
ENV DENO_INSTALL=/usr/local
|
||||
RUN curl -fsSL https://deno.land/x/install/install.sh | sh
|
||||
|
||||
COPY example-welcome-message.txt /usr/local/etc/vscode-dev-containers/first-run-notice.txt
|
9
.github/workflows/ci.yml
vendored
|
@ -113,7 +113,7 @@ jobs:
|
|||
- os: macos-latest
|
||||
NODE_VERSION: 18
|
||||
- os: windows-latest
|
||||
NODE_VERSION: 18
|
||||
NODE_VERSION: 18.17.1
|
||||
fail-fast: false
|
||||
env:
|
||||
NODE_VERSION: ${{ matrix.NODE_VERSION }}
|
||||
|
@ -133,11 +133,6 @@ jobs:
|
|||
node-version: ${{ matrix.NODE_VERSION }}
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Use Deno
|
||||
uses: denoland/setup-deno@v1
|
||||
with:
|
||||
deno-version: v1.35.0
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
|
@ -155,7 +150,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
OS: [ubuntu-latest, windows-latest]
|
||||
NODE_VERSION: [18]
|
||||
NODE_VERSION: [18.17.1]
|
||||
fail-fast: false
|
||||
env:
|
||||
NODE_VERSION: ${{ matrix.NODE_VERSION }}
|
||||
|
|
3
.github/workflows/release.yml
vendored
|
@ -22,6 +22,9 @@ jobs:
|
|||
name: Changelog PR or Release
|
||||
if: ${{ github.repository_owner == 'withastro' }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
|
|
7
.github/workflows/snapshot-release.yml
vendored
|
@ -19,6 +19,11 @@ jobs:
|
|||
name: Create a snapshot release of a pull request
|
||||
if: ${{ github.repository_owner == 'withastro' && github.event.issue.pull_request && startsWith(github.event.comment.body, '!preview') }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: "Check if user has admin access (only admins can publish snapshot releases)."
|
||||
uses: "lannonbr/repo-permission-check-action@2.0.0"
|
||||
|
@ -81,6 +86,8 @@ jobs:
|
|||
id: publish
|
||||
run: |
|
||||
pnpm run release --tag next--${{ steps.getSnapshotName.outputs.result }} > publish.output.txt 2>&1
|
||||
echo "Release complete"
|
||||
cat publish.output.txt
|
||||
echo ::set-output name=result::`cat publish.output.txt`
|
||||
env:
|
||||
# Needs access to publish to npm
|
||||
|
|
18
.github/workflows/test-hosts.yml
vendored
|
@ -11,8 +11,6 @@ env:
|
|||
VERCEL_ORG_ID: ${{ secrets.VERCEL_TEST_ORG_ID }}
|
||||
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_TEST_PROJECT_ID }}
|
||||
VERCEL_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }}
|
||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_TEST_SITE_ID }}
|
||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_TEST_AUTH_TOKEN }}
|
||||
FORCE_COLOR: true
|
||||
|
||||
jobs:
|
||||
|
@ -35,21 +33,19 @@ jobs:
|
|||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Install Hosts CLIs
|
||||
run: pnpm install --global netlify-cli vercel
|
||||
- name: Build Astro
|
||||
run: pnpm turbo build --filter astro --filter @astrojs/vercel
|
||||
|
||||
- name: Deploy Vercel
|
||||
- name: Build test project
|
||||
working-directory: ./packages/integrations/vercel/test/hosted/hosted-astro-project
|
||||
run:
|
||||
pnpm run build
|
||||
vercel --prod --prebuilt
|
||||
|
||||
- name: Deploy Netlify
|
||||
working-directory: ./packages/integrations/netlify/test/hosted/hosted-astro-project
|
||||
- name: Deploy to Vercel
|
||||
working-directory: ./packages/integrations/vercel/test/hosted/hosted-astro-project
|
||||
run:
|
||||
pnpm run build
|
||||
netlify deploy --prod
|
||||
pnpm dlx vercel --prod --prebuilt
|
||||
|
||||
- name: Test both hosts
|
||||
- name: Test
|
||||
run:
|
||||
pnpm run test:e2e:hosts
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
---
|
||||
image:
|
||||
file: .Dockerfile
|
||||
# Commands to start on workspace startup
|
||||
tasks:
|
||||
- before: |
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
# Convert context URL to an array
|
||||
mapfile -t CONTEXT_URL_ITEMS < <(echo "$GITPOD_WORKSPACE_CONTEXT_URL" | tr '/' '\n')
|
||||
|
||||
# Install latest pnpm
|
||||
curl -fsSL https://get.pnpm.io/install.sh | SHELL=`which bash` bash -
|
||||
|
||||
# Check if Gitpod started from a specific example directory in the repository
|
||||
if [ "${CONTEXT_URL_ITEMS[7]}" = "examples" ]; then
|
||||
EXAMPLE_PROJECT=${CONTEXT_URL_ITEMS[8]}
|
||||
|
|
|
@ -52,8 +52,6 @@ Join us on [Discord](https://astro.build/chat) to meet other maintainers. We'll
|
|||
| [@astrojs/svelte](packages/integrations/svelte) | [![astro version](https://img.shields.io/npm/v/@astrojs/svelte.svg?label=%20)](packages/integrations/svelte/CHANGELOG.md) |
|
||||
| [@astrojs/vue](packages/integrations/vue) | [![astro version](https://img.shields.io/npm/v/@astrojs/vue.svg?label=%20)](packages/integrations/vue/CHANGELOG.md) |
|
||||
| [@astrojs/lit](packages/integrations/lit) | [![astro version](https://img.shields.io/npm/v/@astrojs/lit.svg?label=%20)](packages/integrations/lit/CHANGELOG.md) |
|
||||
| [@astrojs/deno](packages/integrations/deno) | [![astro version](https://img.shields.io/npm/v/@astrojs/deno.svg?label=%20)](packages/integrations/deno/CHANGELOG.md) |
|
||||
| [@astrojs/netlify](packages/integrations/netlify) | [![astro version](https://img.shields.io/npm/v/@astrojs/netlify.svg?label=%20)](packages/integrations/netlify/CHANGELOG.md) |
|
||||
| [@astrojs/node](packages/integrations/node) | [![astro version](https://img.shields.io/npm/v/@astrojs/node.svg?label=%20)](packages/integrations/node/CHANGELOG.md) |
|
||||
| [@astrojs/vercel](packages/integrations/vercel) | [![astro version](https://img.shields.io/npm/v/@astrojs/vercel.svg?label=%20)](packages/integrations/vercel/CHANGELOG.md) |
|
||||
| [@astrojs/cloudflare](packages/integrations/cloudflare) | [![astro version](https://img.shields.io/npm/v/@astrojs/cloudflare.svg?label=%20)](packages/integrations/cloudflare/CHANGELOG.md) |
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^3.1.4"
|
||||
"astro": "^3.2.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/mdx": "^1.1.0",
|
||||
"@astrojs/mdx": "^1.1.1",
|
||||
"@astrojs/rss": "^3.0.0",
|
||||
"@astrojs/sitemap": "^3.0.0",
|
||||
"astro": "^3.1.4"
|
||||
"@astrojs/sitemap": "^3.0.1",
|
||||
"astro": "^3.2.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
],
|
||||
"scripts": {},
|
||||
"devDependencies": {
|
||||
"astro": "^3.1.4"
|
||||
"astro": "^3.2.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"astro": "^2.0.0-beta.0"
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
FROM node:18-bullseye
|
4
examples/deno/.vscode/extensions.json
vendored
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"unwantedRecommendations": []
|
||||
}
|
11
examples/deno/.vscode/launch.json
vendored
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "./node_modules/.bin/astro dev",
|
||||
"name": "Development server",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
# Astro Starter Kit: Deno
|
||||
|
||||
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/deno)
|
||||
[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/deno)
|
||||
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/deno/devcontainer.json)
|
||||
|
||||
```sh
|
||||
npm create astro@latest -- --template deno
|
||||
```
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
|
||||
![basics](https://user-images.githubusercontent.com/4677417/186188965-73453154-fdec-4d6b-9c34-cb35c248ae5b.png)
|
||||
|
||||
## 🚀 Project Structure
|
||||
|
||||
Inside of your Astro project, you'll see the following folders and files:
|
||||
|
||||
```text
|
||||
/
|
||||
├── public/
|
||||
│ └── favicon.svg
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ │ └── Layout.astro
|
||||
│ └── pages/
|
||||
│ └── index.astro
|
||||
├── package.json
|
||||
└── tsconfig.json
|
||||
```
|
||||
|
||||
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
||||
|
||||
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
||||
|
||||
Any static assets, like images, can be placed in the `public/` directory.
|
||||
|
||||
## 🧞 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 |
|
||||
| | (preview uses Deno CLI) |
|
||||
| `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,9 +0,0 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
|
||||
import deno from '@astrojs/deno';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
output: 'server',
|
||||
adapter: deno(),
|
||||
});
|
|
@ -1,18 +0,0 @@
|
|||
{
|
||||
"name": "@example/deno",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "deno run --allow-net --allow-read --allow-env ./dist/server/entry.mjs",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^3.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/deno": "^5.0.1"
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
|
||||
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
|
||||
<style>
|
||||
path { fill: #000; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
path { fill: #FFF; }
|
||||
}
|
||||
</style>
|
||||
</svg>
|
Before Width: | Height: | Size: 749 B |
|
@ -1,61 +0,0 @@
|
|||
---
|
||||
interface Props {
|
||||
title: string;
|
||||
}
|
||||
|
||||
const { title } = Astro.props as Props;
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<title>{title}</title>
|
||||
</head>
|
||||
<body>
|
||||
<slot />
|
||||
<style>
|
||||
:root {
|
||||
--font-size-base: clamp(1rem, 0.34vw + 0.91rem, 1.19rem);
|
||||
--font-size-lg: clamp(1.2rem, 0.7vw + 1.2rem, 1.5rem);
|
||||
--font-size-xl: clamp(2.44rem, 2.38vw + 1.85rem, 3rem);
|
||||
|
||||
--color-text: hsl(12, 5%, 4%);
|
||||
--color-bg: hsl(10, 21%, 95%);
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: system-ui, sans-serif;
|
||||
font-size: var(--font-size-base);
|
||||
color: var(--color-text);
|
||||
background-color: var(--color-bg);
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
:global(h1) {
|
||||
font-size: var(--font-size-xl);
|
||||
}
|
||||
|
||||
:global(h2) {
|
||||
font-size: var(--font-size-lg);
|
||||
}
|
||||
|
||||
:global(code) {
|
||||
font-family:
|
||||
Menlo,
|
||||
Monaco,
|
||||
Lucida Console,
|
||||
Liberation Mono,
|
||||
DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono,
|
||||
Courier New,
|
||||
monospace;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
|
@ -1,188 +0,0 @@
|
|||
---
|
||||
import Layout from '../components/Layout.astro';
|
||||
|
||||
export const prerender = true;
|
||||
---
|
||||
|
||||
<Layout title="Welcome to Astro (on Deno).">
|
||||
<main>
|
||||
<h1>Welcome to <span class="text-gradient">Astro</span> on Deno</h1>
|
||||
<p class="instructions">
|
||||
<strong>Your first mission:</strong> tweak this message to try our hot module reloading. Check
|
||||
the <code>src/pages</code> directory!
|
||||
</p>
|
||||
<ul role="list" class="link-card-grid">
|
||||
<li class="link-card">
|
||||
<a href="https://astro.build/integrations/">
|
||||
<h2>Integrations <span>→</span></h2>
|
||||
<p>Add component frameworks, Tailwind, Partytown, and more!</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="link-card">
|
||||
<a href="https://astro.build/themes/">
|
||||
<h2>Themes <span>→</span></h2>
|
||||
<p>Explore a galaxy of community-built starters.</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="link-card">
|
||||
<a href="https://docs.astro.build/">
|
||||
<h2>Docs <span>→</span></h2>
|
||||
<p>Learn our complete feature set and explore the API.</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="link-card">
|
||||
<a href="https://astro.build/chat/">
|
||||
<h2>Chat <span>→</span></h2>
|
||||
<p>
|
||||
Ask, contribute, and have fun on our community Discord
|
||||
<svg
|
||||
class="heart"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 512 512"
|
||||
width="16"
|
||||
height="16"
|
||||
fill="currentColor"
|
||||
>
|
||||
<title>heart</title>
|
||||
<path
|
||||
d="M256 448l-30.164-27.211C118.718 322.442 48 258.61 48 179.095 48 114.221 97.918 64 162.4 64c36.399 0 70.717 16.742 93.6 43.947C278.882 80.742 313.199 64 349.6 64 414.082 64 464 114.221 464 179.095c0 79.516-70.719 143.348-177.836 241.694L256 448z"
|
||||
></path>
|
||||
</svg>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</main>
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--color-border: hsl(17, 24%, 90%);
|
||||
--astro-gradient: linear-gradient(0deg, #4f39fa, #da62c4);
|
||||
--link-gradient: linear-gradient(45deg, #4f39fa, #da62c4 30%, var(--color-border) 60%);
|
||||
--night-sky-gradient: linear-gradient(
|
||||
0deg,
|
||||
#392362 -33%,
|
||||
#431f69 10%,
|
||||
#30216b 50%,
|
||||
#1f1638 100%
|
||||
);
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
transition: color 0.6s cubic-bezier(0.22, 1, 0.36, 1);
|
||||
}
|
||||
|
||||
h2 span {
|
||||
display: inline-block;
|
||||
transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.875em;
|
||||
border: 0.1em solid var(--color-border);
|
||||
border-radius: 4px;
|
||||
padding: 0.15em 0.25em;
|
||||
}
|
||||
|
||||
main {
|
||||
margin: auto;
|
||||
padding: 1em;
|
||||
max-width: 60ch;
|
||||
}
|
||||
|
||||
.text-gradient {
|
||||
font-weight: 900;
|
||||
background-image: var(--astro-gradient);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-size: 100% 200%;
|
||||
background-position-y: 100%;
|
||||
border-radius: 0.4rem;
|
||||
animation: pulse 4s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%,
|
||||
100% {
|
||||
background-position-y: 0%;
|
||||
}
|
||||
50% {
|
||||
background-position-y: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
.instructions {
|
||||
line-height: 1.8;
|
||||
margin-bottom: 2rem;
|
||||
background-image: var(--night-sky-gradient);
|
||||
padding: 1.5rem;
|
||||
border-radius: 0.4rem;
|
||||
color: var(--color-bg);
|
||||
}
|
||||
|
||||
.link-card-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(24ch, 1fr));
|
||||
gap: 1rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.link-card {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
padding: 0.15rem;
|
||||
background-image: var(--link-gradient);
|
||||
background-size: 400%;
|
||||
border-radius: 0.5rem;
|
||||
background-position: 100%;
|
||||
transition: background-position 0.6s cubic-bezier(0.22, 1, 0.36, 1);
|
||||
}
|
||||
|
||||
.link-card > a {
|
||||
width: 100%;
|
||||
text-decoration: none;
|
||||
line-height: 1.4;
|
||||
padding: 1em 1.3em;
|
||||
border-radius: 0.35rem;
|
||||
color: var(--text-color);
|
||||
background-color: white;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.link-card:is(:hover, :focus-within) {
|
||||
background-position: 0;
|
||||
}
|
||||
|
||||
.link-card:is(:hover, :focus-within) h2 {
|
||||
color: #4f39fa;
|
||||
}
|
||||
|
||||
.link-card:is(:hover, :focus-within) h2 span {
|
||||
transform: translateX(2px);
|
||||
}
|
||||
|
||||
.heart {
|
||||
display: inline-block;
|
||||
color: #da62c4;
|
||||
animation: heartbeat 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes heartbeat {
|
||||
0%,
|
||||
50%,
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
5% {
|
||||
transform: scale(1.125);
|
||||
}
|
||||
10% {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
15% {
|
||||
transform: scale(1.25);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"extends": "astro/tsconfigs/base"
|
||||
}
|
|
@ -11,9 +11,9 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/alpinejs": "^0.3.0",
|
||||
"@astrojs/alpinejs": "^0.3.1",
|
||||
"@types/alpinejs": "^3.7.2",
|
||||
"alpinejs": "^3.12.3",
|
||||
"astro": "^3.1.4"
|
||||
"astro": "^3.2.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/lit": "^3.0.0",
|
||||
"@astrojs/lit": "^3.0.1",
|
||||
"@webcomponents/template-shadowroot": "^0.2.1",
|
||||
"astro": "^3.1.4",
|
||||
"astro": "^3.2.4",
|
||||
"lit": "^2.8.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,12 +11,12 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/preact": "^3.0.0",
|
||||
"@astrojs/react": "^3.0.2",
|
||||
"@astrojs/solid-js": "^3.0.1",
|
||||
"@astrojs/svelte": "^4.0.2",
|
||||
"@astrojs/vue": "^3.0.0",
|
||||
"astro": "^3.1.4",
|
||||
"@astrojs/preact": "^3.0.1",
|
||||
"@astrojs/react": "^3.0.3",
|
||||
"@astrojs/solid-js": "^3.0.2",
|
||||
"@astrojs/svelte": "^4.0.3",
|
||||
"@astrojs/vue": "^3.0.1",
|
||||
"astro": "^3.2.4",
|
||||
"preact": "^10.17.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/preact": "^3.0.0",
|
||||
"@astrojs/preact": "^3.0.1",
|
||||
"@preact/signals": "^1.2.1",
|
||||
"astro": "^3.1.4",
|
||||
"astro": "^3.2.4",
|
||||
"preact": "^10.17.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,10 +11,10 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/react": "^3.0.2",
|
||||
"@astrojs/react": "^3.0.3",
|
||||
"@types/react": "^18.2.21",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
"astro": "^3.1.4",
|
||||
"astro": "^3.2.4",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/solid-js": "^3.0.1",
|
||||
"astro": "^3.1.4",
|
||||
"@astrojs/solid-js": "^3.0.2",
|
||||
"astro": "^3.2.4",
|
||||
"solid-js": "^1.7.11"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/svelte": "^4.0.2",
|
||||
"astro": "^3.1.4",
|
||||
"@astrojs/svelte": "^4.0.3",
|
||||
"astro": "^3.2.4",
|
||||
"svelte": "^4.2.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/vue": "^3.0.0",
|
||||
"astro": "^3.1.4",
|
||||
"@astrojs/vue": "^3.0.1",
|
||||
"astro": "^3.2.4",
|
||||
"vue": "^3.3.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/node": "^6.0.1",
|
||||
"astro": "^3.1.4"
|
||||
"@astrojs/node": "^6.0.3",
|
||||
"astro": "^3.2.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ export default function createIntegration(): AstroIntegration {
|
|||
// See the @astrojs/react integration for an example
|
||||
// https://github.com/withastro/astro/blob/main/packages/integrations/react/src/index.ts
|
||||
},
|
||||
'astro:build:setup': ({ config, updateConfig }) => {
|
||||
// See the @astrojs/netlify integration for an example
|
||||
// https://github.com/withastro/astro/blob/main/packages/integrations/netlify/src/integration-functions.ts
|
||||
'astro:build:setup': ({ pages, updateConfig }) => {
|
||||
// See the @astrojs/lit integration for an example
|
||||
// https://github.com/withastro/astro/blob/main/packages/integrations/lit/src/index.ts
|
||||
},
|
||||
'astro:build:done': ({ dir, routes }) => {
|
||||
// See the @astrojs/partytown integration for an example
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
],
|
||||
"scripts": {},
|
||||
"devDependencies": {
|
||||
"astro": "^3.1.4"
|
||||
"astro": "^3.2.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"astro": "^2.0.0-beta.0"
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
"server": "node dist/server/entry.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/node": "^6.0.1",
|
||||
"astro": "^3.1.4",
|
||||
"@astrojs/node": "^6.0.3",
|
||||
"astro": "^3.2.4",
|
||||
"html-minifier": "^4.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^3.1.4"
|
||||
"astro": "^3.2.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^3.1.4"
|
||||
"astro": "^3.2.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^3.1.4"
|
||||
"astro": "^3.2.4"
|
||||
}
|
||||
}
|
||||
|
|
21
examples/social-feed/.gitignore
vendored
|
@ -1,21 +0,0 @@
|
|||
# build output
|
||||
dist/
|
||||
# generated types
|
||||
.astro/
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# macOS-specific files
|
||||
.DS_Store
|
4
examples/social-feed/.vscode/extensions.json
vendored
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"unwantedRecommendations": []
|
||||
}
|
11
examples/social-feed/.vscode/launch.json
vendored
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "./node_modules/.bin/astro dev",
|
||||
"name": "Development server",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
# Astro Starter Kit: Social Feed
|
||||
|
||||
```
|
||||
npm create astro@latest -- --template social-feed
|
||||
```
|
||||
|
||||
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/social-feed)
|
||||
[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/s/github/withastro/astro/tree/latest/examples/social-feed)
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
|
||||
## 🚀 Project Structure
|
||||
|
||||
Inside of your Astro project, you'll see the following folders and files:
|
||||
|
||||
```
|
||||
/
|
||||
├── public/
|
||||
├── src/
|
||||
│ └── pages/
|
||||
│ └── index.astro
|
||||
└── package.json
|
||||
```
|
||||
|
||||
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
||||
|
||||
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
||||
|
||||
Any static assets, like images, can be placed in the `public/` directory.
|
||||
|
||||
## 🧞 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:3000` |
|
||||
| `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,13 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 36 36">
|
||||
<path fill="#000" d="M22.25 4h-8.5a1 1 0 0 0-.96.73l-5.54 19.4a.5.5 0 0 0 .62.62l5.05-1.44a2 2 0 0 0 1.38-1.4l3.22-11.66a.5.5 0 0 1 .96 0l3.22 11.67a2 2 0 0 0 1.38 1.39l5.05 1.44a.5.5 0 0 0 .62-.62l-5.54-19.4a1 1 0 0 0-.96-.73Z"/>
|
||||
<path fill="url(#gradient)" d="M18 28a7.63 7.63 0 0 1-5-2c-1.4 2.1-.35 4.35.6 5.55.14.17.41.07.47-.15.44-1.8 2.93-1.22 2.93.6 0 2.28.87 3.4 1.72 3.81.34.16.59-.2.49-.56-.31-1.05-.29-2.46 1.29-3.25 3-1.5 3.17-4.83 2.5-6-.67.67-2.6 2-5 2Z"/>
|
||||
<defs>
|
||||
<linearGradient id="gradient" x1="16" x2="16" y1="32" y2="24" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#000"/>
|
||||
<stop offset="1" stop-color="#000" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<style>
|
||||
@media (prefers-color-scheme:dark){:root{filter:invert(100%)}}
|
||||
</style>
|
||||
</svg>
|
Before Width: | Height: | Size: 873 B |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 99 KiB |
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 25 KiB |
|
@ -1,58 +0,0 @@
|
|||
---
|
||||
import ArticleHeader from './ArticleHeader.astro';
|
||||
import type { Article } from '../content/config.js';
|
||||
|
||||
export interface Props {
|
||||
article: Article;
|
||||
}
|
||||
|
||||
const { article } = Astro.props;
|
||||
|
||||
const { Content } = await article.render();
|
||||
---
|
||||
|
||||
<article>
|
||||
<ArticleHeader {article} class="header" />
|
||||
<div class="e-content">
|
||||
<Content />
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<style>
|
||||
article {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--theme-space-lg);
|
||||
padding-block: var(--theme-space-md);
|
||||
width: 100%;
|
||||
max-width: var(--theme-size-content-3);
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.e-content {
|
||||
max-width: var(--theme-size-content-3);
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.e-content > :global(* + *) {
|
||||
margin-block-start: 1em;
|
||||
}
|
||||
|
||||
.e-content > :global(p:first-child::first-letter) {
|
||||
float: left;
|
||||
font-size: 3.5rem;
|
||||
padding-inline-end: 0.5rem;
|
||||
padding-block-start: 0.35rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.e-content :global(img, video, figure) {
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
@media (min-width: 50em) {
|
||||
.e-content > :global(* + *) {
|
||||
margin-block-start: 1.5em;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,132 +0,0 @@
|
|||
---
|
||||
import type { HTMLAttributes } from 'astro/types';
|
||||
import { Image } from 'astro:assets';
|
||||
import getReadingTime from 'reading-time';
|
||||
import FormattedDate from './FormattedDate.astro';
|
||||
import Icon from './Icon.astro';
|
||||
import TagList from './TagList.astro';
|
||||
import settings from '../settings.js';
|
||||
import type { Article } from '../content/config.js';
|
||||
|
||||
interface Props extends HTMLAttributes<'header'> {
|
||||
article: Article;
|
||||
}
|
||||
|
||||
const { article, ...attrs } = Astro.props;
|
||||
|
||||
const { text: readingTime } = await getReadingTime(article.body);
|
||||
---
|
||||
|
||||
<header {...attrs}>
|
||||
<div class="cover">
|
||||
{
|
||||
article.data.cover && (
|
||||
<Image src={article.data.cover.src} alt={article.data.cover.alt} class="u-photo" />
|
||||
)
|
||||
}
|
||||
|
||||
<div class="p-author h-card">
|
||||
<Image src={settings.avatar.src} alt={settings.avatar.alt} width={80} class="u-photo" />
|
||||
<p class="p-name">{settings.name}</p>
|
||||
<p class="p-nickname">{settings.username}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="meta">
|
||||
<FormattedDate date={article.data.pubDate} class="dt-published" />
|
||||
<span>•</span>
|
||||
<p>
|
||||
<Icon icon="clock" size="1rem" />
|
||||
<span>{readingTime}</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h1 class="p-name">article.data.title}</h1>
|
||||
|
||||
{article.data.categories?.length > 0 && <TagList tags={article.data.categories} />}
|
||||
</header>
|
||||
|
||||
<style>
|
||||
header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--theme-space-sm);
|
||||
}
|
||||
|
||||
.cover {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
min-height: 150px;
|
||||
background: var(--theme-gradient-main);
|
||||
border-radius: var(--theme-radius-xl);
|
||||
margin-block-end: var(--theme-space-md);
|
||||
}
|
||||
|
||||
.cover > img {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
width: 100%;
|
||||
min-height: inherit;
|
||||
height: 100%;
|
||||
aspect-ratio: 2.777;
|
||||
object-fit: cover;
|
||||
border-radius: inherit;
|
||||
}
|
||||
|
||||
.p-author {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--theme-space-2xs);
|
||||
width: fit-content;
|
||||
height: fit-content;
|
||||
align-self: end;
|
||||
justify-self: center;
|
||||
transform: translateY(50%);
|
||||
box-shadow: var(--theme-shadow-md);
|
||||
background-color: var(--theme-accent-light);
|
||||
padding: var(--theme-space-3xs) var(--theme-space-md);
|
||||
border-radius: var(--theme-radius-xl);
|
||||
border: 3px solid var(--theme-accent-dark);
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.cover {
|
||||
margin-block-end: var(--theme-space-sm);
|
||||
}
|
||||
|
||||
.p-author {
|
||||
justify-self: end;
|
||||
margin-inline-end: var(--theme-space-xl);
|
||||
}
|
||||
}
|
||||
|
||||
.p-author img {
|
||||
width: var(--theme-space-lg);
|
||||
height: var(--theme-space-lg);
|
||||
}
|
||||
|
||||
.p-author .p-name {
|
||||
font-family: var(--font-brand);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.p-author .p-nickname {
|
||||
color: var(--theme-gray-300);
|
||||
font-size: var(--theme-text-sm);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
font-size: var(--theme-text-sm);
|
||||
color: var(--theme-gray-200);
|
||||
}
|
||||
|
||||
.meta svg {
|
||||
margin-block-end: var(--theme-space-3xs);
|
||||
}
|
||||
</style>
|
|
@ -1,132 +0,0 @@
|
|||
---
|
||||
import type { HTMLAttributes } from 'astro/types';
|
||||
import { Image } from 'astro:assets';
|
||||
import FormattedDate from './FormattedDate.astro';
|
||||
import Icon from './Icon.astro';
|
||||
import TagList from './TagList.astro';
|
||||
import settings from '../settings.js';
|
||||
import { isArticle, type Post } from '../content/config.js';
|
||||
|
||||
export interface Props extends HTMLAttributes<'article'> {
|
||||
post: Post;
|
||||
}
|
||||
|
||||
const { post, class: className, ...attrs } = Astro.props;
|
||||
|
||||
const { pubDate, categories = [] } = post.data;
|
||||
const cover = 'cover' in post.data && post.data.cover;
|
||||
const title = 'title' in post.data && post.data.title;
|
||||
|
||||
const postUrl = `/post/${post.slug}/`;
|
||||
---
|
||||
|
||||
<article class:list={['h-entry', className]} transition:name={`card-${post.slug}`} {...attrs}>
|
||||
<header class="p-author h-card">
|
||||
<Image {...settings.avatar} width={120} class="u-photo" />
|
||||
<strong class="p-name">{settings.name}</strong>
|
||||
<div class="p-nickname">
|
||||
{settings.username}
|
||||
•
|
||||
<FormattedDate date={pubDate} class="dt-published" />
|
||||
</div>
|
||||
{categories.length > 0 && <TagList tags={categories} class="tags" />}
|
||||
</header>
|
||||
{cover && <Image {...cover} width={1060} class="u-photo" />}
|
||||
{title && <h3 class="p-name">{title}</h3>}
|
||||
{
|
||||
isArticle(post) ? (
|
||||
<p class="p-summary">{post.data.description}</p>
|
||||
) : (
|
||||
post.render().then(({ Content }) => (
|
||||
<div class="e-content">
|
||||
<Content />
|
||||
</div>
|
||||
))
|
||||
)
|
||||
}
|
||||
<footer>
|
||||
{
|
||||
Astro.url.pathname !== postUrl && (
|
||||
<a href={`/post/${post.slug}/`} class="u-url">
|
||||
Full {post.collection === 'articles' ? 'article' : 'note'}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
<a
|
||||
href={`javascript: navigator.clipboard.writeText(window.location.href + "post/${post.slug}/");`}
|
||||
>
|
||||
<Icon icon="share" size="1.5rem" />
|
||||
<span class="sr-only">Share this post</span>
|
||||
</a>
|
||||
</footer>
|
||||
</article>
|
||||
|
||||
<style>
|
||||
article {
|
||||
max-width: var(--theme-size-content-2);
|
||||
padding: var(--theme-space-sm) var(--theme-space-sm) var(--theme-space-md);
|
||||
background-color: var(--theme-bg-accent);
|
||||
border-radius: var(--theme-radius-xl);
|
||||
box-shadow: var(--theme-shadow-md);
|
||||
}
|
||||
article > :global(* + *) {
|
||||
margin-block-start: var(--theme-space-sm);
|
||||
}
|
||||
header {
|
||||
display: grid;
|
||||
grid-template-columns: auto auto 1fr;
|
||||
grid-template-areas: 'avatar name' 'avatar nickname' 'tags tags';
|
||||
align-items: center;
|
||||
row-gap: var(--theme-space-3xs);
|
||||
column-gap: var(--theme-space-sm);
|
||||
}
|
||||
.h-card .u-photo {
|
||||
grid-area: avatar;
|
||||
width: var(--theme-space-xl);
|
||||
height: var(--theme-space-xl);
|
||||
border-radius: var(--theme-radius-full);
|
||||
background-color: var(--theme-shade-subtle);
|
||||
}
|
||||
.p-name {
|
||||
grid-area: name;
|
||||
font-family: var(--font-brand);
|
||||
font-weight: bold;
|
||||
}
|
||||
.p-nickname {
|
||||
grid-area: nickname;
|
||||
font-size: var(--theme-text-sm);
|
||||
color: var(--theme-gray-300);
|
||||
}
|
||||
.tags {
|
||||
grid-area: tags;
|
||||
margin-block-start: var(--theme-space-2xs);
|
||||
}
|
||||
article > .u-photo {
|
||||
aspect-ratio: 21/9;
|
||||
object-fit: cover;
|
||||
border-radius: var(--theme-radius-lg);
|
||||
}
|
||||
.e-content > :global(* + *) {
|
||||
margin-block-start: 1em;
|
||||
}
|
||||
.e-content :global(:where(img, picture, video)) {
|
||||
width: 100%;
|
||||
}
|
||||
footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
footer > *:only-child {
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
@media (min-width: 50em) {
|
||||
header {
|
||||
grid-template-areas: 'avatar name nickname' 'avatar tags tags';
|
||||
}
|
||||
|
||||
.tags {
|
||||
margin-block-start: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,30 +0,0 @@
|
|||
---
|
||||
import settings from '../settings';
|
||||
import Icon from './Icon.astro';
|
||||
---
|
||||
|
||||
<footer>
|
||||
<p>
|
||||
{settings.name} © {new Date().getFullYear()}
|
||||
</p>
|
||||
<p>
|
||||
Designed & Developed with ♥
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<style>
|
||||
footer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: auto;
|
||||
border-top: 3px solid var(--theme-shade-subtle);
|
||||
border-radius: var(--theme-radius-xl);
|
||||
padding: var(--theme-space-md);
|
||||
row-gap: var(--theme-space-sm);
|
||||
column-gap: var(--theme-space-lg);
|
||||
color: var(--theme-gray-200);
|
||||
font-size: var(--theme-text-sm);
|
||||
}
|
||||
</style>
|
|
@ -1,19 +0,0 @@
|
|||
---
|
||||
import type { HTMLAttributes } from 'astro/types';
|
||||
|
||||
interface Props extends HTMLAttributes<'time'> {
|
||||
date: Date;
|
||||
}
|
||||
|
||||
const { date } = Astro.props;
|
||||
---
|
||||
|
||||
<time datetime={date.toISOString()}>
|
||||
{
|
||||
date.toLocaleDateString('en-us', {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
})
|
||||
}
|
||||
</time>
|
|
@ -1,33 +0,0 @@
|
|||
---
|
||||
import type { HTMLAttributes } from 'astro/types';
|
||||
import settings from '../settings';
|
||||
import ThemeToggle from './ThemeToggle.astro';
|
||||
|
||||
export interface Props extends HTMLAttributes<'header'> {}
|
||||
---
|
||||
|
||||
<header {...Astro.props}>
|
||||
<a class="site-name" href="/">{settings.username}</a>
|
||||
<ThemeToggle />
|
||||
</header>
|
||||
|
||||
<style>
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-block: var(--theme-space-md);
|
||||
}
|
||||
|
||||
.site-name {
|
||||
font-size: var(--theme-text-lg);
|
||||
font-weight: 700;
|
||||
font-family: var(--theme-font-brand);
|
||||
text-decoration: none;
|
||||
color: var(--theme-accent-dark);
|
||||
}
|
||||
|
||||
.site-name:hover {
|
||||
text-decoration: 1px solid underline var(--theme-accent-dark);
|
||||
}
|
||||
</style>
|
|
@ -1,32 +0,0 @@
|
|||
---
|
||||
import { iconPaths } from './IconPaths';
|
||||
|
||||
export interface Props {
|
||||
icon: keyof typeof iconPaths;
|
||||
color?: string;
|
||||
size?: string;
|
||||
}
|
||||
|
||||
const { icon, color, size } = Astro.props;
|
||||
const iconPath = iconPaths[icon];
|
||||
---
|
||||
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="40"
|
||||
height="40"
|
||||
viewBox="0 0 256 256"
|
||||
aria-hidden="true"
|
||||
stroke="currentcolor"
|
||||
fill="currentcolor"
|
||||
set:html={iconPath}
|
||||
/>
|
||||
|
||||
<style define:vars={{ color, size }}>
|
||||
svg {
|
||||
color: var(--color, inherit);
|
||||
vertical-align: middle;
|
||||
width: var(--size, 1em);
|
||||
height: var(--size, 1em);
|
||||
}
|
||||
</style>
|
|
@ -1,36 +0,0 @@
|
|||
/**
|
||||
* Want to add more icons?
|
||||
* 1. Find the icon you want as an SVG.
|
||||
* 2. Scale it to 256×256px.
|
||||
* 3. Paste the SVG code in your editor.
|
||||
* 4. Remove the `<svg>` wrapper so you only have elements like `<path>`, `<circle>`, `<rect>` etc.
|
||||
* 5. Remove any `stroke="{color}"` attributes
|
||||
* 6. Replace any `fill="{color}"` attributes with `stroke="none"`
|
||||
* (or add `stroke="none"` on shapes with no `fill` or `stroke` specified).
|
||||
*/
|
||||
export const iconPaths = {
|
||||
'arrow-right': `<path d="m117.5 69.6 7-7c2.9-3 7.6-3 10.6 0l60.7 60.7c3 3 3 7.7 0 10.6L135 194.6c-3 3-7.7 3-10.6 0l-7-6.9c-3-3-2.9-7.8.2-10.7l37.6-35.9H65.5a7.5 7.5 0 0 1-7.5-7.5v-10c0-4.1 3.4-7.5 7.5-7.5h89.8l-37.6-35.8a7.4 7.4 0 0 1-.2-10.7Z"/>`,
|
||||
'arrow-left': `<path d="m138.5 187-7 7c-2.9 3-7.6 3-10.6 0l-60.7-60.7c-3-3-3-7.7 0-10.6L121 62c3-3 7.7-3 10.6 0l7 7c3 2.9 2.9 7.7-.2 10.6l-37.6 35.9h89.8c4.1 0 7.5 3.3 7.5 7.5v10c0 4.2-3.4 7.5-7.5 7.5h-89.8l37.6 35.9a7.4 7.4 0 0 1 .2 10.7Z"/>`,
|
||||
'rss-alt': `<path d="M71.8 153.01a28.65 28.65 0 1 0 40.49 40.5 28.65 28.65 0 0 0 0-40.5 29.41 29.41 0 0 0-40.49 0Zm27.02 27.03a9.55 9.55 0 0 1-13.56 0 9.55 9.55 0 0 1 0-13.56 9.55 9.55 0 0 1 13.56 0 9.54 9.54 0 0 1 0 13.56Zm-6.78-73.62a9.55 9.55 0 1 0 0 19.1 47.74 47.74 0 0 1 47.75 47.74 9.55 9.55 0 1 0 19.1 0 66.84 66.84 0 0 0-66.85-66.84Zm0-38.2a9.55 9.55 0 1 0 0 19.1 85.94 85.94 0 0 1 85.94 85.94 9.55 9.55 0 1 0 19.1 0A105.04 105.04 0 0 0 92.04 68.22Z"/>`,
|
||||
'link-h': `<path d="M96.9 128.25a7.78 7.78 0 0 0 7.77 7.77h46.66a7.78 7.78 0 1 0 0-15.55h-46.66a7.77 7.77 0 0 0-7.78 7.78Zm15.55 23.32H89.12a23.33 23.33 0 0 1 0-46.65h23.33a7.78 7.78 0 1 0 0-15.55H89.12a38.88 38.88 0 0 0 0 77.76h23.33a7.78 7.78 0 1 0 0-15.56Zm54.43-62.2h-23.33a7.78 7.78 0 1 0 0 15.55h23.33a23.33 23.33 0 0 1 0 46.65h-23.33a7.77 7.77 0 1 0 0 15.56h23.33a38.88 38.88 0 1 0 0-77.76Z"/>`,
|
||||
'location-point': `<path d="M193.8 110.2a66.1 66.1 0 1 0-112.5 53.1l41.3 41.3a7.8 7.8 0 0 0 11 0l41-41.3a65.8 65.8 0 0 0 19.2-53.1Zm-30 42.1L128 188.1l-35.8-35.8a50.5 50.5 0 0 1-7.5-61.9A51 51 0 0 1 128 65.8a50.3 50.3 0 0 1 50.3 45.8 50.5 50.5 0 0 1-14.5 40.7ZM128 82a35 35 0 1 0 0 70 35 35 0 0 0 0-70Zm0 54.4a19.4 19.4 0 1 1 0-38.9 19.4 19.4 0 0 1 0 38.9Z"/>`,
|
||||
clock: `<path d="M158 118H138V78C138 75.3478 136.946 72.8043 135.071 70.929C133.196 69.0536 130.652 68 128 68C125.348 68 122.804 69.0536 120.929 70.929C119.054 72.8043 118 75.3478 118 78V128C118 130.652 119.054 133.196 120.929 135.071C122.804 136.946 125.348 138 128 138H158C160.653 138 163.195 136.946 165.07 135.071C166.947 133.196 168 130.652 168 128C168 125.348 166.947 122.804 165.07 120.929C163.195 119.054 160.653 118 158 118ZM128 28C108.222 28 88.8878 33.865 72.443 44.853C55.9981 55.8411 43.1808 71.459 35.612 89.7317C28.0434 108.004 26.063 128.111 29.9214 147.509C33.78 166.907 43.3042 184.725 57.2893 198.71C71.2746 212.696 89.093 222.221 108.491 226.078C127.889 229.938 147.996 227.957 166.269 220.387C184.541 212.819 200.158 200.002 211.147 183.557C222.134 167.112 228 147.778 228 128C228 114.868 225.413 101.864 220.387 89.7317C215.363 77.599 207.997 66.5752 198.71 57.2893C189.426 48.0035 178.402 40.6374 166.269 35.612C154.136 30.5866 141.132 28 128 28ZM128 208C112.177 208 96.7104 203.309 83.5544 194.517C70.3984 185.726 60.1446 173.232 54.0896 158.615C48.0347 143.997 46.4504 127.911 49.5371 112.393C52.624 96.8742 60.2432 82.6197 71.4315 71.4315C82.6197 60.2432 96.8742 52.624 112.393 49.5371C127.911 46.4504 143.997 48.0346 158.615 54.0896C173.232 60.1446 185.726 70.3984 194.517 83.5544C203.309 96.7102 208 112.177 208 128C208 149.217 199.571 169.566 184.568 184.568C169.566 199.571 149.217 208 128 208Z" fill="currentColor"/>`,
|
||||
share: `<path d="M192 149.333C185.698 149.375 179.483 150.812 173.803 153.541C168.123 156.271 163.117 160.225 159.147 165.12L104.747 140.053C107.305 132.221 107.305 123.778 104.747 115.947L159.147 90.8799C165.564 98.6235 174.51 103.851 184.406 105.641C194.304 107.43 204.514 105.666 213.236 100.66C221.96 95.654 228.634 87.7276 232.08 78.2799C235.528 68.832 235.526 58.47 232.078 49.0229C228.629 39.5756 221.953 31.6505 213.23 26.6459C204.507 21.6415 194.296 19.8793 184.399 21.6706C174.504 23.4618 165.557 28.6913 159.141 36.4361C152.725 44.1809 149.252 53.9431 149.333 63.9999C149.365 66.541 149.615 69.0747 150.08 71.5732L93.76 97.4932C87.7556 91.622 80.1519 87.6534 71.9019 86.0844C63.6519 84.5155 55.1224 85.4161 47.3819 88.6732C39.6414 91.9305 33.0343 97.3995 28.3883 104.395C23.7423 111.391 21.264 119.602 21.264 128C21.264 136.398 23.7423 144.609 28.3883 151.604C33.0343 158.6 39.6414 164.069 47.3819 167.327C55.1224 170.583 63.6519 171.485 71.9019 169.916C80.1519 168.347 87.7556 164.378 93.76 158.507L150.08 184.427C149.615 186.925 149.365 189.459 149.333 192C149.333 200.438 151.836 208.688 156.524 215.704C161.212 222.721 167.876 228.19 175.673 231.419C183.469 234.648 192.047 235.493 200.324 233.846C208.601 232.2 216.203 228.136 222.17 222.17C228.137 216.203 232.201 208.6 233.846 200.324C235.493 192.047 234.649 183.469 231.419 175.672C228.19 167.876 222.721 161.212 215.705 156.524C208.688 151.836 200.438 149.333 192 149.333ZM192 42.6665C196.22 42.6665 200.344 43.9177 203.852 46.2618C207.36 48.606 210.095 51.9378 211.71 55.836C213.324 59.7341 213.746 64.0235 212.924 68.1618C212.1 72.3 210.068 76.1013 207.085 79.0849C204.101 82.0683 200.3 84.1001 196.162 84.9233C192.024 85.7464 187.734 85.324 183.836 83.7093C179.938 82.0947 176.606 79.3603 174.262 75.852C171.918 72.3437 170.667 68.2193 170.667 63.9999C170.667 58.3419 172.914 52.9157 176.915 48.9149C180.916 44.9142 186.342 42.6665 192 42.6665ZM64 149.333C59.7806 149.333 55.6561 148.082 52.1479 145.738C48.6396 143.394 45.9052 140.062 44.2906 136.164C42.6759 132.266 42.2535 127.976 43.0766 123.838C43.8998 119.699 45.9316 115.899 48.915 112.915C51.8986 109.932 55.6998 107.9 59.8381 107.076C63.9764 106.253 68.2657 106.676 72.1639 108.29C76.0621 109.905 79.3939 112.64 81.7381 116.148C84.0822 119.656 85.3334 123.78 85.3334 128C85.3334 133.658 83.0857 139.084 79.0849 143.085C75.0842 147.086 69.658 149.333 64 149.333ZM192 213.333C187.78 213.333 183.657 212.082 180.148 209.738C176.64 207.394 173.905 204.062 172.29 200.164C170.676 196.266 170.254 191.977 171.076 187.838C171.9 183.699 173.932 179.899 176.915 176.915C179.899 173.932 183.7 171.9 187.838 171.076C191.977 170.254 196.266 170.676 200.164 172.29C204.062 173.905 207.394 176.64 209.738 180.148C212.082 183.655 213.333 187.78 213.333 192C213.333 197.658 211.086 203.084 207.085 207.085C203.084 211.086 197.658 213.333 192 213.333Z" fill="currentColor"/>`,
|
||||
user: `<path d="M156.9 133.5a46.7 46.7 0 1 0-57.7 0 77.8 77.8 0 0 0-48.4 63.6 7.8 7.8 0 0 0 15.5 1.7 62.2 62.2 0 0 1 123.7 0 7.8 7.8 0 0 0 7.8 7h.8a7.8 7.8 0 0 0 6.9-8.6 77.8 77.8 0 0 0-48.6-63.7ZM128 128a31.1 31.1 0 1 1 0-62.2 31.1 31.1 0 0 1 0 62.2Z"/>`,
|
||||
heart: `<path d="M187.84 74.61A46.17 46.17 0 0 0 128 70.16a46.17 46.17 0 0 0-62.29 6.86 45.56 45.56 0 0 0 2.45 62.27l54.63 54.32a7.32 7.32 0 0 0 8.03 1.6c.9-.37 1.7-.92 2.39-1.6l54.63-54.32a45.68 45.68 0 0 0 13.48-32.34 45.48 45.48 0 0 0-13.48-32.34Zm-10.34 54.4L128 178.15l-49.5-49.14a31.15 31.15 0 0 1-6.8-33.89 31.24 31.24 0 0 1 11.47-14 31.51 31.51 0 0 1 17.33-5.34c8.26.02 16.17 3.3 22 9.11a7.34 7.34 0 0 0 10.41 0 31.42 31.42 0 0 1 42.74 1.6 31.05 31.05 0 0 1 1.26 42.52h.59Z"/>`,
|
||||
'moon-stars': `<path fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="20" d="M216 112V64m24 24h-48m-24-64v32m16-16h-32m65 113A92 92 0 0 1 103 39h0a92 92 0 1 0 114 114Z"/>`,
|
||||
sun: `<circle cx="128" cy="128" r="60" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="20"/><path fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="20" d="M128 36V16M63 63 49 49m-13 79H16m47 65-14 14m79 13v20m65-47 14 14m13-79h20m-47-65 14-14"/>`,
|
||||
twitter: `<path fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="16" d="M128 88c0-22 18.5-40.3 40.5-40a40 40 0 0 1 36.2 24H240l-32.3 32.3A127.9 127.9 0 0 1 80 224c-32 0-40-12-40-12s32-12 48-36c0 0-64-32-48-120 0 0 40 40 88 48Z"/>`,
|
||||
codepen: `<path fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="16" d="m232 101-104 59-104-59 100.1-56.8a8.3 8.3 0 0 1 7.8 0Z"/><path fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="16" d="m232 165-100.1 56.8a8.3 8.3 0 0 1-7.8 0L24 165l104-59Zm0-64v64M24 101v64m104-5v62.8m0-179.6V106"/>`,
|
||||
github: `<g stroke-linecap="round" stroke-linejoin="round"><path fill="none" stroke-width="14.7" d="M55.7 167.2c13.9 1 21.3 13.1 22.2 14.6 4.2 7.2 10.4 9.6 18.3 7.1l1.1-3.4a60.3 60.3 0 0 1-25.8-11.9c-12-10.1-18-25.6-18-46.3"/><path fill="none" stroke-width="16" d="M61.4 205.1a24.5 24.5 0 0 1-3-6.1c-3.2-7.9-7.1-10.6-7.8-11.1l-1-.6c-2.4-1.6-9.5-6.5-7.2-13.9 1.4-4.5 6-7.2 12.3-7.2h.8c4 .3 7.6 1.5 10.7 3.2-9.1-10.1-13.6-24.3-13.6-42.3 0-11.3 3.5-21.7 10.1-30.4A46.7 46.7 0 0 1 65 67.3a8.3 8.3 0 0 1 5-4.7c2.8-.9 13.3-2.7 33.2 9.9a105 105 0 0 1 50.5 0c19.9-12.6 30.4-10.8 33.2-9.9 2.3.7 4.1 2.4 5 4.7 5 12.7 4 23.2 2.6 29.4 6.7 8.7 10 18.9 10 30.4 0 42.6-25.8 54.7-43.6 58.7 1.4 4.1 2.2 8.8 2.2 13.7l-.1 23.4v2.3"/><path fill="none" stroke-width="16" d="M160.9 185.7c1.4 4.1 2.2 8.8 2.2 13.7l-.1 23.4v2.3A98.6 98.6 0 1 0 61.4 205c-1.4-2.1-11.3-17.5-11.8-17.8-2.4-1.6-9.5-6.5-7.2-13.9 1.4-4.5 6-7.2 12.3-7.2h.8c4 .3 7.6 1.5 10.7 3.2-9.1-10.1-13.6-24.3-13.6-42.3 0-11.3 3.5-21.7 10.1-30.4A46.4 46.4 0 0 1 65 67.3a8.3 8.3 0 0 1 5-4.7c2.8-.9 13.3-2.7 33.2 9.9a105 105 0 0 1 50.5 0c19.9-12.6 30.4-10.8 33.2-9.9 2.3.7 4.1 2.4 5 4.7 5 12.7 4 23.2 2.6 29.4 6.7 8.7 10 18.9 10 30.4.1 42.6-25.8 54.7-43.6 58.6z"/><path fill="none" stroke-width="18.7" d="m170.1 203.3 17.3-12 17.2-18.7 9.5-26.6v-27.9l-9.5-27.5" /><path fill="none" stroke-width="22.7" d="m92.1 57.3 23.3-4.6 18.7-1.4 29.3 5.4m-110 32.6-8 16-4 21.4.6 20.3 3.4 13" /><path fill="none" stroke-width="13.3" d="M28.8 133a100 100 0 0 0 66.9 94.4v-8.7c-22.4 1.8-33-11.5-35.6-19.8-3.4-8.6-7.8-11.4-8.5-11.8"/></g>`,
|
||||
twitch: `<path fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="16" d="M165 200h-42a8 8 0 0 0-5 2l-46 38v-40H48a8 8 0 0 1-8-8V48a8 8 0 0 1 8-8h160a8 8 0 0 1 8 8v108a8 8 0 0 1-3 6l-43 36a8 8 0 0 1-5 2Zm3-112v48m-48-48v48"/>`,
|
||||
youtube: `<path fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="16" d="m160 128-48-32v64l48-32z"/><path fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="16" d="M24 128c0 30 3 47 5 56a16 16 0 0 0 10 11c34 13 89 13 89 13s56 0 89-13a16 16 0 0 0 10-11c2-9 5-26 5-56s-3-47-5-56a16 16 0 0 0-10-11c-33-13-89-13-89-13s-55 0-89 13a16 16 0 0 0-10 11c-2 9-5 26-5 56Z"/>`,
|
||||
dribbble: `<circle cx="128" cy="128" r="96" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/><path fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="16" d="M71 205a160 160 0 0 1 137-77l16 1m-36-76a160 160 0 0 1-124 59 165 165 0 0 1-30-3"/><path fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="16" d="M86 42a161 161 0 0 1 74 177"/>`,
|
||||
discord: `<circle stroke="none" cx="96" cy="144" r="12"/><circle stroke="none" cx="160" cy="144" r="12"/><path fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="16" d="M74 80a175 175 0 0 1 54-8 175 175 0 0 1 54 8m0 96a175 175 0 0 1-54 8 175 175 0 0 1-54-8"/><path fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="16" d="m155 182 12 24a8 8 0 0 0 9 4c25-6 46-16 61-30a8 8 0 0 0 3-8L206 59a8 8 0 0 0-5-5 176 176 0 0 0-30-9 8 8 0 0 0-9 5l-8 24m-53 108-12 24a8 8 0 0 1-9 4c-25-6-46-16-61-30a8 8 0 0 1-3-8L50 59a8 8 0 0 1 5-5 176 176 0 0 1 30-9 8 8 0 0 1 9 5l8 24"/>`,
|
||||
linkedin: `<rect width="184" height="184" x="36" y="36" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="16" rx="8"/><path fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="16" d="M120 112v64m-32-64v64m32-36a28 28 0 0 1 56 0v36"/><circle stroke="none" cx="88" cy="80" r="12"/>`,
|
||||
instagram: `<circle cx="128" cy="128" r="40" fill="none" stroke-miterlimit="10" stroke-width="16"/><rect width="184" height="184" x="36" y="36" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="16" rx="48"/><circle cx="180" cy="76" r="12" stroke="none" />`,
|
||||
tiktok: `<path fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="16" d="M168 106a96 96 0 0 0 56 18V84a56 56 0 0 1-56-56h-40v128a28 28 0 1 1-40-25V89a68 68 0 1 0 80 67Z"/>`,
|
||||
devto: `<path fill-rule="evenodd" d="M37 33c-2.2.5-4 2-4.7 4.2l-.3.8v181.8l.3.8c.7 2 2 3.3 4 4l.8.3H219l.7-.3c2-.7 3.3-2 4-4l.3-.8V38l-.3-.8c-.7-2-2-3.3-4-4l-.8-.3H37Zm43.6 58.3A20.7 20.7 0 0 1 98 109.6c.3 1.9.3 36.7 0 38.6a20.5 20.5 0 0 1-16 17.9c-2.6.5-1.8.5-14.9.6h-12V91h12.2c11 0 12.4 0 13.2.2Zm63.6 6.5v6.8H120v17.6h14.8v13.4H120v17.5h24.2v13.6h-30l-.8-.3a9.3 9.3 0 0 1-6.7-6.7l-.2-.9v-60l.2-.8c1-3.4 3.6-6 7-6.7.8-.2 1.8-.2 15.7-.2h14.8v6.7Zm27 8.6a268210 268210 0 0 1 9.5 36.4 5274.6 5274.6 0 0 0 13.5-51.6H209l-8.8 33a527.2 527.2 0 0 1-9.3 34.2 15 15 0 0 1-6.5 7.5c-1.3.6-2 .7-3.7.7-1.2 0-1.6 0-2.2-.2-3.2-.8-5.8-3.3-8-7.7l-.7-1.5-8.7-32.9-8.7-33c0-.2.3-.2 7.4-.2h7.4l4 15.3ZM68.7 128.8v24.3h9.5l.8-.3a9 9 0 0 0 4.7-3.4 7 7 0 0 0 1-2.4v-35.7l-.1-.8c-.6-2.3-1.9-3.8-4.3-5-1.8-.9-1.9-.9-7-1h-4.6v24.3Z" clip-rule="evenodd"/>`,
|
||||
mastodon: `<path d="M219.3 74.8a49.7 49.7 0 0 0-43-40.4c-3.7-.6-17.6-2.5-49.8-2.5h-.3c-32.2 0-39.1 2-42.8 2.5-21.1 3-40.5 17.8-45.2 39a132.2 132.2 0 0 0-2 32.4c.6 15.1.7 30.3 2 45.3 1 10 2.7 20 5 29.8 4.5 18 22.6 33.1 40.3 39.2a108.8 108.8 0 0 0 65.1 1.4c4.7-1.5 10.3-3.2 14.4-6a.5.5 0 0 0 .2-.4v-14.7a.4.4 0 0 0-.4-.4h-.2a158 158 0 0 1-38.1 4.4c-22.1 0-28-10.3-29.8-14.7a45.1 45.1 0 0 1-2.4-12 .4.4 0 0 1 .4 0c12.3 3 24.9 4.4 37.5 4.4h9.1c12.7-.4 26.1-1 38.6-3.5.3 0 .6 0 .9-.2 19.7-3.7 38.5-15.5 40.4-45.3l.3-13.5c0-4 1.3-29.3-.2-44.8Zm-30.4 74.3h-20.7V99c0-10.6-4.5-16-13.6-16-10 0-15 6.4-15 19v27.5h-20.5V102c0-12.6-5-19-15-19-9 0-13.5 5.4-13.5 16v50H69.9V97.4A37 37 0 0 1 78 72c5.6-6.2 13-9.4 22.1-9.4 10.7 0 18.7 4 24 12.1l5.2 8.6 5.2-8.6c5.3-8 13.3-12 24-12 9 0 16.5 3.1 22.1 9.3a36.9 36.9 0 0 1 8.2 25.3V149Z"/>`,
|
||||
|
||||
};
|
|
@ -1,128 +0,0 @@
|
|||
---
|
||||
import type { Page as Props } from 'astro';
|
||||
import Icon from './Icon.astro';
|
||||
|
||||
const { currentPage, lastPage, url } = Astro.props;
|
||||
const firstPage = 1;
|
||||
|
||||
interface Item {
|
||||
page: number;
|
||||
url: string;
|
||||
current: boolean;
|
||||
}
|
||||
|
||||
const makeItem = (page: number): Item => ({
|
||||
page,
|
||||
url: page === 1 ? '/' : `/${page}`,
|
||||
current: page === currentPage,
|
||||
});
|
||||
|
||||
const items: (Item | null)[] = [];
|
||||
|
||||
/** The number of pages to show before/after the current page. */
|
||||
const beforeAfter = 1;
|
||||
// Get range of pages around current page.
|
||||
const min = Math.max(
|
||||
Math.min(currentPage - beforeAfter, lastPage - 2 * beforeAfter - 1),
|
||||
firstPage
|
||||
);
|
||||
const max = Math.min(Math.max(min + 2 * beforeAfter, firstPage + 2 * beforeAfter + 1), lastPage);
|
||||
// Always include first page.
|
||||
if (min > firstPage) items.push(makeItem(firstPage));
|
||||
// Show “…” if the range starts at page 4 or higher.
|
||||
if (min > firstPage + 2) items.push(null);
|
||||
// Show page 2 if the range starts at page 3.
|
||||
if (min === firstPage + 2) items.push(makeItem(firstPage + 1));
|
||||
// Show an item for pages in range around current page.
|
||||
for (let i = min; i <= max; i++) items.push(makeItem(i));
|
||||
// Show “…” if the range ends more than 2 pages before the last page.
|
||||
if (max < lastPage - 2) items.push(null);
|
||||
// Show the penultimate page if the range ends 2 pages before the last page.
|
||||
if (max === lastPage - 2) items.push(makeItem(lastPage - 1));
|
||||
// Always include last page.
|
||||
if (max < lastPage) items.push(makeItem(lastPage));
|
||||
---
|
||||
|
||||
{
|
||||
lastPage > 1 && (
|
||||
<nav>
|
||||
<ul>
|
||||
<li class="pagination-arrow">
|
||||
{url.prev === undefined ? (
|
||||
<span>
|
||||
<Icon icon="arrow-left" />
|
||||
<span class="sr-only">Previous</span>
|
||||
</span>
|
||||
) : (
|
||||
<a href={url.prev} rel="prev">
|
||||
<Icon icon="arrow-left" />
|
||||
<span class="sr-only">Previous</span>
|
||||
</a>
|
||||
)}
|
||||
</li>
|
||||
{items.map((item) => (
|
||||
<li class="pagination-item">
|
||||
{item ? (
|
||||
<a href={item.url} aria-current={item.current}>
|
||||
{item.page}
|
||||
</a>
|
||||
) : (
|
||||
<span>…</span>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
<li class="pagination-arrow">
|
||||
{url.next === undefined ? (
|
||||
<span>
|
||||
<span class="sr-only">Next</span>
|
||||
<Icon icon="arrow-right" />
|
||||
</span>
|
||||
) : (
|
||||
<a href={url.next} rel="next">
|
||||
<span class="sr-only">Next</span>
|
||||
<Icon icon="arrow-right" />
|
||||
</a>
|
||||
)}
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
|
||||
<style>
|
||||
ul {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
list-style: none;
|
||||
gap: var(--theme-space-2xs);
|
||||
padding: 0;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: var(--theme-text);
|
||||
}
|
||||
.pagination-item > * {
|
||||
border: 1.5px solid var(--theme-accent-dark);
|
||||
border-radius: var(--theme-radius-base);
|
||||
padding: 0.375rem 0.75rem;
|
||||
background-color: var(--theme-bg-accent);
|
||||
font-size: var(--theme-text-sm);
|
||||
font-weight: 700;
|
||||
box-shadow: var(--theme-shadow-sm);
|
||||
}
|
||||
.pagination-item > [aria-current='true'] {
|
||||
background-color: var(--theme-accent-dark);
|
||||
color: var(--theme-text-invert);
|
||||
}
|
||||
|
||||
.pagination-arrow > * {
|
||||
color: var(--theme-accent-dark);
|
||||
opacity: 0.35;
|
||||
font-size: var(--theme-text-xl);
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.pagination-arrow > a {
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
|
@ -1,32 +0,0 @@
|
|||
---
|
||||
import type { HTMLAttributes } from 'astro/types';
|
||||
|
||||
export interface Props extends HTMLAttributes<'div'> {
|
||||
reverse?: boolean;
|
||||
}
|
||||
|
||||
const { reverse = false, class: className, ...attrs } = Astro.props;
|
||||
---
|
||||
|
||||
<div class:list={[className, { reverse }]} {...attrs}>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: var(--theme-space-lg);
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
max-width: var(--theme-size-content-3);
|
||||
}
|
||||
|
||||
@media (min-width: 50em) {
|
||||
div {
|
||||
flex-direction: row;
|
||||
align-items: initial;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,41 +0,0 @@
|
|||
---
|
||||
import type { HTMLAttributes } from 'astro/types';
|
||||
|
||||
interface Props extends HTMLAttributes<'ul'> {
|
||||
tags: string[];
|
||||
}
|
||||
|
||||
const { tags, ...attrs } = Astro.props;
|
||||
---
|
||||
|
||||
<ul {...attrs}>
|
||||
{
|
||||
tags.map((tag) => (
|
||||
<li>
|
||||
<a href={`/category/${tag}/`} rel="category tag" class="p-category">
|
||||
{tag}
|
||||
</a>
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
|
||||
<style>
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
gap: var(--theme-space-3xs);
|
||||
}
|
||||
.p-category {
|
||||
padding: var(--theme-space-3xs) var(--theme-space-2xs);
|
||||
border-radius: var(--theme-radius-full);
|
||||
background-color: var(--theme-accent-dark);
|
||||
color: var(--theme-text-invert);
|
||||
font-size: var(--theme-text-sm);
|
||||
font-weight: 500;
|
||||
}
|
||||
.p-category::before {
|
||||
content: '#';
|
||||
}
|
||||
</style>
|
|
@ -1,107 +0,0 @@
|
|||
---
|
||||
import Icon from './Icon.astro';
|
||||
---
|
||||
|
||||
<theme-toggle>
|
||||
<button>
|
||||
<span class="sr-only">Dark theme</span>
|
||||
<span class="icon light"><Icon icon="sun" /></span>
|
||||
<span class="icon dark"><Icon icon="moon-stars" /></span>
|
||||
</button>
|
||||
</theme-toggle>
|
||||
|
||||
<style>
|
||||
button {
|
||||
position: relative;
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
border: 0;
|
||||
border-radius: var(--theme-radius-full);
|
||||
padding: 0.1875rem;
|
||||
background-color: var(--theme-accent-light);
|
||||
box-shadow: var(--theme-shadow-lg);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button::before {
|
||||
position: absolute;
|
||||
inset: -0.125rem;
|
||||
content: '';
|
||||
border-radius: var(--theme-radius-full);
|
||||
background: var(--theme-gradient-main);
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.icon {
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: 0.3125rem;
|
||||
width: 1.625rem;
|
||||
height: 1.625rem;
|
||||
font-size: 1rem;
|
||||
color: var(--theme-accent-dark);
|
||||
}
|
||||
|
||||
.icon.light::before {
|
||||
content: '';
|
||||
z-index: -1;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-color: var(--theme-accent-dark);
|
||||
border-radius: 999rem;
|
||||
}
|
||||
|
||||
:global(.theme-dark) .icon.light::before {
|
||||
transform: translateX(calc(100% + 0.25rem));
|
||||
}
|
||||
|
||||
:global(.theme-dark) .icon.dark,
|
||||
:global(html:not(.theme-dark)) .icon.light,
|
||||
button[aria-pressed='false'] .icon.light {
|
||||
color: var(--theme-text-invert);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.icon,
|
||||
.icon.light::before {
|
||||
transition: transform var(--theme-transition),
|
||||
color var(--theme-transition);
|
||||
}
|
||||
}
|
||||
|
||||
@media (forced-colors: active) {
|
||||
.icon.light::before {
|
||||
background-color: SelectedItem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
class ThemeToggle extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const button = this.querySelector('button')!;
|
||||
|
||||
/** Set the theme to dark/light mode. */
|
||||
const setTheme = (dark: boolean) => {
|
||||
document.documentElement.classList[dark ? 'add' : 'remove'](
|
||||
'theme-dark'
|
||||
);
|
||||
button.setAttribute('aria-pressed', String(dark));
|
||||
};
|
||||
|
||||
// Toggle the theme when a user clicks the button.
|
||||
button.addEventListener('click', () => setTheme(!this.isDark()));
|
||||
|
||||
// Initialize button state to reflect current theme.
|
||||
setTheme(this.isDark());
|
||||
}
|
||||
|
||||
isDark() {
|
||||
return document.documentElement.classList.contains('theme-dark');
|
||||
}
|
||||
}
|
||||
customElements.define('theme-toggle', ThemeToggle);
|
||||
</script>
|
|
@ -1,164 +0,0 @@
|
|||
---
|
||||
import { Image } from 'astro:assets';
|
||||
import settings from '../settings';
|
||||
import Icon from './Icon.astro';
|
||||
|
||||
const socialLinks = Object.entries(settings.social);
|
||||
---
|
||||
|
||||
<div class="h-card">
|
||||
<div>
|
||||
<div class="u-photo">
|
||||
<Image {...settings.avatar} width={220} />
|
||||
</div>
|
||||
<h1>
|
||||
<span class="p-name">{settings.name}</span>
|
||||
<small class="p-nickname">{settings.username}</small>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="bio-sections">
|
||||
<div class="bio">
|
||||
<p>🚀 <a href="https://astro.build/">Astro</a> Mascot</p>
|
||||
<p>😊 The cutest</p>
|
||||
<p>🎨 Whimsical Speedy Web</p>
|
||||
</div>
|
||||
<div class="bio">
|
||||
{
|
||||
settings.pronouns && (
|
||||
<p>
|
||||
<Icon icon="user" color="var(--theme-accent-dark)" size="1.75rem" />
|
||||
<span class="sr-only">Pronouns</span>
|
||||
{settings.pronouns}
|
||||
</p>
|
||||
)
|
||||
}
|
||||
{
|
||||
settings.location && (
|
||||
<p>
|
||||
<Icon icon="location-point" color="var(--theme-accent-dark)" size="1.75rem" />
|
||||
<span class="sr-only">Location</span>
|
||||
<span class="p-locality">{settings.location}</span>
|
||||
</p>
|
||||
)
|
||||
}
|
||||
{
|
||||
settings.homepage && (
|
||||
<p>
|
||||
<Icon icon="link-h" color="var(--theme-accent-dark)" size="1.75rem" />
|
||||
<span class="sr-only">Homepage</span>
|
||||
<a href={settings.homepage} class="u-url">{settings.homepage.replace(/^https?:\/\/(www\.)?/, '')}</a>
|
||||
</p>
|
||||
)
|
||||
}
|
||||
<p>
|
||||
<Icon icon="rss-alt" color="var(--theme-accent-dark)" size="1.75rem" />
|
||||
<a href="/rss.xml">RSS Feed</a>
|
||||
</p>
|
||||
</div>
|
||||
<ul class="social">
|
||||
{
|
||||
socialLinks.map(([key, { url, title }]) => (
|
||||
<li>
|
||||
<a href={url} rel="me">
|
||||
<span class="sr-only">{title}</span>
|
||||
<Icon icon={`${key}`} size="1.75rem" />
|
||||
</a>
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.h-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--theme-space-md);
|
||||
}
|
||||
|
||||
.u-photo {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.u-photo::after {
|
||||
border-radius: var(--theme-radius-full);
|
||||
position: absolute;
|
||||
content: '';
|
||||
inset: 0;
|
||||
border: 3px solid var(--theme-text);
|
||||
}
|
||||
|
||||
.u-photo img {
|
||||
width: 110px;
|
||||
height: 110px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: var(--theme-text-xl);
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: var(--theme-text-base);
|
||||
font-family: var(--theme-font-body);
|
||||
color: var(--theme-gray-200);
|
||||
}
|
||||
|
||||
.bio-sections {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
align-items: flex-start;
|
||||
gap: var(--theme-space-sm) var(--theme-space-md);
|
||||
}
|
||||
|
||||
.bio-sections > :nth-child(2) {
|
||||
grid-row: span 2;
|
||||
}
|
||||
|
||||
.bio {
|
||||
font-size: var(--theme-text-sm);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.bio > * + * {
|
||||
margin-top: var(--theme-space-xs);
|
||||
}
|
||||
|
||||
.bio :global(svg) {
|
||||
/* Slightly hacky way to avoid the icon height being included in the box calculation. */
|
||||
margin: -50% 0;
|
||||
}
|
||||
|
||||
.social {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--theme-space-3xs);
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
grid-row: 2;
|
||||
}
|
||||
|
||||
.social a {
|
||||
color: var(--theme-accent-dark);
|
||||
}
|
||||
|
||||
@media (min-width: 35em) {
|
||||
.bio-sections {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
.social {
|
||||
grid-row: unset;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 50em) {
|
||||
.bio-sections {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,29 +0,0 @@
|
|||
---
|
||||
title: First post on my new site!
|
||||
description: Dignissim eu sagittis aliquet magna sagittis. Eu etiam faucibus quis non. Laoreet amet aliquam enim sapien. Cras ac enim nulla morbi ultrices elementum metus neque nulla. Quis mi consectetur donec tempor habitant.
|
||||
pubDate: 2023-01-01
|
||||
categories: [keyboards, thoughts]
|
||||
cover:
|
||||
src: ../../assets/stock-1.jpg
|
||||
alt: A laptop with a code editor open
|
||||
---
|
||||
|
||||
Dignissim eu sagittis aliquet magna sagittis. Eu etiam faucibus quis non. Laoreet amet aliquam enim sapien. Cras ac enim nulla morbi ultrices elementum metus neque nulla. Quis mi consectetur donec tempor habitant.
|
||||
|
||||
Id at orci nulla nunc. Habitant a amet turpis facilisi purus cursus dui imperdiet. Integer fermentum amet nunc tristique scelerisque feugiat pellentesque phasellus. Feugiat euismod id varius id mattis ac ut. Donec aliquet fusce ut egestas vehicula sagittis.
|
||||
|
||||
Mauris vulputate tristique porttitor sed integer felis. In eget sodales lobortis laoreet molestie aliquet est aliquet tortor. Sodales erat rhoncus tellus mattis etiam nunc ornare. Nisi ut tellus elementum gravida dictum diam porta. Nulla porttitor magna duis pretium egestas nisl ornare.
|
||||
|
||||
## Heading One
|
||||
|
||||
Suscipit id porttitor laoreet purus semper fermentum libero cras magna. Non hendrerit lectus tincidunt condimentum. Sollicitudin pretium at vel nibh tempus proin faucibus donec sed. Habitant et risus auctor platea viverra tellus. Faucibus dapibus neque enim metus porttitor pulvinar pharetra amet sem. Nibh a facilisis pellentesque ut pellentesque. Amet semper ultrices est lacus facilisis pulvinar viverra. Quis velit cursus viverra varius vestibulum. Ultricies interdum id dapibus nunc bibendum vitae varius in. Lorem vel congue in amet et pellentesque sed facilisis. Id amet sed suspendisse tincidunt lacinia sit. Ut libero id ornare cursus porttitor elementum.
|
||||
|
||||
## Heading Number Two
|
||||
|
||||
Sagittis fames arcu tempor morbi sed mauris eu blandit cras. Risus amet nec auctor nunc pretium commodo. Dictum duis nascetur est molestie ullamcorper sit tempor. Vestibulum dictumst magna cursus aenean vitae ornare amet non.
|
||||
|
||||
Dui tortor viverra eu montes. Elit pretium pharetra aliquam pellentesque congue id morbi maecenas. Donec a egestas ipsum sit a ipsum. Quis vestibulum feugiat tincidunt justo tellus turpis. Luctus dignissim porta dictumst ut auctor neque in.
|
||||
|
||||
![Close-up of a mechanical keyboard with LED backlighting](../../assets/mechanical-keyboard.png)
|
||||
|
||||
Pellentesque faucibus faucibus magna tempus proin amet in viverra. Eros non ipsum justo pellentesque vestibulum morbi proin euismod. Sagittis in amet at aliquet facilisis.
|
|
@ -1,9 +0,0 @@
|
|||
---
|
||||
title: Second time lucky
|
||||
description: Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
|
||||
pubDate: 2023-01-02
|
||||
---
|
||||
|
||||
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
|
||||
|
||||
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
title: Three is a magic number
|
||||
description: Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
|
||||
pubDate: 2023-01-03
|
||||
cover:
|
||||
src: ../../assets/stock-2.jpg
|
||||
alt: A backlit multicolored mechanical keyboard
|
||||
---
|
||||
|
||||
Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
|
@ -1,48 +0,0 @@
|
|||
import { rssSchema } from '@astrojs/rss';
|
||||
import { defineCollection, z, type CollectionEntry } from 'astro:content';
|
||||
|
||||
const articles = defineCollection({
|
||||
schema: ({ image }) => rssSchema
|
||||
.extend({
|
||||
cover: z
|
||||
.object({
|
||||
src: image().refine(
|
||||
(img) => img.width >= 885,
|
||||
'Cover image must be at least 885px wide.'
|
||||
),
|
||||
alt: z.string(),
|
||||
})
|
||||
.optional(),
|
||||
})
|
||||
.required({
|
||||
// requiring the description for articles, this will be shown as the short preview text on cards
|
||||
title: true,
|
||||
description: true
|
||||
})
|
||||
.strict(),
|
||||
})
|
||||
|
||||
const notes = defineCollection({
|
||||
schema: rssSchema
|
||||
.omit({
|
||||
// notes are short, self-contained content without unique titles or descriptions
|
||||
description: true,
|
||||
title: true
|
||||
})
|
||||
.strict()
|
||||
})
|
||||
|
||||
export const collections = { articles, notes };
|
||||
|
||||
export type Article = CollectionEntry<'articles'>;
|
||||
export type Note = CollectionEntry<'notes'>;
|
||||
// eslint-disable-next-line @typescript-eslint/no-duplicate-type-constituents
|
||||
export type Post = Article | Note;
|
||||
|
||||
export function isArticle(post: Post): post is Article {
|
||||
return post.collection === 'articles'
|
||||
}
|
||||
|
||||
export function isNote(post: Post): post is Note {
|
||||
return post.collection === 'notes'
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
---
|
||||
pubDate: 2023-01-10
|
||||
---
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis commodo odio aenean sed. Enim nulla aliquet porttitor lacus luctus accumsan tortor posuere ac.
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Aenean vel elit scelerisque mauris. Sapien eget mi proin sed libero enim sed.
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
pubDate: 2023-01-04
|
||||
---
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Adipiscing elit ut aliquam purus sit amet luctus. Rhoncus aenean vel elit scelerisque mauris. Nulla pellentesque dignissim enim sit amet venenatis urna cursus.
|
|
@ -1,7 +0,0 @@
|
|||
---
|
||||
pubDate: 2023-01-05
|
||||
---
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pellentesque habitant morbi tristique senectus et netus et.
|
||||
|
||||
![Mechanical keyboard with LED backlighting](../../assets/mechanical-keyboard.png)
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
pubDate: 2023-01-06
|
||||
---
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Donec adipiscing tristique risus nec feugiat in fermentum posuere. Mauris pellentesque pulvinar pellentesque habitant morbi tristique senectus et netus. Cursus sit amet dictum sit amet justo donec.
|
|
@ -1,7 +0,0 @@
|
|||
---
|
||||
pubDate: 2023-01-07
|
||||
---
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Volutpat maecenas volutpat blandit aliquam etiam erat velit.
|
||||
|
||||
Read more in [the docs](https://docs.astro.build)
|
|
@ -1,7 +0,0 @@
|
|||
---
|
||||
pubDate: 2023-01-08
|
||||
---
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Adipiscing bibendum est ultricies integer quis auctor.
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Semper viverra nam libero justo laoreet sit amet cursus sit.
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
pubDate: 2023-01-09
|
||||
---
|
||||
|
||||
ultrices neque ornare aenean euismod elementum
|
|
@ -1,24 +0,0 @@
|
|||
import { getCollection } from 'astro:content';
|
||||
import type { Article, Note } from '../content/config';
|
||||
|
||||
export function sortPosts(order: 'asc' | 'desc' = 'desc') {
|
||||
return function(a: Article | Note, b: Article | Note) {
|
||||
return order === 'asc'
|
||||
? a.data.pubDate.getTime() - b.data.pubDate.getTime()
|
||||
: b.data.pubDate.getTime() - a.data.pubDate.getTime()
|
||||
}
|
||||
}
|
||||
|
||||
/** Get everything in your posts collection, sorted by date. */
|
||||
export async function getSortedPosts(order: 'asc' | 'desc' = 'desc') {
|
||||
const posts = await Promise.all([
|
||||
getCollection('articles'),
|
||||
getCollection('notes'),
|
||||
])
|
||||
.then((collections) => collections
|
||||
.flat()
|
||||
.sort(sortPosts(order)
|
||||
));
|
||||
|
||||
return posts;
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
---
|
||||
import settings from '../settings';
|
||||
import '../style/theme.css';
|
||||
import '../style/global.css';
|
||||
import '../style/utilities.css';
|
||||
import Header from '../components/Header.astro';
|
||||
import Footer from '../components/Footer.astro';
|
||||
|
||||
export interface Props {
|
||||
title?: string;
|
||||
}
|
||||
|
||||
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
||||
|
||||
const { title = settings.name } = Astro.props;
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>{title}</title>
|
||||
|
||||
<!-- Canonical URL -->
|
||||
<link rel="canonical" href={canonicalURL} />
|
||||
|
||||
<!-- RSS Feed Discovery -->
|
||||
<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml" />
|
||||
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Montserrat:wght@500;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<script is:inline>
|
||||
// This code is inlined in the head to make dark mode instant & blocking.
|
||||
const getThemePreference = () => {
|
||||
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
|
||||
return localStorage.getItem('theme');
|
||||
}
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||
};
|
||||
const isDark = getThemePreference() === 'dark';
|
||||
document.documentElement.classList[isDark ? 'add' : 'remove']('theme-dark');
|
||||
if (typeof localStorage !== 'undefined') {
|
||||
// Watch the document element and persist user preference when it changes.
|
||||
const observer = new MutationObserver(() => {
|
||||
const isDark = document.documentElement.classList.contains('theme-dark');
|
||||
localStorage.setItem('theme', isDark ? 'dark' : 'light');
|
||||
});
|
||||
observer.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ['class'],
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<Header class="header" />
|
||||
<main>
|
||||
<slot />
|
||||
</main>
|
||||
<Footer />
|
||||
<style>
|
||||
html {
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--theme-space-lg);
|
||||
}
|
||||
|
||||
.header,
|
||||
main {
|
||||
padding-inline: var(--theme-space-sm-lg);
|
||||
}
|
||||
|
||||
main {
|
||||
width: 100%;
|
||||
max-width: 55rem;
|
||||
margin-inline: auto;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
import Layout, { type Props as LayoutProps } from './Base.astro';
|
||||
import UserProfile from '../components/UserProfile.astro';
|
||||
import SplitLayout from '../components/SplitLayout.astro';
|
||||
|
||||
export interface Props extends LayoutProps {}
|
||||
---
|
||||
|
||||
<Layout {...Astro.props}>
|
||||
<SplitLayout>
|
||||
<UserProfile />
|
||||
<div>
|
||||
<slot />
|
||||
</div>
|
||||
</SplitLayout>
|
||||
</Layout>
|
|
@ -1,48 +0,0 @@
|
|||
---
|
||||
import type { GetStaticPathsOptions, Page } from 'astro';
|
||||
import Card from '../components/Card.astro';
|
||||
import Pagination from '../components/Pagination.astro';
|
||||
import { getSortedPosts } from '../helpers/getSortedPosts';
|
||||
import Layout from '../layouts/Feed.astro';
|
||||
import type { Post } from '../content/config.js';
|
||||
|
||||
export async function getStaticPaths({ paginate }: GetStaticPathsOptions) {
|
||||
return paginate(await getSortedPosts(), { pageSize: 3 });
|
||||
}
|
||||
|
||||
interface Props {
|
||||
page: Page<Post>;
|
||||
}
|
||||
|
||||
const { page } = Astro.props;
|
||||
---
|
||||
|
||||
<Layout>
|
||||
<div class="stack">
|
||||
<ol>
|
||||
{
|
||||
page.data.map((post) => (
|
||||
<li>
|
||||
<Card {post} />
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ol>
|
||||
<Pagination {...page} />
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
.stack {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2.5rem;
|
||||
}
|
||||
ol {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.25rem;
|
||||
}
|
||||
</style>
|
|
@ -1,102 +0,0 @@
|
|||
---
|
||||
import Article from '../../components/Article.astro';
|
||||
import Card from '../../components/Card.astro';
|
||||
import Icon from '../../components/Icon.astro';
|
||||
import { getSortedPosts } from '../../helpers/getSortedPosts';
|
||||
import Layout from '../../layouts/Base.astro';
|
||||
import { isArticle, type Post } from '../../content/config';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const posts = await getSortedPosts();
|
||||
return posts.map((post, idx) => ({
|
||||
params: { slug: post.slug },
|
||||
props: { post, prev: posts[idx - 1], next: posts[idx + 1] },
|
||||
}));
|
||||
}
|
||||
|
||||
interface Props {
|
||||
post: Post;
|
||||
prev?: Post;
|
||||
next?: Post;
|
||||
}
|
||||
|
||||
const { post, prev, next } = Astro.props;
|
||||
|
||||
const { title } = isArticle(post) && post.data;
|
||||
---
|
||||
|
||||
<Layout {title}>
|
||||
<a href="/" class="back">
|
||||
<Icon icon="arrow-left" color="var(--theme-accent-dark)" size="var(--theme-space-md)" />
|
||||
<span>Back to feed</span>
|
||||
</a>
|
||||
|
||||
{isArticle(post) ? <Article article={post} /> : <Card {post} class="card" />}
|
||||
|
||||
{
|
||||
(next || prev) && (
|
||||
<footer>
|
||||
{prev && (
|
||||
<a href={`/post/${prev.slug}`} class="prev">
|
||||
<Icon icon="arrow-left" size="var(--theme-space-md)" color="var(--theme-accent-dark)" />
|
||||
<span>Previous post</span>
|
||||
</a>
|
||||
)}
|
||||
{next && (
|
||||
<a href={`/post/${next.slug}`} class="next">
|
||||
<span>Next post</span>
|
||||
<Icon
|
||||
icon="arrow-right"
|
||||
size="var(--theme-space-md)"
|
||||
color="var(--theme-accent-dark)"
|
||||
/>
|
||||
</a>
|
||||
)}
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
.back {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.back {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--theme-space-2xs);
|
||||
margin-inline-start: -4px;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: 100%;
|
||||
margin: var(--theme-space-md) auto;
|
||||
}
|
||||
|
||||
.center {
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.prev,
|
||||
.next {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-inline: -4px;
|
||||
}
|
||||
|
||||
footer a {
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.next:first-child {
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
</style>
|
|
@ -1,27 +0,0 @@
|
|||
import rss from '@astrojs/rss';
|
||||
import type { APIContext } from 'astro';
|
||||
import { sortPosts } from '../helpers/getSortedPosts';
|
||||
import settings from '../settings';
|
||||
import { getCollection } from 'astro:content';
|
||||
|
||||
const { title, description } = settings.rss;
|
||||
|
||||
export async function GET(context: APIContext) {
|
||||
const posts = await getCollection('articles');
|
||||
|
||||
return rss({
|
||||
// `<title>` field in output xml
|
||||
title,
|
||||
// `<description>` field in output xml
|
||||
description,
|
||||
// Pull in your project "site" from the endpoint context
|
||||
// https://docs.astro.build/en/reference/api-reference/#contextsite
|
||||
site: context.site!.href,
|
||||
// Array of `<item>`s in output xml
|
||||
// See "Generating items" section for examples using content collections and glob imports
|
||||
items: posts
|
||||
.sort(sortPosts())
|
||||
.map(({ data, slug }) => ({ ...data, link: `/post/${slug}` })),
|
||||
stylesheet: '/rss/styles.xsl',
|
||||
});
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
import { iconPaths } from './components/IconPaths.js'
|
||||
import avatar from './assets/avatar.webp'
|
||||
|
||||
export interface Image {
|
||||
src: ImageMetadata
|
||||
alt: string
|
||||
}
|
||||
|
||||
export interface Settings {
|
||||
name: string
|
||||
username: string
|
||||
avatar: Image
|
||||
rss: {
|
||||
title: string,
|
||||
description: string
|
||||
},
|
||||
pronouns?: string | undefined
|
||||
location?: string | undefined
|
||||
homepage?: string | undefined
|
||||
social: Partial<{
|
||||
[icon in keyof typeof iconPaths]: {
|
||||
url: string,
|
||||
title: string,
|
||||
}
|
||||
}>
|
||||
}
|
||||
|
||||
const settings: Settings = {
|
||||
name: 'Houston Astro',
|
||||
username: '@houston',
|
||||
avatar: {
|
||||
src: avatar,
|
||||
alt: 'Astro mascot Houston smiling',
|
||||
},
|
||||
rss: {
|
||||
title: 'Houston Astro’s Feed',
|
||||
description: 'Stay up-to-date with the latest posts from Houston Astro!',
|
||||
},
|
||||
pronouns: 'They/Them',
|
||||
location: 'Space',
|
||||
homepage: 'https://astro.build',
|
||||
social: {
|
||||
twitter: {
|
||||
url: 'https://twitter.com/astrodotbuild',
|
||||
title: 'Twitter'
|
||||
},
|
||||
github: {
|
||||
url: 'https://github.com/withastro',
|
||||
title: 'GitHub',
|
||||
},
|
||||
mastodon: {
|
||||
url: 'https://m.webtoo.ls/@astro',
|
||||
title: 'Mastodon'
|
||||
},
|
||||
youtube: {
|
||||
url: 'https://www.youtube.com/@astrodotbuild',
|
||||
title: 'YouTube',
|
||||
},
|
||||
discord: {
|
||||
url: 'https://astro.build/chat',
|
||||
title: 'Discord'
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default settings;
|
|
@ -1,45 +0,0 @@
|
|||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--theme-bg);
|
||||
color: var(--theme-text);
|
||||
font-size: var(--theme-text-base);
|
||||
font-family: var(--theme-font-body);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
img,
|
||||
picture,
|
||||
video,
|
||||
canvas {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
img {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--theme-text);
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5 {
|
||||
line-height: 1.2;
|
||||
font-family: var(--theme-font-brand);
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
:root {
|
||||
/* Colors */
|
||||
--theme-bg: #eceaf5;
|
||||
--theme-bg-accent: #f6f5fb;
|
||||
--theme-text: #171b26;
|
||||
--theme-text-invert: #fdfdfd;
|
||||
--theme-gray-200: #505d84;
|
||||
--theme-gray-400: #505d84;
|
||||
--theme-gray-700: #505d84;
|
||||
--theme-accent-light: #ddd6fc;
|
||||
--theme-accent-medium: #8577eb;
|
||||
--theme-accent-dark: #5a48d9;
|
||||
--theme-shade-subtle: var(--theme-accent-light);
|
||||
|
||||
/* Gradients */
|
||||
--theme-gradient-main: linear-gradient(83.21deg, var(--theme-accent-dark) 6.77%, #c561f6 93.75%);
|
||||
--theme-gradient-text: linear-gradient(
|
||||
83.21deg,
|
||||
var(--theme-accent-dark) 10.42%,
|
||||
#7a4fe2 76.04%,
|
||||
#c561f6 100%
|
||||
);
|
||||
|
||||
/* Shadows */
|
||||
--theme-shadow-sm: 1px 1px 5px rgba(0, 0, 0, 0.1);
|
||||
--theme-shadow-md: 2px 2px 10px rgba(0, 0, 0, 0.1);
|
||||
--theme-shadow-lg: 2px 2px 20px rgba(0, 0, 0, 0.2);
|
||||
|
||||
/* Content Sizes */
|
||||
--theme-size-content-1: 30ch;
|
||||
--theme-size-content-2: 45ch;
|
||||
--theme-size-content-3: 65ch;
|
||||
|
||||
/* Type Scale */
|
||||
/* @link https://utopia.fyi/type/calculator?c=320,16,1.2,1240,20,1.2,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
|
||||
--theme-text-sm: clamp(0.83rem, calc(0.76rem + 0.36vw), 1.04rem);
|
||||
--theme-text-base: clamp(1.00rem, calc(0.91rem + 0.43vw), 1.25rem);
|
||||
--theme-text-lg: clamp(1.20rem, calc(1.10rem + 0.52vw), 1.50rem);
|
||||
--theme-text-xl: clamp(1.44rem, calc(1.31rem + 0.63vw), 1.80rem);
|
||||
--theme-text-2xl: clamp(1.73rem, calc(1.58rem + 0.75vw), 2.16rem);
|
||||
--theme-text-3xl: clamp(2.07rem, calc(1.89rem + 0.90vw), 2.59rem);
|
||||
--theme-text-4xl: clamp(2.49rem, calc(2.27rem + 1.08vw), 3.11rem);
|
||||
/* @link https://utopia.fyi/type/calculator?c=320,16,1.2,1240,18,1.2,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
|
||||
--theme-text-sm: clamp(0.83rem, calc(0.80rem + 0.18vw), 0.94rem);
|
||||
--theme-text-base: clamp(1.00rem, calc(0.96rem + 0.22vw), 1.13rem);
|
||||
--theme-text-lg: clamp(1.20rem, calc(1.15rem + 0.26vw), 1.35rem);
|
||||
--theme-text-xl: clamp(1.44rem, calc(1.38rem + 0.31vw), 1.62rem);
|
||||
--theme-text-2xl: clamp(1.73rem, calc(1.65rem + 0.38vw), 1.94rem);
|
||||
--theme-text-3xl: clamp(2.07rem, calc(1.98rem + 0.45vw), 2.33rem);
|
||||
--theme-text-4xl: clamp(2.49rem, calc(2.38rem + 0.54vw), 2.80rem);
|
||||
|
||||
/* Fonts */
|
||||
--__font-system: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
|
||||
Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
--theme-font-body: var(--__font-system);
|
||||
--theme-font-brand: 'Montserrat', var(--__font-system);
|
||||
|
||||
/* Corners */
|
||||
--theme-radius-base: 0.3125rem;
|
||||
--theme-radius-lg: 0.625rem;
|
||||
--theme-radius-xl: 1.25rem;
|
||||
--theme-radius-full: 999rem;
|
||||
|
||||
/* Transitions */
|
||||
--theme-transition: 0.2s ease-in-out;
|
||||
|
||||
/* Spacing */
|
||||
/* @link https://utopia.fyi/space/calculator?c=320,16,1.2,1240,18,1.2,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&g=s,l,xl,12 */
|
||||
--theme-space-3xs: clamp(0.25rem, calc(0.23rem + 0.11vw), 0.31rem);
|
||||
--theme-space-2xs: clamp(0.50rem, calc(0.48rem + 0.11vw), 0.56rem);
|
||||
--theme-space-xs: clamp(0.75rem, calc(0.71rem + 0.22vw), 0.88rem);
|
||||
--theme-space-sm: clamp(1.00rem, calc(0.96rem + 0.22vw), 1.13rem);
|
||||
--theme-space-md: clamp(1.50rem, calc(1.43rem + 0.33vw), 1.69rem);
|
||||
--theme-space-lg: clamp(2.00rem, calc(1.91rem + 0.43vw), 2.25rem);
|
||||
--theme-space-xl: clamp(3.00rem, calc(2.87rem + 0.65vw), 3.38rem);
|
||||
--theme-space-2xl: clamp(4.00rem, calc(3.83rem + 0.87vw), 4.50rem);
|
||||
--theme-space-3xl: clamp(6.00rem, calc(5.74rem + 1.30vw), 6.75rem);
|
||||
|
||||
/* One-up pairs */
|
||||
--theme-space-3xs-2xs: clamp(0.25rem, calc(0.14rem + 0.54vw), 0.56rem);
|
||||
--theme-space-2xs-xs: clamp(0.50rem, calc(0.37rem + 0.65vw), 0.88rem);
|
||||
--theme-space-xs-sm: clamp(0.75rem, calc(0.62rem + 0.65vw), 1.13rem);
|
||||
--theme-space-sm-md: clamp(1.00rem, calc(0.76rem + 1.20vw), 1.69rem);
|
||||
--theme-space-md-lg: clamp(1.50rem, calc(1.24rem + 1.30vw), 2.25rem);
|
||||
--theme-space-lg-xl: clamp(2.00rem, calc(1.52rem + 2.39vw), 3.38rem);
|
||||
--theme-space-xl-2xl: clamp(3.00rem, calc(2.48rem + 2.61vw), 4.50rem);
|
||||
--theme-space-2xl-3xl: clamp(4.00rem, calc(3.04rem + 4.78vw), 6.75rem);
|
||||
|
||||
/* Custom pairs */
|
||||
--theme-space-sm-lg: clamp(1.00rem, calc(0.57rem + 2.17vw), 2.25rem);
|
||||
}
|
||||
|
||||
:root.theme-dark {
|
||||
/* Colors (dark) */
|
||||
--theme-bg: #141925;
|
||||
--theme-bg-accent: #202c49;
|
||||
--theme-text: #fdfdfd;
|
||||
--theme-text-invert: #171b26;
|
||||
--theme-gray-200: #c3cadb;
|
||||
--theme-gray-400: #8490b5;
|
||||
--theme-gray-700: #3d4663;
|
||||
--theme-accent-light: #ebd2f8;
|
||||
--theme-accent-medium: #c779ed;
|
||||
--theme-accent-dark: #c561f6;
|
||||
--theme-shade-subtle: var(--theme-bg-accent);
|
||||
|
||||
/* Gradients (dark) */
|
||||
--theme-gradient-main: linear-gradient(83.21deg, var(--theme-accent-dark) 6.25%, #5a48d9 100%);
|
||||
--theme-gradient-text: linear-gradient(
|
||||
83.21deg,
|
||||
var(--theme-accent-dark) 6.25%,
|
||||
#b45df1 75.52%,
|
||||
#5a48d9 100%
|
||||
);
|
||||
|
||||
/* Shadows (dark) */
|
||||
--theme-shadow-sm: 1px 1px 5px rgba(0, 0, 0, 0.1);
|
||||
--theme-shadow-md: 4px 4px 10px rgba(9, 11, 17, 0.2);
|
||||
--theme-shadow-lg: 4px 4px 30px rgba(0, 0, 0, 0.6);
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"extends": "astro/tsconfigs/base"
|
||||
}
|
|
@ -12,9 +12,9 @@
|
|||
"server": "node dist/server/entry.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/node": "^6.0.1",
|
||||
"@astrojs/svelte": "^4.0.2",
|
||||
"astro": "^3.1.4",
|
||||
"@astrojs/node": "^6.0.3",
|
||||
"@astrojs/svelte": "^4.0.3",
|
||||
"astro": "^3.2.4",
|
||||
"svelte": "^4.2.0"
|
||||
}
|
||||
}
|
||||
|
|
30
examples/view-transitions/README.md
Normal file
|
@ -0,0 +1,30 @@
|
|||
# Astro Movies View Transitions Demo
|
||||
|
||||
### 👉🏽 [Live Demo](https://astro-movies.pages.dev/)
|
||||
|
||||
![Screenshot](./screenshot.png)
|
||||
|
||||
## 🚀 Getting Started
|
||||
|
||||
1. Clone this repository and install dependencies with `npm install`.
|
||||
2. Start the project locally with npm run dev, or deploy it to your favorite server.
|
||||
3. Have fun! ✨
|
||||
|
||||
## 🧞 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:3000` |
|
||||
| `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?
|
||||
|
||||
Check out [Astro's documentation](https://docs.astro.build) or jump into their [Discord server](https://astro.build/chat).
|
||||
|
||||
You can also reach out to [Maxi on Twitter](https://twitter.com/charca).
|
15
examples/view-transitions/astro.config.mjs
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
import tailwind from '@astrojs/tailwind';
|
||||
import nodejs from '@astrojs/node';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [tailwind()],
|
||||
output: 'server',
|
||||
adapter: nodejs({ mode: 'standalone' }),
|
||||
vite: {
|
||||
define: {
|
||||
'process.env.TMDB_API_KEY': JSON.stringify(process.env.TMDB_API_KEY),
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"name": "@example/social-feed",
|
||||
"type": "module",
|
||||
"name": "@example/view-transitions",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
@ -10,9 +9,9 @@
|
|||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/rss": "^3.0.0",
|
||||
"astro": "^3.0.1",
|
||||
"reading-time": "^1.5.0"
|
||||
"devDependencies": {
|
||||
"@astrojs/tailwind": "^5.0.2",
|
||||
"@astrojs/node": "^6.0.3",
|
||||
"astro": "^3.2.4"
|
||||
}
|
||||
}
|
BIN
examples/view-transitions/public/favicon.ico
Normal file
After Width: | Height: | Size: 4.2 KiB |
17
examples/view-transitions/src/components/Footer.astro
Normal file
|
@ -0,0 +1,17 @@
|
|||
<footer class="border border-t border-gray-800">
|
||||
<div class="container mx-auto text-sm px-4 py-6">
|
||||
Made with ❤️ by <a
|
||||
href="https://www.twitter.com/charca"
|
||||
target="_blank"
|
||||
class="underline hover:text-gray-300">Maxi Ferreira</a
|
||||
> — Powered by <a
|
||||
href="https://astro.build"
|
||||
target="_blank"
|
||||
class="underline hover:text-gray-300">Astro</a
|
||||
> and <a
|
||||
href="https://www.themoviedb.org/documentation/api"
|
||||
target="_blank"
|
||||
class="underline hover:text-gray-300">TMDb API</a
|
||||
>.
|
||||
</div>
|
||||
</footer>
|
31
examples/view-transitions/src/components/MovieCard.astro
Normal file
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
const { movie } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="mt-8">
|
||||
<a href={`/movies/${movie.id}`}>
|
||||
<img
|
||||
src={`https://image.tmdb.org/t/p/w500${movie.poster_path}`}
|
||||
alt={`${movie.title} Poster`}
|
||||
class="thumbnail hover:opacity-75 transition ease-in-out duration-150"
|
||||
id={`movie-poster-${movie.id}`}
|
||||
transition:name={`poster-${movie.id}`}
|
||||
/>
|
||||
</a>
|
||||
<div class="mt-2">
|
||||
<a href={`/movies/${movie.id}`} class="text-lg mt-2 hover:text-gray-300">{movie.title}</a>
|
||||
<div class="flex items-center text-gray-400 text-sm mt-1">
|
||||
<svg class="fill-current text-orange-500 w-4" viewBox="0 0 24 24"
|
||||
><g data-name="Layer 2"
|
||||
><path
|
||||
d="M17.56 21a1 1 0 01-.46-.11L12 18.22l-5.1 2.67a1 1 0 01-1.45-1.06l1-5.63-4.12-4a1 1 0 01-.25-1 1 1 0 01.81-.68l5.7-.83 2.51-5.13a1 1 0 011.8 0l2.54 5.12 5.7.83a1 1 0 01.81.68 1 1 0 01-.25 1l-4.12 4 1 5.63a1 1 0 01-.4 1 1 1 0 01-.62.18z"
|
||||
data-name="star"></path></g
|
||||
></svg
|
||||
>
|
||||
<span class="ml-1">{movie.vote_average}</span>
|
||||
<span class="mx-2">|</span>
|
||||
<span>{movie.release_date}</span>
|
||||
</div>
|
||||
<div class="text-gray-400 text-sm">{movie.genres}</div>
|
||||
</div>
|
||||
</div>
|
125
examples/view-transitions/src/components/MovieDetails.astro
Normal file
|
@ -0,0 +1,125 @@
|
|||
---
|
||||
const { data } = Astro.props;
|
||||
|
||||
const movie = {
|
||||
...data,
|
||||
poster_path: data.poster_path
|
||||
? 'https://image.tmdb.org/t/p/w500/' + data.poster_path
|
||||
: 'https://via.placeholder.com/500x750',
|
||||
vote_average: (data.vote_average * 10).toFixed(2) + '%',
|
||||
release_date: new Date(data.release_date).toLocaleDateString('en-us', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
}),
|
||||
genres: data.genres.map((g: any) => g.name).join(', '),
|
||||
crew: data.credits.crew.slice(0, 3),
|
||||
cast: data.credits.cast.slice(0, 5).map((c: any) => ({
|
||||
...c,
|
||||
profile_path: c.profile_path
|
||||
? 'https://image.tmdb.org/t/p/w300/' + c.profile_path
|
||||
: 'https://via.placeholder.com/300x450',
|
||||
})),
|
||||
images: data.images.backdrops.slice(0, 9),
|
||||
};
|
||||
---
|
||||
|
||||
<div class="movie-info border-b border-gray-800">
|
||||
<div class="container mx-auto px-4 py-16 flex flex-col md:flex-row">
|
||||
<div class="flex-none">
|
||||
<img
|
||||
src={movie.poster_path}
|
||||
alt={`${movie.title} Poster`}
|
||||
class="movie-poster w-64 lg:w-96"
|
||||
id="movie-poster"
|
||||
transition:name={`poster-${movie.id}`}
|
||||
/>
|
||||
</div>
|
||||
<div class="md:ml-24">
|
||||
<h2 class="text-4xl mt-4 md:mt-0 mb-2 font-semibold">{movie.title}</h2>
|
||||
<div class="flex flex-wrap items-center text-gray-400 text-sm">
|
||||
<svg class="fill-current text-orange-500 w-4" viewBox="0 0 24 24"
|
||||
><g data-name="Layer 2"
|
||||
><path
|
||||
d="M17.56 21a1 1 0 01-.46-.11L12 18.22l-5.1 2.67a1 1 0 01-1.45-1.06l1-5.63-4.12-4a1 1 0 01-.25-1 1 1 0 01.81-.68l5.7-.83 2.51-5.13a1 1 0 011.8 0l2.54 5.12 5.7.83a1 1 0 01.81.68 1 1 0 01-.25 1l-4.12 4 1 5.63a1 1 0 01-.4 1 1 1 0 01-.62.18z"
|
||||
data-name="star"></path></g
|
||||
></svg
|
||||
>
|
||||
<span class="ml-1">{movie.vote_average}</span>
|
||||
<span class="mx-2">|</span>
|
||||
<span>{movie.release_date}</span>
|
||||
<span class="mx-2">|</span>
|
||||
<span>{movie.genres}</span>
|
||||
</div>
|
||||
|
||||
<p class="text-gray-300 mt-8">
|
||||
{movie.overview}
|
||||
</p>
|
||||
|
||||
<div class="mt-12">
|
||||
<h4 class="text-white font-semibold">Featured Crew</h4>
|
||||
<div class="flex mt-4">
|
||||
{
|
||||
movie.crew.map((crew: any) => (
|
||||
<div class="mr-8">
|
||||
<div>{crew.name}</div>
|
||||
<div class="text-gray-400 text-sm">{crew.job}</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end movie-info -->
|
||||
|
||||
<div class="movie-cast border-b border-gray-800">
|
||||
<div class="container mx-auto px-4 py-16">
|
||||
<h2 class="text-4xl font-semibold">Cast</h2>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-8">
|
||||
{
|
||||
movie.cast.map((cast: any) => (
|
||||
<div class="mt-8">
|
||||
<span>
|
||||
<img
|
||||
id={`person-photo-${cast.id}`}
|
||||
src={cast.profile_path}
|
||||
alt={cast.name}
|
||||
class="thumbnail hover:opacity-75 transition ease-in-out duration-150"
|
||||
/>
|
||||
</span>
|
||||
<div class="mt-2">
|
||||
<span class="text-lg mt-2 hover:text-gray:300">{cast.name}</span>
|
||||
<div class="text-sm text-gray-400">{cast.character}</div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end movie-cast -->
|
||||
|
||||
<div class="movie-images">
|
||||
<div class="container mx-auto px-4 py-16">
|
||||
<h2 class="text-4xl font-semibold">Images</h2>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-8">
|
||||
{
|
||||
movie.images.map((image: any) => (
|
||||
<div class="mt-8">
|
||||
<span>
|
||||
<img
|
||||
src={`https://image.tmdb.org/t/p/w500${image.file_path}`}
|
||||
loading="lazy"
|
||||
alt={movie.name}
|
||||
class="hover:opacity-75 transition ease-in-out duration-150"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end movie-images -->
|
15
examples/view-transitions/src/components/MovieList.astro
Normal file
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
import MovieCard from './MovieCard.astro';
|
||||
import movies from '../popular-movies.json';
|
||||
const popularMovies = movies.results;
|
||||
---
|
||||
|
||||
<div class="container mx-auto px-4 pt-16 mb-16">
|
||||
<div class="popular-movies">
|
||||
<h2 class="uppercase tracking-wider text-orange-500 text-lg font-semibold">Popular Movies</h2>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-8">
|
||||
{popularMovies.map((movie) => <MovieCard movie={movie} />)}
|
||||
</div>
|
||||
</div>
|
||||
<!-- end pouplar-movies -->
|
||||
</div>
|
18
examples/view-transitions/src/components/Nav.astro
Normal file
|
@ -0,0 +1,18 @@
|
|||
<nav class="nav border-b border-gray-800 sticky top-0 z-30 bg-gray-900">
|
||||
<div
|
||||
class="container mx-auto px-4 flex flex-col md:flex-row items-center justify-between px-4 py-6"
|
||||
>
|
||||
<ul class="flex flex-col md:flex-row items-center">
|
||||
<li>
|
||||
<a href="/" class="flex items-center font-bold text-xl">
|
||||
<span>Movies</span>
|
||||
|
||||
<span class="text-orange-500">List</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="md:ml-16 mt-3 md:mt-0">
|
||||
<a href="/" class="hover:text-gray-300">Movies</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
12
examples/view-transitions/src/content/config.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { z, defineCollection } from 'astro:content';
|
||||
|
||||
const movies = defineCollection({
|
||||
type: 'data',
|
||||
schema: z.object({
|
||||
data: z.any(),
|
||||
}),
|
||||
});
|
||||
|
||||
// Expose your defined collection to Astro
|
||||
// with the `collections` export
|
||||
export const collections = { movies };
|
4056
examples/view-transitions/src/content/movies/1008042.json
Normal file
345
examples/view-transitions/src/content/movies/1085218.json
Normal file
|
@ -0,0 +1,345 @@
|
|||
{
|
||||
"data": {
|
||||
"adult": false,
|
||||
"backdrop_path": "/e8FyMnifoN5BMuRFE97fS1lJZ6S.jpg",
|
||||
"belongs_to_collection": {
|
||||
"id": 1153632,
|
||||
"name": "Darkland Collection",
|
||||
"poster_path": null,
|
||||
"backdrop_path": null
|
||||
},
|
||||
"budget": 0,
|
||||
"genres": [
|
||||
{ "id": 28, "name": "Action" },
|
||||
{ "id": 53, "name": "Thriller" }
|
||||
],
|
||||
"homepage": "",
|
||||
"id": 1085218,
|
||||
"imdb_id": "tt20204996",
|
||||
"original_language": "da",
|
||||
"original_title": "Underverden 2",
|
||||
"overview": "Seven years ago, Zaid went to war against the Copenhagen underworld to avenge his dead brother. His identity as a respected doctor of cardiology and life as a family man is but a fading dream, and in prison Zaid suffers the loss of his son Noah, whom he barely knows. When a police agent approaches Zaid and offers him a deal to be released in exchange for infiltrating the Copenhagen underworld, he sees his chance to reclaim the remnants of the family life he left behind. But everything has a price, and Zaid realizes that he has now seriously endangered his son's life. After all, once you become part of the underworld, is there any way out?",
|
||||
"popularity": 524.476,
|
||||
"poster_path": "/c8B4DsVcFVDLVmbpHMHU3RjLNAV.jpg",
|
||||
"production_companies": [
|
||||
{
|
||||
"id": 64293,
|
||||
"logo_path": "/lbYGnir9KeY8NyQZrUFZbf3QDej.png",
|
||||
"name": "Profile Pictures",
|
||||
"origin_country": "DK"
|
||||
}
|
||||
],
|
||||
"production_countries": [{ "iso_3166_1": "DK", "name": "Denmark" }],
|
||||
"release_date": "2023-04-13",
|
||||
"revenue": 0,
|
||||
"runtime": 110,
|
||||
"spoken_languages": [
|
||||
{ "english_name": "Arabic", "iso_639_1": "ar", "name": "العربية" },
|
||||
{ "english_name": "Danish", "iso_639_1": "da", "name": "Dansk" }
|
||||
],
|
||||
"status": "Released",
|
||||
"tagline": "",
|
||||
"title": "Darkland: The Return",
|
||||
"video": false,
|
||||
"vote_average": 6.32,
|
||||
"vote_count": 64,
|
||||
"credits": {
|
||||
"cast": [
|
||||
{
|
||||
"adult": false,
|
||||
"gender": 2,
|
||||
"id": 234907,
|
||||
"known_for_department": "Acting",
|
||||
"name": "Dar Salim",
|
||||
"original_name": "Dar Salim",
|
||||
"popularity": 16.442,
|
||||
"profile_path": "/oTYCqdF6nfZTsvt1fbypi54ydI.jpg",
|
||||
"cast_id": 1,
|
||||
"character": "Zaid",
|
||||
"credit_id": "6429b39701b1ca0113cc2840",
|
||||
"order": 0
|
||||
},
|
||||
{
|
||||
"adult": false,
|
||||
"gender": 1,
|
||||
"id": 90514,
|
||||
"known_for_department": "Acting",
|
||||
"name": "Birgitte Hjort Sørensen",
|
||||
"original_name": "Birgitte Hjort Sørensen",
|
||||
"popularity": 9.741,
|
||||
"profile_path": "/uPak0FlCPdsc9B1pw4bBkuaMLXT.jpg",
|
||||
"cast_id": 2,
|
||||
"character": "Helle",
|
||||
"credit_id": "6429b3d101b1ca00d5e8507e",
|
||||
"order": 1
|
||||
},
|
||||
{
|
||||
"adult": false,
|
||||
"gender": 1,
|
||||
"id": 32682,
|
||||
"known_for_department": "Acting",
|
||||
"name": "Stine Fischer Christensen",
|
||||
"original_name": "Stine Fischer Christensen",
|
||||
"popularity": 3.87,
|
||||
"profile_path": "/6MYODCa28L1IzfhcYTUZUYThoF2.jpg",
|
||||
"cast_id": 3,
|
||||
"character": "Stine",
|
||||
"credit_id": "6429b42c9cc67b05796bcdcc",
|
||||
"order": 2
|
||||
},
|
||||
{
|
||||
"adult": false,
|
||||
"gender": 0,
|
||||
"id": 1178394,
|
||||
"known_for_department": "Acting",
|
||||
"name": "Henrik Vestergaard",
|
||||
"original_name": "Henrik Vestergaard",
|
||||
"popularity": 0.766,
|
||||
"profile_path": "/1Opgkbdkyt1x5iEOLgV3VJ29ZpA.jpg",
|
||||
"cast_id": 4,
|
||||
"character": "Lars",
|
||||
"credit_id": "6429b45401b1ca0097fdfb0f",
|
||||
"order": 3
|
||||
},
|
||||
{
|
||||
"adult": false,
|
||||
"gender": 0,
|
||||
"id": 3236472,
|
||||
"known_for_department": "Acting",
|
||||
"name": "Soheil Bavi",
|
||||
"original_name": "Soheil Bavi",
|
||||
"popularity": 0.6,
|
||||
"profile_path": null,
|
||||
"cast_id": 5,
|
||||
"character": "Muhdir",
|
||||
"credit_id": "6429b4828de0ae00b65514de",
|
||||
"order": 4
|
||||
},
|
||||
{
|
||||
"adult": false,
|
||||
"gender": 0,
|
||||
"id": 3991209,
|
||||
"known_for_department": "Acting",
|
||||
"name": "Jack Pedersen",
|
||||
"original_name": "Jack Pedersen",
|
||||
"popularity": 0.648,
|
||||
"profile_path": null,
|
||||
"cast_id": 6,
|
||||
"character": "Shahin",
|
||||
"credit_id": "6429b4f4ac8e6b00d32aa4eb",
|
||||
"order": 5
|
||||
},
|
||||
{
|
||||
"adult": false,
|
||||
"gender": 0,
|
||||
"id": 2595279,
|
||||
"known_for_department": "Acting",
|
||||
"name": "Mohamed Djeziri",
|
||||
"original_name": "Mohamed Djeziri",
|
||||
"popularity": 0.84,
|
||||
"profile_path": null,
|
||||
"cast_id": 11,
|
||||
"character": "",
|
||||
"credit_id": "64c14243871b340101072cf6",
|
||||
"order": 6
|
||||
},
|
||||
{
|
||||
"adult": false,
|
||||
"gender": 0,
|
||||
"id": 4188787,
|
||||
"known_for_department": "Acting",
|
||||
"name": "Abud Mustafa",
|
||||
"original_name": "Abud Mustafa",
|
||||
"popularity": 0.98,
|
||||
"profile_path": null,
|
||||
"cast_id": 12,
|
||||
"character": "",
|
||||
"credit_id": "64c6c269db8a0000e3286594",
|
||||
"order": 7
|
||||
},
|
||||
{
|
||||
"adult": false,
|
||||
"gender": 0,
|
||||
"id": 4188788,
|
||||
"known_for_department": "Acting",
|
||||
"name": "Ahmad Ayman",
|
||||
"original_name": "Ahmad Ayman",
|
||||
"popularity": 0.6,
|
||||
"profile_path": null,
|
||||
"cast_id": 13,
|
||||
"character": "",
|
||||
"credit_id": "64c6c27f63aad20209a58505",
|
||||
"order": 8
|
||||
},
|
||||
{
|
||||
"adult": false,
|
||||
"gender": 0,
|
||||
"id": 4188789,
|
||||
"known_for_department": "Acting",
|
||||
"name": "Sebastian Nørgaard",
|
||||
"original_name": "Sebastian Nørgaard",
|
||||
"popularity": 0.6,
|
||||
"profile_path": null,
|
||||
"cast_id": 14,
|
||||
"character": "",
|
||||
"credit_id": "64c6c298db8a0000e32865ab",
|
||||
"order": 9
|
||||
},
|
||||
{
|
||||
"adult": false,
|
||||
"gender": 0,
|
||||
"id": 4188791,
|
||||
"known_for_department": "Acting",
|
||||
"name": "Hamed \"Baloosh\" Balosha",
|
||||
"original_name": "Hamed \"Baloosh\" Balosha",
|
||||
"popularity": 0.6,
|
||||
"profile_path": null,
|
||||
"cast_id": 15,
|
||||
"character": "",
|
||||
"credit_id": "64c6c2a3eec5b500ff5262cb",
|
||||
"order": 10
|
||||
},
|
||||
{
|
||||
"adult": false,
|
||||
"gender": 0,
|
||||
"id": 3549264,
|
||||
"known_for_department": "Acting",
|
||||
"name": "Noah Carter",
|
||||
"original_name": "Noah Carter",
|
||||
"popularity": 0.6,
|
||||
"profile_path": null,
|
||||
"cast_id": 16,
|
||||
"character": "",
|
||||
"credit_id": "64c6c2b0cadb6b00c82a2404",
|
||||
"order": 11
|
||||
},
|
||||
{
|
||||
"adult": false,
|
||||
"gender": 0,
|
||||
"id": 4188792,
|
||||
"known_for_department": "Acting",
|
||||
"name": "Asgar Hansen",
|
||||
"original_name": "Asgar Hansen",
|
||||
"popularity": 0.6,
|
||||
"profile_path": null,
|
||||
"cast_id": 17,
|
||||
"character": "",
|
||||
"credit_id": "64c6c2bc30f79c00c781a97c",
|
||||
"order": 12
|
||||
}
|
||||
],
|
||||
"crew": [
|
||||
{
|
||||
"adult": false,
|
||||
"gender": 0,
|
||||
"id": 1183636,
|
||||
"known_for_department": "Directing",
|
||||
"name": "Fenar Ahmad",
|
||||
"original_name": "Fenar Ahmad",
|
||||
"popularity": 1.646,
|
||||
"profile_path": null,
|
||||
"credit_id": "6429b673c04429026b13a94a",
|
||||
"department": "Directing",
|
||||
"job": "Director"
|
||||
},
|
||||
{
|
||||
"adult": false,
|
||||
"gender": 0,
|
||||
"id": 1183636,
|
||||
"known_for_department": "Directing",
|
||||
"name": "Fenar Ahmad",
|
||||
"original_name": "Fenar Ahmad",
|
||||
"popularity": 1.646,
|
||||
"profile_path": null,
|
||||
"credit_id": "642ed070158c8501263ad755",
|
||||
"department": "Writing",
|
||||
"job": "Writer"
|
||||
},
|
||||
{
|
||||
"adult": false,
|
||||
"gender": 0,
|
||||
"id": 2405913,
|
||||
"known_for_department": "Directing",
|
||||
"name": "Behrouz Bigdeli",
|
||||
"original_name": "Behrouz Bigdeli",
|
||||
"popularity": 0.6,
|
||||
"profile_path": null,
|
||||
"credit_id": "642ed08058361b00f2f13338",
|
||||
"department": "Writing",
|
||||
"job": "Writer"
|
||||
}
|
||||
]
|
||||
},
|
||||
"videos": { "results": [] },
|
||||
"images": {
|
||||
"backdrops": [
|
||||
{
|
||||
"aspect_ratio": 1.778,
|
||||
"height": 1080,
|
||||
"iso_639_1": "da",
|
||||
"file_path": "/4wVFtesa5YEWuAUHRcxoCN1Y1uN.jpg",
|
||||
"vote_average": 5.172,
|
||||
"vote_count": 1,
|
||||
"width": 1920
|
||||
},
|
||||
{
|
||||
"aspect_ratio": 1.778,
|
||||
"height": 720,
|
||||
"iso_639_1": null,
|
||||
"file_path": "/e8FyMnifoN5BMuRFE97fS1lJZ6S.jpg",
|
||||
"vote_average": 0,
|
||||
"vote_count": 0,
|
||||
"width": 1280
|
||||
},
|
||||
{
|
||||
"aspect_ratio": 1.778,
|
||||
"height": 1116,
|
||||
"iso_639_1": null,
|
||||
"file_path": "/tDT465D3JZiABgz2uug9jCgOUlw.jpg",
|
||||
"vote_average": 0,
|
||||
"vote_count": 0,
|
||||
"width": 1984
|
||||
}
|
||||
],
|
||||
"logos": [],
|
||||
"posters": [
|
||||
{
|
||||
"aspect_ratio": 0.667,
|
||||
"height": 3000,
|
||||
"iso_639_1": "da",
|
||||
"file_path": "/A8EPXv3SV9qiNCIttIM4ezJRmhW.jpg",
|
||||
"vote_average": 5.312,
|
||||
"vote_count": 1,
|
||||
"width": 2000
|
||||
},
|
||||
{
|
||||
"aspect_ratio": 0.667,
|
||||
"height": 1200,
|
||||
"iso_639_1": "da",
|
||||
"file_path": "/A0cxUcMWBruPknr5ZSePIYFfe7z.jpg",
|
||||
"vote_average": 5.172,
|
||||
"vote_count": 1,
|
||||
"width": 800
|
||||
},
|
||||
{
|
||||
"aspect_ratio": 0.7,
|
||||
"height": 2834,
|
||||
"iso_639_1": "en",
|
||||
"file_path": "/c8B4DsVcFVDLVmbpHMHU3RjLNAV.jpg",
|
||||
"vote_average": 0,
|
||||
"vote_count": 0,
|
||||
"width": 1984
|
||||
},
|
||||
{
|
||||
"aspect_ratio": 0.7,
|
||||
"height": 2834,
|
||||
"iso_639_1": "en",
|
||||
"file_path": "/my1ve6HKygOVNYJBi3A0pRpPm2l.jpg",
|
||||
"vote_average": 0,
|
||||
"vote_count": 0,
|
||||
"width": 1984
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|