fix: behaviour of exclude-from-list categories and posts therein
This commit is contained in:
@@ -288,7 +288,7 @@ export class BlogGenerationEngine {
|
|||||||
}
|
}
|
||||||
const publishedListPosts = Array.from(publishedListPostById.values())
|
const publishedListPosts = Array.from(publishedListPostById.values())
|
||||||
.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
||||||
const feedPosts = publishedPosts.slice(0, maxPostsPerPage);
|
const feedPosts = publishedListPosts.slice(0, maxPostsPerPage);
|
||||||
|
|
||||||
onProgress(3, `Found ${publishedPosts.length} published posts`);
|
onProgress(3, `Found ${publishedPosts.length} published posts`);
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
{% assign resolved_pico_stylesheet_href = pico_stylesheet_href | default: '/assets/pico.min.css' %}
|
{% assign resolved_pico_stylesheet_href = pico_stylesheet_href | default: '/assets/pico.min.css' %}
|
||||||
<link rel="stylesheet" href="{{ resolved_pico_stylesheet_href }}" />
|
<link rel="stylesheet" href="{{ resolved_pico_stylesheet_href }}" />
|
||||||
<link rel="stylesheet" href="/assets/lightbox.min.css" />
|
<link rel="stylesheet" href="/assets/lightbox.min.css" />
|
||||||
|
<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml" />
|
||||||
|
<link rel="alternate" type="application/atom+xml" title="Atom" href="/atom.xml" />
|
||||||
{% render 'partials/styles' %}
|
{% render 'partials/styles' %}
|
||||||
<script defer src="/assets/d3.layout.cloud.js"></script>
|
<script defer src="/assets/d3.layout.cloud.js"></script>
|
||||||
<script defer src="/assets/tag-cloud.js"></script>
|
<script defer src="/assets/tag-cloud.js"></script>
|
||||||
|
|||||||
@@ -153,8 +153,21 @@ describe('BlogGenerationEngine', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function setupPosts(posts: PostData[]): void {
|
function setupPosts(posts: PostData[]): void {
|
||||||
mockPostEngine.getPostsFiltered.mockImplementation(async (filter: { status?: string }) => {
|
mockPostEngine.getPostsFiltered.mockImplementation(async (filter: { status?: string; excludeCategories?: string[] }) => {
|
||||||
return posts.filter((p) => p.status === (filter.status ?? p.status));
|
return posts.filter((p) => {
|
||||||
|
if (p.status !== (filter.status ?? p.status)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(filter.excludeCategories) && filter.excludeCategories.length > 0) {
|
||||||
|
const categories = Array.isArray(p.categories) ? p.categories : [];
|
||||||
|
if (categories.some((category) => filter.excludeCategories?.includes(category))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
mockPostEngine.getPublishedVersion.mockResolvedValue(null);
|
mockPostEngine.getPublishedVersion.mockResolvedValue(null);
|
||||||
mockPostEngine.getPost.mockImplementation(async (id: string) => {
|
mockPostEngine.getPost.mockImplementation(async (id: string) => {
|
||||||
@@ -162,7 +175,15 @@ describe('BlogGenerationEngine', () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generate(posts: PostData[], options?: Partial<{ maxPostsPerPage: number; language: string; pageTitle: string }>) {
|
async function generate(
|
||||||
|
posts: PostData[],
|
||||||
|
options?: Partial<{
|
||||||
|
maxPostsPerPage: number;
|
||||||
|
language: string;
|
||||||
|
pageTitle: string;
|
||||||
|
categorySettings: Record<string, { renderInLists: boolean; showTitle: boolean }>;
|
||||||
|
}>,
|
||||||
|
) {
|
||||||
setupPosts(posts);
|
setupPosts(posts);
|
||||||
const { BlogGenerationEngine } = await import('../../src/main/engine/BlogGenerationEngine');
|
const { BlogGenerationEngine } = await import('../../src/main/engine/BlogGenerationEngine');
|
||||||
const engine = new BlogGenerationEngine();
|
const engine = new BlogGenerationEngine();
|
||||||
@@ -175,6 +196,7 @@ describe('BlogGenerationEngine', () => {
|
|||||||
maxPostsPerPage: options?.maxPostsPerPage,
|
maxPostsPerPage: options?.maxPostsPerPage,
|
||||||
language: options?.language,
|
language: options?.language,
|
||||||
pageTitle: options?.pageTitle,
|
pageTitle: options?.pageTitle,
|
||||||
|
categorySettings: options?.categorySettings,
|
||||||
}, onProgress);
|
}, onProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,6 +233,10 @@ describe('BlogGenerationEngine', () => {
|
|||||||
expect(html).toContain('/assets/pico.min.css');
|
expect(html).toContain('/assets/pico.min.css');
|
||||||
expect(html).toContain('/assets/lightbox.min.css');
|
expect(html).toContain('/assets/lightbox.min.css');
|
||||||
expect(html).toContain('/assets/tag-cloud.js');
|
expect(html).toContain('/assets/tag-cloud.js');
|
||||||
|
expect(html).toContain('rel="alternate" type="application/rss+xml"');
|
||||||
|
expect(html).toContain('href="/rss.xml"');
|
||||||
|
expect(html).toContain('rel="alternate" type="application/atom+xml"');
|
||||||
|
expect(html).toContain('href="/atom.xml"');
|
||||||
expect(html).not.toContain('function parseWords(');
|
expect(html).not.toContain('function parseWords(');
|
||||||
expect(html).toContain('archive-day-marker');
|
expect(html).toContain('archive-day-marker');
|
||||||
expect(html).toContain('15.01.2025');
|
expect(html).toContain('15.01.2025');
|
||||||
@@ -418,6 +444,66 @@ describe('BlogGenerationEngine', () => {
|
|||||||
expect(await fileExists(path.join(tempDir, 'html', 'category', 'my%20category', 'index.html'))).toBe(true);
|
expect(await fileExists(path.join(tempDir, 'html', 'category', 'my%20category', 'index.html'))).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('omits excluded categories from category archives and sitemap', async () => {
|
||||||
|
const posts = [
|
||||||
|
makePost({ id: '1', slug: 'aside-post', title: 'Aside Post', categories: ['aside'] }),
|
||||||
|
];
|
||||||
|
|
||||||
|
await generate(posts, {
|
||||||
|
categorySettings: {
|
||||||
|
aside: { renderInLists: false, showTitle: false },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const categoryArchivePath = path.join(tempDir, 'html', 'category', 'aside', 'index.html');
|
||||||
|
expect(await fileExists(categoryArchivePath)).toBe(false);
|
||||||
|
|
||||||
|
const sitemap = await readFile(path.join(tempDir, 'html', 'sitemap.xml'), 'utf-8');
|
||||||
|
expect(sitemap).not.toContain('https://example.com/category/aside');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('omits excluded-category posts from RSS and Atom feeds', async () => {
|
||||||
|
const posts = [
|
||||||
|
makePost({ id: '1', slug: 'aside-post', title: 'Aside Post', categories: ['aside'] }),
|
||||||
|
];
|
||||||
|
|
||||||
|
await generate(posts, {
|
||||||
|
categorySettings: {
|
||||||
|
aside: { renderInLists: false, showTitle: false },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const rss = await readFile(path.join(tempDir, 'html', 'rss.xml'), 'utf-8');
|
||||||
|
const atom = await readFile(path.join(tempDir, 'html', 'atom.xml'), 'utf-8');
|
||||||
|
|
||||||
|
expect(rss).not.toContain('<title>Aside Post</title>');
|
||||||
|
expect(atom).not.toContain('<title>Aside Post</title>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('omits posts that mix included and excluded categories from list outputs and feeds', async () => {
|
||||||
|
const posts = [
|
||||||
|
makePost({ id: '1', slug: 'mixed-post', title: 'Mixed Post', categories: ['news', 'aside'] }),
|
||||||
|
];
|
||||||
|
|
||||||
|
await generate(posts, {
|
||||||
|
categorySettings: {
|
||||||
|
aside: { renderInLists: false, showTitle: false },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(await fileExists(path.join(tempDir, 'html', 'category', 'news', 'index.html'))).toBe(false);
|
||||||
|
expect(await fileExists(path.join(tempDir, 'html', 'category', 'aside', 'index.html'))).toBe(false);
|
||||||
|
|
||||||
|
const rss = await readFile(path.join(tempDir, 'html', 'rss.xml'), 'utf-8');
|
||||||
|
const atom = await readFile(path.join(tempDir, 'html', 'atom.xml'), 'utf-8');
|
||||||
|
const sitemap = await readFile(path.join(tempDir, 'html', 'sitemap.xml'), 'utf-8');
|
||||||
|
|
||||||
|
expect(rss).not.toContain('<title>Mixed Post</title>');
|
||||||
|
expect(atom).not.toContain('<title>Mixed Post</title>');
|
||||||
|
expect(sitemap).not.toContain('https://example.com/category/news');
|
||||||
|
expect(sitemap).not.toContain('https://example.com/category/aside');
|
||||||
|
});
|
||||||
|
|
||||||
it('generates static page routes at /{slug}/index.html for posts in category page', async () => {
|
it('generates static page routes at /{slug}/index.html for posts in category page', async () => {
|
||||||
const posts = [
|
const posts = [
|
||||||
makePost({ id: 'page-1', slug: 'about', title: 'About', categories: ['page'] }),
|
makePost({ id: 'page-1', slug: 'about', title: 'About', categories: ['page'] }),
|
||||||
|
|||||||
Reference in New Issue
Block a user