From 79fd506d30eef3d113f4a8e3ab9ebd9004f1e8cc Mon Sep 17 00:00:00 2001 From: João Augusto Costa Branco Marado Torres Date: Sat, 28 Jun 2025 18:14:22 -0300 Subject: feat: index page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: João Augusto Costa Branco Marado Torres --- src/pages/blog/[...year].astro | 30 +++++------ src/pages/blog/micro/[page].astro | 32 +++++++++++ src/pages/blog/read/[...slug].astro | 74 +++++++++++++------------ src/pages/index.astro | 104 ++++++++++++++++++++++++++++++++---- src/pages/robots.txt.ts | 4 +- src/pages/rss.xml.js | 16 ------ src/pages/rss.xml.ts | 32 +++++++++++ 7 files changed, 214 insertions(+), 78 deletions(-) create mode 100644 src/pages/blog/micro/[page].astro delete mode 100644 src/pages/rss.xml.js create mode 100644 src/pages/rss.xml.ts (limited to 'src/pages') diff --git a/src/pages/blog/[...year].astro b/src/pages/blog/[...year].astro index f148a76..1742baa 100644 --- a/src/pages/blog/[...year].astro +++ b/src/pages/blog/[...year].astro @@ -1,20 +1,16 @@ --- +import type { + GetStaticPaths, + InferGetStaticParamsType, + InferGetStaticPropsType, +} from "astro"; import { getCollection } from "astro:content"; -import type { CollectionEntry } from "astro:content"; import Base from "@layouts/Base.astro"; import DateSelector from "@components/DateSelector.astro"; import BlogCard from "@components/BlogCard.astro"; +import { sortLastCreated } from "@lib/collection/helpers"; -type Props = { - posts: CollectionEntry<"blog">[]; - next: string; - previous: string; - years: number[]; - months: number[]; - days?: number[]; -}; - -export async function getStaticPaths() { +export const getStaticPaths = (async () => { const posts = await getCollection("blog"); const archive = { @@ -128,7 +124,7 @@ export async function getStaticPaths() { paths.push({ params: { year: ymd }, props: { - posts: archive.postsByDate.get(ymd), + posts: archive.postsByDate.get(ymd) ?? [], next: archive.sortedDates?.[i + 1], previous: archive.sortedDates?.[i - 1], years: sortedYears, @@ -139,16 +135,16 @@ export async function getStaticPaths() { } return paths; -} +}) satisfies GetStaticPaths; + +export type Params = InferGetStaticParamsType; +export type Props = InferGetStaticPropsType; const title = "Blog"; const description = "Latest articles."; let { posts, previous, next, years, months, days } = Astro.props; -posts = posts.sort((a, b) => - new Date(b.data.dateCreated).valueOf() - - new Date(a.data.dateCreated).valueOf() -); +posts = posts.sort(sortLastCreated); const date = posts[0].data.dateCreated as Date; --- diff --git a/src/pages/blog/micro/[page].astro b/src/pages/blog/micro/[page].astro new file mode 100644 index 0000000..9fb04f1 --- /dev/null +++ b/src/pages/blog/micro/[page].astro @@ -0,0 +1,32 @@ +--- +import MicroBlog from "@components/templates/MicroBlog.astro"; +import Base from "@layouts/Base.astro"; +import { fromPosts, isMicro } from "@lib/collection/helpers"; +import { identity } from "@utils/anonymous"; +import type { + GetStaticPaths, + InferGetStaticParamsType, + InferGetStaticPropsType, +} from "astro"; + +export const getStaticPaths = (async ({ paginate }) => { + const micros = await fromPosts(isMicro, identity); + + return paginate(micros, { pageSize: 20 }); +}) satisfies GetStaticPaths; + +export type Params = InferGetStaticParamsType; +export type Props = InferGetStaticPropsType; + +const { page } = Astro.props; +--- + +

Page {page.currentPage}

+
    + {page.data.map((micro) =>
  • )} +
+ {page.url.first ? First : null} + {page.url.prev ? Previous : null} + {page.url.next ? Next : null} + {page.url.last ? Last : null} + diff --git a/src/pages/blog/read/[...slug].astro b/src/pages/blog/read/[...slug].astro index 05d68e8..348a976 100644 --- a/src/pages/blog/read/[...slug].astro +++ b/src/pages/blog/read/[...slug].astro @@ -9,9 +9,9 @@ import Keywords from "@components/Keywords.astro"; import Citations from "@components/Citations.astro"; import Signature from "@components/signature/Signature.astro"; import CopyrightNotice from "@components/CopyrightNotice.astro"; -import { getEntries } from "astro:content"; import { verifier as verifierPrototype } from "@lib/pgp/verify"; -import { defined, get } from "@utils/anonymous"; +import { getSigners } from "@lib/collection/helpers"; +import { get } from "@utils/anonymous"; import Authors from "@components/signature/Authors.astro"; import { getEntry } from "astro:content"; @@ -27,8 +27,9 @@ type Props = CollectionEntry<"blog">; const post = Astro.props; -if (defined(post.data.translationOf)) { - const original = await getEntry( +let original: CollectionEntry<"blog">; +if (post.data.kind === "translation") { + original = await getEntry( post.data.translationOf as CollectionEntry<"blog">, ); @@ -40,15 +41,15 @@ if (defined(post.data.translationOf)) { (s) => s.role === "author", ).map((s) => s.entity.id)?.[0]; const originalCoAuthors = new Set( - (original.data.signer ?? []).filter( + (original.data.signers ?? []).filter( (s) => s.role === "co-author", ).map((s) => s.entity.id), ); - const translationAuthor = (post.data.signer ?? []).filter( + const translationAuthor = (post.data.signers ?? []).filter( (s) => s.role === "author", ).map((s) => s.entity.id)?.[0]; const translationCoAuthors = new Set( - (post.data.signer ?? []).filter( + (post.data.signers ?? []).filter( (s) => s.role === "co-author", ).map((s) => s.entity.id), ); @@ -63,7 +64,7 @@ if (defined(post.data.translationOf)) { ); } - const translators = (post.data.signer ?? []).filter( + const translators = (post.data.signers ?? []).filter( (s) => s.role === "translator", ).map((s) => s.entity.id); @@ -77,7 +78,8 @@ if (defined(post.data.translationOf)) { } } } else { - if (post.data.signer?.some((x) => x.role === "translator")) { + original = post; + if (post.data.signers?.some((x) => x.role === "translator")) { throw new Error( `Post ${post.id} is not a translation but has translators defined`, ); @@ -89,8 +91,8 @@ const translationsSet = new Set( (await getCollection( "blog", (x) => - x.data.translationOf?.id === - (post.data.translationOf !== undefined + (x.data.kind === "translation") && x.data.translationOf.id === + (post.data.kind === "translation" ? post.data.translationOf.id : post.id), ) ?? []).map(({ id }) => id), @@ -102,16 +104,7 @@ const translations = [...translationsSet.values()].map((id) => ({ id, })); -const signers = await getEntries( - post.data.signer?.map(get("entity")) ?? [], -).then((x) => x.filter(defined)) - .then((x) => - x.map((x) => ({ - entity: x, - role: post.data.signer?.find((y) => y.entity.id === x.id)?.role, - })) - ) - .then((x) => x.filter((x) => x.role !== undefined)); +const signers = await getSigners(post); const verifier = await verifierPrototype.then((x) => x.clone()); @@ -137,7 +130,12 @@ const commit = await verification?.commit; - + @@ -151,7 +149,7 @@ const commit = await verification?.commit;

{post.data.title}

{ - post.data.subtitle && ( + "subtitle" in post.data && (

{post.data.subtitle}

@@ -159,7 +157,8 @@ const commit = await verification?.commit; }
{ - post.data.description && ( + "description" in post.data && post.data.description && + (

Resumo

{ @@ -181,7 +180,7 @@ const commit = await verification?.commit; ) } @@ -201,7 +200,7 @@ const commit = await verification?.commit; post.data.dateUpdated && (
Última atualização

- - + { + "keywords" in original.data && ( + + ) + } + { + "relatedPosts" in original.data && ( + + ) + } diff --git a/src/pages/index.astro b/src/pages/index.astro index eea5205..7e506bd 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,28 +1,112 @@ --- +import MicroBlog from "@components/templates/MicroBlog.astro"; +import SimplePostList from "@components/templates/SimplePostList.astro"; import Base from "@layouts/Base.astro"; -import { SITE_TITLE } from "src/consts"; +import { + fromPosts, + isMicro, + isOriginal, + sortLastUpdated, +} from "@lib/collection/helpers"; +import { env } from "@lib/env"; + +const { PUBLIC_SITE_TITLE } = env; + +const originals = await fromPosts( + isOriginal, + (originals) => originals.sort(sortLastUpdated).slice(0, 10), +); +const micro = await fromPosts( + isMicro, + (originals) => originals.sort(sortLastUpdated)?.[0], +); --- - +

Viva abril!

- «Los que le cierran el camino a la revolución - pacífica le abren al mismo tiempo el camino a la - revolución violenta». + «Los que le cierran el camino a la revolución pacífica le abren al + mismo tiempo el camino a la revolución violenta.»
- — Hugo Chávez. + — Hugo Chávez.

- Tradução: “Aqueles que fecham o caminho para a - revolução pacífica abrem, ao mesmo tempo, o - caminho para a revolução violenta.” + Tradução: “Aqueles que fecham o caminho para a + revolução pacífica abrem, ao mesmo tempo, o caminho para a + revolução violenta”.

-

Portugal fez diferente!

+

Portugal fez diferente!

+ { + (originals.length > 0 || micro) && ( +
+

Últimas aplicações atualizadas

+ {micro &&
} +
+
+ ) + }
+ + diff --git a/src/pages/robots.txt.ts b/src/pages/robots.txt.ts index 4edef8b..78c9fdf 100644 --- a/src/pages/robots.txt.ts +++ b/src/pages/robots.txt.ts @@ -1,4 +1,4 @@ -import type { APIRoute } from "astro"; +import type { APIContext, APIRoute } from "astro"; const getRobotsTxt = (sitemapURL: URL) => ` User-agent: * @@ -7,7 +7,7 @@ Allow: / Sitemap: ${sitemapURL.href} `; -export const GET: APIRoute = ({ site }) => { +export const GET: APIRoute = ({ site }: APIContext): Response => { const sitemapURL = new URL("sitemap-index.xml", site); return new Response(getRobotsTxt(sitemapURL)); }; diff --git a/src/pages/rss.xml.js b/src/pages/rss.xml.js deleted file mode 100644 index de5685b..0000000 --- a/src/pages/rss.xml.js +++ /dev/null @@ -1,16 +0,0 @@ -import rss from "@astrojs/rss"; -import { getCollection } from "astro:content"; -import { SITE_DESCRIPTION, SITE_TITLE } from "../consts"; - -export async function GET(context) { - const posts = await getCollection("blog"); - return rss({ - title: SITE_TITLE, - description: SITE_DESCRIPTION, - site: context.site, - items: posts.map((post) => ({ - ...post.data, - link: `/blog/${post.id}/`, - })), - }); -} diff --git a/src/pages/rss.xml.ts b/src/pages/rss.xml.ts new file mode 100644 index 0000000..c07f3bd --- /dev/null +++ b/src/pages/rss.xml.ts @@ -0,0 +1,32 @@ +import rss, { type RSSFeedItem } from "@astrojs/rss"; +import { getCollection } from "astro:content"; +import type { APIContext, APIRoute } from "astro"; +import { Blog } from "../lib/collection/schemas.ts"; +import { getFirstAuthorEmail } from "../lib/collection/helpers.ts"; +import { env } from "../lib/env.ts"; + +const { PUBLIC_SITE_TITLE, PUBLIC_SITE_DESCRIPTION, PUBLIC_SITE_URL } = env; + +export const GET: APIRoute = async (context: APIContext): Promise => { + const posts = await getCollection("blog"); + return rss({ + title: PUBLIC_SITE_TITLE, + description: PUBLIC_SITE_DESCRIPTION, + site: context.site ?? PUBLIC_SITE_URL, + items: await Promise.all(posts.map(async (post): Promise => { + const { id, rendered } = post; + const blog = Blog.parse(post.data); + + const { title, dateUpdated, dateCreated } = blog; + return { + description: "description" in blog ? blog.description : undefined, + title, + author: await getFirstAuthorEmail(post), + content: rendered?.html, + pubDate: dateUpdated ?? dateCreated, + categories: "keywords" in blog ? blog.keywords : undefined, + link: `/blog/read/${id}/`, + }; + })), + }); +}; -- cgit v1.2.3