ld-site/src/components/article/CollectionSummary.astro

111 lines
3.4 KiB
Plaintext

---
import type { CollectionEntry, ContentEntryMap } from "astro:content";
import { getCollection, type CollectionKey } from "astro:content";
import CategorySummary from "./CategorySummary.astro";
import * as pinyinpro from "pinyin-pro";
interface Props {
collectionName: CollectionKey;
sortByTimeline: boolean;
sortByArticleTitle: boolean;
}
const { collectionName, sortByTimeline, sortByArticleTitle } = Astro.props;
type CategoriedPosts = {
[categoryName: string]: Array<CollectionEntry<CollectionKey>>;
};
const allPosts: CollectionEntry<CollectionKey>[] =
await getCollection(collectionName);
const allCategories: Array<string> = Array.from(
new Set(
allPosts.map((entry) => {
return entry.data.category;
}),
),
);
const categoriedPostList: Array<CategoriedPosts> = allCategories.map((key) => {
let object: CategoriedPosts = {};
object[key] = allPosts.filter((post) => post.data.category === key);
// article sort function by article title
function sortPostByTitlePinyin(
postA: CollectionEntry<CollectionKey>,
postB: CollectionEntry<CollectionKey>,
): number {
let postATitle = pinyinpro.convert(pinyinpro.pinyin(postA.data.title), {
format: "symbolToNum",
});
let postBTitle = pinyinpro.convert(pinyinpro.pinyin(postB.data.title), {
format: "symbolToNum",
});
return postATitle.localeCompare(postBTitle, "en");
}
if (sortByTimeline) {
// sort article by update date
object[key].sort((postA, postB) => {
// if two articles is updated on the same day, sort them by title
if (postA.data.lastUpdate !== postB.data.lastUpdate) {
return postA.data.lastUpdate < postB.data.lastUpdate ? 1 : -1;
}
return sortPostByTitlePinyin(postA, postB);
});
} else if (sortByArticleTitle) {
// sort article by title
// get articles with titles started in Chinese or the alphabet
let postWithAlphabetStartedTitle: CollectionEntry<keyof ContentEntryMap>[] =
object[key].filter((post) => /^[a-zA-Z]/.test(post.data.title));
let postWithChineseStartedTitle: CollectionEntry<keyof ContentEntryMap>[] =
object[key].filter((post) => /^[^a-zA-Z]/.test(post.data.title));
// sort two Array by article title
postWithAlphabetStartedTitle.sort((postA, postB) =>
sortPostByTitlePinyin(postA, postB),
);
postWithChineseStartedTitle.sort((postA, postB) =>
sortPostByTitlePinyin(postA, postB),
);
// articles that have title start with Chinese prior to
// those which have titles start with the alphabet
object[key] = postWithChineseStartedTitle.concat(
postWithAlphabetStartedTitle,
);
}
return object;
});
const categoriedPostListSortedByArticleAmount: Array<CategoriedPosts> =
JSON.parse(JSON.stringify(categoriedPostList)).sort(
(a: CategoriedPosts, b: CategoriedPosts) => {
const aKey: string = Object.keys(a)[0];
const bKey: string = Object.keys(b)[0];
return b[bKey].length - a[aKey].length;
},
);
---
<div class="collection-desc">
{
categoriedPostListSortedByArticleAmount.map((obj) => (
<div class="collection-desc-item">
<CategorySummary
collectionName={collectionName}
categoryName={Object.keys(obj)[0]}
posts={obj[Object.keys(obj)[0]]}
/>
</div>
))
}
</div>
<style>
.collection-desc::after {
display: block;
content: "";
clear: both;
}
</style>