optimize posts images and other improvements

This commit is contained in:
Juan Carlos Manzanero Domínguez 2024-06-25 17:13:28 -06:00
parent 9c3e631c78
commit ec3bccb0de
13 changed files with 80 additions and 100 deletions

View File

@ -28,10 +28,10 @@
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"lucide-react": "^0.396.0", "lucide-react": "^0.396.0",
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
"marked": "^13.0.1",
"node-html-parser": "^6.1.13", "node-html-parser": "^6.1.13",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-markdown": "^9.0.1",
"rehype-pretty-code": "^0.13.2", "rehype-pretty-code": "^0.13.2",
"rehype-slug": "^6.0.0", "rehype-slug": "^6.0.0",
"sanitize-html": "^2.13.0", "sanitize-html": "^2.13.0",

41
pnpm-lock.yaml generated
View File

@ -62,6 +62,9 @@ importers:
markdown-it: markdown-it:
specifier: ^14.1.0 specifier: ^14.1.0
version: 14.1.0 version: 14.1.0
marked:
specifier: ^13.0.1
version: 13.0.1
node-html-parser: node-html-parser:
specifier: ^6.1.13 specifier: ^6.1.13
version: 6.1.13 version: 6.1.13
@ -71,9 +74,6 @@ importers:
react-dom: react-dom:
specifier: ^18.3.1 specifier: ^18.3.1
version: 18.3.1(react@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: rehype-pretty-code:
specifier: ^0.13.2 specifier: ^0.13.2
version: 0.13.2(shiki@1.9.0) version: 0.13.2(shiki@1.9.0)
@ -1648,9 +1648,6 @@ packages:
html-escaper@3.0.3: html-escaper@3.0.3:
resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==}
html-url-attributes@3.0.0:
resolution: {integrity: sha512-/sXbVCWayk6GDVg3ctOX6nxaVj7So40FcFAnWlWGNAB1LpYKcV5Cd10APjPjW80O7zYW2MsjBV4zZ7IZO5fVow==}
html-void-elements@3.0.0: html-void-elements@3.0.0:
resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
@ -1898,6 +1895,11 @@ packages:
markdown-table@3.0.3: markdown-table@3.0.3:
resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} 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: mdast-util-definitions@6.0.0:
resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==} resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==}
@ -2377,12 +2379,6 @@ packages:
peerDependencies: peerDependencies:
react: ^18.3.1 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: react-refresh@0.14.2:
resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -4811,8 +4807,6 @@ snapshots:
html-escaper@3.0.3: {} html-escaper@3.0.3: {}
html-url-attributes@3.0.0: {}
html-void-elements@3.0.0: {} html-void-elements@3.0.0: {}
htmlparser2@8.0.2: htmlparser2@8.0.2:
@ -5017,6 +5011,8 @@ snapshots:
markdown-table@3.0.3: {} markdown-table@3.0.3: {}
marked@13.0.1: {}
mdast-util-definitions@6.0.0: mdast-util-definitions@6.0.0:
dependencies: dependencies:
'@types/mdast': 4.0.4 '@types/mdast': 4.0.4
@ -5748,23 +5744,6 @@ snapshots:
react: 18.3.1 react: 18.3.1
scheduler: 0.23.2 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-refresh@0.14.2: {}
react-remove-scroll-bar@2.3.6(@types/react@18.3.3)(react@18.3.1): react-remove-scroll-bar@2.3.6(@types/react@18.3.3)(react@18.3.1):

View File

@ -5,9 +5,16 @@ const { src, alt } = Astro.props;
--- ---
<Image <Image
id="img"
src={src} src={src}
alt={alt} alt={alt}
width={1092} width={1092}
height={986} 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>

View 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>

View File

@ -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>
);
}

View File

