feat: refactor static paths and photoswipe on blog page, move script to base layout
This commit is contained in:
3
bun.lock
3
bun.lock
@@ -49,6 +49,7 @@
|
|||||||
"@tailwindcss/forms": "^0.5.11",
|
"@tailwindcss/forms": "^0.5.11",
|
||||||
"@tailwindcss/typography": "^0.5.19",
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"@types/markdown-it": "^14.1.2",
|
"@types/markdown-it": "^14.1.2",
|
||||||
|
"@types/photoswipe": "^5.2.5",
|
||||||
"eslint": "^10.0.3",
|
"eslint": "^10.0.3",
|
||||||
"eslint-config-prettier": "^10.1.8",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-plugin-astro": "^1.6.0",
|
"eslint-plugin-astro": "^1.6.0",
|
||||||
@@ -849,6 +850,8 @@
|
|||||||
|
|
||||||
"@types/parse-json": ["@types/parse-json@4.0.2", "", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="],
|
"@types/parse-json": ["@types/parse-json@4.0.2", "", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="],
|
||||||
|
|
||||||
|
"@types/photoswipe": ["@types/photoswipe@5.2.5", "", { "dependencies": { "photoswipe": "*" } }, "sha512-1x8LpPy/a9cMdy8AgSQZOgVN4b1BEAGGLFjkg20RAUbv2vzovH8U2iSZmjlM6Gd6oY/BI+Thdph0kOlxEZHskQ=="],
|
||||||
|
|
||||||
"@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "3.2.3" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
|
"@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "3.2.3" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
|
||||||
|
|
||||||
"@types/react-dom": ["@types/react-dom@19.1.7", "", { "peerDependencies": { "@types/react": "19.2.14" } }, "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw=="],
|
"@types/react-dom": ["@types/react-dom@19.1.7", "", { "peerDependencies": { "@types/react": "19.2.14" } }, "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw=="],
|
||||||
|
|||||||
@@ -73,6 +73,7 @@
|
|||||||
"@tailwindcss/forms": "^0.5.11",
|
"@tailwindcss/forms": "^0.5.11",
|
||||||
"@tailwindcss/typography": "^0.5.19",
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"@types/markdown-it": "^14.1.2",
|
"@types/markdown-it": "^14.1.2",
|
||||||
|
"@types/photoswipe": "^5.2.5",
|
||||||
"eslint": "^10.0.3",
|
"eslint": "^10.0.3",
|
||||||
"eslint-config-prettier": "^10.1.8",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-plugin-astro": "^1.6.0",
|
"eslint-plugin-astro": "^1.6.0",
|
||||||
|
|||||||
@@ -120,6 +120,48 @@ const normalizeTitle = !title ? global.name : `${title} | ${global.name}`;
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import PhotoSwipeLightbox from 'photoswipe/lightbox';
|
||||||
|
import PhotoSwipe from "photoswipe";
|
||||||
|
|
||||||
|
let lightbox: PhotoSwipeLightbox | null = null;
|
||||||
|
|
||||||
|
function initPhotoSwipe() {
|
||||||
|
const links = document.querySelectorAll<HTMLAnchorElement>('a.pswp-link');
|
||||||
|
|
||||||
|
links.forEach((link) => {
|
||||||
|
const img = link.querySelector('img');
|
||||||
|
if (img) {
|
||||||
|
const applyDimensions = () => {
|
||||||
|
link.dataset.pswpWidth = (img.naturalWidth || 1920).toString();
|
||||||
|
link.dataset.pswpHeight = (img.naturalHeight || 1080).toString();
|
||||||
|
};
|
||||||
|
if (img.complete) {
|
||||||
|
applyDimensions();
|
||||||
|
} else {
|
||||||
|
img.addEventListener('load', applyDimensions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (lightbox) {
|
||||||
|
lightbox.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
lightbox = new PhotoSwipeLightbox({
|
||||||
|
gallery: '.prose',
|
||||||
|
children: 'a.pswp-link',
|
||||||
|
pswpModule: PhotoSwipe,
|
||||||
|
allowPanToNext: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
lightbox.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
initPhotoSwipe();
|
||||||
|
document.addEventListener('swup:page:view', initPhotoSwipe);
|
||||||
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const animateContent = () => {
|
const animateContent = () => {
|
||||||
const smoothReveal = document.querySelectorAll('.smooth-reveal');
|
const smoothReveal = document.querySelectorAll('.smooth-reveal');
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
---
|
---
|
||||||
|
|
||||||
import { Image } from 'astro:assets';
|
import { Image } from 'astro:assets';
|
||||||
import { marked } from 'marked';
|
import { marked } from 'marked';
|
||||||
import markedShiki from 'marked-shiki';
|
import markedShiki from 'marked-shiki';
|
||||||
import { createHighlighter } from 'shiki';
|
import { createHighlighter } from 'shiki';
|
||||||
import { readItems, readSingleton } from '@directus/sdk';
|
import { readItems, readSingleton } from '@directus/sdk';
|
||||||
import 'photoswipe/style.css';
|
import "photoswipe/style.css";
|
||||||
|
|
||||||
|
import type { Post } from '@/lib/directusTypes'
|
||||||
|
|
||||||
import SocialShareButton from '@components/buttons/SocialShareButton.astro';
|
import SocialShareButton from '@components/buttons/SocialShareButton.astro';
|
||||||
import PostMetadataSnippet from '@/components/snippets/PostMetadataSnippet.astro';
|
import PostMetadataSnippet from '@/components/snippets/PostMetadataSnippet.astro';
|
||||||
@@ -13,39 +14,51 @@ import BaseLayout from '@layouts/BaseLayout.astro';
|
|||||||
import directus from '@lib/directus';
|
import directus from '@lib/directus';
|
||||||
import { getDirectusImageURL } from '@/support/url';
|
import { getDirectusImageURL } from '@/support/url';
|
||||||
|
|
||||||
const post = Astro.props;
|
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const posts = await directus.request(readItems('posts', {
|
const posts = await directus.request(readItems('posts', {
|
||||||
fields: ['*', { category: ['*'] }],
|
fields: ['*', { category: ['*'] }],
|
||||||
}));
|
}));
|
||||||
return posts.map((post) => ({
|
const globalData = await directus.request(readSingleton('site_global'));
|
||||||
|
const highlighter = await createHighlighter({
|
||||||
|
themes: ['github-light', 'github-dark'],
|
||||||
|
langs: ['typescript', 'python', 'css', 'html', 'yaml', 'bash', 'json'],
|
||||||
|
});
|
||||||
|
const renderer = {
|
||||||
|
image({ href, title, text }: { href: string; title: string | null; text: string }) {
|
||||||
|
return `
|
||||||
|
<a
|
||||||
|
href="${href}"
|
||||||
|
class="pswp-link"
|
||||||
|
data-pswp-src="${href}"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<img src="${href}" alt="${text}" title="${title || ''}" loading="lazy" />
|
||||||
|
</a>
|
||||||
|
`;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
marked.use({ renderer });
|
||||||
|
marked.use(markedShiki({
|
||||||
|
highlight(code, lang) {
|
||||||
|
return highlighter.codeToHtml(code, {
|
||||||
|
lang: lang || 'plaintext',
|
||||||
|
themes: { light: 'github-light', dark: 'github-dark' },
|
||||||
|
defaultColor: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
return posts.map((post: Post) => ({
|
||||||
params: { slug: post.slug },
|
params: { slug: post.slug },
|
||||||
props: post,
|
props: {
|
||||||
|
post,
|
||||||
|
global: globalData,
|
||||||
|
content: marked.parse(post.content || ''),
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
const global = await directus.request(readSingleton('site_global'));
|
const { post, global, content } = Astro.props;
|
||||||
|
|
||||||
const highlighter = await createHighlighter({
|
|
||||||
themes: ['github-light', 'github-dark'],
|
|
||||||
langs: ['typescript', 'python', 'css', 'html', 'yaml', 'bash', 'json'],
|
|
||||||
});
|
|
||||||
|
|
||||||
marked.use(markedShiki({
|
|
||||||
highlight(code, lang) {
|
|
||||||
return highlighter.codeToHtml(code, {
|
|
||||||
lang: lang || 'plaintext',
|
|
||||||
themes: {
|
|
||||||
light: 'github-light',
|
|
||||||
dark: 'github-dark',
|
|
||||||
},
|
|
||||||
defaultColor: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
const content = marked.parse(post.content || '');
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout
|
<BaseLayout
|
||||||
@@ -65,7 +78,7 @@ const content = marked.parse(post.content || '');
|
|||||||
name: global.name,
|
name: global.name,
|
||||||
description: global.about,
|
description: global.about,
|
||||||
},
|
},
|
||||||
image: [],
|
image: [getDirectusImageURL(post.image)],
|
||||||
headline: post.title,
|
headline: post.title,
|
||||||
datePublished: post.published_date,
|
datePublished: post.published_date,
|
||||||
dateModified: post.updated_date,
|
dateModified: post.updated_date,
|
||||||
@@ -85,7 +98,7 @@ const content = marked.parse(post.content || '');
|
|||||||
<Image
|
<Image
|
||||||
class="rounded-2xl sm:rounded-b-none w-full max-h-150 object-cover"
|
class="rounded-2xl sm:rounded-b-none w-full max-h-150 object-cover"
|
||||||
src={getDirectusImageURL(post.image)}
|
src={getDirectusImageURL(post.image)}
|
||||||
alt={post.image_alt}
|
alt={post.image_alt || post.title}
|
||||||
draggable="false"
|
draggable="false"
|
||||||
format="webp"
|
format="webp"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
@@ -110,13 +123,15 @@ const content = marked.parse(post.content || '');
|
|||||||
</article>
|
</article>
|
||||||
|
|
||||||
<div class="grid sm:flex sm:items-center sm:justify-between gap-y-5 sm:gap-y-0 max-w-5xl mx-auto mt-10 md:mt-14">
|
<div class="grid sm:flex sm:items-center sm:justify-between gap-y-5 sm:gap-y-0 max-w-5xl mx-auto mt-10 md:mt-14">
|
||||||
<div class="flex flex-wrap sm:flex-nowrap sm:items-center gap-x-2 gap-y-1 sm:gap-y-0">
|
{post.tags && post.tags.length > 0 && (
|
||||||
{post.tags.map((tag: string) => (
|
<div class="flex flex-wrap sm:flex-nowrap sm:items-center gap-x-2 gap-y-1 sm:gap-y-0">
|
||||||
<span class="inline-flex items-center button-base bg-cobalt dark:bg-turquoise text-neutral-100 text-xs font-bold rounded-lg gap-x-1.5 px-3 py-1.5">
|
{post.tags.map((tag: string) => (
|
||||||
{tag}
|
<span class="inline-flex items-center button-base bg-cobalt dark:bg-turquoise text-neutral-100 text-xs font-bold rounded-lg gap-x-1.5 px-3 py-1.5">
|
||||||
</span>
|
{tag}
|
||||||
))}
|
</span>
|
||||||
</div>
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<SocialShareButton pageTitle={post.title}/>
|
<SocialShareButton pageTitle={post.title}/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -139,39 +154,3 @@ const content = marked.parse(post.content || '');
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
</BaseLayout>
|
</BaseLayout>
|
||||||
|
|
||||||
<script>
|
|
||||||
import PhotoSwipeLightbox from 'photoswipe/lightbox';
|
|
||||||
const prose = document.querySelector('.prose');
|
|
||||||
if (prose) {
|
|
||||||
const images = prose.querySelectorAll('img');
|
|
||||||
images.forEach((img) => {
|
|
||||||
if (img.closest('a')) return;
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = img.src;
|
|
||||||
link.dataset.pswpSrc = img.src;
|
|
||||||
link.dataset.pswpWidth = img.naturalWidth.toString();
|
|
||||||
link.dataset.pswpHeight = img.naturalHeight.toString();
|
|
||||||
link.target = '_blank';
|
|
||||||
link.classList.add('pswp-link');
|
|
||||||
|
|
||||||
img.parentNode?.insertBefore(link, img);
|
|
||||||
link.appendChild(img);
|
|
||||||
|
|
||||||
if (!img.complete) {
|
|
||||||
img.onload = () => {
|
|
||||||
link.dataset.pswpWidth = img.naturalWidth.toString();
|
|
||||||
link.dataset.pswpHeight = img.naturalHeight.toString();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const lightbox = new PhotoSwipeLightbox({
|
|
||||||
gallery: prose,
|
|
||||||
children: 'a.pswp-link',
|
|
||||||
pswpModule: () => import('photoswipe'),
|
|
||||||
});
|
|
||||||
|
|
||||||
lightbox.init();
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|||||||
Reference in New Issue
Block a user