optimize posts images and other improvements
This commit is contained in:
parent
9c3e631c78
commit
ec3bccb0de
@ -28,10 +28,10 @@
|
||||
"fast-glob": "^3.3.2",
|
||||
"lucide-react": "^0.396.0",
|
||||
"markdown-it": "^14.1.0",
|
||||
"marked": "^13.0.1",
|
||||
"node-html-parser": "^6.1.13",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-markdown": "^9.0.1",
|
||||
"rehype-pretty-code": "^0.13.2",
|
||||
"rehype-slug": "^6.0.0",
|
||||
"sanitize-html": "^2.13.0",
|
||||
|
41
pnpm-lock.yaml
generated
41
pnpm-lock.yaml
generated
@ -62,6 +62,9 @@ importers:
|
||||
markdown-it:
|
||||
specifier: ^14.1.0
|
||||
version: 14.1.0
|
||||
marked:
|
||||
specifier: ^13.0.1
|
||||
version: 13.0.1
|
||||
node-html-parser:
|
||||
specifier: ^6.1.13
|
||||
version: 6.1.13
|
||||
@ -71,9 +74,6 @@ importers:
|
||||
react-dom:
|
||||
specifier: ^18.3.1
|
||||
version: 18.3.1(react@18.3.1)
|
||||
react-markdown:
|
||||
specifier: ^9.0.1
|
||||
version: 9.0.1(@types/react@18.3.3)(react@18.3.1)
|
||||
rehype-pretty-code:
|
||||
specifier: ^0.13.2
|
||||
version: 0.13.2(shiki@1.9.0)
|
||||
@ -1648,9 +1648,6 @@ packages:
|
||||
html-escaper@3.0.3:
|
||||
resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==}
|
||||
|
||||
html-url-attributes@3.0.0:
|
||||
resolution: {integrity: sha512-/sXbVCWayk6GDVg3ctOX6nxaVj7So40FcFAnWlWGNAB1LpYKcV5Cd10APjPjW80O7zYW2MsjBV4zZ7IZO5fVow==}
|
||||
|
||||
html-void-elements@3.0.0:
|
||||
resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
|
||||
|
||||
@ -1898,6 +1895,11 @@ packages:
|
||||
markdown-table@3.0.3:
|
||||
resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==}
|
||||
|
||||
marked@13.0.1:
|
||||
resolution: {integrity: sha512-7kBohS6GrZKvCsNXZyVVXSW7/hGBHe49ng99YPkDCckSUrrG7MSFLCexsRxptzOmyW2eT5dySh4Md1V6my52fA==}
|
||||
engines: {node: '>= 18'}
|
||||
hasBin: true
|
||||
|
||||
mdast-util-definitions@6.0.0:
|
||||
resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==}
|
||||
|
||||
@ -2377,12 +2379,6 @@ packages:
|
||||
peerDependencies:
|
||||
react: ^18.3.1
|
||||
|
||||
react-markdown@9.0.1:
|
||||
resolution: {integrity: sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg==}
|
||||
peerDependencies:
|
||||
'@types/react': '>=18'
|
||||
react: '>=18'
|
||||
|
||||
react-refresh@0.14.2:
|
||||
resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -4811,8 +4807,6 @@ snapshots:
|
||||
|
||||
html-escaper@3.0.3: {}
|
||||
|
||||
html-url-attributes@3.0.0: {}
|
||||
|
||||
html-void-elements@3.0.0: {}
|
||||
|
||||
htmlparser2@8.0.2:
|
||||
@ -5017,6 +5011,8 @@ snapshots:
|
||||
|
||||
markdown-table@3.0.3: {}
|
||||
|
||||
marked@13.0.1: {}
|
||||
|
||||
mdast-util-definitions@6.0.0:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
@ -5748,23 +5744,6 @@ snapshots:
|
||||
react: 18.3.1
|
||||
scheduler: 0.23.2
|
||||
|
||||
react-markdown@9.0.1(@types/react@18.3.3)(react@18.3.1):
|
||||
dependencies:
|
||||
'@types/hast': 3.0.4
|
||||
'@types/react': 18.3.3
|
||||
devlop: 1.1.0
|
||||
hast-util-to-jsx-runtime: 2.3.0
|
||||
html-url-attributes: 3.0.0
|
||||
mdast-util-to-hast: 13.2.0
|
||||
react: 18.3.1
|
||||
remark-parse: 11.0.0
|
||||
remark-rehype: 11.1.0
|
||||
unified: 11.0.5
|
||||
unist-util-visit: 5.0.0
|
||||
vfile: 6.0.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
react-refresh@0.14.2: {}
|
||||
|
||||
react-remove-scroll-bar@2.3.6(@types/react@18.3.3)(react@18.3.1):
|
||||
|
@ -5,9 +5,16 @@ const { src, alt } = Astro.props;
|
||||
---
|
||||
|
||||
<Image
|
||||
id="img"
|
||||
src={src}
|
||||
alt={alt}
|
||||
width={1092}
|
||||
height={986}
|
||||
class="w-auto h-auto rounded-md aspect-auto"
|
||||
class=".markdown-image w-auto h-auto rounded-md aspect-auto"
|
||||
/>
|
||||
|
||||
<script>
|
||||
const image = document.getElementById("img")!;
|
||||
|
||||
image.setAttribute("loading", "eager");
|
||||
</script>
|
||||
|
38
src/components/microblog-item.astro
Normal file
38
src/components/microblog-item.astro
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
import { marked } from "marked";
|
||||
import formatDate from "@/utils/format-date";
|
||||
import type { MicroblogsResponse, TagsResponse } from "@/utils/pocketbase";
|
||||
|
||||
type Props = MicroblogsResponse<unknown> & {
|
||||
props: {
|
||||
tags: TagsResponse[];
|
||||
};
|
||||
};
|
||||
|
||||
const props = Astro.props;
|
||||
const content = marked.parse(props.content);
|
||||
---
|
||||
|
||||
<article class="rounded-md border px-4 py-2">
|
||||
<header class="mb-2">
|
||||
<div class="flex items-center justify-between text-sm">
|
||||
<span class="font-light">
|
||||
{formatDate(new Date(props.published))}{" "}
|
||||
</span>
|
||||
<span class="text-sm font-thin">
|
||||
{new Date(props.published).toLocaleTimeString()}
|
||||
</span>
|
||||
</div>
|
||||
<div class="mt-1">
|
||||
{
|
||||
props &&
|
||||
props.expand.tags &&
|
||||
props.expand.tags.map(
|
||||
(tag: any) =>
|
||||
tag && <span class="text-sm">#{tag.name} </span>,
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</header>
|
||||
<main set:html={content} />
|
||||
</article>
|
@ -1,41 +0,0 @@
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import type { MicroblogsResponse, TagsResponse } from "@/utils/pocketbase";
|
||||
import formatDate from "@/utils/format-date";
|
||||
|
||||
type Props = MicroblogsResponse<unknown> & {
|
||||
expand: {
|
||||
tags: TagsResponse[];
|
||||
};
|
||||
};
|
||||
|
||||
export default function MicroblogItem(props: Props) {
|
||||
return (
|
||||
<article className="rounded-sm border px-4 py-2">
|
||||
<header className="mb-2">
|
||||
<div className="flex items-center justify-between text-sm">
|
||||
<span className="font-light">
|
||||
{formatDate(new Date(props.published))}{" "}
|
||||
</span>
|
||||
<span className="text-sm font-thin">
|
||||
{new Date(props.published).toLocaleTimeString()}
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-1">
|
||||
{props.expand &&
|
||||
props.expand.tags &&
|
||||
props.expand.tags.map(
|
||||
(tag) =>
|
||||
tag && (
|
||||
<span className="text-sm" key={tag.id}>
|
||||
#{tag.name}{" "}
|
||||
</span>
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
<ReactMarkdown>{props.content}</ReactMarkdown>
|
||||
</main>
|
||||
</article>
|
||||
);
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
---
|
||||
import { navItems } from "@/utils/nav-links";
|
||||
import MobileMenu from "@/components/mobile-menu";
|
||||
import logo from "@/assets/logo.png";
|
||||
import { Image } from "astro:assets";
|
||||
import { navItems } from "@/utils/nav-links";
|
||||
import MobileMenu from "@/components/mobile-menu";
|
||||
import LinkButton from "@/components/link-button";
|
||||
---
|
||||
|
||||
@ -23,6 +23,7 @@ import LinkButton from "@/components/link-button";
|
||||
src={logo}
|
||||
width={80}
|
||||
height={80}
|
||||
loading="eager"
|
||||
class="w-auto h-auto"
|
||||
alt="juancmandev logo"
|
||||
/>
|
||||
@ -31,7 +32,7 @@ import LinkButton from "@/components/link-button";
|
||||
<section class="hidden items-center md:flex">
|
||||
<ul class="flex items-center gap-1">
|
||||
{
|
||||
navItems.map((navItem) => (
|
||||
navItems.map((navItem: any) => (
|
||||
<li class="w-max h-max">
|
||||
<LinkButton
|
||||
variant="link"
|
||||
|
@ -11,7 +11,7 @@ interface Props {
|
||||
export async function getStaticPaths() {
|
||||
const allPages = await getCollection("pages");
|
||||
|
||||
return allPages.map((page) => ({
|
||||
return allPages.map((page: CollectionEntry<"pages">) => ({
|
||||
params: { slug: page.slug },
|
||||
props: { page },
|
||||
}));
|
||||
|
@ -1,13 +1,11 @@
|
||||
---
|
||||
import PostItem from "@/components/post-item";
|
||||
import Layout from "@/layouts/Layout.astro";
|
||||
import { sortContentByDate } from "@/utils/sorts";
|
||||
import { getCollection } from "astro:content";
|
||||
|
||||
const allPosts = await getCollection("blog", ({ data }) => data.draft !== true);
|
||||
allPosts.sort(
|
||||
(a, b) =>
|
||||
Date.parse(b.data.date.toString()) - Date.parse(a.data.date.toString()),
|
||||
);
|
||||
sortContentByDate(allPosts);
|
||||
---
|
||||
|
||||
<Layout title="Blog" description="Check my projects.">
|
||||
@ -17,7 +15,7 @@ allPosts.sort(
|
||||
</section>
|
||||
<ul class="mt-4 flex flex-col gap-4">
|
||||
{
|
||||
allPosts.map((blogpost) => (
|
||||
allPosts.map((blogpost: any) => (
|
||||
<li>
|
||||
<PostItem
|
||||
type="blog"
|
||||
|
@ -3,22 +3,17 @@ import Layout from "@/layouts/Layout.astro";
|
||||
import LinkButton from "@/components/link-button";
|
||||
import { getCollection } from "astro:content";
|
||||
import PostItem from "@/components/post-item";
|
||||
import { sortContentByDate } from "@/utils/sorts";
|
||||
|
||||
const allPosts = await getCollection("blog", ({ data }) => data.draft !== true);
|
||||
allPosts.sort(
|
||||
(a, b) =>
|
||||
Date.parse(b.data.date.toString()) - Date.parse(a.data.date.toString()),
|
||||
);
|
||||
sortContentByDate(allPosts);
|
||||
const last3Blogs = allPosts.slice(0, 3);
|
||||
|
||||
const allProjects = await getCollection(
|
||||
"portfolio",
|
||||
({ data }) => data.draft !== true,
|
||||
);
|
||||
allProjects.sort(
|
||||
(a, b) =>
|
||||
Date.parse(b.data.date.toString()) - Date.parse(a.data.date.toString()),
|
||||
);
|
||||
sortContentByDate(allProjects);
|
||||
const last3Projects = allProjects.slice(0, 3);
|
||||
---
|
||||
|
||||
@ -46,7 +41,7 @@ const last3Projects = allProjects.slice(0, 3);
|
||||
<h2 class="text-3xl">Latest posts</h2>
|
||||
<ul class="mt-4 flex flex-col gap-4">
|
||||
{
|
||||
last3Blogs.map((blogpost) => (
|
||||
last3Blogs.map((blogpost: any) => (
|
||||
<li>
|
||||
<PostItem
|
||||
type="blog"
|
||||
@ -66,7 +61,7 @@ const last3Projects = allProjects.slice(0, 3);
|
||||
<h2 class="text-3xl">Latest projects</h2>
|
||||
<ul class="mt-4 flex flex-col gap-4">
|
||||
{
|
||||
last3Projects.map((project) => (
|
||||
last3Projects.map((project: any) => (
|
||||
<li>
|
||||
<PostItem
|
||||
type="portfolio"
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
import MicroblogItem from "@/components/microblog-item";
|
||||
import MicroblogItem from "@/components/microblog-item.astro";
|
||||
import Layout from "@/layouts/Layout.astro";
|
||||
import { createServerClient } from "@/utils/pocketbase";
|
||||
|
||||
|
@ -1,16 +1,14 @@
|
||||
---
|
||||
import PostItem from "@/components/post-item";
|
||||
import Layout from "@/layouts/Layout.astro";
|
||||
import { sortContentByDate } from "@/utils/sorts";
|
||||
import { getCollection } from "astro:content";
|
||||
|
||||
const allProjects = await getCollection(
|
||||
"portfolio",
|
||||
({ data }) => data.draft !== true,
|
||||
);
|
||||
allProjects.sort(
|
||||
(a, b) =>
|
||||
Date.parse(b.data.date.toString()) - Date.parse(a.data.date.toString()),
|
||||
);
|
||||
sortContentByDate(allProjects);
|
||||
---
|
||||
|
||||
<Layout title="Blog" description="Long format about thoughts and other topics.">
|
||||
@ -20,7 +18,7 @@ allProjects.sort(
|
||||
</section>
|
||||
<ul class="mt-4 flex flex-col gap-4">
|
||||
{
|
||||
allProjects.map((project) => (
|
||||
allProjects.map((project: any) => (
|
||||
<li>
|
||||
<PostItem
|
||||
type="portfolio"
|
||||
|
@ -12,7 +12,6 @@ export const navItems: TNavItem[] = [
|
||||
label: "Portfolio",
|
||||
to: "/portfolio",
|
||||
},
|
||||
|
||||
{
|
||||
label: "Microblog",
|
||||
to: "/microblog",
|
6
src/utils/sorts.ts
Normal file
6
src/utils/sorts.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export function sortContentByDate(array: any[]) {
|
||||
array.sort(
|
||||
(a: any, b: any) =>
|
||||
Date.parse(b.data.date.toString()) - Date.parse(a.data.date.toString()),
|
||||
);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user