Merge branch 'withastro:main' into fix/node18.1-host
This commit is contained in:
commit
5731e3fadf
1137 changed files with 28163 additions and 11792 deletions
5
.changeset/breezy-llamas-behave.md
Normal file
5
.changeset/breezy-llamas-behave.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fix certain characters showing incorrectly in `astro check`
|
5
.changeset/brown-drinks-leave.md
Normal file
5
.changeset/brown-drinks-leave.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
public assets should always take priority over page routes in SSR deployments
|
5
.changeset/chatty-bikes-sin.md
Normal file
5
.changeset/chatty-bikes-sin.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@astrojs/image': patch
|
||||
---
|
||||
|
||||
Updates the <Picture /> component to pass the `alt` attribute down to the <img> element
|
5
.changeset/chilled-cherries-decide.md
Normal file
5
.changeset/chilled-cherries-decide.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@astrojs/sitemap": patch
|
||||
---
|
||||
|
||||
Update README to reflect `@astrojs/sitemap@0.2.0` changes
|
5
.changeset/cold-bears-sneeze.md
Normal file
5
.changeset/cold-bears-sneeze.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@astrojs/markdown-remark': minor
|
||||
---
|
||||
|
||||
fixed generated slugs in markdown that ends with a dash
|
5
.changeset/cold-eyes-run.md
Normal file
5
.changeset/cold-eyes-run.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Add export keyword to astro config file stub created by add cli command
|
5
.changeset/dull-eagles-beg.md
Normal file
5
.changeset/dull-eagles-beg.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Use a base middleware for better base path handling in dev.
|
5
.changeset/flat-shoes-camp.md
Normal file
5
.changeset/flat-shoes-camp.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
[#3859](https://github.com/withastro/astro/pull/3859) Overhaul Astro error handling, using Vite's built-in error overlay when possible
|
5
.changeset/gentle-mails-mate.md
Normal file
5
.changeset/gentle-mails-mate.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@astrojs/image": patch
|
||||
---
|
||||
|
||||
Handle EXIF orientation flag
|
8
.changeset/happy-parrots-stare.md
Normal file
8
.changeset/happy-parrots-stare.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
'astro': minor
|
||||
'@astrojs/cloudflare': minor
|
||||
'@astrojs/netlify': minor
|
||||
'@astrojs/vercel': minor
|
||||
---
|
||||
|
||||
Support for 404 and 500 pages in SSR
|
5
.changeset/lemon-tools-rescue.md
Normal file
5
.changeset/lemon-tools-rescue.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'create-astro': patch
|
||||
---
|
||||
|
||||
Fixes support for using templates from any GitHub repository
|
5
.changeset/loud-apes-flash.md
Normal file
5
.changeset/loud-apes-flash.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': minor
|
||||
---
|
||||
|
||||
Removes warnings for integrations/ssr
|
5
.changeset/lovely-lions-attend.md
Normal file
5
.changeset/lovely-lions-attend.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@astrojs/svelte': patch
|
||||
---
|
||||
|
||||
Fix optional props not being recognized properly in the editor
|
6
.changeset/mighty-poets-prove.md
Normal file
6
.changeset/mighty-poets-prove.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
'astro': patch
|
||||
'@astrojs/lit': patch
|
||||
---
|
||||
|
||||
Fixes Lit compat with Vite 3.0.1
|
6
.changeset/moody-crabs-occur.md
Normal file
6
.changeset/moody-crabs-occur.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
'astro': patch
|
||||
'@astrojs/markdown-remark': patch
|
||||
---
|
||||
|
||||
Avoid parsing JSX, components, and Astro islands when using "plain" md mode. This brings `markdown.mode: 'md'` in-line with our docs description.
|
9
.changeset/moody-teachers-knock.md
Normal file
9
.changeset/moody-teachers-knock.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
"@astrojs/image": patch
|
||||
"@astrojs/partytown": patch
|
||||
"@astrojs/prefetch": patch
|
||||
"@astrojs/sitemap": patch
|
||||
"@astrojs/tailwind": patch
|
||||
---
|
||||
|
||||
[READMEs] removed "experimental" from astro add instructions
|
5
.changeset/new-coats-cheer.md
Normal file
5
.changeset/new-coats-cheer.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@astrojs/mdx': minor
|
||||
---
|
||||
|
||||
Add remarkPlugins and rehypePlugins to config, with the same default plugins as our standard Markdown parser
|
5
.changeset/old-walls-draw.md
Normal file
5
.changeset/old-walls-draw.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Added missing `media` attributes from the JSX definitions for the `meta` element
|
18
.changeset/olive-dryers-sell.md
Normal file
18
.changeset/olive-dryers-sell.md
Normal file
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
'astro': minor
|
||||
'@astrojs/cloudflare': minor
|
||||
'@astrojs/deno': minor
|
||||
'@astrojs/netlify': minor
|
||||
'@astrojs/vercel': minor
|
||||
'@astrojs/node': minor
|
||||
---
|
||||
|
||||
Adds support for Astro.clientAddress
|
||||
|
||||
The new `Astro.clientAddress` property allows you to get the IP address of the requested user.
|
||||
|
||||
```astro
|
||||
<div>Your address { Astro.clientAddress }</div>
|
||||
```
|
||||
|
||||
This property is only available when building for SSR, and only if the adapter you are using supports providing the IP address. If you attempt to access the property in a SSG app it will throw an error.
|
5
.changeset/perfect-islands-teach.md
Normal file
5
.changeset/perfect-islands-teach.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@astrojs/image': patch
|
||||
---
|
||||
|
||||
Fixing TypeScript definition exports for image components
|
5
.changeset/popular-taxis-prove.md
Normal file
5
.changeset/popular-taxis-prove.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Overhaul HMR handling for more stable live reload behavior
|
5
.changeset/real-camels-roll.md
Normal file
5
.changeset/real-camels-roll.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@astrojs/mdx': minor
|
||||
---
|
||||
|
||||
Support Prism and Shiki syntax highlighting based on project config
|
5
.changeset/rotten-candles-count.md
Normal file
5
.changeset/rotten-candles-count.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@astrojs/vercel': minor
|
||||
---
|
||||
|
||||
Removed requirement for `ENABLE_VC_BUILD=1`, since Build Output v3 is now stable. [Learn more](https://vercel.com/blog/build-output-api).
|
5
.changeset/shiny-pumpkins-return.md
Normal file
5
.changeset/shiny-pumpkins-return.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@astrojs/mdx': patch
|
||||
---
|
||||
|
||||
Include page url in MDX glob result
|
6
.changeset/silent-clocks-pump.md
Normal file
6
.changeset/silent-clocks-pump.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
'@astrojs/mdx': minor
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Support YAML frontmatter in MDX files
|
5
.changeset/sixty-drinks-search.md
Normal file
5
.changeset/sixty-drinks-search.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fix `define:vars` bugs with both `style` and `script`
|
6
.changeset/smooth-seahorses-hear.md
Normal file
6
.changeset/smooth-seahorses-hear.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
'astro': patch
|
||||
'@astrojs/node': patch
|
||||
---
|
||||
|
||||
Fixes Node adapter to accept a request body
|
5
.changeset/spotty-apricots-deny.md
Normal file
5
.changeset/spotty-apricots-deny.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Allow defining aliases with tsconfig
|
5
.changeset/strong-stingrays-compete.md
Normal file
5
.changeset/strong-stingrays-compete.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Add support for `.html` components and pages
|
8
.changeset/thirty-beans-poke.md
Normal file
8
.changeset/thirty-beans-poke.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
'astro': minor
|
||||
'@astrojs/image': minor
|
||||
'@astrojs/svelte': minor
|
||||
'@astrojs/vue': minor
|
||||
---
|
||||
|
||||
Bump to Vite 3!
|
6
.changeset/tiny-glasses-play.md
Normal file
6
.changeset/tiny-glasses-play.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
'@astrojs/image': minor
|
||||
---
|
||||
|
||||
- Fixes two bugs that were blocking SSR support when deployed to a hosting service
|
||||
- The built-in `sharp` service now automatically rotates images based on EXIF data
|
20
.changeset/two-hounds-sort.md
Normal file
20
.changeset/two-hounds-sort.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
'astro': minor
|
||||
'@astrojs/markdown-component': minor
|
||||
'@astrojs/markdown-remark': minor
|
||||
---
|
||||
|
||||
The use of components and JSX expressions in Markdown are no longer supported by default.
|
||||
|
||||
For long term support, migrate to the `@astrojs/mdx` integration for MDX support (including `.mdx` pages!).
|
||||
|
||||
Not ready to migrate to MDX? Add the legacy flag to your Astro config to re-enable the previous Markdown support.
|
||||
|
||||
```js
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
legacy: {
|
||||
astroFlavoredMarkdown: true,
|
||||
}
|
||||
});
|
||||
```
|
5
.changeset/unlucky-panthers-yawn.md
Normal file
5
.changeset/unlucky-panthers-yawn.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Deprecate Astro.canonicalURL, in favor of Astro.url instead.
|
5
.changeset/wet-wombats-prove.md
Normal file
5
.changeset/wet-wombats-prove.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Improve warning logs on astro.config change
|
22
.changeset/wild-socks-drive.md
Normal file
22
.changeset/wild-socks-drive.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
'astro': minor
|
||||
'@astrojs/markdown-component': minor
|
||||
---
|
||||
|
||||
Move the Markdown component to its own package
|
||||
|
||||
This change moves the Markdown component into its own package where it will be maintained separately. All that needs to change from a user's perspective is the import statement:
|
||||
|
||||
```astro
|
||||
---
|
||||
import { Markdown } from 'astro/components';
|
||||
---
|
||||
```
|
||||
|
||||
Becomes:
|
||||
|
||||
```astro
|
||||
---
|
||||
import Markdown from '@astrojs/markdown-component';
|
||||
---
|
||||
```
|
5
.changeset/yellow-drinks-judge.md
Normal file
5
.changeset/yellow-drinks-judge.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Add Astro.url helper for getting the request URL
|
|
@ -1,8 +1,9 @@
|
|||
**/*.js
|
||||
**/*.ts
|
||||
!packages/astro/**/*.js
|
||||
!packages/astro/**/*.ts
|
||||
packages/astro/test/**/*.js
|
||||
**/*.d.ts
|
||||
packages/**/dist/**/*
|
||||
packages/**/fixtures/**/*
|
||||
packages/webapi/**/*
|
||||
packages/astro/vendor/vite/**/*
|
||||
examples/**/*
|
||||
scripts/**/*
|
||||
.github
|
||||
.changeset
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
extends: ['plugin:@typescript-eslint/recommended', 'prettier'],
|
||||
plugins: ['@typescript-eslint', 'prettier'],
|
||||
plugins: ['@typescript-eslint', 'prettier', 'no-only-tests'],
|
||||
rules: {
|
||||
'@typescript-eslint/ban-ts-comment': 'off',
|
||||
'@typescript-eslint/camelcase': 'off',
|
||||
|
@ -17,5 +17,6 @@ module.exports = {
|
|||
'prefer-const': 'off',
|
||||
'no-shadow': 'off',
|
||||
'@typescript-eslint/no-shadow': ['error'],
|
||||
'no-only-tests/no-only-tests': 'error',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
# Switch to tabs (Use Accessible Indentation #2253)
|
||||
6ddd7678ffb6598ae6e263706813cb5e94535f02
|
||||
# prettier config update
|
||||
1335797903a57716e9a02b0ffd8ca636b3883c62
|
||||
1335797903a57716e9a02b0ffd8ca636b3883c62
|
||||
# Manually format .astro files in example projects (#3862)
|
||||
59e8c71786fd1c154904b3fefa7d26d88f4d92d2
|
||||
|
|
2
.github/ISSUE_TEMPLATE/---01-bug-report.yml
vendored
2
.github/ISSUE_TEMPLATE/---01-bug-report.yml
vendored
|
@ -11,7 +11,7 @@ body:
|
|||
Thank you for taking the time to file a bug report! Please fill out this form as completely as possible.
|
||||
|
||||
✅ I am using the **latest version of Astro** and all plugins.
|
||||
✅ I am using a version of Node that supports ESM (`v14.15.0+`, or `v16.0.0+`)
|
||||
✅ I am using a version of Node that supports ESM (`v14.18.0+`, or `v16.12.0+`)
|
||||
- type: input
|
||||
id: astro-version
|
||||
attributes:
|
||||
|
|
11
.github/extract-artifacts.sh
vendored
11
.github/extract-artifacts.sh
vendored
|
@ -1,11 +0,0 @@
|
|||
cd artifacts
|
||||
mkdir -p ../tmp/packages
|
||||
mv * ../tmp/packages
|
||||
cd ../tmp
|
||||
tar -cvzpf artifacts.tar.gz *
|
||||
mv artifacts.tar.gz ../artifacts.tar.gz
|
||||
cd ..
|
||||
tar -xvzpf artifacts.tar.gz
|
||||
rm -rf artifacts
|
||||
rm -rf tmp
|
||||
rm -f artifacts.tar.gz
|
142
.github/workflows/ci.yml
vendored
142
.github/workflows/ci.yml
vendored
|
@ -7,6 +7,7 @@ on:
|
|||
pull_request:
|
||||
paths-ignore:
|
||||
- '.vscode/**'
|
||||
- '**/*.md'
|
||||
|
||||
# Automatically cancel in-progress actions on the same branch
|
||||
concurrency:
|
||||
|
@ -17,8 +18,13 @@ defaults:
|
|||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
||||
FORCE_COLOR: true
|
||||
ASTRO_TELEMETRY_DISABLED: true
|
||||
|
||||
jobs:
|
||||
# Lint can run in parallel with Build.
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -54,9 +60,6 @@ jobs:
|
|||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
eslint: true
|
||||
eslint_args: --ignore-pattern test --ignore-pattern vendor
|
||||
eslint_dir: packages/astro
|
||||
eslint_extensions: ts
|
||||
prettier: false
|
||||
auto_fix: true
|
||||
git_name: github-actions[bot]
|
||||
|
@ -68,13 +71,17 @@ jobs:
|
|||
# Checks that the formatter runs successfully on all files
|
||||
# In the future, we may have this fail PRs on unformatted code
|
||||
- name: Format Check
|
||||
run: yarn format --list
|
||||
run: pnpm run format --list
|
||||
|
||||
# Build installs all devDependencies and runs our full build pipeline.
|
||||
# We upload all `dist/` artifacts to GitHub, which can be shared by all dependent jobs.
|
||||
# Build primes out build caches for Turbo
|
||||
build:
|
||||
name: Build Packages
|
||||
runs-on: ubuntu-latest
|
||||
name: 'Build: ${{ matrix.os }}'
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
node_version: [14]
|
||||
fail-fast: true
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
@ -82,47 +89,32 @@ jobs:
|
|||
- name: Setup PNPM
|
||||
uses: pnpm/action-setup@v2.2.1
|
||||
|
||||
- name: Setup Node
|
||||
- name: Setup node@${{ matrix.node_version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
node-version: ${{ matrix.node_version }}
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
|
||||
- name: Build Packages
|
||||
run: pnpm run build
|
||||
|
||||
- name: Upload Package Artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: artifacts
|
||||
path: |
|
||||
packages/*/dist/**
|
||||
packages/*/*/dist/**
|
||||
packages/webapi/mod.js
|
||||
packages/webapi/mod.js.map
|
||||
if-no-files-found: error
|
||||
|
||||
# Test depends on Build's output, which allows us to skip any build process!
|
||||
test:
|
||||
name: 'Test: ${{ matrix.os }} (node@${{ matrix.node_version }})'
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
ASTRO_TELEMETRY_DISABLED: true
|
||||
needs: build
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
node_version: [14, 16]
|
||||
include:
|
||||
- os: windows-latest
|
||||
node_version: 16
|
||||
node_version: 14
|
||||
- os: macos-latest
|
||||
node_version: 16
|
||||
node_version: 14
|
||||
fail-fast: false
|
||||
needs:
|
||||
- build
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
@ -141,35 +133,25 @@ jobs:
|
|||
with:
|
||||
deno-version: v1.19.3
|
||||
|
||||
- name: Download Build Artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
|
||||
- name: Extract Artifacts
|
||||
run: ./.github/extract-artifacts.sh
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Build Packages
|
||||
run: pnpm run build
|
||||
|
||||
- name: Test
|
||||
run: pnpm run test
|
||||
|
||||
e2e:
|
||||
name: 'E2E: ${{ matrix.os }} (node@${{ matrix.node_version }})'
|
||||
name: 'Test (E2E): ${{ matrix.os }} (node@${{ matrix.node_version }})'
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
ASTRO_TELEMETRY_DISABLED: true
|
||||
timeout-minutes: 20
|
||||
needs: build
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
node_version: [14, 16]
|
||||
include:
|
||||
- os: windows-latest
|
||||
node_version: 16
|
||||
- os: macos-latest
|
||||
node_version: 16
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
node_version: [14]
|
||||
fail-fast: false
|
||||
needs:
|
||||
- build
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
@ -183,73 +165,58 @@ jobs:
|
|||
node-version: ${{ matrix.node_version }}
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Download Build Artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
|
||||
- name: Extract Artifacts
|
||||
run: ./.github/extract-artifacts.sh
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Build Packages
|
||||
run: pnpm run build
|
||||
|
||||
- name: Test
|
||||
run: pnpm run test:e2e
|
||||
|
||||
smoke:
|
||||
name: 'Test (Smoke) ${{ matrix.os }}'
|
||||
name: 'Test (Smoke): ${{ matrix.os }} (node@${{ matrix.node_version }})'
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: build
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest]
|
||||
needs:
|
||||
- build
|
||||
os: [ubuntu-latest]
|
||||
node_version: [14]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Update submodules
|
||||
run: git submodule update --remote
|
||||
|
||||
- name: Setup PNPM
|
||||
uses: pnpm/action-setup@v2.2.1
|
||||
|
||||
- name: Setup Node
|
||||
- name: Setup node@${{ matrix.node_version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 14
|
||||
node-version: ${{ matrix.node_version }}
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Download Build Artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
|
||||
- name: Extract Artifacts
|
||||
run: ./.github/extract-artifacts.sh
|
||||
- name: Checkout docs
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: withastro/docs
|
||||
path: smoke/docs
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --no-frozen-lockfile
|
||||
|
||||
- name: Build Packages
|
||||
run: pnpm run build
|
||||
|
||||
- name: Test
|
||||
run: pnpm run test:smoke
|
||||
|
||||
- name: Memory Leak Test
|
||||
run: |
|
||||
node ./scripts/memory/mk.js
|
||||
node --expose-gc ./scripts/memory/index.js --ci
|
||||
|
||||
|
||||
# Changelog can only run _after_ build.
|
||||
# We download all `dist/` artifacts from GitHub to skip the build process.
|
||||
changelog:
|
||||
name: Changelog PR or Release
|
||||
if: ${{ (github.ref_name == 'main' || github.head_ref == 'next') && github.repository_owner == 'withastro' }}
|
||||
needs: [build]
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup PNPM
|
||||
uses: pnpm/action-setup@v2.2.1
|
||||
|
@ -260,15 +227,12 @@ jobs:
|
|||
node-version: 16
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Download Build Artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
|
||||
- name: Extract Artifacts
|
||||
run: ./.github/extract-artifacts.sh
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Build Packages
|
||||
run: pnpm run build
|
||||
|
||||
- name: Create Release Pull Request or Publish
|
||||
id: changesets
|
||||
uses: changesets/action@v1
|
||||
|
@ -279,7 +243,9 @@ jobs:
|
|||
commit: '[ci] release'
|
||||
title: '[ci] release'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# Needs access to push to main
|
||||
GITHUB_TOKEN: ${{ secrets.FREDKBOT_GITHUB_TOKEN }}
|
||||
# Needs access to publish to npm
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
- name: Generate Notification
|
||||
|
|
6
.github/workflows/format.yml
vendored
6
.github/workflows/format.yml
vendored
|
@ -8,11 +8,15 @@ on:
|
|||
jobs:
|
||||
format:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
steps:
|
||||
- name: Check out code using Git
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
# Needs access to push to main
|
||||
token: ${{ secrets.FREDKBOT_GITHUB_TOKEN }}
|
||||
- name: Setup PNPM
|
||||
uses: pnpm/action-setup@v2.2.1
|
||||
- name: Setup Node
|
||||
|
@ -29,3 +33,5 @@ jobs:
|
|||
with:
|
||||
commit_message: '[ci] format'
|
||||
branch: ${{ github.head_ref }}
|
||||
commit_user_name: fredkbot
|
||||
commit_user_email: fred+astrobot@astro.build
|
||||
|
|
16
.github/workflows/nightly.yml
vendored
16
.github/workflows/nightly.yml
vendored
|
@ -29,12 +29,16 @@ jobs:
|
|||
- name: Collect stats
|
||||
run: node scripts/stats/index.js
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# Needs access to collect stats from the GitHub API
|
||||
GITHUB_TOKEN: ${{ secrets.FREDKBOT_GITHUB_TOKEN }}
|
||||
|
||||
- name: Commit changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: '[ci] collect stats'
|
||||
branch: ${{ github.head_ref }}
|
||||
# Needs access to push to main
|
||||
token: ${{ secrets.FREDKBOT_GITHUB_TOKEN }}
|
||||
|
||||
lockfile:
|
||||
if: github.repository_owner == 'withastro'
|
||||
|
@ -53,15 +57,19 @@ jobs:
|
|||
node-version: 16
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Upgrade recursive
|
||||
run: pnpm upgrade --recursive
|
||||
- name: Delete the existing pnpm-lock.yaml file
|
||||
run: rm pnpm-lock.yaml
|
||||
|
||||
- name: Create a fresh pnpm lockfile (no install)
|
||||
run: pnpm install --lockfile-only
|
||||
|
||||
- name: Create Pull Request
|
||||
id: createpr
|
||||
uses: peter-evans/create-pull-request@v3
|
||||
with:
|
||||
branch: ci/lockfile
|
||||
token: ${{ secrets.NIGHTLY_PERSONAL_GITHUB_TOKEN }}
|
||||
# Access token is needed to trigger CI on this PR
|
||||
token: ${{ secrets.FREDKBOT_GITHUB_TOKEN }}
|
||||
commit-message: '[ci] update lockfile'
|
||||
title: '[ci] update lockfile'
|
||||
body: >
|
||||
|
|
2
.github/workflows/scripts.yml
vendored
2
.github/workflows/scripts.yml
vendored
|
@ -4,6 +4,8 @@ on:
|
|||
pull_request:
|
||||
branches:
|
||||
- 'main'
|
||||
paths:
|
||||
- 'packages/astro/src/runtime/client/**/*'
|
||||
|
||||
# Automatically cancel in-progress actions on the same branch
|
||||
concurrency:
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -16,6 +16,7 @@ package-lock.json
|
|||
# do not commit .env files or any files that end with `.env`
|
||||
*.env
|
||||
|
||||
packages/astro/src/**/*.prebuilt.ts
|
||||
!packages/astro/vendor/vite/dist
|
||||
packages/integrations/**/.netlify/
|
||||
|
||||
|
|
8
.gitmodules
vendored
8
.gitmodules
vendored
|
@ -1,8 +0,0 @@
|
|||
[submodule "smoke/docs"]
|
||||
path = smoke/docs
|
||||
url = git@github.com:withastro/docs.git
|
||||
branch = main
|
||||
[submodule "smoke/astro.build"]
|
||||
path = smoke/astro.build
|
||||
url = git@github.com:withastro/astro.build.git
|
||||
branch = main
|
|
@ -1,76 +0,0 @@
|
|||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||
level of experience, education, socio-economic status, nationality, personal
|
||||
appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
- Using welcoming and inclusive language
|
||||
- Being respectful of differing viewpoints and experiences
|
||||
- Gracefully accepting constructive criticism
|
||||
- Focusing on what is best for the community
|
||||
- Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
- The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
All complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
See [GOVERNANCE.md](GOVERNANCE.md#Moderation) for instructions on reporting a Code of Conduct violation and a full description of the review process.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
https://www.contributor-covenant.org/faq
|
|
@ -10,8 +10,8 @@ We welcome contributions of any size and skill level. As an open source project,
|
|||
### Prerequisite
|
||||
|
||||
```shell
|
||||
node: "^14.15.0 || >=16.0.0"
|
||||
pnpm: "^7.0.0"
|
||||
node: "^14.18.0 || >=16.12.0"
|
||||
pnpm: "^7.5.0"
|
||||
# otherwise, your build will fail
|
||||
```
|
||||
|
||||
|
@ -31,6 +31,13 @@ In [#2254](https://github.com/withastro/astro/pull/2254) a `.git-blame-ignore-re
|
|||
git config --local blame.ignoreRevsFile .git-blame-ignore-revs
|
||||
```
|
||||
|
||||
To automatically handle merge conflicts in `pnpm-lock.yaml`, you should run the following commands locally.
|
||||
|
||||
```shell
|
||||
pnpm add -g @pnpm/merge-driver
|
||||
pnpx npm-merge-driver install --driver-name pnpm-merge-driver --driver "pnpm-merge-driver %A %O %B %P" --files pnpm-lock.yaml
|
||||
```
|
||||
|
||||
### Development
|
||||
|
||||
```shell
|
||||
|
@ -144,7 +151,7 @@ Understanding in which environment code runs, and at which stage in the process,
|
|||
|
||||
## Releasing Astro
|
||||
|
||||
_Note: Only [core maintainers (L3+)](https://github.com/withastro/astro/blob/main/GOVERNANCE.md#level-3-l3---core-maintainer) can release new versions of Astro._
|
||||
_Note: Only [core maintainers (L3+)](https://github.com/withastro/.github/blob/main/GOVERNANCE.md#level-3-l3---core-maintainer) can release new versions of Astro._
|
||||
|
||||
The repo is set up with automatic releases, using the changeset GitHub action & bot.
|
||||
|
||||
|
@ -154,21 +161,28 @@ To release a new version of Astro, find the `Version Packages` PR, read it over,
|
|||
|
||||
Our release tool `changeset` has a feature for releasing "snapshot" releases from a PR or custom branch. These are npm package publishes that live temporarily, so that you can give users a way to test a PR before merging. This can be a great way to get early user feedback while still in the PR review process.
|
||||
|
||||
To run `changeset version` locally, you'll need to create a GitHub [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) and set it as a `GITHUB_TOKEN` environment variable.
|
||||
|
||||
To release a snapshot, run the following locally:
|
||||
|
||||
```shell
|
||||
# Note: XXX should be a keyword to identify this release. Ex: `--snapshot routing` & `--tag next--routing`
|
||||
# Notes:
|
||||
# - YYY should be a keyword to identify this release. Ex: `--snapshot routing` & `--tag next--routing`
|
||||
# - Use npm/npx instead of pnpm, since npm handles registry login, authentication and publishing.
|
||||
# - Adding GITHUB_TOKEN in the command adds that token to your bash history. Set a short expiration!
|
||||
|
||||
# 1:
|
||||
pnpm exec changeset version --snapshot XXX
|
||||
# 2: (Manual) review the diff, and make sure that you're not releasing more than you need to.
|
||||
# 1: Tag the new release versions
|
||||
GITHUB_TOKEN=XXX npx changeset version --snapshot YYY
|
||||
# 2: Review the diff, and make sure that you're not releasing more than you need to.
|
||||
git checkout -- examples/
|
||||
# 3:
|
||||
pnpm run release --tag next--XXX
|
||||
# 4: (Manual) review the publish, and if you're happy then you can throw out all local changes
|
||||
# 3: Release
|
||||
npm run release --tag next--YYY
|
||||
# 4: If you're satisfied, you can now throw out all local changes
|
||||
git reset --hard
|
||||
```
|
||||
|
||||
By default, every package with a changeset will be released. If you only want to target a smaller subset of packages for release, you can consider clearing out the `.changesets` directory to replace all existing changesets with a single changeset of only the packages that you want to release. Just be sure not to commit or push this to `main`, since it will destroy existing changesets that you will still want to eventually release.
|
||||
|
||||
Full documentation: https://github.com/atlassian/changesets/blob/main/docs/snapshot-releases.md
|
||||
|
||||
### Releasing `astro@next` (aka "prerelease mode")
|
||||
|
|
40
FUNDING.md
40
FUNDING.md
|
@ -1,40 +0,0 @@
|
|||
# Astro Project Funding
|
||||
|
||||
_Last Updated: 02-09-2022_
|
||||
|
||||
## Raising Funds
|
||||
|
||||
Astro is an MIT licensed open source project and completely free to use. However, the amount of effort needed to maintain and develop new features for Astro is not sustainable without proper financial backing. We need your help to achieve this.
|
||||
|
||||
Learn more about sponsorship on our [Open Collective.](https://opencollective.com/astrodotbuild).
|
||||
|
||||
### Why Open Collective?
|
||||
|
||||
- **Full Transparency.** Everyone gets to see where money is coming from and where it's going.
|
||||
- **Individual and Corporate Sponsors.** Open Collective makes it easy for both individuals and companies to sponsor open source projects.
|
||||
- **Potential Tax Benefits.** Because funds are paid to the Open Source Collective, a 501(c)(6) organization in the U.S., there may be tax benefits for some donors (please check with your accountant).
|
||||
- **Automatic Invoicing.** For corporate sponsors, Open Collective automatically generates and sends invoices for tracking purposes.
|
||||
- **Open Participation.** Anyone can request reimbursement for funds spent helping the Astro project and Astro can pay out to anyone.
|
||||
|
||||
_List borrowed from [ESLint: "Funding ESLint's Future."](https://eslint.org/blog/2019/02/funding-eslint-future)_
|
||||
|
||||
## Distributing Funds
|
||||
|
||||
100% of money raised is invested back into the community. Every dollar spent **must** support and/or improve Astro in some way.
|
||||
|
||||
See all past expenses on our [Open Collective.](https://opencollective.com/astrodotbuild)
|
||||
|
||||
Below is a (non-exhaustive) list of how we plan to distribute raised funds:
|
||||
|
||||
- **Swag!** Creating stickers, t-shirts, etc. for sponsors and community members.
|
||||
- **Improve documentation.**
|
||||
- **Improve translations.**
|
||||
- **Improve website.**
|
||||
- **User research.**
|
||||
- **Sponsoring conferences.**
|
||||
- **Sponsoring community members to represent Astro at meetups, conferences, etc.**
|
||||
- **Dedicated support for GitHub, Discord, Stack Overflow, etc.**
|
||||
|
||||
## Eligibility
|
||||
|
||||
**Employees of The Astro Technology Company are not eligible to receive funds from Open Collective.** These funds exist solely to serve the larger Astro community.
|
12
FUNDING.yml
12
FUNDING.yml
|
@ -1,12 +0,0 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: astrodotbuild
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
463
GOVERNANCE.md
463
GOVERNANCE.md
|
@ -1,463 +0,0 @@
|
|||
# Governance
|
||||
|
||||
This document outlines the governance model for Astro. This includes detailed descriptions of different roles, nomination processes, code review processes, and Code of Conduct enforcement.
|
||||
|
||||
👉 **All community members must follow the [Code of Conduct (CoC)](CODE_OF_CONDUCT.md).**
|
||||
Consequences for CoC violations are detailed in [Moderation](#moderation).
|
||||
|
||||
👉 **Want to trigger a vote, nomination, or perform some other action?**
|
||||
Scroll down to [Playbook](#governance-playbook).
|
||||
|
||||
## Get Involved
|
||||
|
||||
**Anything that supports the Astro community is a valuable contribution!**
|
||||
|
||||
All types of contribution are meaningful. This can include code changes, type fixes, Discord activity, and even posting about Astro to your personal blog. No contribution is too small!
|
||||
|
||||
Anyone can become an Astro contributor (yes, even you!). Engineering ability is not required. Our goal is to recognize all contributors to the project regardless of skill, experience or background.
|
||||
|
||||
## Contributor Levels
|
||||
|
||||
We recognize different levels of contribution as four different **Contributor Levels.** Because each level comes with a new set of privileges and responsibilities, you may also see these levels referred to as **Contributor Roles**.
|
||||
|
||||
Contributor levels are available to **all members** of the Astro community, regardless of coding skill or experience.
|
||||
|
||||
Two important things that we look for in a contributor are:
|
||||
|
||||
- **Being here** - Everyone's time is valuable, and the fact that you're here and contributing to Astro is amazing! Thank you for being a part of this project with us.
|
||||
- **Being a positive member of our community** - Go above and beyond our [Code of Conduct](CODE_OF_CONDUCT.md) and commit to healthy communication across pull requests, issue discussions, Discord conversations, and any interactions outside of our community (ex: no Twitter bullies allowed :)
|
||||
|
||||
All Contributor roles are granted for as long as the individual wishes to engage with the project.
|
||||
|
||||
Contributors can voluntarily leave the project at any time. See [Retiring a Role](#retiring-a-role-alumni) below for more information.
|
||||
|
||||
In extreme cases -- such as a Code of Conduct violation -- a role may be revoked by a project Steward at their discretion.
|
||||
|
||||
Each new Contributor level unlocks new privileges and responsibilities both on Discord and on GitHub. Below is a summary of each level.
|
||||
|
||||
### Level 1 - Contributor
|
||||
|
||||
Have you done something (big or small) to contribute to the health, success, or growth of Astro? **Congratulations, you're officially recognized as a contributor to the project!**
|
||||
|
||||
#### Examples of recognized contributions
|
||||
|
||||
- **GitHub:** Submitting a merged pull request.
|
||||
- **GitHub:** Filing a detailed bug report or RFC.
|
||||
- **GitHub:** Updating documentation or fixing a typo.
|
||||
- Helping people on GitHub, Discord, etc.
|
||||
- Answering questions on Stack Overflow, Twitter, etc.
|
||||
- Blogging, Vlogging, Podcasting, and Livestreaming about Astro.
|
||||
- This list is incomplete! Similar contributions are also recognized.
|
||||
|
||||
#### Privileges
|
||||
|
||||
- New role on [Discord](https://astro.build/chat): `@contributor`
|
||||
- New name color on Discord: **light blue**.
|
||||
- Invitations to contributor-only events, sticker drops, and the occasional swag drop.
|
||||
|
||||
#### Responsibilities
|
||||
|
||||
This role does not require any extra responsibilities nor time commitment. We hope you stick around and keep participating in our community!
|
||||
|
||||
If you're interested in reaching the next level and becoming a **Maintainer**, you can explore some of those responsibilities in the [next section](#level-2-l2---maintainer).
|
||||
|
||||
#### Nomination Process
|
||||
|
||||
You may self-nominate by sending the message `!contribute` in any Discord channel. If you do this, please share a second message with a link or description of your contribution so that people can recognize you for the contribution.
|
||||
|
||||
You may also be granted this role automatically if you are active and helpful on Discord.
|
||||
|
||||
### Level 2 (L2) - Maintainer
|
||||
|
||||
The **Maintainer** role is available to contributors who want to join the team and take part in the long-term maintenance and growth of Astro.
|
||||
|
||||
The Maintainer role is critical to the long-term health of Astro. Maintainers act as the first line of defense when it comes to new issues, pull requests and Discord activity. Maintainers are most likely the first people that a user will interact with on Discord or GitHub.
|
||||
|
||||
**Maintainers are not required to write code!** Some Maintainers spend most of their time inside of Discord, maintaining a healthy community there. Others work on technical documentation, support, or design.
|
||||
|
||||
**A Maintainer has moderation privileges!** All maintainers are trusted with the ability to help moderate our Discord and GitHub communities for things like spam. There is also a special (optional, opt-in) `@mods` role open to maintainers who are also interested in helping out when a community member reaches out for moderation help.
|
||||
|
||||
#### Recognized Contributions
|
||||
|
||||
There is no strict minimum number of contributions needed to reach this level, as long as you can show **sustained** involvement over some amount of time (at least a few months).
|
||||
|
||||
- **GitHub:** Submitting multiple non-trivial pull requests and RFCs
|
||||
- **GitHub:** Reviewing multiple non-trivial pull requests and RFCs
|
||||
- **Discord:** Supporting users in Discord, especially in the #support channel
|
||||
- **Discord:** Active participation in RFC calls and other events
|
||||
- **GitHub + Discord:** Triaging and confirming user issues
|
||||
- This list is incomplete! Similar contributions are also recognized.
|
||||
|
||||
#### Privileges
|
||||
|
||||
- All privileges of the [Contributor role](#level-1---contributor), plus...
|
||||
- Invitation to the `@maintainer` role on [Discord](https://astro.build/chat)
|
||||
- Invitation to the private `#maintainers` channel on Discord.
|
||||
- Invitation to the `withastro` organization on GitHub.
|
||||
- Invitation to the `@maintainers` team on GitHub.
|
||||
- New name color on Discord: **blue**.
|
||||
- Ability to moderate Discord to remove spam, harmful speech, etc.
|
||||
- Ability to join the `@mods` role on Discord (optional, opt-in).
|
||||
- Ability to push branches directly to the `withastro` GitHub organization (personal forks no longer needed).
|
||||
- Ability to review GitHub PRs.
|
||||
- Ability to merge _some_ GitHub PRs.
|
||||
- Ability to vote on _some_ initiatives (see [Voting](#voting) below).
|
||||
|
||||
#### Responsibilities
|
||||
|
||||
- Participate in the project as a team player.
|
||||
- Bring a friendly, welcoming voice to the Astro community.
|
||||
- Be active on Discord, especially in the #support channel.
|
||||
- Triage new issues.
|
||||
- Review pull requests.
|
||||
- Merge some, non-trivial community pull requests.
|
||||
- Merge your own pull requests (once reviewed and approved).
|
||||
|
||||
#### Nomination
|
||||
|
||||
- To be nominated, a nominee is expected to already be performing some of the responsibilities of a Maintainer.
|
||||
- You can be nominated by any existing Maintainer (L2 or above).
|
||||
- Once nominated, there will be a vote by existing Maintainers.
|
||||
- See [vote rules & requirements](#voting) for info on how the vote works.
|
||||
|
||||
### Level 3 (L3) - Core
|
||||
|
||||
The **Core** role is available to community members who have a larger-than-usual impact on the Astro project and community. They are seen as leaders in the project and are listened to by the wider Astro community, often before they have even reached this level. A Core member is recognized for contributing a significant amount of time and energy to the project through issues, pull requests, bug fixes, implementing advanced enhancements/features, and/or actively posting on Discord.
|
||||
|
||||
Not every contributor will reach this level, and that's okay! L2 Maintainers still have significant responsibility and privileges within our community.
|
||||
|
||||
#### Privileges
|
||||
|
||||
- All privileges of the [Maintainer role](#level-2---maintainer), plus...
|
||||
- `@core` role on [Discord](https://astro.build/chat)
|
||||
- New name color on Discord: **yellow**.
|
||||
- Invitation to the private `#core` channel on Discord.
|
||||
- Invitation to the `core` team on GitHub.
|
||||
- Ability to vote on most initiatives (see [Voting](#voting) below).
|
||||
|
||||
#### Responsibilities
|
||||
|
||||
- All of the responsibilities of L2, including...
|
||||
- Ownership over specific part(s) of the project.
|
||||
- Ownership over the long-term health and success of Astro.
|
||||
- Leadership as a role-model to other maintainers and community members.
|
||||
|
||||
#### Nomination
|
||||
|
||||
- To be nominated, a nominee is expected to already be performing some of the responsibilities of a Core member.
|
||||
- You can be nominated by any existing Core member (L3 or above).
|
||||
- Once nominated, there will be a vote by existing Core members.
|
||||
- See [vote rules & requirements](#voting) for info on how the vote works.
|
||||
|
||||
#### Special Membership Type: Core Residency
|
||||
|
||||
**Core Residency** is a special type of Core membership that is limited in the following way(s):
|
||||
|
||||
- No voting abilities.
|
||||
- No nomination abilities.
|
||||
- Can be revoked at any time by the project Steward.
|
||||
|
||||
Because of these limitations, this type of Core membership is useful for anyone who has been brought in to work on or contribute to the Astro project without rising through our normal contributor levels. For example: an Astro designer or developer advocate hired by The Astro Technology Company to assist the community could be nominated for a Core Residency role without having a previously earned contributor level.
|
||||
|
||||
A Core Residency nomination must still be approved through the normal Core nomination and voting process. During the nomination, the Project Steward will state that the nomination is for the Core Residency designation. The project Steward is the only one who can officially make this designation during the nomination process.
|
||||
|
||||
A Core Residency member can become a full Core member (with all limitations removed) through the normal Core nomination and voting procedure.
|
||||
|
||||
If a Core Residency member has their membership revoked, the project Steward may choose to impose a waiting period of some number of days, during which the member can not be re-nominated to become a full Core member.
|
||||
|
||||
### Level 4 - Project Steward
|
||||
|
||||
The **Steward** is an additional role bestowed to 1 (or more) Core member of the project.
|
||||
|
||||
The role of Steward is mainly an administrative one. Stewards control and maintain sensitive project assets, assist in resolving conflicts, and act as tiebreakers in the event of disagreements.
|
||||
|
||||
In extremely rare cases, a Steward can act unilaterally when they believe it is in the project's best interest and can prove that the issue cannot be resolved through normal governance procedure. The steward must publicly state their reason for unilateral action before taking it.
|
||||
|
||||
The project Steward is currently: **@FredKSchott**
|
||||
|
||||
#### Responsibilities
|
||||
|
||||
- Access to the [@astrodotbuild Twitter account](https://twitter.com/astrodotbuild)
|
||||
- Administration privileges on the [astro GitHub org](https://github.com/snowpackjs)
|
||||
- Administration privileges on the [astro Discord server](https://astro.build/chat)
|
||||
- Publish access to the [`astro` npm package](https://www.npmjs.com/package/astro)
|
||||
- Domain registrar and DNS access to `astro.build` and all other domains
|
||||
- Administration access to the `astro.build` Vercel account
|
||||
- Ability to initiate a [vote](GOVERNANCE.md#voting)
|
||||
- Ability to veto [votes](GOVERNANCE.md#voting) and resolve voting deadlocks
|
||||
- Define project direction and planning
|
||||
- Ability to decide on moderation decisions
|
||||
- Access to the `*@astro.build` email address
|
||||
|
||||
#### Nomination
|
||||
|
||||
- Stewards cannot be self-nominated.
|
||||
- Only Core members are eligible.
|
||||
- New Stewards will be added based on a unanimous vote by the existing Steward(s).
|
||||
- In the event that someone is unreachable then the decision will be deferred.
|
||||
|
||||
## Other Roles
|
||||
|
||||
### Project Teams
|
||||
|
||||
Besides our contributor levels described above, there are additional roles and teams available that community members are welcome to join. Roles are a great way to organize around different projects and initiatives in our community. For example:
|
||||
|
||||
- `@team-docs` runs the `#docs` channel and organizes the growth and development of Astro documentation.
|
||||
- `@i18n-gang` runs the `#docs-i18n` channel and organizes translations in several languages.
|
||||
- `@support-squad` runs the `#support-threads` channel and helps anyone who needs help using Astro.
|
||||
|
||||
Many of these team roles can be browsed and joined automatically by visiting the `#manage-roles` channel in our Discord. Getting involved with a team is a great way to start contributing to Astro!
|
||||
|
||||
### Moderator
|
||||
|
||||
**Moderator** is a special role available to Maintainers (L2 and above). While all maintainers are granted permissions to moderate for bad behavior across our community, a Moderator actively takes on this the responsibility. For example, a community member may ping moderators (via the `@mods` role) to resolve spam posts or Code of Conduct violations.
|
||||
|
||||
Trivial tasks (like removing spam) can be acted on unilaterally by a Moderator. Other non-trivial tasks (like assisting with or resolving a Code of Conduct violation) should involve the entire Moderator team (and in some cases, the project Steward).
|
||||
|
||||
#### Privileges
|
||||
|
||||
- `@mods` role on [Discord](https://astro.build/chat)
|
||||
- Invitation to the private `#moderators` channel on Discord
|
||||
- Invitation to the `staff` team on GitHub.
|
||||
|
||||
#### Nomination
|
||||
|
||||
Any Maintainer (L2 and above) can self-nominate by messaging the project Steward (`@steward`) on Discord.
|
||||
|
||||
### Technical Steering Committee (TSC)
|
||||
|
||||
The **TSC** is a special role available to Core members (L3 and above). TSC members are responsible for the growth and maintenance of the Astro codebase.
|
||||
|
||||
TSC members are guardians over the Astro codebase. Their duty is to ensure code quality, correctness and security.
|
||||
|
||||
A TSC member guides the direction of the project and ensures a healthy future for the Astro codebase. TSC members are ultimately responsible for technical decision making when it comes to any changes to the Astro codebase.
|
||||
|
||||
A TSC member has significant sway in software design decisions. For this reason, coding experience is critical for this role. TSC membership is one of the only roles that requires a significant contribution history of code to the Astro project on GitHub.
|
||||
|
||||
#### Privileges
|
||||
|
||||
- `@tsc` role on [Discord](https://astro.build/chat)
|
||||
- Invitation to the private `#tsc` channel on Discord
|
||||
- Invitation to the `tsc` team on GitHub.
|
||||
- Ability to merge all GitHub PRs.
|
||||
- Ability to vote on RFCs and technical initiatives (see [Voting](#voting) below).
|
||||
|
||||
#### Responsibilities
|
||||
|
||||
- Participating in RFC discussions and technical meetings.
|
||||
- Assisting with design and implementation of non-trivial GitHub PRs.
|
||||
- Reviewing and merging larger, non-trivial PRs.
|
||||
- Maintaining and improving overall codebase architecture.
|
||||
- Tracking and ensuring progress of open pull requests.
|
||||
- Mentoring and guiding other community contributors.
|
||||
|
||||
#### Nomination
|
||||
|
||||
- To be nominated, a nominee is expected to already be active in technical discussions and performing some of the responsibilities of a TSC member.
|
||||
- You can be nominated by any existing Core member (L3 or above). Note: This includes all existing TSC members as well.
|
||||
- Once nominated, there will be a vote by existing Core members.
|
||||
- See [vote rules & requirements](#voting) for info on how this vote works.
|
||||
|
||||
### Staff
|
||||
|
||||
**Staff** is a special designation for employees of [The Astro Technology Company](https://astro.build/company).
|
||||
|
||||
#### Privileges
|
||||
|
||||
- `@staff` role on [Discord](https://astro.build/chat)
|
||||
- New name color on Discord: **yellow**.
|
||||
- Invitation to some private channels on Discord, at the discretion of the project Steward.
|
||||
- Invitation to the `staff` team on GitHub.
|
||||
|
||||
Staff membership does not grant any additional abilities when it comes to voting and project governance. A Staff member is still eligible for other roles in the community and may still vote as defined by their other roles. For example, a Staff member who is also a part of `@core` will be able to vote as any other `@core` member would.
|
||||
|
||||
### Alumni
|
||||
|
||||
**Alumni** is a special designation for Maintainers (L2 and above) who have stepped away from the project and no longer contribute regularly. See [Retiring a Role](#retiring-a-role-alumni) below for more information.
|
||||
|
||||
#### Privileges
|
||||
|
||||
- `@alumni` role on [Discord](https://astro.build/chat)
|
||||
- New name color on Discord: **light blue**.
|
||||
- Invitation to the private `#alumni` channel on Discord.
|
||||
|
||||
## Retiring a Role (Alumni)
|
||||
|
||||
Contributor roles are granted for as long as the person wishes to engage with the project. However, over time an active community member may choose to step away from the Astro project to work on other things. Moving on from a project is a natural and well-understood part of any open source community, and we celebrate it!
|
||||
|
||||
**Alumni** is a special designation and role for any person who was once an active maintainer (L2 or above) but is now no longer actively involved. By retiring and joining Alumni you trade-in your current set of roles, privileges, and responsibilities for a new, special Alumni role (which comes with its own set of Privileges, as described above).
|
||||
|
||||
As a Maintainer (L2 or above) you can retire your role at any time by pinging the project Steward and requesting Alumni status. You can initiate this action yourself if you know ahead-of-time that you need to step away from the project. Or, if you have gone several months without interacting with the Astro community, the project Steward may actively reach out to you to discuss retiring as a way to make room for new contributors.
|
||||
|
||||
As an Alumni member, you are still a part of the Astro community and can continue to be a part of our Discord, GitHub, and anywhere else. You may also request to have your old roles reinstated at any time through the normal nomination & voting process for that role.
|
||||
|
||||
Rejoining the project as a contributor (L1 or above) will automatically remove you from the Alumni role.
|
||||
|
||||
# Governance Playbook
|
||||
|
||||
## Voting
|
||||
|
||||
Certain project decisions (like governance changes and membership nominations) require a vote. Below are the changes that require a vote, and the rules that govern that vote.
|
||||
|
||||
The project Steward may initiate a vote for any unlisted project decision. [General Rules](#general-rules) will apply, along with any addition rules provided at the steward's discretion. If this unlisted project decision is expected to be repeated in the future, voting rules should be agreed on and then added to this document.
|
||||
|
||||
### General Voting Rules
|
||||
|
||||
- Members may abstain from any vote.
|
||||
- Members who do not vote within 3 days will automatically abstain.
|
||||
- Stewards may reduce the 3 day automatic abstain for urgent decisions.
|
||||
- Stewards reserve the right to veto approval with a publicly disclosed reason.
|
||||
|
||||
## Voting: Maintainer (L2) Nomination
|
||||
|
||||
This process kicks off once a valid nomination has been made. See ["Maintainer - Nomination Process"](#nomination-process) above for more details on nomination.
|
||||
|
||||
**Who can vote:** All Maintainers (L2 and above).
|
||||
|
||||
1. A vote thread should be created in Discord #maintainers channel (the private channel for all maintainers).
|
||||
2. A vote thread can be created by any Maintainer, Core member, or the Steward.
|
||||
3. Once a vote thread is created, existing Maintainers can discuss the nomination in private.
|
||||
4. The normal 3 day voting & discussion window begins with the thread creation.
|
||||
5. Voting can be done in the thread (visible to other voters) or in a private DM to the project Steward.
|
||||
6. Once the vote is complete, the thread is deleted.
|
||||
7. The vote must receive an overwhelming majority (70%+) to pass.
|
||||
8. **If the vote passes:** the nominee will be made a Maintainer and all privileges will be made available to them.
|
||||
9. **If the vote fails:** the project Steward is responsible for informing the nominee with constructive, actionable feedback. (Note: this is not required if the nomination was made in the `#core` channel, or if the nominee was otherwise not made aware of their nomination).
|
||||
|
||||
#### Draft message to send to accepted maintainer, informing them of the decision:
|
||||
|
||||
```
|
||||
Hey ${NAME}!
|
||||
|
||||
**I have some exciting news — you've been given the role of L2 Contributor (aka Maintainer/Moderator) in the Astro community!**
|
||||
|
||||
Some background: I nominated you for the role in the (private) #maintainers channel, and the consensus was overwhelmingly positive. Some quotes from the nomination thread that sum up the impact you've already had on the project so far:
|
||||
|
||||
- ...
|
||||
- ...
|
||||
- ...
|
||||
|
||||
Thank you for ${1 SENTENCE DESCRIPTION OF CONTRIBUTIONS}. Your impact has definitely been felt and we would be thrilled to have your help building a healthy future for Astro! There is no required time commitment: you can continue to contribute as often or as little as you'd like. This is mainly a chance to recognize your contributions and give you more privileges in Discord and GitHub.
|
||||
|
||||
Please let me know if you’re interested in accepting this invitation. If so, we’ll start getting your roles up to date. And if you have any questions, feel free to let me know.
|
||||
|
||||
Best,
|
||||
${MY_NAME}
|
||||
|
||||
*PS: As a reminder, our Governance document describes the following privileges and responsibilities for the **L2 - Maintainer** role: https://github.com/withastro/astro/blob/main/GOVERNANCE.md*
|
||||
```
|
||||
|
||||
## Voting: Core Member (L3) Nomination
|
||||
|
||||
This process kicks off once a valid nomination has been made. See ["Core Member - Nomination Process"](#nomination-process) above for more details on nomination.
|
||||
|
||||
**Who can vote:** All Core members (L3 and above).
|
||||
|
||||
1. A vote thread should be created in Discord `#core` channel (the private channel for Core members).
|
||||
2. A vote thread can be created by any Core member, or the Steward.
|
||||
3. Once a vote thread is created, existing Core members can discuss the nomination in private.
|
||||
4. The normal 3 day voting & discussion window begins with the thread creation.
|
||||
5. Voting can be done in the thread (visible to other voters) or in a private DM to the project Steward.
|
||||
6. Once the vote is complete, the thread is deleted.
|
||||
7. The vote must receive an overwhelming majority (70%+) to pass.
|
||||
8. **If the vote passes:** the nominee will be made a Core Member and all privileges will be made available to them.
|
||||
9. **If the vote fails:** the project Steward is responsible for informing the nominee with constructive, actionable feedback. (Note: this is not required if the nomination was made in the #core channel, or if the nominee was otherwise not made aware of their nomination).
|
||||
|
||||
#### Draft message to send to accepted maintainer, informing them of the decision:
|
||||
|
||||
```
|
||||
Hey $NAME!
|
||||
|
||||
I have some exciting news—you’ve been nominated and accepted as a member of the Astro Core team! The Core team held a vote and overwhelmingly agree that you would be a great addition to the team. Congratulations! Thanks for all of your significant contributions to Astro to date and your continued dedication to this project and our community. We would be thrilled to have your help ensuring a healthy future for Astro!
|
||||
|
||||
Please let me know if you’re interested in accepting this invitation. If so, we’ll start getting your roles and permissions up to date.
|
||||
|
||||
As a reminder, our Governance document describes the following privileges and responsibilities for a **Core Member**:
|
||||
|
||||
#### Privileges
|
||||
|
||||
$COPY_AND_PASTE_FROM_ABOVE
|
||||
|
||||
#### Responsibilities
|
||||
|
||||
$COPY_AND_PASTE_FROM_ABOVE
|
||||
```
|
||||
|
||||
## Voting: Governance Change
|
||||
|
||||
A vote is initiated once a pull request to the GOVERNANCE.md file is submitted by a Core Member.
|
||||
|
||||
If the pull request submitter is not a Core Member, the PR can be closed by any Maintainer without a vote. However, any Core Member may request a vote on that PR, in which case a vote is initiated.
|
||||
|
||||
**Who can vote:** Core members (L3 and above). All Maintainers are encouraged to discuss and voice their opinion in the pull request discussion. Core members should take the opinions of Maintainers into consideration when voting.
|
||||
|
||||
1. The pull request discussion thread is used to discuss the governance change.
|
||||
2. The normal 3 day voting & discussion window begins with either the PR creation or the removal of `WIP:` from the PR title if the PR was created as a draft.
|
||||
3. Voting can be done in the pull request via a review of either **Approve (For)** or **Change Requested (Against)**.
|
||||
4. The vote must receive a simple majority (50%+) to pass.
|
||||
5. **If the vote passes:** the PR is merged and the changes take effect immediately.
|
||||
6. **If the vote fails:** the PR is closed and no change occurs.
|
||||
|
||||
## Voting: RFC Proposals
|
||||
|
||||
Astro features are discussed using a model called [Consensus-seeking decision-making](https://en.wikipedia.org/wiki/Consensus-seeking_decision-making). This model attempts to achieve consensus on all significant changes to Astro, but has a fallback voting procedure in place if consensus appears unattainable.
|
||||
|
||||
**Who can vote:** All [TSC](#technical-steering-committee-tsc) members.
|
||||
|
||||
1. Anyone can submit an RFC to suggest changes to Astro.
|
||||
2. A trivial change can be discussed and approved entirely within the RFC GitHub issue, as long as there are no objections from Core or TSC members. This is not considered a formal vote.
|
||||
3. A non-trivial, significant change should be discussed within the RFC and approved during an RFC meeting call. In some cases, an RFC may be approved outside of an RFC meeting using Pull Request reviews as a proxy for votes.
|
||||
4. During an RFC meeting, the person leading the call will attempt to achieve consensus on the RFC proposal.
|
||||
5. **If consensus is reached:** the RFC is approved.
|
||||
6. **If consensus is not reached:** The RFC author and TSC members must make all reasonable attempts to resolve issues and reach consensus in GitHub or a follow-up RFC meeting. The process of reaching consensus can take time, and should not be rushed as long as all participants are making a reasonable effort to respond.
|
||||
7. **If consensus still cannot be reached:** The project Steward may invoke [rough consensus](https://en.wikipedia.org/wiki/Rough_consensus) to resolve an RFC that has not achieved absolute consensus, as described below (borrowed from the [IETF](https://datatracker.ietf.org/doc/html/rfc2418)):
|
||||
|
||||
> Working groups make decisions through a "rough consensus" process. Astro consensus does not require that all participants agree although this is, of course, preferred. In general, the dominant view of the TSC shall prevail. (However, "dominance" is not to be determined on the basis of volume or persistence, but rather a more general sense of agreement). Consensus can be determined by a show of hands, humming, or any other means on which the TSC agrees (by rough consensus, of course). Note that 51% of the TSC does not qualify as "rough consensus" and 99% is better than rough. It is up to the project Steward to determine if rough consensus has been reached.
|
||||
|
||||
## Moderation
|
||||
|
||||
Outlined below is the process for Code of Conduct violation reviews.
|
||||
|
||||
### Reporting
|
||||
|
||||
Anyone may report a violation. Violations can be reported in the following ways:
|
||||
|
||||
- In private, via email to one or more stewards.
|
||||
- In private, via direct message to a project steward on Discord.
|
||||
- In public, via a GitHub comment (mentioning `@snowpackjs/maintainers`).
|
||||
- In public, via the project Discord server (mentioning `staff`).
|
||||
|
||||
### Who gets involved?
|
||||
|
||||
Each report will be assigned reviewers. These will initially be all project [stewards](#stewards).
|
||||
|
||||
In the event of any conflict of interest - ie. stewards who are personally connected to a situation, they must immediately recuse themselves.
|
||||
|
||||
At request of the reporter and if deemed appropriate by the reviewers, another neutral third-party may be involved in the review and decision process.
|
||||
|
||||
### Review
|
||||
|
||||
If a report doesn’t contain enough information, the reviewers will strive to obtain all relevant data before acting.
|
||||
|
||||
The reviewers will then review the incident and determine, to the best of their ability:
|
||||
|
||||
- What happened.
|
||||
- Whether this event constitutes a Code of Conduct violation.
|
||||
- Who, if anyone, was involved in the violation.
|
||||
- Whether this is an ongoing situation.
|
||||
|
||||
The reviewers should aim to have a resolution agreed very rapidly; if not agreed within a week, they will inform the parties of the planned date.
|
||||
|
||||
### Resolution
|
||||
|
||||
Responses will be determined by the reviewers on the basis of the information gathered and of the potential consequences. It may include:
|
||||
|
||||
- taking no further action
|
||||
- issuing a reprimand (private or public)
|
||||
- asking for an apology (private or public)
|
||||
- permanent ban from the GitHub org and Discord server
|
||||
- revoked contributor status
|
||||
|
||||
---
|
||||
|
||||
Inspired by [ESLint](https://eslint.org/docs/6.0.0/maintainer-guide/governance), [Rome](https://github.com/rome/tools/blob/main/GOVERNANCE.md) and [Blitz](https://blitzjs.com/docs/maintainers).
|
|
@ -49,6 +49,7 @@ Join us on [Discord](https://astro.build/chat) to meet other maintainers. We'll
|
|||
| [@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/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) |
|
||||
| [@astrojs/partytown](packages/integrations/partytown) | [![astro version](https://img.shields.io/npm/v/@astrojs/partytown.svg?label=%20)](packages/integrations/partytown/CHANGELOG.md) |
|
||||
| [@astrojs/sitemap](packages/integrations/sitemap) | [![astro version](https://img.shields.io/npm/v/@astrojs/sitemap.svg?label=%20)](packages/integrations/sitemap/CHANGELOG.md) |
|
||||
| [@astrojs/tailwind](packages/integrations/tailwind) | [![astro version](https://img.shields.io/npm/v/@astrojs/tailwind.svg?label=%20)](packages/integrations/tailwind/CHANGELOG.md) |
|
||||
|
@ -65,16 +66,16 @@ Several official projects are maintained outside of this repo:
|
|||
## Links
|
||||
|
||||
- [License (MIT)](LICENSE)
|
||||
- [Code of Conduct](CODE_OF_CONDUCT.md)
|
||||
- [Open Governance & Voting](GOVERNANCE.md)
|
||||
- [Project Funding](FUNDING.md)
|
||||
- [Code of Conduct](https://github.com/withastro/.github/blob/main/CODE_OF_CONDUCT.md)
|
||||
- [Open Governance & Voting](https://github.com/withastro/.github/blob/main/GOVERNANCE.md)
|
||||
- [Project Funding](https://github.com/withastro/.github/blob/main/FUNDING.md)
|
||||
- [Website](https://astro.build/)
|
||||
|
||||
## Sponsors
|
||||
|
||||
Astro is generously supported by Netlify, Vercel, and several other amazing organizations.
|
||||
|
||||
[❤️ Sponsor Astro! ❤️](FUNDING.md)
|
||||
[❤️ Sponsor Astro! ❤️](https://github.com/withastro/.github/blob/main/FUNDING.md)
|
||||
|
||||
### Platinum Sponsors
|
||||
|
||||
|
|
|
@ -9,6 +9,6 @@
|
|||
"preview": "astro preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"astro": "^1.0.0-beta.46"
|
||||
"astro": "^1.0.0-beta.73"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
---
|
||||
export interface Props {
|
||||
title: string,
|
||||
body: string,
|
||||
href: string,
|
||||
title: string;
|
||||
body: string;
|
||||
href: string;
|
||||
}
|
||||
const {href, title, body} = Astro.props;
|
||||
const { href, title, body } = Astro.props;
|
||||
---
|
||||
|
||||
<li class="link-card">
|
||||
<a href={href}>
|
||||
<h2>
|
||||
{title}
|
||||
<span>→</span>
|
||||
</h2>
|
||||
<p>
|
||||
{body}
|
||||
</p>
|
||||
</a>
|
||||
<a href={href}>
|
||||
<h2>
|
||||
{title}
|
||||
<span>→</span>
|
||||
</h2>
|
||||
<p>
|
||||
{body}
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
<style>
|
||||
|
||||
:root {
|
||||
--link-gradient: linear-gradient(45deg, #4F39FA, #DA62C4 30%, var(--color-border) 60%);
|
||||
--link-gradient: linear-gradient(45deg, #4f39fa, #da62c4 30%, var(--color-border) 60%);
|
||||
}
|
||||
|
||||
.link-card {
|
||||
|
@ -49,11 +49,11 @@ const {href, title, body} = Astro.props;
|
|||
margin: 0;
|
||||
transition: color 0.6s cubic-bezier(0.22, 1, 0.36, 1);
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0.75rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0.75rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
h2 span {
|
||||
display: inline-block;
|
||||
|
@ -65,7 +65,7 @@ const {href, title, body} = Astro.props;
|
|||
}
|
||||
|
||||
.link-card:is(:hover, :focus-within) h2 {
|
||||
color: #4F39FA;
|
||||
color: #4f39fa;
|
||||
}
|
||||
|
||||
.link-card:is(:hover, :focus-within) h2 span {
|
||||
|
|
|
@ -8,49 +8,48 @@ 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/x-icon" href="/favicon.ico" />
|
||||
<title>{title}</title>
|
||||
</head>
|
||||
<body>
|
||||
<slot />
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<title>{title}</title>
|
||||
</head>
|
||||
<body>
|
||||
<slot />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<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, 3.75rem);
|
||||
: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, 3.75rem);
|
||||
|
||||
--color-text: hsl(12, 5%, 4%);
|
||||
--color-bg: hsl(10, 21%, 95%);
|
||||
--color-text: hsl(12, 5%, 4%);
|
||||
--color-bg: hsl(10, 21%, 95%);
|
||||
--color-border: hsl(17, 24%, 90%);
|
||||
}
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: system-ui, sans-serif;
|
||||
font-size: var(--font-size-base);
|
||||
color: var(--color-text);
|
||||
background-color: var(--color-bg);
|
||||
}
|
||||
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;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
:global(h1) {
|
||||
font-size: var(--font-size-xl);
|
||||
}
|
||||
:global(h1) {
|
||||
font-size: var(--font-size-xl);
|
||||
}
|
||||
|
||||
:global(h2) {
|
||||
font-size: var(--font-size-lg);
|
||||
}
|
||||
:global(h2) {
|
||||
font-size: var(--font-size-lg);
|
||||
}
|
||||
|
||||
:global(code) {
|
||||
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
||||
:global(code) {
|
||||
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono, Courier New, monospace;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,26 +1,43 @@
|
|||
---
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
import Card from '../components/Card.astro';
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
import Card from "../components/Card.astro";
|
||||
---
|
||||
|
||||
<Layout title="Welcome to Astro.">
|
||||
<main>
|
||||
<h1>Welcome to <span class="text-gradient">Astro</span></h1>
|
||||
<p class="instructions">
|
||||
Check out the <code>src/pages</code> directory to get started.<br/>
|
||||
Check out the <code>src/pages</code> directory to get started.<br />
|
||||
<strong>Code Challenge:</strong> Tweak the "Welcome to Astro" message above.
|
||||
</p>
|
||||
<ul role="list" class="link-card-grid">
|
||||
<Card href="https://docs.astro.build/" title="Documentation" body="Learn how Astro works and explore the official API docs." />
|
||||
<Card href="https://astro.build/integrations/" title="Integrations" body="Supercharge your project with new frameworks and libraries." />
|
||||
<Card href="https://astro.build/themes/" title="Themes" body="Explore a galaxy of community-built starter themes." />
|
||||
<Card href="https://astro.build/chat/" title="Chat" body="Come say hi to our amazing Discord community. ❤️" />
|
||||
<Card
|
||||
href="https://docs.astro.build/"
|
||||
title="Documentation"
|
||||
body="Learn how Astro works and explore the official API docs."
|
||||
/>
|
||||
<Card
|
||||
href="https://astro.build/integrations/"
|
||||
title="Integrations"
|
||||
body="Supercharge your project with new frameworks and libraries."
|
||||
/>
|
||||
<Card
|
||||
href="https://astro.build/themes/"
|
||||
title="Themes"
|
||||
body="Explore a galaxy of community-built starter themes."
|
||||
/>
|
||||
<Card
|
||||
href="https://astro.build/chat/"
|
||||
title="Chat"
|
||||
body="Come say hi to our amazing Discord community. ❤️"
|
||||
/>
|
||||
</ul>
|
||||
</main>
|
||||
</Layout>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--astro-gradient: linear-gradient(0deg,#4F39FA, #DA62C4);
|
||||
--astro-gradient: linear-gradient(0deg, #4f39fa, #da62c4);
|
||||
}
|
||||
|
||||
h1 {
|
||||
|
@ -29,7 +46,7 @@ import Card from '../components/Card.astro';
|
|||
|
||||
main {
|
||||
margin: auto;
|
||||
padding: 1em;
|
||||
padding: 1em;
|
||||
max-width: 60ch;
|
||||
}
|
||||
|
||||
|
@ -45,15 +62,20 @@ import Card from '../components/Card.astro';
|
|||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% { background-position-y: 0%; }
|
||||
50% { background-position-y: 80%; }
|
||||
0%,
|
||||
100% {
|
||||
background-position-y: 0%;
|
||||
}
|
||||
50% {
|
||||
background-position-y: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
.instructions {
|
||||
line-height: 1.6;
|
||||
margin: 1rem 0;
|
||||
background: #4F39FA;
|
||||
padding: 1.0rem;
|
||||
background: #4f39fa;
|
||||
padding: 1rem;
|
||||
border-radius: 0.4rem;
|
||||
color: var(--color-bg);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"resolveJsonModule": true,
|
||||
// Enable stricter transpilation for better output.
|
||||
"isolatedModules": true,
|
||||
// Add type definitions for our Vite runtime.
|
||||
"types": ["vite/client"]
|
||||
// Add type definitions for our Astro runtime.
|
||||
"types": ["astro/client"]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,4 +5,5 @@ import preact from '@astrojs/preact';
|
|||
export default defineConfig({
|
||||
// Enable the Preact integration to support Preact JSX components.
|
||||
integrations: [preact()],
|
||||
site: `http://astro.build`,
|
||||
});
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
"preview": "astro preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/preact": "^0.1.3",
|
||||
"astro": "^1.0.0-beta.46",
|
||||
"@astrojs/preact": "^0.5.2",
|
||||
"astro": "^1.0.0-beta.73",
|
||||
"sass": "^1.52.2"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
import '../styles/global.css';
|
||||
import "../styles/global.css";
|
||||
|
||||
export interface Props {
|
||||
title: string;
|
||||
|
@ -19,7 +19,10 @@ const { title, description, image, type, next, prev, canonicalURL } = Astro.prop
|
|||
<title>{title}</title>
|
||||
<meta name="description" content={description} />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Spectral:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Spectral:ital,wght@0,400;0,700;1,400;1,700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<!-- Sitemap -->
|
||||
<link rel="sitemap" href="/sitemap.xml" />
|
||||
<!-- RSS -->
|
||||
|
@ -30,17 +33,17 @@ const { title, description, image, type, next, prev, canonicalURL } = Astro.prop
|
|||
|
||||
<!-- SEO -->
|
||||
<link rel="canonical" href={canonicalURL} />
|
||||
{next && <link rel="next" aria-label="Previous Page" href={new URL(next, canonicalURL).href}>}
|
||||
{prev && <link rel="prev" aria-label="Next Page" href={new URL(prev, canonicalURL).href}>}
|
||||
{next && <link rel="next" aria-label="Previous Page" href={new URL(next, canonicalURL).href} />}
|
||||
{prev && <link rel="prev" aria-label="Next Page" href={new URL(prev, canonicalURL).href} />}
|
||||
|
||||
<!-- OpenGraph -->
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={description} />
|
||||
{image && (<meta property="og:image" content={new URL(image, canonicalURL)}>)}
|
||||
{image && <meta property="og:image" content={new URL(image, canonicalURL)} />}
|
||||
|
||||
<!-- Twitter -->
|
||||
<meta name="twitter:card" content={image ? 'summary_large_image' : 'summary'} />
|
||||
<meta name="twitter:card" content={image ? "summary_large_image" : "summary"} />
|
||||
<meta name="twitter:site" content="@astro" />
|
||||
<meta name="twitter:title" content={title} />
|
||||
<meta name="twitter:description" content={description} />
|
||||
{image && (<meta name="twitter:image" content={image}>)}
|
||||
{image && <meta name="twitter:image" content={image} />}
|
||||
|
|
|
@ -9,8 +9,8 @@ const { prevUrl, nextUrl } = Astro.props;
|
|||
|
||||
<div class="wrapper">
|
||||
<nav class="nav">
|
||||
<a class="prev" href={prevUrl || '#'} aria-label="Previous Page">Prev</a>
|
||||
<a class="next" href={nextUrl || '#'} aria-label="Next Page">Next</a>
|
||||
<a class="prev" href={prevUrl || "#"} aria-label="Previous Page">Prev</a>
|
||||
<a class="next" href={nextUrl || "#"} aria-label="Next Page">Next</a>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
|
@ -29,7 +29,7 @@ const { prevUrl, nextUrl } = Astro.props;
|
|||
text-transform: uppercase;
|
||||
font-size: 0.8em;
|
||||
|
||||
&[href='#'] {
|
||||
&[href="#"] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ const { post, author } = Astro.props;
|
|||
const { frontmatter } = post;
|
||||
|
||||
function formatDate(date) {
|
||||
return new Date(date).toUTCString().replace(/(\d\d\d\d) .*/, '$1'); // remove everything after YYYY
|
||||
return new Date(date).toUTCString().replace(/(\d\d\d\d) .*/, "$1"); // remove everything after YYYY
|
||||
}
|
||||
---
|
||||
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
---
|
||||
import MainHead from '../components/MainHead.astro';
|
||||
import Nav from '../components/Nav.astro';
|
||||
import authorData from '../data/authors.json';
|
||||
import MainHead from "../components/MainHead.astro";
|
||||
import Nav from "../components/Nav.astro";
|
||||
|
||||
const { content } = Astro.props;
|
||||
let canonicalURL = Astro.canonicalURL;
|
||||
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
||||
---
|
||||
|
||||
<html lang={content.lang || 'en'}>
|
||||
<html lang={content.lang || "en"}>
|
||||
<head>
|
||||
<title>{content.title}</title>
|
||||
<MainHead title={content.title} description={content.description} image={content.image} {canonicalURL} />
|
||||
<MainHead
|
||||
title={content.title}
|
||||
description={content.description}
|
||||
image={content.image}
|
||||
{canonicalURL}
|
||||
/>
|
||||
<style lang="scss">
|
||||
.title {
|
||||
margin-top: 4rem;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
---
|
||||
import MainHead from '../components/MainHead.astro';
|
||||
import Nav from '../components/Nav.astro';
|
||||
import MainHead from "../components/MainHead.astro";
|
||||
import Nav from "../components/Nav.astro";
|
||||
|
||||
let title = 'About';
|
||||
let description = 'About page of an example blog on Astro';
|
||||
let canonicalURL = Astro.canonicalURL;
|
||||
let title = "About";
|
||||
let description = "About page of an example blog on Astro";
|
||||
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
|
@ -54,15 +54,19 @@ let canonicalURL = Astro.canonicalURL;
|
|||
</div>
|
||||
<div class="text">
|
||||
<p>
|
||||
The book cover and spine above and the images which follow were not part of the original Ormsby translation—they are taken from the 1880 edition of J. W. Clark,
|
||||
illustrated by Gustave Doré. Clark in his edition states that, “The English text of ‘Don Quixote’ adopted in this edition is that of Jarvis, with occasional corrections
|
||||
from Motteaux.”
|
||||
The book cover and spine above and the images which follow were not part of the original
|
||||
Ormsby translation—they are taken from the 1880 edition of J. W. Clark, illustrated by
|
||||
Gustave Doré. Clark in his edition states that, “The English text of ‘Don Quixote’ adopted
|
||||
in this edition is that of Jarvis, with occasional corrections from Motteaux.”
|
||||
</p>
|
||||
<p>
|
||||
See in the introduction below John Ormsby’s critique of both the Jarvis and Motteaux translations. It has been elected in the present Project Gutenberg edition to attach
|
||||
the famous engravings of Gustave Doré to the Ormsby translation instead of the Jarvis/Motteaux. The detail of many of the Doré engravings can be fully appreciated only by
|
||||
utilizing the “Full Size” button to expand them to their original dimensions. Ormsby in his Preface has criticized the fanciful nature of Doré’s illustrations; others
|
||||
feel these woodcuts and steel engravings well match Quixote’s dreams.
|
||||
See in the introduction below John Ormsby’s critique of both the Jarvis and Motteaux
|
||||
translations. It has been elected in the present Project Gutenberg edition to attach the
|
||||
famous engravings of Gustave Doré to the Ormsby translation instead of the
|
||||
Jarvis/Motteaux. The detail of many of the Doré engravings can be fully appreciated only
|
||||
by utilizing the “Full Size” button to expand them to their original dimensions. Ormsby in
|
||||
his Preface has criticized the fanciful nature of Doré’s illustrations; others feel these
|
||||
woodcuts and steel engravings well match Quixote’s dreams.
|
||||
</p>
|
||||
</div>
|
||||
</main>
|
||||
|
|
|
@ -1,28 +1,36 @@
|
|||
---
|
||||
import MainHead from '../../components/MainHead.astro';
|
||||
import Nav from '../../components/Nav.astro';
|
||||
import PostPreview from '../../components/PostPreview.astro';
|
||||
import authorData from '../../data/authors.json';
|
||||
import MainHead from "../../components/MainHead.astro";
|
||||
import Nav from "../../components/Nav.astro";
|
||||
import PostPreview from "../../components/PostPreview.astro";
|
||||
import authorData from "../../data/authors.json";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const allPosts = await Astro.glob('../post/*.md');
|
||||
const allPosts = await Astro.glob("../post/*.md");
|
||||
let allAuthorsUnique = [...new Set(allPosts.map((p) => p.frontmatter.author))];
|
||||
return allAuthorsUnique.map((author) => ({ params: { author }, props: { allPosts } }));
|
||||
}
|
||||
|
||||
const { allPosts } = Astro.props;
|
||||
const title = 'Don’s Blog';
|
||||
const description = 'An example blog on Astro';
|
||||
const title = "Don’s Blog";
|
||||
const description = "An example blog on Astro";
|
||||
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
||||
|
||||
/** filter posts by author, sort by date */
|
||||
const posts = allPosts.filter((post) => post.frontmatter.author === Astro.params.author).sort((a, b) => new Date(b.frontmatter.date).valueOf() - new Date(a.frontmatter.date).valueOf());
|
||||
const posts = allPosts
|
||||
.filter((post) => post.frontmatter.author === Astro.params.author)
|
||||
.sort((a, b) => new Date(b.frontmatter.date).valueOf() - new Date(a.frontmatter.date).valueOf());
|
||||
const author = authorData[posts[0].frontmatter.author];
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>{title}</title>
|
||||
<MainHead {title} {description} image={posts[0].frontmatter.image} canonicalURL={Astro.canonicalURL.toString()} />
|
||||
<MainHead
|
||||
{title}
|
||||
{description}
|
||||
image={posts[0].frontmatter.image}
|
||||
canonicalURL={canonicalURL.toString()}
|
||||
/>
|
||||
|
||||
<style lang="scss">
|
||||
.title {
|
||||
|
|
|
@ -1,22 +1,24 @@
|
|||
---
|
||||
// Component Imports
|
||||
import MainHead from '../components/MainHead.astro';
|
||||
import Nav from '../components/Nav.astro';
|
||||
import PostPreview from '../components/PostPreview.astro';
|
||||
import Pagination from '../components/Pagination.astro';
|
||||
import authorData from '../data/authors.json';
|
||||
import MainHead from "../components/MainHead.astro";
|
||||
import Nav from "../components/Nav.astro";
|
||||
import PostPreview from "../components/PostPreview.astro";
|
||||
import Pagination from "../components/Pagination.astro";
|
||||
import authorData from "../data/authors.json";
|
||||
|
||||
// Component Script:
|
||||
// You can write any JavaScript/TypeScript that you'd like here.
|
||||
// It will run during the build, but never in the browser.
|
||||
// All variables are available to use in the HTML template below.
|
||||
let title = 'Don’s Blog';
|
||||
let description = 'An example blog on Astro';
|
||||
let canonicalURL = Astro.canonicalURL;
|
||||
let title = "Don’s Blog";
|
||||
let description = "An example blog on Astro";
|
||||
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
||||
|
||||
// Data Fetching: List all Markdown posts in the repo.
|
||||
let allPosts = await Astro.glob('./post/*.md');
|
||||
allPosts.sort((a, b) => new Date(b.frontmatter.date).valueOf() - new Date(a.frontmatter.date).valueOf());
|
||||
let allPosts = await Astro.glob("./post/*.md");
|
||||
allPosts.sort(
|
||||
(a, b) => new Date(b.frontmatter.date).valueOf() - new Date(a.frontmatter.date).valueOf()
|
||||
);
|
||||
let firstPage = allPosts.slice(0, 2);
|
||||
// Full Astro Component Syntax:
|
||||
// https://docs.astro.build/core-concepts/astro-components/
|
||||
|
@ -31,7 +33,9 @@ let firstPage = allPosts.slice(0, 2);
|
|||
<Nav {title} />
|
||||
|
||||
<main class="wrapper">
|
||||
{allPosts.map((post) => <PostPreview post={post} author={authorData[post.frontmatter.author]} />)}
|
||||
{allPosts.map((post) => (
|
||||
<PostPreview post={post} author={authorData[post.frontmatter.author]} />
|
||||
))}
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
---
|
||||
import MainHead from '../../components/MainHead.astro';
|
||||
import Nav from '../../components/Nav.astro';
|
||||
import PostPreview from '../../components/PostPreview.astro';
|
||||
import Pagination from '../../components/Pagination.astro';
|
||||
import authorData from '../../data/authors.json';
|
||||
import MainHead from "../../components/MainHead.astro";
|
||||
import Nav from "../../components/Nav.astro";
|
||||
import PostPreview from "../../components/PostPreview.astro";
|
||||
import Pagination from "../../components/Pagination.astro";
|
||||
import authorData from "../../data/authors.json";
|
||||
|
||||
export async function getStaticPaths({ paginate, rss }) {
|
||||
const allPosts = await Astro.glob('../post/*.md');
|
||||
const sortedPosts = allPosts.sort((a, b) => new Date(b.frontmatter.date).valueOf() - new Date(a.frontmatter.date).valueOf());
|
||||
const allPosts = await Astro.glob("../post/*.md");
|
||||
const sortedPosts = allPosts.sort(
|
||||
(a, b) => new Date(b.frontmatter.date).valueOf() - new Date(a.frontmatter.date).valueOf()
|
||||
);
|
||||
|
||||
// Generate an RSS feed from this collection of posts.
|
||||
// NOTE: This is disabled by default, since it requires `site` to be set in your "astro.config.mjs" file.
|
||||
|
@ -28,16 +30,23 @@ export async function getStaticPaths({ paginate, rss }) {
|
|||
}
|
||||
|
||||
// page
|
||||
const title = 'Don’s Blog';
|
||||
const description = 'An example blog on Astro';
|
||||
const { canonicalURL } = Astro;
|
||||
const title = "Don’s Blog";
|
||||
const description = "An example blog on Astro";
|
||||
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
||||
const { page } = Astro.props;
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>{title}</title>
|
||||
<MainHead {title} {description} image={page.data[0].frontmatter.image} canonicalURL={canonicalURL.toString()} prev={page.url.prev} next={page.url.next} />
|
||||
<MainHead
|
||||
{title}
|
||||
{description}
|
||||
image={page.data[0].frontmatter.image}
|
||||
canonicalURL={canonicalURL.toString()}
|
||||
prev={page.url.prev}
|
||||
next={page.url.next}
|
||||
/>
|
||||
|
||||
<style lang="scss">
|
||||
.title {
|
||||
|
@ -62,7 +71,9 @@ const { page } = Astro.props;
|
|||
<main class="wrapper">
|
||||
<h2 class="title">All Posts</h2>
|
||||
<small class="count">{page.start + 1}–{page.end + 1} of {page.total}</small>
|
||||
{page.data.map((post) => <PostPreview post={post} author={authorData[post.frontmatter.author]} />)}
|
||||
{page.data.map((post) => (
|
||||
<PostPreview post={post} author={authorData[post.frontmatter.author]} />
|
||||
))}
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"resolveJsonModule": true,
|
||||
// Enable stricter transpilation for better output.
|
||||
"isolatedModules": true,
|
||||
// Add type definitions for our Vite runtime.
|
||||
"types": ["vite/client"]
|
||||
// Add type definitions for our Astro runtime.
|
||||
"types": ["astro/client"]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,24 +12,40 @@ Features:
|
|||
|
||||
- ✅ SEO-friendly setup with canonical URLs and OpenGraph data
|
||||
- ✅ Full Markdown support
|
||||
- ✅ RSS 2.0 generation
|
||||
- ✅ Sitemap.xml generation
|
||||
|
||||
## 🚀 Project Structure
|
||||
|
||||
Inside of your Astro project, you'll see the following folders and files:
|
||||
|
||||
```
|
||||
/
|
||||
├── public/
|
||||
│ ├── robots.txt
|
||||
│ └── favicon.ico
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ │ └── Tour.astro
|
||||
│ └── pages/
|
||||
│ └── index.astro
|
||||
└── package.json
|
||||
├── public
|
||||
│ ├── assets
|
||||
│ │ └── blog
|
||||
│ │ └── introducing-astro.jpg
|
||||
│ ├── favicon.ico
|
||||
│ ├── social.jpg
|
||||
│ └── social.png
|
||||
├── src
|
||||
│ ├── components
|
||||
│ │ ├── Author.astro
|
||||
│ │ ├── BaseHead.astro
|
||||
│ │ ├── BlogPostPreview.astro
|
||||
│ │ ├── FollowMe.astro
|
||||
│ │ ├── Header.astro
|
||||
│ │ └── LikeButton.tsx
|
||||
│ ├── layouts
|
||||
│ │ └── BlogPost.astro
|
||||
│ ├── pages
|
||||
│ │ ├── index.astro
|
||||
│ │ └── posts
|
||||
│ │ ├── interactive-content.md
|
||||
│ │ └── static-content.md
|
||||
│ └── styles
|
||||
│ └── blog.css
|
||||
├── astro.config.mjs
|
||||
├── README.md
|
||||
├── 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.
|
||||
|
@ -43,7 +59,7 @@ Any static assets, like images, can be placed in the `public/` directory.
|
|||
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/` |
|
||||
|
|
|
@ -4,4 +4,5 @@ import preact from '@astrojs/preact';
|
|||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [preact()],
|
||||
site: `http://astro.build`,
|
||||
});
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
"preview": "astro preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/preact": "^0.1.3",
|
||||
"astro": "^1.0.0-beta.46"
|
||||
"@astrojs/preact": "^0.5.2",
|
||||
"astro": "^1.0.0-beta.73"
|
||||
},
|
||||
"dependencies": {
|
||||
"preact": "^10.7.3"
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 172 KiB |
|
@ -1,12 +1,13 @@
|
|||
---
|
||||
import '../styles/blog.css';
|
||||
import "../styles/blog.css";
|
||||
|
||||
export interface Props {
|
||||
title: string;
|
||||
description: string;
|
||||
permalink: string;
|
||||
}
|
||||
const { title, description, permalink } = Astro.props;
|
||||
|
||||
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
||||
const { title, description } = Astro.props;
|
||||
---
|
||||
|
||||
<!-- Global Metadata -->
|
||||
|
@ -21,18 +22,21 @@ const { title, description, permalink } = Astro.props;
|
|||
|
||||
<!-- Open Graph / Facebook -->
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content={permalink} />
|
||||
<meta property="og:url" content={canonicalURL} />
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:image" content="https://astro.build/social.png?v=1" />
|
||||
<meta property="og:image" content="https://astro.build/social.png" />
|
||||
|
||||
<!-- Twitter -->
|
||||
<meta property="twitter:card" content="summary_large_image" />
|
||||
<meta property="twitter:url" content={permalink} />
|
||||
<meta property="twitter:url" content={canonicalURL} />
|
||||
<meta property="twitter:title" content={title} />
|
||||
<meta property="twitter:description" content={description} />
|
||||
<meta property="twitter:image" content="https://astro.build/social.png?v=1" />
|
||||
<meta property="twitter:image" content="https://astro.build/social.png" />
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono&family=IBM+Plex+Sans:wght@400;700&display=swap" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono&family=IBM+Plex+Sans:wght@400;700&display=swap"
|
||||
/>
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
<header class="wrapper">
|
||||
<article>
|
||||
<h1>
|
||||
<a href="/">
|
||||
<svg class="logo" width="32" height="32" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
#flame {
|
||||
fill: #ff5d01;
|
||||
}
|
||||
#a {
|
||||
fill: #000014;
|
||||
}
|
||||
</style>
|
||||
<title>Logo</title>
|
||||
<path
|
||||
id="a"
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M163.008 18.929c1.944 2.413 2.935 5.67 4.917 12.181l43.309 142.27a180.277 180.277 0 00-51.778-17.53l-28.198-95.29a3.67 3.67 0 00-7.042.01l-27.857 95.232a180.225 180.225 0 00-52.01 17.557l43.52-142.281c1.99-6.502 2.983-9.752 4.927-12.16a15.999 15.999 0 016.484-4.798c2.872-1.154 6.271-1.154 13.07-1.154h31.085c6.807 0 10.211 0 13.086 1.157a16.004 16.004 0 016.487 4.806z"
|
||||
></path>
|
||||
<path
|
||||
id="flame"
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M168.19 180.151c-7.139 6.105-21.39 10.268-37.804 10.268-20.147 0-37.033-6.272-41.513-14.707-1.602 4.835-1.961 10.367-1.961 13.902 0 0-1.056 17.355 11.015 29.426 0-6.268 5.081-11.349 11.349-11.349 10.743 0 10.731 9.373 10.721 16.977v.679c0 11.542 7.054 21.436 17.086 25.606a23.27 23.27 0 01-2.339-10.2c0-11.008 6.463-15.107 13.974-19.87 5.976-3.79 12.616-8.001 17.192-16.449a31.024 31.024 0 003.743-14.82c0-3.299-.513-6.479-1.463-9.463z"
|
||||
></path>
|
||||
</svg>
|
||||
<span>My Blog</span>
|
||||
</a>
|
||||
</h1>
|
||||
</article>
|
||||
</header>
|
||||
|
||||
<style>
|
||||
header {
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
height: 5rem;
|
||||
}
|
||||
article {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.header-subitem {
|
||||
display: flex;
|
||||
flex-grow: 0;
|
||||
gap: 0.5em;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--theme-text-lighter);
|
||||
font-size: initial;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
.header-subitem:hover {
|
||||
color: var(--theme-accent);
|
||||
}
|
||||
.header-subitem svg {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
}
|
||||
|
||||
@media (max-width: 32em) {
|
||||
.header-subitem {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
font-size: 1.5rem;
|
||||
max-width: 100%;
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.logo {
|
||||
transform: translateY(0.25rem);
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
}
|
||||
|
||||
h1 a {
|
||||
text-decoration: none;
|
||||
display: inline-flex;
|
||||
}
|
||||
</style>
|
|
@ -1,88 +0,0 @@
|
|||
---
|
||||
import Author from './Author.astro';
|
||||
|
||||
export interface Props {
|
||||
title: string;
|
||||
author: string;
|
||||
publishDate: string;
|
||||
heroImage: string;
|
||||
alt: string;
|
||||
}
|
||||
|
||||
const { title, author, publishDate, heroImage, alt } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="layout">
|
||||
<article class="content">
|
||||
<div>
|
||||
<header>
|
||||
{heroImage && <img width="720" height="420" class="hero-image" loading="lazy" src={heroImage} alt={alt} />}
|
||||
<p class="publish-date">{publishDate}</p>
|
||||
<h1 class="title">{title}</h1>
|
||||
<Author name="@FredKSchott" href="https://twitter.com/FredKSchott" />
|
||||
</header>
|
||||
<main>
|
||||
<slot />
|
||||
</main>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.hero-image {
|
||||
width: 100vw;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 4rem;
|
||||
max-width: 1280px;
|
||||
}
|
||||
|
||||
@media (max-width: 50em) {
|
||||
.hero-image {
|
||||
height: 260px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-bottom: 8rem;
|
||||
}
|
||||
|
||||
.content :global(main > * + *) {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.content :global(h2) {
|
||||
margin-top: 4rem;
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
padding-bottom: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
border-bottom: 4px solid var(--theme-divider);
|
||||
}
|
||||
|
||||
.title,
|
||||
.author,
|
||||
.publish-date {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.publish-date,
|
||||
.author {
|
||||
color: var(--theme-text-lighter);
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 2.25rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
</style>
|
|
@ -1,48 +1,36 @@
|
|||
---
|
||||
export interface Props {
|
||||
post: any;
|
||||
title: string;
|
||||
description: string;
|
||||
publishDate: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
const { post } = Astro.props;
|
||||
const { title, description, publishDate, url } = Astro.props as Props;
|
||||
---
|
||||
|
||||
<article class="post-preview">
|
||||
<header>
|
||||
<p class="publish-date">{post.frontmatter.publishDate}</p>
|
||||
<a href={post.url}><h1 class="title">{post.frontmatter.title}</h1></a>
|
||||
<time>{publishDate}</time>
|
||||
<a href={url}><h1 class="title">{title}</h1></a>
|
||||
</header>
|
||||
<p>{post.frontmatter.description}</p>
|
||||
<a href={post.url}>Read more</a>
|
||||
<p>{description}</p>
|
||||
<a href={url}>Read more</a>
|
||||
</article>
|
||||
|
||||
<style>
|
||||
.content :global(main > * + *) {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.post-preview {
|
||||
padding-bottom: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
border-bottom: 4px solid var(--theme-divider);
|
||||
}
|
||||
|
||||
header {
|
||||
align-items: flex-start;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding-bottom: 2rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.title,
|
||||
.author,
|
||||
.publish-date {
|
||||
time {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.publish-date,
|
||||
.author {
|
||||
time {
|
||||
font-size: 1.25rem;
|
||||
color: var(--theme-text-lighter);
|
||||
}
|
||||
|
|
11
examples/blog/src/components/FollowMe.astro
Normal file
11
examples/blog/src/components/FollowMe.astro
Normal file
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
export interface Props {
|
||||
username: string;
|
||||
href: string;
|
||||
}
|
||||
|
||||
const { username, href } = Astro.props as Props;
|
||||
---
|
||||
|
||||
<p>Follow me <a {href} target="_blank" rel="noreferrer">@{username}</a></p>
|
||||
|
57
examples/blog/src/components/Header.astro
Normal file
57
examples/blog/src/components/Header.astro
Normal file
|
@ -0,0 +1,57 @@
|
|||
<header class="wrapper">
|
||||
<nav>
|
||||
<a href="/">
|
||||
<svg
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 256 256"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<style>
|
||||
#flame {
|
||||
fill: #ff5d01;
|
||||
}
|
||||
#a {
|
||||
fill: #000014;
|
||||
}
|
||||
</style>
|
||||
<path
|
||||
id="a"
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M163.008 18.929c1.944 2.413 2.935 5.67 4.917 12.181l43.309 142.27a180.277 180.277 0 00-51.778-17.53l-28.198-95.29a3.67 3.67 0 00-7.042.01l-27.857 95.232a180.225 180.225 0 00-52.01 17.557l43.52-142.281c1.99-6.502 2.983-9.752 4.927-12.16a15.999 15.999 0 016.484-4.798c2.872-1.154 6.271-1.154 13.07-1.154h31.085c6.807 0 10.211 0 13.086 1.157a16.004 16.004 0 016.487 4.806z"
|
||||
></path>
|
||||
<path
|
||||
id="flame"
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M168.19 180.151c-7.139 6.105-21.39 10.268-37.804 10.268-20.147 0-37.033-6.272-41.513-14.707-1.602 4.835-1.961 10.367-1.961 13.902 0 0-1.056 17.355 11.015 29.426 0-6.268 5.081-11.349 11.349-11.349 10.743 0 10.731 9.373 10.721 16.977v.679c0 11.542 7.054 21.436 17.086 25.606a23.27 23.27 0 01-2.339-10.2c0-11.008 6.463-15.107 13.974-19.87 5.976-3.79 12.616-8.001 17.192-16.449a31.024 31.024 0 003.743-14.82c0-3.299-.513-6.479-1.463-9.463z"
|
||||
></path>
|
||||
</svg>
|
||||
<span>My Blog</span>
|
||||
</a>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<style>
|
||||
header {
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
height: 5rem;
|
||||
}
|
||||
nav {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
display: inline-flex;
|
||||
}
|
||||
</style>
|
35
examples/blog/src/components/LikeButton.tsx
Normal file
35
examples/blog/src/components/LikeButton.tsx
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { useState } from 'preact/hooks';
|
||||
|
||||
interface Props {
|
||||
pageUrl: string;
|
||||
}
|
||||
|
||||
export default function LikeButton({ pageUrl }: Props) {
|
||||
const persistedLike = localStorage.getItem(`liked-${pageUrl}`);
|
||||
const [liked, setLiked] = useState(persistedLike ? JSON.parse(persistedLike) : false);
|
||||
|
||||
function toggleLike() {
|
||||
const toggled = !liked;
|
||||
setLiked(toggled);
|
||||
// preserve your likes as you navigate the site
|
||||
localStorage.setItem(`liked-${pageUrl}`, JSON.stringify(toggled));
|
||||
}
|
||||
|
||||
return (
|
||||
<button onClick={toggleLike}>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
{/* fill the heart when liked ♥ */}
|
||||
<path
|
||||
fill={liked ? 'red' : '#ccc'}
|
||||
d="m12 21.35l-1.45-1.32C5.4 15.36 2 12.27 2 8.5C2 5.41 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.08C13.09 3.81 14.76 3 16.5 3C19.58 3 22 5.41 22 8.5c0 3.77-3.4 6.86-8.55 11.53L12 21.35Z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
);
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
<svg class="logo" width="158" height="170" viewBox="0 0 158 170" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M96.5039 9.46441C97.4758 10.671 97.9714 12.2991 98.9626 15.5553L120.617 86.6902C112.611 82.5368 103.907 79.5413 94.7281 77.9252L80.6289 30.2798C80.3982 29.5002 79.6822 28.9654 78.8692 28.9654C78.0541 28.9654 77.3367 29.503 77.1079 30.2853L63.1795 77.9011C53.9579 79.51 45.2146 82.5109 37.1741 86.6793L58.9347 15.5388C59.929 12.2882 60.4262 10.6629 61.3981 9.45854C62.2562 8.39532 63.3723 7.56959 64.64 7.06003C66.076 6.48285 67.7756 6.48285 71.1749 6.48285H86.7174C90.1211 6.48285 91.823 6.48285 93.2603 7.06124C94.5291 7.575 95.6459 8.39925 96.5039 9.46441Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M99.0951 90.0755C95.5253 93.1279 88.4002 95.2097 80.1929 95.2097C70.1197 95.2097 61.6767 92.0737 59.4363 87.8561C58.6354 90.2733 58.4558 93.0397 58.4558 94.8069C58.4558 94.8069 57.9281 103.485 63.9636 109.52C63.9636 106.386 66.5042 103.846 69.6381 103.846C75.0097 103.846 75.0036 108.532 74.9987 112.334C74.9986 112.448 74.9984 112.561 74.9984 112.673C74.9984 118.444 78.5255 123.391 83.5416 125.477C82.7924 123.936 82.3721 122.205 82.3721 120.377C82.3721 114.873 85.6034 112.823 89.3588 110.441C92.3469 108.546 95.6668 106.441 97.9548 102.217C99.1486 100.013 99.8265 97.4893 99.8265 94.8069C99.8265 93.1573 99.5702 91.5676 99.0951 90.0755Z"
|
||||
fill="#FF5D01"
|
||||
/>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M99.0951 90.0755C95.5253 93.1279 88.4002 95.2097 80.1929 95.2097C70.1197 95.2097 61.6767 92.0737 59.4363 87.8561C58.6354 90.2733 58.4558 93.0397 58.4558 94.8069C58.4558 94.8069 57.9281 103.485 63.9636 109.52C63.9636 106.386 66.5042 103.846 69.6381 103.846C75.0097 103.846 75.0036 108.532 74.9987 112.334C74.9986 112.448 74.9984 112.561 74.9984 112.673C74.9984 118.444 78.5255 123.391 83.5416 125.477C82.7924 123.936 82.3721 122.205 82.3721 120.377C82.3721 114.873 85.6034 112.823 89.3588 110.441C92.3469 108.546 95.6668 106.441 97.9548 102.217C99.1486 100.013 99.8265 97.4893 99.8265 94.8069C99.8265 93.1573 99.5702 91.5676 99.0951 90.0755Z"
|
||||
fill="url(#paint1_linear)"
|
||||
/>
|
||||
<path
|
||||
d="M11.9957 169.024C20.0117 169.024 24.8597 167.104 27.6917 163.12C27.6917 164.896 27.7877 166.576 28.0277 168.112H32.7797C32.3477 165.616 32.2517 163.984 32.2517 159.472V153.328C32.2517 146.704 27.1157 143.2 17.3237 143.2C7.8677 143.2 1.7237 146.848 0.955701 152.128H5.9957C6.7637 148.576 10.7477 146.704 17.3237 146.704C23.8037 146.704 27.6437 148.96 27.6437 152.8V153.28L12.6677 154.144C6.5717 154.48 4.3157 155.344 2.5877 156.592C0.955701 157.792 0.0437012 159.664 0.0437012 161.824C0.0437012 166.384 4.7477 169.024 11.9957 169.024ZM13.5317 165.616C7.9637 165.616 4.8917 164.32 4.8917 161.728C4.8917 158.944 6.8117 157.696 13.5797 157.264L27.6437 156.4V157.504C27.6437 162.544 21.7397 165.616 13.5317 165.616Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M55.9352 169.024C65.8712 169.024 69.8552 165.76 69.8552 161.008C69.8552 157.072 67.4072 155.056 61.1672 154.528L49.5032 153.616C46.3352 153.376 44.5592 152.464 44.5592 150.496C44.5592 148 47.2952 146.704 53.1992 146.704C59.9192 146.704 63.4232 148.048 65.7272 151.024L69.6152 149.152C67.2152 145.408 61.8872 143.2 53.6312 143.2C45.1352 143.2 40.0472 146.032 40.0472 150.688C40.0472 154.864 43.0712 156.88 48.7832 157.36L60.3512 158.272C64.1432 158.56 65.2952 159.328 65.2952 161.296C65.2952 164.128 62.3672 165.472 56.5592 165.472C49.5032 165.472 45.0392 163.552 42.8792 160.048L39.0872 162.112C42.0152 166.528 47.1512 169.024 55.9352 169.024Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M79.6765 147.712V159.28C79.6765 164.032 81.3085 168.784 90.1885 168.784C92.4445 168.784 95.1805 168.352 96.3805 167.824V163.936C94.7005 164.32 92.6845 164.608 90.7165 164.608C86.5405 164.608 84.2845 162.976 84.2845 158.848V147.712H96.2845V144.112H84.2845V136L79.6765 137.872V144.112H72.1404V147.712H79.6765Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M107.728 144.112H103.504V168.112H108.064V159.136C108.064 155.68 108.736 152.752 110.656 150.736C112.336 148.864 114.496 147.808 118.288 147.808C119.584 147.808 120.4 147.904 121.504 148.096V143.68C120.496 143.44 119.632 143.392 118.336 143.392C113.2 143.392 109.12 146.416 107.728 151.072V144.112Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M140.724 169.024C150.948 169.024 157.956 163.84 157.956 156.112C157.956 148.384 150.948 143.2 140.724 143.2C130.5 143.2 123.492 148.384 123.492 156.112C123.492 163.84 130.5 169.024 140.724 169.024ZM140.724 165.232C133.188 165.232 128.34 161.68 128.34 156.112C128.34 150.544 133.188 146.992 140.724 146.992C148.212 146.992 153.108 150.544 153.108 156.112C153.108 161.68 148.212 165.232 140.724 165.232Z"
|
||||
fill="white"
|
||||
/>
|
||||
<defs>
|
||||
<linearGradient id="paint1_linear" x1="115.168" y1="65.245" x2="94.0326" y2="109.491" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FF1639" />
|
||||
<stop offset="1" stop-color="#FF1639" stop-opacity="0" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
<style lang="scss">
|
||||
.logo {
|
||||
margin: 2rem auto;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-family: var(--font-sans);
|
||||
font-size: 1rem;
|
||||
}
|
||||
.title svg {
|
||||
margin-right: -100%;
|
||||
}
|
||||
.title svg text {
|
||||
font-size: 16px;
|
||||
font-family: var(--font-sans);
|
||||
}
|
||||
.title svg text.span {
|
||||
fill: white;
|
||||
font-size: 16.2px;
|
||||
transform: translate(0, 18px);
|
||||
}
|
||||
.title svg text.em {
|
||||
fill: var(--color-green);
|
||||
transform: translate(0, 36px);
|
||||
}
|
||||
|
||||
@media (min-width: 40em) {
|
||||
.title svg {
|
||||
margin-right: 0;
|
||||
margin-bottom: -40px;
|
||||
}
|
||||
.title svg text.span {
|
||||
font-size: 16px;
|
||||
}
|
||||
.title svg text.em {
|
||||
transform: translate(190px, 18px);
|
||||
}
|
||||
}
|
||||
</style>
|
Before Width: | Height: | Size: 5.5 KiB |
|
@ -1,25 +1,102 @@
|
|||
---
|
||||
import BaseHead from '../components/BaseHead.astro';
|
||||
import BlogHeader from '../components/BlogHeader.astro';
|
||||
import BlogPost from '../components/BlogPost.astro';
|
||||
import BaseHead from "../components/BaseHead.astro";
|
||||
import Header from "../components/Header.astro";
|
||||
|
||||
export interface Props {
|
||||
content: {
|
||||
title: string;
|
||||
description: string;
|
||||
publishDate: string;
|
||||
heroImage?: {
|
||||
src: string;
|
||||
alt: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
const { content } = Astro.props;
|
||||
const { title, description, publishDate, author, heroImage, permalink, alt } = content;
|
||||
const {
|
||||
content: { title, description, publishDate, heroImage },
|
||||
} = Astro.props as Props;
|
||||
---
|
||||
|
||||
<html lang={content.lang || 'en'}>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prism-themes@1.9.0/themes/prism-lucario.css"/>
|
||||
<BaseHead {title} {description} {permalink} />
|
||||
<BaseHead title={title} description={description} />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<BlogHeader />
|
||||
<div class="wrapper">
|
||||
<BlogPost {title} {author} {heroImage} {publishDate} {alt}>
|
||||
<slot />
|
||||
</BlogPost>
|
||||
</div>
|
||||
<Header />
|
||||
<article class="wrapper content">
|
||||
<header>
|
||||
{heroImage && (
|
||||
<img
|
||||
width="720"
|
||||
height="420"
|
||||
loading="lazy"
|
||||
src={heroImage.src}
|
||||
alt={heroImage.alt}
|
||||
/>
|
||||
)}
|
||||
<h1 class="title">{title}</h1>
|
||||
<time>{publishDate}</time>
|
||||
</header>
|
||||
<main>
|
||||
<slot></slot>
|
||||
</main>
|
||||
</article>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style>
|
||||
img {
|
||||
width: 100vw;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 4rem;
|
||||
max-width: 1280px;
|
||||
}
|
||||
|
||||
@media (max-width: 50em) {
|
||||
img {
|
||||
height: 260px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-bottom: 8rem;
|
||||
}
|
||||
|
||||
.content :global(h2) {
|
||||
margin-top: 4rem;
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
|
||||
padding-bottom: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
border-bottom: 4px solid var(--theme-divider);
|
||||
}
|
||||
|
||||
.title,
|
||||
time {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
time {
|
||||
color: var(--theme-text-lighter);
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 2.25rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,78 +1,62 @@
|
|||
---
|
||||
// Component Imports
|
||||
import BaseHead from '../components/BaseHead.astro';
|
||||
import BlogHeader from '../components/BlogHeader.astro';
|
||||
import BlogPostPreview from '../components/BlogPostPreview.astro';
|
||||
import BaseHead from "../components/BaseHead.astro";
|
||||
import Header from "../components/Header.astro";
|
||||
import BlogPostPreview from "../components/BlogPostPreview.astro";
|
||||
|
||||
// Component Script:
|
||||
// You can write any JavaScript/TypeScript that you'd like here.
|
||||
// It will run during the build, but never in the browser.
|
||||
// All variables are available to use in the HTML template below.
|
||||
let title = 'Example Blog';
|
||||
let description = 'The perfect starter for your perfect blog.';
|
||||
let permalink = 'https://example.com/';
|
||||
let title = "Example Blog";
|
||||
let description = "The perfect starter for your perfect blog.";
|
||||
|
||||
// Data Fetching: List all Markdown posts in the repo.
|
||||
|
||||
let allPosts = await Astro.glob('./posts/*.md');
|
||||
allPosts = allPosts.sort((a, b) => new Date(b.frontmatter.publishDate).valueOf() - new Date(a.frontmatter.publishDate).valueOf());
|
||||
|
||||
// Full Astro Component Syntax:
|
||||
// https://docs.astro.build/core-concepts/astro-components/
|
||||
// Use Astro.glob to fetch all post with associated frontmatter
|
||||
const unsortedPosts = await Astro.glob("./posts/*.md");
|
||||
const posts = unsortedPosts.sort(function (a, b) {
|
||||
return (
|
||||
new Date(b.frontmatter.publishDate).valueOf() - new Date(a.frontmatter.publishDate).valueOf()
|
||||
);
|
||||
});
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<BaseHead {title} {description} {permalink} />
|
||||
|
||||
<style>
|
||||
header {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: var(--theme-bg-offset);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: 4rem;
|
||||
margin-bottom: 8rem;
|
||||
}
|
||||
|
||||
.content :global(main > * + *) {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.intro {
|
||||
padding-bottom: 4rem;
|
||||
margin-bottom: 2rem;
|
||||
border-bottom: 4px solid var(--theme-divider);
|
||||
}
|
||||
|
||||
.intro > * {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.latest {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
</style>
|
||||
<BaseHead title={title} description={description} />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<BlogHeader />
|
||||
<Header />
|
||||
<div class="wrapper">
|
||||
<main class="content">
|
||||
<section class="intro">
|
||||
<h1 class="latest">{title}</h1>
|
||||
<h1>{title}</h1>
|
||||
<p>{description}</p>
|
||||
</section>
|
||||
<section aria-label="Blog post list">
|
||||
{allPosts.map((p) => <BlogPostPreview post={p} />)}
|
||||
{posts.map(({ url, frontmatter }) => (
|
||||
<BlogPostPreview
|
||||
title={frontmatter.title}
|
||||
description={frontmatter.description}
|
||||
publishDate={frontmatter.publishDate}
|
||||
url={url}
|
||||
/>
|
||||
))}
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style>
|
||||
.content {
|
||||
margin-top: 4rem;
|
||||
margin-bottom: 8rem;
|
||||
}
|
||||
|
||||
.intro {
|
||||
padding-bottom: 4rem;
|
||||
margin-bottom: 2rem;
|
||||
border-bottom: 4px solid var(--theme-divider);
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
---
|
||||
setup: |
|
||||
import Layout from '../../layouts/BlogPost.astro'
|
||||
import Cool from '../../components/Author.astro'
|
||||
title: Hello world!
|
||||
publishDate: 12 Sep 2021
|
||||
name: Nate Moore
|
||||
value: 128
|
||||
description: Just a Hello World Post!
|
||||
---
|
||||
|
||||
<Cool name={frontmatter.name} href="https://twitter.com/n_moore" client:load />
|
||||
|
||||
This is so cool!
|
||||
|
||||
Do variables work {frontmatter.value * 2}?
|
||||
|
||||
```javascript
|
||||
// Example JavaScript
|
||||
|
||||
const x = 7;
|
||||
function returnSeven() {
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
22
examples/blog/src/pages/posts/interactive-content.md
Normal file
22
examples/blog/src/pages/posts/interactive-content.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
layout: "../../layouts/BlogPost.astro"
|
||||
title: "Hello galaxy of possibilities!"
|
||||
description: "Take your blog to astronomical heights"
|
||||
publishDate: "12 Sep 2021"
|
||||
followMe:
|
||||
username: "bholmesdev"
|
||||
href: "https://twitter.com/bholmesdev"
|
||||
halfTheMeaning: 21
|
||||
heroImage:
|
||||
src: "/assets/blog/introducing-astro.jpg"
|
||||
alt: "Space shuttle leaving curved trail in the sky"
|
||||
setup: |
|
||||
import LikeButton from "../../components/LikeButton"
|
||||
import FollowMe from "../../components/FollowMe.astro"
|
||||
---
|
||||
|
||||
<FollowMe username={frontmatter.followMe.username} href={frontmatter.followMe.href} />
|
||||
|
||||
Access all exported properties with JSX expressions. For example, let's find the meaning of life: **{frontmatter.halfTheMeaning * 2}**
|
||||
|
||||
If this seems cool, consider giving my post a like with this Preact component: <LikeButton pageUrl={frontmatter.url} client:load />
|
28
examples/blog/src/pages/posts/static-content.md
Normal file
28
examples/blog/src/pages/posts/static-content.md
Normal file
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
layout: "../../layouts/BlogPost.astro"
|
||||
title: "Hello static content!"
|
||||
description: "Bring your markdown, we'll handle the rest"
|
||||
publishDate: "11 Jul 2022"
|
||||
heroImage:
|
||||
src: "/assets/blog/introducing-astro.jpg"
|
||||
alt: "Space shuttle leaving curved trail in the sky"
|
||||
---
|
||||
|
||||
**Astro has built-in support for markdown pages!** All frontmatter data will be available [via `Astro.glob` imports](https://docs.astro.build/en/reference/api-reference/#astroglob) as well, making blog landing pages easy to build.
|
||||
|
||||
**Code challenge:** Try editing the `title` frontmatter property for this post and [visiting the homepage](/) again.
|
||||
|
||||
## Code block demo
|
||||
|
||||
```typescript
|
||||
// Oh, and get Shiki syntax highlighting out-of-the-box!
|
||||
// See our docs for customization options:
|
||||
// https://docs.astro.build/en/guides/markdown-content/#syntax-highlighting
|
||||
function getDistance(amount: number) {
|
||||
if (amount === Infinity) {
|
||||
return "and beyond!";
|
||||
} else {
|
||||
return "and the normal distance!";
|
||||
}
|
||||
}
|
||||
```
|
|
@ -32,6 +32,8 @@
|
|||
--color-red-rgb: 255, 22, 57;
|
||||
--color-yellow: #ffbe2d;
|
||||
--color-yellow-rgb: 255, 190, 45;
|
||||
|
||||
--content-max-width: 70ch;
|
||||
}
|
||||
|
||||
:root {
|
||||
|
@ -77,7 +79,6 @@ body {
|
|||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
:root {
|
||||
|
@ -101,7 +102,7 @@ body {
|
|||
.wrapper {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 65em;
|
||||
max-width: var(--content-max-width);
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
width: 100%;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"resolveJsonModule": true,
|
||||
// Enable stricter transpilation for better output.
|
||||
"isolatedModules": true,
|
||||
// Add type definitions for our Vite runtime.
|
||||
"types": ["vite/client"]
|
||||
// Add type definitions for our Astro runtime.
|
||||
"types": ["astro/client"]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({});
|
||||
export default defineConfig({
|
||||
vite: {
|
||||
ssr: {
|
||||
noExternal: ['@example/my-component'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -10,6 +10,6 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@example/my-component": "workspace:*",
|
||||
"astro": "^1.0.0-beta.46"
|
||||
"astro": "^1.0.0-beta.73"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
import * as Component from '@example/my-component';
|
||||
import * as Component from "@example/my-component";
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
"serve": "astro --root demo preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"astro": "^1.0.0-beta.46"
|
||||
"astro": "^1.0.0-beta.73"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ const { type, ...props } = {
|
|||
...Astro.props,
|
||||
} as Props;
|
||||
|
||||
props.type = type || 'button';
|
||||
props.type = type || "button";
|
||||
---
|
||||
|
||||
<button {...props}><slot /></button>
|
||||
|
|
|
@ -8,8 +8,8 @@ const { level, role, ...props } = {
|
|||
...Astro.props,
|
||||
} as Props;
|
||||
|
||||
props.role = role || 'heading';
|
||||
props['aria-level'] = level || '1';
|
||||
props.role = role || "heading";
|
||||
props["aria-level"] = level || "1";
|
||||
---
|
||||
|
||||
<h {...props}><slot /></h>
|
||||
|
|
|
@ -10,4 +10,5 @@ export default defineConfig({
|
|||
// Enable React for the Algolia search component.
|
||||
react(),
|
||||
],
|
||||
site: `http://astro.build`,
|
||||
});
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
"@docsearch/react": "^3.1.0",
|
||||
"@types/react": "^17.0.45",
|
||||
"preact": "^10.7.3",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/preact": "^0.1.3",
|
||||
"@astrojs/react": "^0.1.3",
|
||||
"astro": "^1.0.0-beta.46"
|
||||
"@astrojs/preact": "^0.5.2",
|
||||
"@astrojs/react": "^0.4.2",
|
||||
"astro": "^1.0.0-beta.73"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
// fetch all commits for just this page's path
|
||||
const path = 'docs/' + Astro.props.path;
|
||||
const path = "docs/" + Astro.props.path;
|
||||
const url = `https://api.github.com/repos/withastro/astro/commits?path=${path}`;
|
||||
const commitsURL = `https://github.com/withastro/astro/commits/main/${path}`;
|
||||
|
||||
|
@ -8,16 +8,18 @@ async function getCommits(url) {
|
|||
try {
|
||||
const token = import.meta.env.SNOWPACK_PUBLIC_GITHUB_TOKEN;
|
||||
if (!token) {
|
||||
throw new Error('Cannot find "SNOWPACK_PUBLIC_GITHUB_TOKEN" used for escaping rate-limiting.');
|
||||
throw new Error(
|
||||
'Cannot find "SNOWPACK_PUBLIC_GITHUB_TOKEN" used for escaping rate-limiting.'
|
||||
);
|
||||
}
|
||||
|
||||
const auth = `Basic ${Buffer.from(token, 'binary').toString('base64')}`;
|
||||
const auth = `Basic ${Buffer.from(token, "binary").toString("base64")}`;
|
||||
|
||||
const res = await fetch(url, {
|
||||
method: 'GET',
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: auth,
|
||||
'User-Agent': 'astro-docs/1.0',
|
||||
"User-Agent": "astro-docs/1.0",
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -65,14 +67,22 @@ const additionalContributors = unique.length - recentContributors.length; // lis
|
|||
{recentContributors.map((item) => (
|
||||
<li>
|
||||
<a href={`https://github.com/${item.login}`}>
|
||||
<img alt={`Contributor ${item.login}`} title={`Contributor ${item.login}`} width="64" height="64" src={`https://avatars.githubusercontent.com/u/${item.id}`} />
|
||||
<img
|
||||
alt={`Contributor ${item.login}`}
|
||||
title={`Contributor ${item.login}`}
|
||||
width="64"
|
||||
height="64"
|
||||
src={`https://avatars.githubusercontent.com/u/${item.id}`}
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
{additionalContributors > 0 && (
|
||||
<span>
|
||||
<a href={commitsURL}>{`and ${additionalContributors} additional contributor${additionalContributors > 1 ? 's' : ''}.`}</a>
|
||||
<a href={commitsURL}>{`and ${additionalContributors} additional contributor${
|
||||
additionalContributors > 1 ? "s" : ""
|
||||
}.`}</a>
|
||||
</span>
|
||||
)}
|
||||
{unique.length === 0 && <a href={commitsURL}>Contributors</a>}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
import AvatarList from './AvatarList.astro';
|
||||
import AvatarList from "./AvatarList.astro";
|
||||
const { path } = Astro.props;
|
||||
---
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
import '../styles/theme.css';
|
||||
import '../styles/index.css';
|
||||
import "../styles/theme.css";
|
||||
import "../styles/index.css";
|
||||
---
|
||||
|
||||
<!-- Global Metadata -->
|
||||
|
@ -15,19 +15,24 @@ import '../styles/index.css';
|
|||
<!-- Preload Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital@0;1&display=swap" rel="stylesheet" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital@0;1&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<!-- Scrollable a11y code helper -->
|
||||
<script src="/make-scrollable-code-focusable.js" is:inline></script>
|
||||
<script src="/make-scrollable-code-focusable.js" is:inline>
|
||||
|
||||
</script>
|
||||
|
||||
<!-- This is intentionally inlined to avoid FOUC -->
|
||||
<script is:inline>
|
||||
const root = document.documentElement;
|
||||
const theme = localStorage.getItem('theme');
|
||||
if (theme === 'dark' || (!theme && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||
root.classList.add('theme-dark');
|
||||
const theme = localStorage.getItem("theme");
|
||||
if (theme === "dark" || (!theme && window.matchMedia("(prefers-color-scheme: dark)").matches)) {
|
||||
root.classList.add("theme-dark");
|
||||
} else {
|
||||
root.classList.remove('theme-dark');
|
||||
root.classList.remove("theme-dark");
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
---
|
||||
import { SITE, OPEN_GRAPH } from '../config.ts';
|
||||
import { SITE, OPEN_GRAPH } from "../config.ts";
|
||||
export interface Props {
|
||||
content: any;
|
||||
site: any;
|
||||
canonicalURL: URL | string;
|
||||
}
|
||||
const { content = {}, canonicalURL } = Astro.props;
|
||||
|
||||
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
||||
const { content = {} } = Astro.props;
|
||||
const formattedContentTitle = content.title ? `${content.title} 🚀 ${SITE.title}` : SITE.title;
|
||||
const imageSrc = content?.image?.src ?? OPEN_GRAPH.image.src;
|
||||
const canonicalImageSrc = new URL(imageSrc, Astro.site);
|
||||
|
@ -22,14 +24,21 @@ const imageAlt = content?.image?.alt ?? OPEN_GRAPH.image.alt;
|
|||
<meta property="og:locale" content={content.ogLocale ?? SITE.defaultLanguage} />
|
||||
<meta property="og:image" content={canonicalImageSrc} />
|
||||
<meta property="og:image:alt" content={imageAlt} />
|
||||
<meta name="description" property="og:description" content={content.description ? content.description : SITE.description} />
|
||||
<meta
|
||||
name="description"
|
||||
property="og:description"
|
||||
content={content.description ? content.description : SITE.description}
|
||||
/>
|
||||
<meta property="og:site_name" content={SITE.title} />
|
||||
|
||||
<!-- Twitter Tags -->
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content={OPEN_GRAPH.twitter} />
|
||||
<meta name="twitter:title" content={formattedContentTitle} />
|
||||
<meta name="twitter:description" content={content.description ? content.description : SITE.description} />
|
||||
<meta
|
||||
name="twitter:description"
|
||||
content={content.description ? content.description : SITE.description}
|
||||
/>
|
||||
<meta name="twitter:image" content={canonicalImageSrc} />
|
||||
<meta name="twitter:image:alt" content={imageAlt} />
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue