chore: set up prettier & format code

This commit is contained in:
Ayo Ayco 2024-12-26 00:40:32 +01:00
parent e174121ab3
commit 75b29eddc5
17 changed files with 379 additions and 290 deletions

7
.prettierignore Normal file
View file

@ -0,0 +1,7 @@
# someday let's think about formatting html
**/*.html
**/*.md
**/*.css
**/*.yml
**/*.yaml

View file

@ -3,12 +3,12 @@
* @author Ayo Ayco <https://ayo.ayco.io>
*/
import { readFile, writeFile, readdir, unlink } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import { resolve, dirname, join } from 'node:path';
import { build } from 'esbuild';
import { readFile, writeFile, readdir, unlink } from 'node:fs/promises'
import { fileURLToPath } from 'node:url'
import { resolve, dirname, join } from 'node:path'
import { build } from 'esbuild'
const ASTROSW = '@ayco/astro-sw';
const ASTROSW = '@ayco/astro-sw'
/**
* @typedef {import('astro').AstroIntegration} AstroIntegration
* @typedef {import('esbuild').BuildOptions} BuildOptions
@ -41,36 +41,36 @@ const ASTROSW = '@ayco/astro-sw';
* waitFn: () => void,
* }
* }
* }} options
* }} options
* @returns {AstroIntegration}
*/
export default function serviceWorker(options) {
let {
assetCachePrefix = ASTROSW,
assetCacheVersionID = '0',
path: serviceWorkerPath = undefined,
customRoutes = [],
excludeRoutes = [],
logAssets = false,
esbuild = {},
registrationHooks = {}
} = options || {};
let {
assetCachePrefix = ASTROSW,
assetCacheVersionID = '0',
path: serviceWorkerPath = undefined,
customRoutes = [],
excludeRoutes = [],
logAssets = false,
esbuild = {},
registrationHooks = {},
} = options || {}
const {
installing: installingFn = () => { },
waiting: waitingFn = () => { },
active: activeFn = () => { },
error: errorFn = () => { },
unsupported: unsupportedFn = () => { },
afterRegistration: afterRegistrationFn = () => { },
} = registrationHooks;
const {
installing: installingFn = () => {},
waiting: waitingFn = () => {},
active: activeFn = () => {},
error: errorFn = () => {},
unsupported: unsupportedFn = () => {},
afterRegistration: afterRegistrationFn = () => {},
} = registrationHooks
/**
* @type {Array<string>}
*/
let assets = [];
/**
* @type {Array<string>}
*/
let assets = []
const registrationScript = `const registerSW = async () => {
const registrationScript = `const registerSW = async () => {
if ("serviceWorker" in navigator) {
try {
const registration = await navigator.serviceWorker.register("/sw.js", {
@ -95,145 +95,161 @@ export default function serviceWorker(options) {
registerSW();`
let output = 'static';
const __dirname = resolve(dirname('.'));
let output = 'static'
const __dirname = resolve(dirname('.'))
return {
'name': ASTROSW,
'hooks': {
'astro:config:setup': async ({ injectScript, config: _config, command, logger }) => {
return {
name: ASTROSW,
hooks: {
'astro:config:setup': async ({
injectScript,
config: _config,
command,
logger,
}) => {
if (!serviceWorkerPath || serviceWorkerPath === '') {
// REQUIRED OPTION IS MISSING
logger.error('Missing required path to service worker script')
}
// const transformedScript=await transform(registrationScript)
if (!serviceWorkerPath || serviceWorkerPath === '') {
// REQUIRED OPTION IS MISSING
logger.error('Missing required path to service worker script');
}
// const transformedScript=await transform(registrationScript)
output = _config.output;
if (command === 'build') {
injectScript('page', registrationScript);
}
},
'astro:config:done': async ({ injectTypes, logger }) => {
let injectedTypes = `
output = _config.output
if (command === 'build') {
injectScript('page', registrationScript)
}
},
'astro:config:done': async ({ injectTypes, logger }) => {
let injectedTypes = `
declare const __assets: string[];
declare const __version: string;
declare const __prefix: string;`
injectTypes({ filename: 'caching.d.ts', content: injectedTypes })
},
'astro:build:ssr': ({ manifest }) => {
assets = manifest.assets
},
'astro:build:done': async ({ dir, routes, pages, logger }) => {
const outfile = fileURLToPath(new URL('./sw.js', dir));
const swPath = (serviceWorkerPath && serviceWorkerPath !== '')
? join(__dirname, serviceWorkerPath)
: undefined;
let originalScript;
injectTypes({ filename: 'caching.d.ts', content: injectedTypes })
},
'astro:build:ssr': ({ manifest }) => {
assets = manifest.assets
},
'astro:build:done': async ({ dir, routes, pages, logger }) => {
const outfile = fileURLToPath(new URL('./sw.js', dir))
const swPath =
serviceWorkerPath && serviceWorkerPath !== ''
? join(__dirname, serviceWorkerPath)
: undefined
let originalScript
const _publicFiles = (await readdir(dir, { withFileTypes: true }) ?? [])
.filter(dirent => dirent.isFile())
.map(dirent => `/${dirent.name}`);
const _publicFiles = (
(await readdir(dir, { withFileTypes: true })) ?? []
)
.filter((dirent) => dirent.isFile())
.map((dirent) => `/${dirent.name}`)
const _routes = routes
.filter(({ isIndex }) => isIndex)
.flatMap(({ pathname }) => pathname === '/' ? pathname : [pathname, `${pathname}/`])
.filter(pathname => pathname !== '')
?? [];
const _routes =
routes
.filter(({ isIndex }) => isIndex)
.flatMap(({ pathname }) =>
pathname === '/' ? pathname : [pathname, `${pathname}/`]
)
.filter((pathname) => pathname !== '') ?? []
const _pages = pages
.filter(({ pathname }) => pathname !== '')
.map(({ pathname }) => `/${pathname}`)
?? [];
const _pages =
pages
.filter(({ pathname }) => pathname !== '')
.map(({ pathname }) => `/${pathname}`) ?? []
const _pagesWithoutEndSlash = pages
.filter(({ pathname }) => pathname !== '')
.map(({ pathname }) => {
const lastChar = pathname.slice(-1);
const len = pathname.length;
return lastChar === '/'
? `/${pathname.slice(0, len - 1)}`
: `/${pathname}`;
})
.filter(pathname => pathname !== '')
?? [];
const _pagesWithoutEndSlash =
pages
.filter(({ pathname }) => pathname !== '')
.map(({ pathname }) => {
const lastChar = pathname.slice(-1)
const len = pathname.length
return lastChar === '/'
? `/${pathname.slice(0, len - 1)}`
: `/${pathname}`
})
.filter((pathname) => pathname !== '') ?? []
const _excludeRoutes = [
...excludeRoutes,
...excludeRoutes.map(route => `${route}/`)
];
const _excludeRoutes = [
...excludeRoutes,
...excludeRoutes.map((route) => `${route}/`),
]
assets = [...new Set([
...assets,
..._routes,
..._pages,
..._pagesWithoutEndSlash,
...customRoutes,
..._publicFiles
])].filter(asset => !!asset
&& asset !== ''
&& !asset.includes('404')
&& !asset.includes('index.html')
&& !_excludeRoutes.includes(asset)
);
assets = [
...new Set([
...assets,
..._routes,
..._pages,
..._pagesWithoutEndSlash,
...customRoutes,
..._publicFiles,
]),
].filter(
(asset) =>
!!asset &&
asset !== '' &&
!asset.includes('404') &&
!asset.includes('index.html') &&
!_excludeRoutes.includes(asset)
)
if (logAssets) {
logger.info(
`${assets.length} assets for caching: \n${assets.toString().replaceAll(',', '\n ▶ ')}\n`
)
} else {
logger.info(`${assets.length} assets for caching.`)
}
if (logAssets) {
logger.info(`${assets.length} assets for caching: \n${assets.toString().replaceAll(',', '\n ▶ ')}\n`);
} else {
logger.info(`${assets.length} assets for caching.`);
}
try {
logger.info(`Using service worker in path: ${swPath}`);
originalScript = await readFile(swPath);
} catch {
logger.error(`Service worker script not found! ${swPath}`)
if (!swPath) {
logger.error(`
try {
logger.info(`Using service worker in path: ${swPath}`)
originalScript = await readFile(swPath)
} catch {
logger.error(`Service worker script not found! ${swPath}`)
if (!swPath) {
logger.error(`
[${ASTROSW}] ERR: The 'path' option is required!
[${ASTROSW}] INFO: Please see service worker options in https://ayco.io/gh/astro-sw#readme
`);
}
}
const assetsDeclaration = `const __assets = ${JSON.stringify(assets)};\n`;
const versionDeclaration = `const __version = ${JSON.stringify(assetCacheVersionID)};\n`;
const prefixDeclaration = `const __prefix = ${JSON.stringify(assetCachePrefix)};\n`;
const tempFile = `${swPath}.tmp.ts`;
try {
await writeFile(
tempFile,
assetsDeclaration + versionDeclaration + prefixDeclaration + originalScript,
{ flag: 'w+' }
);
} catch (err) {
logger.error(err.toString())
}
try {
await build({
bundle: true,
...esbuild,
outfile,
platform: 'browser',
entryPoints: [tempFile],
})
} catch (err) {
logger.error(err.toString())
}
// remove temp file
try {
await unlink(tempFile);
} catch (err) {
logger.error(err.toString())
}
}
`)
}
}
}
};
const assetsDeclaration = `const __assets = ${JSON.stringify(assets)};\n`
const versionDeclaration = `const __version = ${JSON.stringify(assetCacheVersionID)};\n`
const prefixDeclaration = `const __prefix = ${JSON.stringify(assetCachePrefix)};\n`
const tempFile = `${swPath}.tmp.ts`
try {
await writeFile(
tempFile,
assetsDeclaration +
versionDeclaration +
prefixDeclaration +
originalScript,
{ flag: 'w+' }
)
} catch (err) {
logger.error(err.toString())
}
try {
await build({
bundle: true,
...esbuild,
outfile,
platform: 'browser',
entryPoints: [tempFile],
})
} catch (err) {
logger.error(err.toString())
}
// remove temp file
try {
await unlink(tempFile)
} catch (err) {
logger.error(err.toString())
}
},
},
}
}

View file

@ -1,13 +1,13 @@
// @ts-check
import { defineConfig } from "astro/config";
import node from "@astrojs/node";
import serviceWorker from "./astro-sw.js";
import { defineConfig } from 'astro/config'
import node from '@astrojs/node'
import serviceWorker from './astro-sw.js'
export default defineConfig({
output: "hybrid",
output: 'hybrid',
adapter: node({
mode: "middleware"
mode: 'middleware',
}),
site: 'https://ayo.ayco.io',
integrations: [
@ -16,23 +16,21 @@ export default defineConfig({
customRoutes: [
// '/threads'
],
excludeRoutes: [
'/exclude'
],
excludeRoutes: ['/exclude'],
logAssets: true,
esbuild: {
minify: true
minify: true,
},
registrationHooks: {
installing: () => console.log('>>> installing...'),
waiting: () => console.log('>>> waiting...'),
active: () => console.log('>>> active...'),
error: (error) => console.error('>>> error', error),
'afterRegistration': async () => {
const sw = await navigator.serviceWorker.getRegistration();
console.log('>>> registrered', sw)
}
afterRegistration: async () => {
const sw = await navigator.serviceWorker.getRegistration()
console.log('>>> registrered', sw)
},
},
})
]
});
}),
],
})

View file

@ -2,4 +2,4 @@ export default {
__prefix: false,
__version: false,
__assets: false,
};
}

View file

@ -25,7 +25,8 @@
"build": "astro build",
"build:preview:static": "astro build && astro preview",
"build:preview": "astro build && node ./server.mjs",
"test": "echo \"Error: no test specified\" && exit 1"
"test": "echo \"Error: no test specified\" && exit 1",
"format": "prettier . --write"
},
"keywords": [
"withastro",
@ -38,7 +39,9 @@
"@fastify/middie": "^8.3.1",
"@fastify/static": "^7.0.4",
"astro": "^4.15.2",
"fastify": "^4.28.1"
"fastify": "^4.28.1",
"prettier": "^3.4.2",
"prettier-plugin-astro": "^0.14.1"
},
"dependencies": {
"esbuild": "^0.23.1"

View file

@ -27,6 +27,12 @@ importers:
fastify:
specifier: ^4.28.1
version: 4.28.1
prettier:
specifier: ^3.4.2
version: 3.4.2
prettier-plugin-astro:
specifier: ^0.14.1
version: 0.14.1
packages:
@ -1668,6 +1674,15 @@ packages:
resolution: {integrity: sha512-gYBeFTZLu055D8Vv3cSPox/0iTPtkzxpLroSYYA7WXgRi31WCJ51Uyl8ZiPeUUjyvs2MBzK+S8v9JVUgHU/Sqw==}
engines: {node: '>=18.12'}
prettier-plugin-astro@0.14.1:
resolution: {integrity: sha512-RiBETaaP9veVstE4vUwSIcdATj6dKmXljouXc/DDNwBSPTp8FRkLGDSGFClKsAFeeg+13SB0Z1JZvbD76bigJw==}
engines: {node: ^14.15.0 || >=16.0.0}
prettier@3.4.2:
resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==}
engines: {node: '>=14'}
hasBin: true
prismjs@1.29.0:
resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==}
engines: {node: '>=6'}
@ -1778,6 +1793,9 @@ packages:
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
s.color@0.0.15:
resolution: {integrity: sha512-AUNrbEUHeKY8XsYr/DYpl+qk5+aM+DChopnWOPEzn8YKzOhv4l2zH6LzZms3tOZP3wwdOyc0RmTciyi46HLIuA==}
safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
@ -1788,6 +1806,9 @@ packages:
resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
engines: {node: '>=10'}
sass-formatter@0.7.9:
resolution: {integrity: sha512-CWZ8XiSim+fJVG0cFLStwDvft1VI7uvXdCNJYXhDvowiv+DsbD1nXLiQ4zrE5UBvj5DWZJ93cwN0NX5PMsr1Pw==}
section-matter@1.0.0:
resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
engines: {node: '>=4'}
@ -1901,6 +1922,9 @@ packages:
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
engines: {node: '>=4'}
suf-log@2.5.3:
resolution: {integrity: sha512-KvC8OPjzdNOe+xQ4XWJV2whQA0aM1kGVczMQ8+dStAO6KfEB140JEVQ9dE76ONZ0/Ylf67ni4tILPJB41U0eow==}
supports-color@5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'}
@ -3911,6 +3935,14 @@ snapshots:
find-yarn-workspace-root2: 1.2.16
which-pm: 3.0.0
prettier-plugin-astro@0.14.1:
dependencies:
'@astrojs/compiler': 2.10.3
prettier: 3.4.2
sass-formatter: 0.7.9
prettier@3.4.2: {}
prismjs@1.29.0: {}
process-warning@3.0.0: {}
@ -4077,6 +4109,8 @@ snapshots:
dependencies:
queue-microtask: 1.2.3
s.color@0.0.15: {}
safe-buffer@5.2.1: {}
safe-regex2@3.1.0:
@ -4085,6 +4119,10 @@ snapshots:
safe-stable-stringify@2.5.0: {}
sass-formatter@0.7.9:
dependencies:
suf-log: 2.5.3
section-matter@1.0.0:
dependencies:
extend-shallow: 2.0.1
@ -4223,6 +4261,10 @@ snapshots:
strip-bom@3.0.0: {}
suf-log@2.5.3:
dependencies:
s.color: 0.0.15
supports-color@5.5.0:
dependencies:
has-flag: 3.0.0

21
prettier.config.mjs Normal file
View file

@ -0,0 +1,21 @@
/**
* @see https://prettier.io/docs/en/configuration.html
* @type {import("prettier").Config}
*/
const config = {
trailingComma: 'es5',
tabWidth: 2,
semi: false,
singleQuote: true,
plugins: ['prettier-plugin-astro'],
overrides: [
{
files: '*.astro',
options: {
parser: 'astro',
},
},
],
}
export default config

View file

@ -1,18 +1,18 @@
#!/usr/bin/env node
import Fastify from 'fastify';
import fastifyMiddie from '@fastify/middie';
import fastifyStatic from '@fastify/static';
import { fileURLToPath } from 'node:url';
import { handler as ssrHandler } from './dist/server/entry.mjs';
import Fastify from 'fastify'
import fastifyMiddie from '@fastify/middie'
import fastifyStatic from '@fastify/static'
import { fileURLToPath } from 'node:url'
import { handler as ssrHandler } from './dist/server/entry.mjs'
const app = Fastify({ logger: true });
const app = Fastify({ logger: true })
await app
.register(fastifyStatic, {
root: fileURLToPath(new URL('./dist/client', import.meta.url)),
})
.register(fastifyMiddie);
app.use(ssrHandler);
.register(fastifyMiddie)
app.use(ssrHandler)
app.listen({ port: 4321 });
app.listen({ port: 4321 })

