feat(post-overview): add excludeTag functionality for filtering posts
Deploy / verify (push) Successful in 39s
Deploy / deploy (push) Failing after 1m7s

- Introduced `excludeTag` property in PostOverviewBlockData interface to allow exclusion of specific tag slugs.
- Implemented `excludePostsByTagSlugs` function to filter out posts containing specified tag slugs.
- Updated `resolvePostOverviewBlocks` function to utilize the new exclusion logic, enhancing post filtering capabilities.
This commit is contained in:
Peter Meier
2026-04-19 14:18:50 +02:00
parent 4ec2aa10ec
commit 2ee451f4ca
2 changed files with 29 additions and 0 deletions
+2
View File
@@ -182,6 +182,8 @@ export interface PostOverviewBlockData {
posts?: unknown[]; posts?: unknown[];
/** Tag-Slugs, nach denen gefiltert wird (nur bei allPosts true). */ /** Tag-Slugs, nach denen gefiltert wird (nur bei allPosts true). */
filterByTag?: string[]; filterByTag?: string[];
/** Tag-Slugs, die ausgeschlossen werden (optional, nach filterByTag angewendet). */
excludeTag?: string[];
/** Max. Anzahl Einträge. */ /** Max. Anzahl Einträge. */
numberItems?: number; numberItems?: number;
/** "list" | "cards". */ /** "list" | "cards". */
+27
View File
@@ -164,6 +164,21 @@ export function filterPostsByTagSlugs(
}); });
} }
/** Filtert Posts: entfernt solche, die mindestens einen der Tag-Slugs haben. */
export function excludePostsByTagSlugs(
posts: PostEntry[],
tagSlugs: string[],
): PostEntry[] {
if (!tagSlugs?.length) return posts;
return posts.filter((p) => {
const tags = p.postTag ?? [];
return !tags.some((t) => {
const slug = typeof t === "string" ? t : (t as { _slug?: string })?._slug;
return tagSlugs.includes(slug ?? "");
});
});
}
export function getTotalPages(count: number, perPage: number): number { export function getTotalPages(count: number, perPage: number): number {
return Math.max(1, Math.ceil(count / perPage)); return Math.max(1, Math.ceil(count / perPage));
} }
@@ -347,6 +362,7 @@ function isPostOverviewBlock(item: unknown): item is {
allPosts?: boolean; allPosts?: boolean;
posts?: unknown[]; posts?: unknown[];
filterByTag?: unknown[]; filterByTag?: unknown[];
excludeTag?: unknown[];
numberItems?: number; numberItems?: number;
postsResolved?: unknown[]; postsResolved?: unknown[];
} { } {
@@ -389,6 +405,16 @@ export async function resolvePostOverviewBlocks(
) )
.filter(Boolean) .filter(Boolean)
: []; : [];
const rawExclude = item.excludeTag ?? [];
const excludeSlugs = Array.isArray(rawExclude)
? rawExclude
.map((t) =>
typeof t === "string"
? t
: ((t as { _slug?: string })?._slug ?? ""),
)
.filter(Boolean)
: [];
const hasExplicitPosts = Array.isArray(item.posts) && item.posts.length > 0; const hasExplicitPosts = Array.isArray(item.posts) && item.posts.length > 0;
const useAllPosts = item.allPosts || (tagSlugs.length > 0 && !hasExplicitPosts); const useAllPosts = item.allPosts || (tagSlugs.length > 0 && !hasExplicitPosts);
if (useAllPosts) { if (useAllPosts) {
@@ -400,6 +426,7 @@ export async function resolvePostOverviewBlocks(
}); });
let list = filterHiddenPosts(sortPostsByDate(allPosts)); let list = filterHiddenPosts(sortPostsByDate(allPosts));
if (tagSlugs.length) list = filterPostsByTagSlugs(list, tagSlugs); if (tagSlugs.length) list = filterPostsByTagSlugs(list, tagSlugs);
if (excludeSlugs.length) list = excludePostsByTagSlugs(list, excludeSlugs);
const limit = const limit =
typeof item.numberItems === "number" ? item.numberItems : 9999; typeof item.numberItems === "number" ? item.numberItems : 9999;
item.postsResolved = list.slice(0, limit); item.postsResolved = list.slice(0, limit);