reestructure content lang
This commit is contained in:
parent
57cb8933e2
commit
ad33d51489
@ -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}
|
||||||
|
@ -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.
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
51
src/pages/es/blog/[...slug].astro
Normal file
51
src/pages/es/blog/[...slug].astro
Normal 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>
|
52
src/pages/es/blog/index.astro
Normal file
52
src/pages/es/blog/index.astro
Normal 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>
|
@ -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>
|
||||||
|
51
src/pages/es/portfolio/[...slug].astro
Normal file
51
src/pages/es/portfolio/[...slug].astro
Normal 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>
|
55
src/pages/es/portfolio/index.astro
Normal file
55
src/pages/es/portfolio/index.astro
Normal 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>
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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}`;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user