View file

@ -1,16 +1,16 @@
import { defineCollection, z } from 'astro:content';
import { defineCollection, z } from 'astro:content'
const blog = defineCollection({
type: 'content',
// Type-check frontmatter using a schema
schema: z.object({
title: z.string(),
description: z.string(),
// Transform string to Date object
pubDate: z.coerce.date(),
updatedDate: z.coerce.date().optional(),
heroImage: z.string().optional(),
}),
});
type: 'content',
// Type-check frontmatter using a schema
schema: z.object({
title: z.string(),
description: z.string(),
// Transform string to Date object
pubDate: z.coerce.date(),
updatedDate: z.coerce.date().optional(),
heroImage: z.string().optional(),
}),
})
export const collections = { blog };
export const collections = { blog }

2
src/env.d.ts vendored
View file

@ -1,2 +1,2 @@
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" />
/// <reference types="astro/client" />

View file

@ -1,4 +1,4 @@
import { log } from "./utils";
import { log } from './utils'
/**
* Note: @ayco/astro-sw integration injects variables `__prefix`, `__version`, & `__assets`
@ -7,88 +7,86 @@ import { log } from "./utils";
*/
const cacheName = `${__prefix ?? 'app'}-v${__version ?? '000'}`
const addResourcesToCache = async (resources) => {
const cache = await caches.open(cacheName);
console.log('adding resources to cache...', resources)
await cache.addAll(resources);
};
const cache = await caches.open(cacheName)
console.log('adding resources to cache...', resources)
await cache.addAll(resources)
}
log('test log', {hello: 'world'});
log('test log', { hello: 'world' })
const putInCache = async (request, response) => {
const cache = await caches.open(cacheName);
console.log('adding one response to cache...', request)
await cache.put(request, response);
};
const cache = await caches.open(cacheName)
console.log('adding one response to cache...', request)
await cache.put(request, response)
}
const cacheFirst = async ({ request, preloadResponsePromise, fallbackUrl }) => {
// First try to get the resource from the cache
const responseFromCache = await caches.match(request);
if (responseFromCache) {
return responseFromCache;
}
// First try to get the resource from the cache
const responseFromCache = await caches.match(request)
if (responseFromCache) {
return responseFromCache
}
// Next try to use the preloaded response, if it's there
// NOTE: Chrome throws errors regarding preloadResponse, see:
// https://bugs.chromium.org/p/chromium/issues/detail?id=1420515
// https://github.com/mdn/dom-examples/issues/145
// To avoid those errors, remove or comment out this block of preloadResponse
// code along with enableNavigationPreload() and the "activate" listener.
const preloadResponse = await preloadResponsePromise;
if (preloadResponse) {
console.info('using preload response', preloadResponse);
putInCache(request, preloadResponse.clone());
return preloadResponse;
}
// Next try to use the preloaded response, if it's there
// NOTE: Chrome throws errors regarding preloadResponse, see:
// https://bugs.chromium.org/p/chromium/issues/detail?id=1420515
// https://github.com/mdn/dom-examples/issues/145
// To avoid those errors, remove or comment out this block of preloadResponse
// code along with enableNavigationPreload() and the "activate" listener.
const preloadResponse = await preloadResponsePromise
if (preloadResponse) {
console.info('using preload response', preloadResponse)
putInCache(request, preloadResponse.clone())
return preloadResponse
}
// Next try to get the resource from the network
try {
const responseFromNetwork = await fetch(request.clone());
// response may be used only once
// we need to save clone to put one copy in cache
// and serve second one
putInCache(request, responseFromNetwork.clone());
return responseFromNetwork;
} catch (error) {
const fallbackResponse = await caches.match(fallbackUrl);
if (fallbackResponse) {
return fallbackResponse;
}
// when even the fallback response is not available,
// there is nothing we can do, but we must always
// return a Response object
return new Response('Network error happened', {
status: 408,
headers: { 'Content-Type': 'text/plain' },
});
// Next try to get the resource from the network
try {
const responseFromNetwork = await fetch(request.clone())
// response may be used only once
// we need to save clone to put one copy in cache
// and serve second one
putInCache(request, responseFromNetwork.clone())
return responseFromNetwork
} catch (error) {
const fallbackResponse = await caches.match(fallbackUrl)
if (fallbackResponse) {
return fallbackResponse
}
};
// when even the fallback response is not available,
// there is nothing we can do, but we must always
// return a Response object
return new Response('Network error happened', {
status: 408,
headers: { 'Content-Type': 'text/plain' },
})
}
}
const enableNavigationPreload = async () => {
if (self.registration.navigationPreload) {
// Enable navigation preloads!
await self.registration.navigationPreload.enable();
}
};
if (self.registration.navigationPreload) {
// Enable navigation preloads!
await self.registration.navigationPreload.enable()
}
}
self.addEventListener('activate', (event) => {
console.log('activating...', event)
event.waitUntil(enableNavigationPreload());
});
console.log('activating...', event)
event.waitUntil(enableNavigationPreload())
})
self.addEventListener('install', (event) => {
console.log('installing...', event)
event.waitUntil(
addResourcesToCache(__assets ?? [])
);
});
console.log('installing...', event)
event.waitUntil(addResourcesToCache(__assets ?? []))
})
self.addEventListener('fetch', (event) => {
console.log('fetch happened', event.request)
event.respondWith(
cacheFirst({
request: event.request,
preloadResponsePromise: event.preloadResponse,
fallbackUrl: './',
})
);
});
console.log('fetch happened', event.request)
event.respondWith(
cacheFirst({
request: event.request,
preloadResponsePromise: event.preloadResponse,
fallbackUrl: './',
})
)
})

