reestructure content lang

This commit is contained in:
Juan Carlos Manzanero Domínguez 2024-10-07 16:42:47 -06:00
parent 57cb8933e2
commit ad33d51489
26 changed files with 579 additions and 163 deletions

View File

@ -6,6 +6,7 @@ type Props = {
date: Date | string; date: Date | string;
title: string; title: string;
type: "blog" | "portfolio" | "es/videos"; type: "blog" | "portfolio" | "es/videos";
lang: string;
}; };
export default function PostItem(props: Props) { export default function PostItem(props: Props) {
@ -16,9 +17,16 @@ export default function PostItem(props: Props) {
variant="link" variant="link"
className="px-4 whitespace-normal py-2 hover:no-underline focus:no-underline flex flex-col items-start italic border border-secondary hover:border-foreground focus:border-foreground transition-colors rounded-md" className="px-4 whitespace-normal py-2 hover:no-underline focus:no-underline flex flex-col items-start italic border border-secondary hover:border-foreground focus:border-foreground transition-colors rounded-md"
> >
<a className="no-underline" href={`/${props.type}/${props.slug}`}> <a
className="no-underline"
href={
props.lang === "en"
? `/${props.type}/${props.slug}`
: `/es/${props.type}/${[props.slug]}`
}
>
<span className="text-sm font-light no-underline"> <span className="text-sm font-light no-underline">
{formatDate(props.date)} {formatDate(props.date, props.lang)}
</span> </span>
<span className="text-primary text-underline text-lg font-semibold underline"> <span className="text-primary text-underline text-lg font-semibold underline">
{props.title} {props.title}

View File

@ -1,5 +1,5 @@
--- ---
title: A Better Way for Consuming Content title: Una Mejor Forma de Consumir Contenido
description: description:
Get your news without visiting websites with algorithms that shows content Get your news without visiting websites with algorithms that shows content
that you don't want to see. that you don't want to see.

View File

@ -4,35 +4,48 @@ import { getCollection } from "astro:content";
import components from "@/components/mdx/wrapper"; import components from "@/components/mdx/wrapper";
import formatDate from "@/utils/format-date"; import formatDate from "@/utils/format-date";
import type { CollectionEntry } from "astro:content"; import type { CollectionEntry } from "astro:content";
import { getLangFromUrl } from "@/i18n/utils";
interface Props { interface Props {
post: CollectionEntry<"blog">; post: CollectionEntry<"blog">;
} }
export async function getStaticPaths() { export async function getStaticPaths() {
const allBlogPosts = await getCollection( const allBlogPosts = await getCollection(
"blog", "blog",
({ data }) => data.draft !== true ({ data }) => data.draft !== true,
); );
const filterEnPosts = allBlogPosts.map((post) => {
const [lang, ...slug] = post.slug.split("/");
return allBlogPosts.map((post) => ({ if (lang === "en")
params: { slug: post.slug }, return {
props: { post }, ...post,
})); slug: slug.toString(),
};
else null;
});
return filterEnPosts.map((post) => ({
params: { slug: post?.slug },
props: { post },
}));
} }
const { post } = Astro.props; const { post } = Astro.props;
const { Content } = await post.render(); const { Content } = await post.render();
const lang = getLangFromUrl(Astro.url);
--- ---
<Layout title={post.data.title} description={post.data.description}> <Layout title={post.data.title} description={post.data.description}>
<article class="prose prose-invert"> <article class="prose prose-invert">
<h1>{post.data.title}</h1> <h1>{post.data.title}</h1>
<Content components={{ ...components }} /> <Content components={{ ...components }} />
<hr /> <hr />
<p> <p>
<strong>Posted: </strong> <strong>Posted: </strong>
{post.data.date && formatDate(new Date(post.data.date))} {post.data.date && formatDate(new Date(post.data.date), lang)}
</p> </p>
</article> </article>
</Layout> </Layout>

View File

@ -1,35 +1,52 @@
--- ---
import PostItem from "@/components/post-item"; import PostItem from "@/components/post-item";
import { getLangFromUrl } from "@/i18n/utils";
import Layout from "@/layouts/Layout.astro"; import Layout from "@/layouts/Layout.astro";
import { sortContentByDate } from "@/utils/sorts"; import { sortContentByDate } from "@/utils/sorts";
import { getCollection } from "astro:content"; import { getCollection } from "astro:content";
const pageData = { const pageData = {
title: "Blog", title: "Blog",
description: "Long format about thoughts and other topics.", description: "Long format about thoughts and other topics.",
}; };
const allPosts = await getCollection("blog", ({ data }) => data.draft !== true); const allPosts = await getCollection("blog", ({ data }) => data.draft !== true);
sortContentByDate(allPosts); const filterEnPosts = allPosts.map((post) => {
const [lang, ...slug] = post.slug.split("/");
if (lang === "en")
return {
...post,
slug: slug.toString(),
};
else null;
});
sortContentByDate(filterEnPosts);
const lang = getLangFromUrl(Astro.url);
--- ---
<Layout {...pageData}> <Layout {...pageData}>
<section class="prose prose-invert"> <section class="prose prose-invert">
<h1>{pageData.title}</h1> <h1>{pageData.title}</h1>
<p>{pageData.description}</p> <p>{pageData.description}</p>
</section> </section>
<ul class="mt-4 flex flex-col gap-4"> <ul class="mt-4 flex flex-col gap-4">
{ {
allPosts.map((blogpost: any) => ( filterEnPosts.map(
<li> (blogpost) =>
<PostItem blogpost && (
type="blog" <li>
slug={blogpost.slug} <PostItem
date={blogpost.data.date!} type="blog"
title={blogpost.data.title!} lang={lang}
/> slug={blogpost.slug}
</li> date={blogpost.data.date!}
)) title={blogpost.data.title!}
} />
</ul> </li>
),
)
}
</ul>
</Layout> </Layout>

View File

@ -0,0 +1,51 @@
---
import Layout from "@/layouts/Layout.astro";
import { getCollection } from "astro:content";
import components from "@/components/mdx/wrapper";
import formatDate from "@/utils/format-date";
import type { CollectionEntry } from "astro:content";
import { getLangFromUrl } from "@/i18n/utils";
interface Props {
post: CollectionEntry<"blog">;
}
export async function getStaticPaths() {
const allBlogPosts = await getCollection(
"blog",
({ data }) => data.draft !== true,
);
const filterEsPosts = allBlogPosts.map((post) => {
const [lang, ...slug] = post.slug.split("/");
if (lang === "es")
return {
...post,
slug: slug.toString(),
};
else null;
});
return filterEsPosts.map((post) => ({
params: { slug: post?.slug },
props: { post },
}));
}
const { post } = Astro.props;
const { Content } = await post.render();
const lang = getLangFromUrl(Astro.url);
---
<Layout title={post.data.title} description={post.data.description}>
<article class="prose prose-invert">
<h1>{post.data.title}</h1>
<Content components={{ ...components }} />
<hr />
<p>
<strong>Publicado: </strong>
{post.data.date && formatDate(new Date(post.data.date), lang)}
</p>
</article>
</Layout>

View File

@ -0,0 +1,52 @@
---
import PostItem from "@/components/post-item";
import { getLangFromUrl } from "@/i18n/utils";
import Layout from "@/layouts/Layout.astro";
import { sortContentByDate } from "@/utils/sorts";
import { getCollection } from "astro:content";
const pageData = {
title: "Blog",
description: "Formato largo sobre pensamientos y otros temas.",
};
const allPosts = await getCollection("blog", ({ data }) => data.draft !== true);
const filterEsPosts = allPosts.map((post) => {
const [lang, ...slug] = post.slug.split("/");
if (lang === "es")
return {
...post,
slug: slug.toString(),
};
else null;
});
sortContentByDate(filterEsPosts);
const lang = getLangFromUrl(Astro.url);
---
<Layout {...pageData}>
<section class="prose prose-invert">
<h1>{pageData.title}</h1>
<p>{pageData.description}</p>
</section>
<ul class="mt-4 flex flex-col gap-4">
{
filterEsPosts.map(
(post) =>
post && (
<li>
<PostItem
type="blog"
lang={lang}
slug={post?.slug}
date={post?.data.date!}
title={post?.data.title!}
/>
</li>
),
)
}
</ul>
</Layout>

View File

@ -1,24 +1,114 @@
--- ---
import LinkButton from "@/components/link-button";
import PostItem from "@/components/post-item";
import { getLangFromUrl } from "@/i18n/utils";
import Layout from "@/layouts/Layout.astro"; 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);
const allEsPosts = allPosts.map((post) => {
const [lang, ...slug] = post.slug.split("/");
if (lang === "es")
return {
...post,
slug: slug.toString(),
};
else null;
});
sortContentByDate(allEsPosts);
const last3Blogs = allEsPosts.slice(0, 3);
const allProjects = await getCollection(
"portfolio",
({ data }) => data.draft !== true,
);
const allEnProjects = allProjects.map((project) => {
const [lang, ...slug] = project.slug.split("/");
if (lang === "es")
return {
...project,
slug: slug.toString(),
};
else null;
});
sortContentByDate(allEnProjects);
const last3Projects = allEnProjects.slice(0, 3);
const lang = getLangFromUrl(Astro.url);
--- ---
<Layout <Layout
title="juancmandev" title="juancmandev"
description="Bienvenido a mi dominio, extraño. Soy juancmandev; Desarrollador Web, entusiasta de Linux, y defensor de la privacidad." description="Bienvenido a mi dominio, extraño. Soy juancmandev; Desarrollador Web, entusiasta de Linux, y defensor de la privacidad."
> >
<div class="prose prose-invert"> <div class="prose prose-invert">
<h1 class="text-primary">Bienvenido a mi dominio, extraño.</h1> <h1 class="text-primary">Bienvenido a mi dominio, extraño.</h1>
<p> <p>
Soy <strong class="text-primary">juancmandev</strong>; <strong Soy <strong class="text-primary">juancmandev</strong>; <strong
>Desarrollador Web</strong >Desarrollador Web</strong
>, entusiasta de <strong>Linux</strong> y defensor de la <strong >, entusiasta de <strong>Linux</strong> y defensor de la <strong
>privacidad.</strong >privacidad.</strong
> >
</p> </p>
<p> <p>
Este es mi <strong>website</strong>, un pedazo de Internet al que puedo Este es mi <strong>website</strong>, un pedazo de Internet al que
llamar <strong>hogar</strong>. Aquí comparto mi pasión por proyectos open puedo llamar <strong>hogar</strong>. Aquí comparto mi pasión por
source y otros temas. proyectos open source y otros temas.
</p> </p>
</div> <section>
<h2>Últimos posts</h2>
<ul class="mt-0 p-0 list-none">
{
last3Blogs.map(
(blogpost) =>
blogpost && (
<li class="p-0">
<PostItem
type="blog"
lang={lang}
slug={blogpost?.slug}
date={blogpost.data.date}
title={blogpost.data.title}
/>
</li>
),
)
}
</ul>
<LinkButton
variant="secondary"
href="/blog"
className="no-underline">Más posts</LinkButton
>
</section>
<section>
<h2>Últimos proyectos</h2>
<ul class="mt-0 p-0 list-none">
{
last3Projects.map(
(project) =>
project && (
<li class="p-0">
<PostItem
lang={lang}
type="portfolio"
slug={project.slug}
date={project.data.date!}
title={project.data.title!}
/>
</li>
),
)
}
</ul>
<LinkButton
variant="secondary"
href="/portfolio"
className="no-underline">More projects</LinkButton
>
</section>
</div>
</Layout> </Layout>

View File

@ -0,0 +1,51 @@
---
import Layout from "@/layouts/Layout.astro";
import { getCollection } from "astro:content";
import components from "@/components/mdx/wrapper";
import formatDate from "@/utils/format-date";
import type { CollectionEntry } from "astro:content";
import { getLangFromUrl } from "@/i18n/utils";
interface Props {
project: CollectionEntry<"portfolio">;
}
export async function getStaticPaths() {
const allProjects = await getCollection(
"portfolio",
({ data }) => data.draft !== true,
);
const filterEnProjects = allProjects.map((project) => {
const [lang, ...slug] = project.slug.split("/");
if (lang === "es")
return {
...project,
slug: slug.toString(),
};
else null;
});
return filterEnProjects.map((project) => ({
params: { slug: project?.slug },
props: { project },
}));
}
const { project } = Astro.props;
const { Content } = await project.render();
const lang = getLangFromUrl(Astro.url);
---
<Layout title={project.data.title} description={project.data.description}>
<article class="prose prose-invert">
<h1>{project.data.title}</h1>
<Content components={{ ...components }} />
<hr />
<p>
<strong>Publicado: </strong>
{project.data.date && formatDate(new Date(project.data.date), lang)}
</p>
</article>
</Layout>

View File

@ -0,0 +1,55 @@
---
import PostItem from "@/components/post-item";
import { getLangFromUrl } from "@/i18n/utils";
import Layout from "@/layouts/Layout.astro";
import { sortContentByDate } from "@/utils/sorts";
import { getCollection } from "astro:content";
const pageData = {
title: "Portfolio",
description: "Revisa mis proyectos.",
};
const allProjects = await getCollection(
"portfolio",
({ data }) => data.draft !== true,
);
const allEsProjects = allProjects.map((project) => {
const [lang, ...slug] = project.slug.split("/");
if (lang === "es")
return {
...project,
slug: slug.toString(),
};
else null;
});
sortContentByDate(allEsProjects);
const lang = getLangFromUrl(Astro.url);
---
<Layout {...pageData}>
<section class="prose prose-invert">
<h1>{pageData.title}</h1>
<p>{pageData.description}</p>
</section>
<ul class="mt-4 flex flex-col gap-4">
{
allEsProjects.map(
(project) =>
project && (
<li>
<PostItem
lang={lang}
type="portfolio"
slug={project.slug}
date={project.data.date!}
title={project.data.title!}
/>
</li>
),
)
}
</ul>
</Layout>

View File

@ -4,74 +4,106 @@ 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"; import { sortContentByDate } from "@/utils/sorts";
import { getLangFromUrl } from "@/i18n/utils";
const allPosts = await getCollection("blog", ({ data }) => data.draft !== true); const allPosts = await getCollection("blog", ({ data }) => data.draft !== true);
sortContentByDate(allPosts); const allEnPosts = allPosts.map((post) => {
const last3Blogs = allPosts.slice(0, 3); const [lang, ...slug] = post.slug.split("/");
if (lang !== "es")
return {
...post,
slug: slug.toString(),
};
else null;
});
sortContentByDate(allEnPosts);
const last3Blogs = allEnPosts.slice(0, 3);
const allProjects = await getCollection( const allProjects = await getCollection(
"portfolio", "portfolio",
({ data }) => data.draft !== true ({ data }) => data.draft !== true,
); );
sortContentByDate(allProjects); const allEnProjects = allProjects.map((project) => {
const last3Projects = allProjects.slice(0, 3); const [lang, ...slug] = project.slug.split("/");
if (lang !== "es")
return {
...project,
slug: slug.toString(),
};
else null;
});
sortContentByDate(allEnProjects);
const last3Projects = allEnProjects.slice(0, 3);
const lang = getLangFromUrl(Astro.url);
--- ---
<Layout <Layout
title="juancmandev" title="juancmandev"
description="Welcome to my domain, stranger. I am juancmandev; Web Developer, Linux enthusiast, and privacy defender." description="Welcome to my domain, stranger. I am juancmandev; Web Developer, Linux enthusiast, and privacy defender."
> >
<div class="prose prose-invert"> <div class="prose prose-invert">
<h1 class="text-primary">Welcome to my domain, stranger.</h1> <h1 class="text-primary">Welcome to my domain, stranger.</h1>
<p> <p>
I am <strong class="text-primary">juancmandev</strong>; <strong I am <strong class="text-primary">juancmandev</strong>; <strong
>Web Developer</strong >Web Developer</strong
>, <strong>Linux</strong> enthusiast, and <strong>privacy</strong> defender. >, <strong>Linux</strong> enthusiast, and <strong>privacy</strong> defender.
</p> </p>
<p> <p>
This is my <strong>website</strong>, a piece of the Internet that I could This is my <strong>website</strong>, a piece of the Internet that I
call my <strong>home base</strong>. Here, I share my passion about open could call my <strong>home base</strong>. Here, I share my passion
source projects and other topics. about open source projects and other topics.
</p> </p>
<section> <section>
<h2>Latest posts</h2> <h2>Latest posts</h2>
<ul class="mt-0 p-0 list-none"> <ul class="mt-0 p-0 list-none">
{ {
last3Blogs.map((blogpost: any) => ( last3Blogs.map((blogpost: any) => (
<li class="p-0"> <li class="p-0">
<PostItem <PostItem
type="blog" type="blog"
slug={blogpost.slug} lang={lang}
date={blogpost.data.date!} slug={blogpost.slug}
title={blogpost.data.title!} date={blogpost.data.date!}
/> title={blogpost.data.title!}
</li> />
)) </li>
} ))
</ul> }
<LinkButton variant="secondary" href="/blog" className="no-underline" </ul>
>More posts</LinkButton <LinkButton
> variant="secondary"
</section> href="/blog"
<section> className="no-underline">More posts</LinkButton
<h2>Latest projects</h2> >
<ul class="mt-0 p-0 list-none"> </section>
{ <section>
last3Projects.map((project: any) => ( <h2>Latest projects</h2>
<li class="p-0"> <ul class="mt-0 p-0 list-none">
<PostItem {
type="portfolio" last3Projects.map(
slug={project.slug} (project) =>
date={project.data.date!} project && (
title={project.data.title!} <li class="p-0">
/> <PostItem
</li> lang={lang}
)) type="portfolio"
} slug={project.slug}
</ul> date={project.data.date!}
<LinkButton variant="secondary" href="/portfolio" className="no-underline" title={project.data.title!}
>More projects</LinkButton />
> </li>
</section> ),
</div> )
}
</ul>
<LinkButton
variant="secondary"
href="/portfolio"
className="no-underline">More projects</LinkButton
>
</section>
</div>
</Layout> </Layout>

View File

@ -4,35 +4,48 @@ import { getCollection } from "astro:content";
import components from "@/components/mdx/wrapper"; import components from "@/components/mdx/wrapper";
import formatDate from "@/utils/format-date"; import formatDate from "@/utils/format-date";
import type { CollectionEntry } from "astro:content"; import type { CollectionEntry } from "astro:content";
import { getLangFromUrl } from "@/i18n/utils";
interface Props { interface Props {
project: CollectionEntry<"portfolio">; project: CollectionEntry<"portfolio">;
} }
export async function getStaticPaths() { export async function getStaticPaths() {
const allProjects = await getCollection( const allProjects = await getCollection(
"portfolio", "portfolio",
({ data }) => data.draft !== true ({ data }) => data.draft !== true,
); );
const filterEnProjects = allProjects.map((project) => {
const [lang, ...slug] = project.slug.split("/");
return allProjects.map((project) => ({ if (lang === "en")
params: { slug: project.slug }, return {
props: { project }, ...project,
})); slug: slug.toString(),
};
else null;
});
return filterEnProjects.map((project) => ({
params: { slug: project?.slug },
props: { project },
}));
} }
const { project } = Astro.props; const { project } = Astro.props;
const { Content } = await project.render(); const { Content } = await project.render();
const lang = getLangFromUrl(Astro.url);
--- ---
<Layout title={project.data.title} description={project.data.description}> <Layout title={project.data.title} description={project.data.description}>
<article class="prose prose-invert"> <article class="prose prose-invert">
<h1>{project.data.title}</h1> <h1>{project.data.title}</h1>
<Content components={{ ...components }} /> <Content components={{ ...components }} />
<hr /> <hr />
<p> <p>
<strong>Posted: </strong> <strong>Posted: </strong>
{project.data.date && formatDate(new Date(project.data.date))} {project.data.date && formatDate(new Date(project.data.date), lang)}
</p> </p>
</article> </article>
</Layout> </Layout>

View File

@ -1,38 +1,55 @@
--- ---
import PostItem from "@/components/post-item"; import PostItem from "@/components/post-item";
import { getLangFromUrl } from "@/i18n/utils";
import Layout from "@/layouts/Layout.astro"; import Layout from "@/layouts/Layout.astro";
import { sortContentByDate } from "@/utils/sorts"; import { sortContentByDate } from "@/utils/sorts";
import { getCollection } from "astro:content"; import { getCollection } from "astro:content";
const pageData = { const pageData = {
title: "Portfolio", title: "Portfolio",
description: "Check my projects.", description: "Check my projects.",
}; };
const allProjects = await getCollection( const allProjects = await getCollection(
"portfolio", "portfolio",
({ data }) => data.draft !== true ({ data }) => data.draft !== true,
); );
sortContentByDate(allProjects); const allEnProjects = allProjects.map((project) => {
const [lang, ...slug] = project.slug.split("/");
if (lang === "en")
return {
...project,
slug: slug,
};
else null;
});
sortContentByDate(allEnProjects);
const lang = getLangFromUrl(Astro.url);
--- ---
<Layout {...pageData}> <Layout {...pageData}>
<section class="prose prose-invert"> <section class="prose prose-invert">
<h1>{pageData.title}</h1> <h1>{pageData.title}</h1>
<p>{pageData.description}</p> <p>{pageData.description}</p>
</section> </section>
<ul class="mt-4 flex flex-col gap-4"> <ul class="mt-4 flex flex-col gap-4">
{ {
allProjects.map((project: any) => ( allEnProjects.map(
<li> (project) =>
<PostItem project && (
type="portfolio" <li>
slug={project.slug} <PostItem
date={project.data.date!} lang={lang}
title={project.data.title!} type="portfolio"
/> slug={project.slug}
</li> date={project.data.date!}
)) title={project.data.title!}
} />
</ul> </li>
),
)
}
</ul>
</Layout> </Layout>

View File

@ -12,12 +12,29 @@ const months = [
"November", "November",
"December", "December",
]; ];
const meses = [
"Enero",
"Febrero",
"Marzo",
"Abril",
"Mayo",
"Junio",
"Julio",
"Agosto",
"Septiembre",
"Octubre",
"Noviembre",
"Diciembre",
];
export default function formatDate(date: Date | string) { export default function formatDate(date: Date | string, lang: string) {
const newDate = new Date(date); const newDate = new Date(date);
const month = months[newDate.getMonth()]; const month = months[newDate.getMonth()];
const mes = meses[newDate.getMonth()];
const day = newDate.getDate(); const day = newDate.getDate();
const year = newDate.getFullYear(); const year = newDate.getFullYear();
return `${month} ${day}, ${year}`; return lang !== "es"
? `${month} ${day}, ${year}`
: `${day} de ${mes} del ${year}`;
} }