@ -1,8 +1,8 @@
--- ---
import { navItems } from "@/utils/nav-links";
import MobileMenu from "@/components/mobile-menu";
import logo from "@/assets/logo.png"; import logo from "@/assets/logo.png";
import { Image } from "astro:assets"; import { Image } from "astro:assets";
import { navItems } from "@/utils/nav-links";
import MobileMenu from "@/components/mobile-menu";
import LinkButton from "@/components/link-button"; import LinkButton from "@/components/link-button";
--- ---
@ -23,6 +23,7 @@ import LinkButton from "@/components/link-button";
src={logo} src={logo}
width={80} width={80}
height={80} height={80}
loading="eager"
class="w-auto h-auto" class="w-auto h-auto"
alt="juancmandev logo" alt="juancmandev logo"
/> />
@ -31,7 +32,7 @@ import LinkButton from "@/components/link-button";
<section class="hidden items-center md:flex"> <section class="hidden items-center md:flex">
<ul class="flex items-center gap-1"> <ul class="flex items-center gap-1">
{ {
navItems.map((navItem) => ( navItems.map((navItem: any) => (
<li class="w-max h-max"> <li class="w-max h-max">
<LinkButton <LinkButton
variant="link" variant="link"

View File

@ -11,7 +11,7 @@ interface Props {
export async function getStaticPaths() { export async function getStaticPaths() {
const allPages = await getCollection("pages"); const allPages = await getCollection("pages");
return allPages.map((page) => ({ return allPages.map((page: CollectionEntry<"pages">) => ({
params: { slug: page.slug }, params: { slug: page.slug },
props: { page }, props: { page },
})); }));

View File

@ -1,13 +1,11 @@
--- ---
import PostItem from "@/components/post-item"; import PostItem from "@/components/post-item";
import Layout from "@/layouts/Layout.astro"; import Layout from "@/layouts/Layout.astro";
import { sortContentByDate } from "@/utils/sorts";
import { getCollection } from "astro:content"; import { getCollection } from "astro:content";
const allPosts = await getCollection("blog", ({ data }) => data.draft !== true); const allPosts = await getCollection("blog", ({ data }) => data.draft !== true);
allPosts.sort( sortContentByDate(allPosts);
(a, b) =>
Date.parse(b.data.date.toString()) - Date.parse(a.data.date.toString()),
);
--- ---
<Layout title="Blog" description="Check my projects."> <Layout title="Blog" description="Check my projects.">
@ -17,7 +15,7 @@ allPosts.sort(
</section> </section>
<ul class="mt-4 flex flex-col gap-4"> <ul class="mt-4 flex flex-col gap-4">
{ {
allPosts.map((blogpost) => ( allPosts.map((blogpost: any) => (
<li> <li>
<PostItem <PostItem
type="blog" type="blog"

View File

@ -3,22 +3,17 @@ import Layout from "@/layouts/Layout.astro";
import LinkButton from "@/components/link-button"; import LinkButton from "@/components/link-button";
import { getCollection } from "astro:content"; import { getCollection } from "astro:content";
import PostItem from "@/components/post-item"; import PostItem from "@/components/post-item";
import { sortContentByDate } from "@/utils/sorts";
const allPosts = await getCollection("blog", ({ data }) => data.draft !== true); const allPosts = await getCollection("blog", ({ data }) => data.draft !== true);
allPosts.sort( sortContentByDate(allPosts);
(a, b) =>
Date.parse(b.data.date.toString()) - Date.parse(a.data.date.toString()),
);
const last3Blogs = allPosts.slice(0, 3); const last3Blogs = allPosts.slice(0, 3);
const allProjects = await getCollection( const allProjects = await getCollection(
"portfolio", "portfolio",
({ data }) => data.draft !== true, ({ data }) => data.draft !== true,
); );
allProjects.sort( sortContentByDate(allProjects);
(a, b) =>
Date.parse(b.data.date.toString()) - Date.parse(a.data.date.toString()),
);
const last3Projects = allProjects.slice(0, 3); const last3Projects = allProjects.slice(0, 3);
--- ---
@ -46,7 +41,7 @@ const last3Projects = allProjects.slice(0, 3);
<h2 class="text-3xl">Latest posts</h2> <h2 class="text-3xl">Latest posts</h2>
<ul class="mt-4 flex flex-col gap-4"> <ul class="mt-4 flex flex-col gap-4">
{ {
last3Blogs.map((blogpost) => ( last3Blogs.map((blogpost: any) => (
<li> <li>
<PostItem <PostItem
type="blog" type="blog"
@ -66,7 +61,7 @@ const last3Projects = allProjects.slice(0, 3);
<h2 class="text-3xl">Latest projects</h2> <h2 class="text-3xl">Latest projects</h2>
<ul class="mt-4 flex flex-col gap-4"> <ul class="mt-4 flex flex-col gap-4">
{ {
last3Projects.map((project) => ( last3Projects.map((project: any) => (
<li> <li>
<PostItem <PostItem
type="portfolio" type="portfolio"

View File

@ -1,5 +1,5 @@
--- ---
import MicroblogItem from "@/components/microblog-item"; import MicroblogItem from "@/components/microblog-item.astro";
import Layout from "@/layouts/Layout.astro"; import Layout from "@/layouts/Layout.astro";
import { createServerClient } from "@/utils/pocketbase"; import { createServerClient } from "@/utils/pocketbase";

View File

@ -1,16 +1,14 @@
--- ---
import PostItem from "@/components/post-item"; import PostItem from "@/components/post-item";
import Layout from "@/layouts/Layout.astro"; import Layout from "@/layouts/Layout.astro";
import { sortContentByDate } from "@/utils/sorts";
import { getCollection } from "astro:content"; import { getCollection } from "astro:content";
const allProjects = await getCollection( const allProjects = await getCollection(
"portfolio", "portfolio",
({ data }) => data.draft !== true, ({ data }) => data.draft !== true,
); );
allProjects.sort( sortContentByDate(allProjects);
(a, b) =>
Date.parse(b.data.date.toString()) - Date.parse(a.data.date.toString()),
);
--- ---
<Layout title="Blog" description="Long format about thoughts and other topics."> <Layout title="Blog" description="Long format about thoughts and other topics.">
@ -20,7 +18,7 @@ allProjects.sort(
</section> </section>
<ul class="mt-4 flex flex-col gap-4"> <ul class="mt-4 flex flex-col gap-4">
{ {
allProjects.map((project) => ( allProjects.map((project: any) => (
<li> <li>
<PostItem <PostItem
type="portfolio" type="portfolio"

View File

@ -12,7 +12,6 @@ export const navItems: TNavItem[] = [
label: "Portfolio", label: "Portfolio",
to: "/portfolio", to: "/portfolio",
}, },
{ {
label: "Microblog", label: "Microblog",
to: "/microblog", to: "/microblog",

6
src/utils/sorts.ts Normal file
View 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()),
);
}