View file

@ -1,3 +1,5 @@
---
---
404
404

View file

@ -1,17 +1,17 @@
---
import { type CollectionEntry, getCollection } from 'astro:content';
import { type CollectionEntry, getCollection } from 'astro:content'
export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map((post) => ({
params: { slug: post.slug },
props: post,
}));
const posts = await getCollection('blog')
return posts.map((post) => ({
params: { slug: post.slug },
props: post,
}))
}
type Props = CollectionEntry<'blog'>;
type Props = CollectionEntry<'blog'>
const post = Astro.props;
const { Content } = await post.render();
const post = Astro.props
const { Content } = await post.render()
---
<Content />

View file

@ -1,5 +1,7 @@
---
---
blog index
<a href="/blog/building-a-cozy-web">post</a>
<a href="/blog/building-a-cozy-web">post</a>

View file

@ -1,4 +1,5 @@
---
---
exclude
---
exclude

View file

@ -1,15 +1,14 @@
---
export const prerender = false
---
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Hello</title>
</head>
<body>
Hello
</body>
</head>
<body> Hello </body>
</html>
<!-- <Fragment set:html={content} /> -->
<!-- <Fragment set:html={content} /> -->

View file

@ -1,3 +1,3 @@
export function log(message: any, ...data) {
console.log(message, ...data)
}
console.log(message, ...data)
}