From 4ee67d66be5f83db09b66fb61dcbeb2739d633e0 Mon Sep 17 00:00:00 2001
From: Fushihara <1039534+fushihara@users.noreply.github.com>
Date: Wed, 25 Sep 2024 22:12:43 +0900
Subject: =?UTF-8?q?=E8=A8=98=E4=BA=8B=E3=82=92=E3=82=BF=E3=82=B0=E3=81=A7?=
=?UTF-8?q?=E7=B5=9E=E3=82=8A=E8=BE=BC=E3=82=93=E3=81=A0=E3=83=9A=E3=83=BC?=
=?UTF-8?q?=E3=82=B8=E3=82=82=E3=83=9A=E3=83=BC=E3=82=B8=E3=83=B3=E3=82=B0?=
=?UTF-8?q?=E5=AF=BE=E5=BF=9C=E3=81=97=E3=81=9F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/app/article/_components/pagenationElement.tsx | 100 ++++++++++++++++++
src/app/article/all/[pageId]/page.tsx | 122 ++--------------------
src/app/article/tag/[tagName]/[pageNum]/page.tsx | 54 ++++++++++
src/app/article/tag/[tagName]/page.tsx | 33 +++---
src/util/arrayChunk.ts | 10 ++
src/util/articleLoader.ts | 73 +++++--------
src/util/consts.ts | 4 +
7 files changed, 225 insertions(+), 171 deletions(-)
create mode 100644 src/app/article/_components/pagenationElement.tsx
create mode 100644 src/app/article/tag/[tagName]/[pageNum]/page.tsx
create mode 100644 src/util/arrayChunk.ts
create mode 100644 src/util/consts.ts
diff --git a/src/app/article/_components/pagenationElement.tsx b/src/app/article/_components/pagenationElement.tsx
new file mode 100644
index 0000000..79191bc
--- /dev/null
+++ b/src/app/article/_components/pagenationElement.tsx
@@ -0,0 +1,100 @@
+import Link from "next/link";
+import { createPagenation } from "../../../util/pagenation";
+
+export function pagenationElement(now: number, max: number, getHrefBuilder: (page: number) => string) {
+ const pagenationData = createPagenation({ now: now, max: max, between: 2 });
+ const liElements: JSX.Element[] = [];
+ for (const v of pagenationData) {
+ if (v.type == "back") {
+ if (v.link == null) {
+ liElements.push(
+
+
+ Previous
+
+
+
+ );
+ } else {
+ liElements.push(
+
+
+ Previous
+
+
+
+ );
+ }
+ } else if (v.type == "next") {
+ if (v.link == null) {
+ liElements.push(
+
+
+ Next
+
+
+
+ );
+ } else {
+ liElements.push(
+
+
+ Next
+
+
+
+ );
+ }
+ } else if (v.type == "num") {
+ if (v.link == null) {
+ if (v.num == now) {
+ liElements.push(
+
+ {v.num}
+
+ );
+ } else {
+ liElements.push(
+
+ {v.num}
+
+ );
+ }
+ } else {
+ liElements.push(
+
+ {v.num}
+
+ );
+ }
+ } else if (v.type == "sp") {
+
+ ...
+
+ }
+ }
+ return (
+
+ );
+}
diff --git a/src/app/article/all/[pageId]/page.tsx b/src/app/article/all/[pageId]/page.tsx
index 622edbb..2b9685c 100644
--- a/src/app/article/all/[pageId]/page.tsx
+++ b/src/app/article/all/[pageId]/page.tsx
@@ -1,8 +1,9 @@
-import Link from "next/link";
import { ArticleLoader } from "../../../../util/articleLoader";
import dateformat from "dateformat";
-import { createPagenation } from "../../../../util/pagenation";
import { ArticleListElement } from "../../_components/articleListElement";
+import { PPV } from "../../../../util/consts";
+import { chunk } from "../../../../util/arrayChunk";
+import { pagenationElement } from "../../_components/pagenationElement";
dateformat.i18n.dayNames = [
'日', '月', '火', '水', '木', '金', '土',
'日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日'
@@ -26,119 +27,21 @@ export default async function Page(context: PageType) {
const displayData = chunkdData[pageId - 1];
return (
- {pagenationElement(pageId, chunkdData.length)}
+ {pagenationElement(pageId, chunkdData.length, getHrefBuilder)}
全:{loadedData.articles.length}件
{ArticleListElement(displayData, loadedData.categoryTag)}
- {pagenationElement(pageId, chunkdData.length)}
+ {pagenationElement(pageId, chunkdData.length, getHrefBuilder)}
);
}
-function pagenationElement(now: number, max: number) {
- const pagenationData = createPagenation({ now: now, max: max, between: 2 });
- const liElements: JSX.Element[] = [];
- for (const v of pagenationData) {
- if (v.type == "back") {
- if (v.link == null) {
- liElements.push(
-
-
- Previous
-
-
-
- );
- } else {
- liElements.push(
-
-
- Previous
-
-
-
- );
- }
- } else if (v.type == "next") {
- if (v.link == null) {
- liElements.push(
-
-
- Next
-
-
-
- );
- } else {
- liElements.push(
-
-
- Next
-
-
-
- );
- }
- } else if (v.type == "num") {
- if (v.link == null) {
- if (v.num == now) {
- liElements.push(
-
- {v.num}
-
- );
- } else {
- liElements.push(
-
- {v.num}
-
- );
- }
- } else {
- liElements.push(
-
- {v.num}
-
- );
- }
- } else if (v.type == "sp") {
-
- ...
-
- }
- }
- return (
-
- );
+function getHrefBuilder(page: number): string {
+ return `/article/all/page-${page}`;
}
function getPageIdNumber(pageIdStr: string) {
const m = pageIdStr.match(/page-(\d+)/)!;
const id = Number(m[1]);
return id;
}
-const PPV = Number(process.env["AKIBA_SOUKEN_AR_ITEM_PPV"] ?? "100");
-if (!Number.isInteger(PPV)) {
- throw new Error(`AKIBA_SOUKEN_AR_ITEM_PPVに整数をセットして下さい`);
-}
//export const dynamicParams = true;
export async function generateStaticParams() {
const loadedData = await ArticleLoader.instance.loadData();
@@ -147,14 +50,3 @@ export async function generateStaticParams() {
return { pageId: `page-${index + 1}`, data: data };
});
}
-
-function chunk(list: T[], len: number) {
- if (len <= 0) {
- throw new Error();
- }
- const result: T[][] = [];
- for (let i = 0; i < list.length; i += len) {
- result.push(list.slice(i, i + len));
- }
- return result;
-}
\ No newline at end of file
diff --git a/src/app/article/tag/[tagName]/[pageNum]/page.tsx b/src/app/article/tag/[tagName]/[pageNum]/page.tsx
new file mode 100644
index 0000000..1820f65
--- /dev/null
+++ b/src/app/article/tag/[tagName]/[pageNum]/page.tsx
@@ -0,0 +1,54 @@
+import { chunk } from "../../../../../util/arrayChunk";
+import { ArticleLoader } from "../../../../../util/articleLoader";
+import { PPV } from "../../../../../util/consts";
+import { ArticleListElement } from "../../../_components/articleListElement";
+import { pagenationElement } from "../../../_components/pagenationElement";
+
+type PageType = {
+ searchParams: Record,
+ params: {
+ tagName: string,
+ pageNum: string,
+ }
+}
+export async function generateMetadata(context: PageType) {
+ return {
+ title: `アキバ総研アーカイブ:タグの記事一覧 ${context.params.tagName}`,
+ }
+}
+export default async function Page(context: PageType) {
+ const pageNumber = Number(context.params.pageNum);
+ const nowPageTagName = decodeURIComponent(context.params.tagName);
+ const categoryTag = await ArticleLoader.instance.getCategoryTag();
+ const loadedData = await ArticleLoader.instance.getTagArticle(nowPageTagName);
+ const chunkdData = chunk(loadedData, PPV);
+ const displayData = chunkdData[pageNumber - 1];
+ return (
+
+
タグ:{nowPageTagName} の記事一覧
+
全:{loadedData.length}件
+ {pagenationElement(pageNumber, chunkdData.length, getHrefBuilder(nowPageTagName))}
+ {ArticleListElement(displayData, categoryTag)}
+ {pagenationElement(pageNumber, chunkdData.length, getHrefBuilder(nowPageTagName))}
+
+ );
+}
+function getHrefBuilder(tagName: string) {
+ return (page: number) => {
+ if (page == 1) {
+ return `/article/tag/${tagName}/`;
+ } else {
+ return `/article/tag/${tagName}/${page}/`;
+ }
+ }
+}
+export async function generateStaticParams() {
+ const articleData = await ArticleLoader.instance.loadData();
+ const result: PageType["params"][] = [];
+ for (const [tag, data] of articleData.categoryTag.data) {
+ for (let page = 2; page <= Math.ceil(data.count / PPV); page++) {
+ result.push({ tagName: tag, pageNum: String(page) });
+ }
+ }
+ return result;
+}
diff --git a/src/app/article/tag/[tagName]/page.tsx b/src/app/article/tag/[tagName]/page.tsx
index 7fbce4c..4cef1d3 100644
--- a/src/app/article/tag/[tagName]/page.tsx
+++ b/src/app/article/tag/[tagName]/page.tsx
@@ -1,5 +1,8 @@
+import { chunk } from "../../../../util/arrayChunk";
import { ArticleLoader } from "../../../../util/articleLoader";
+import { PPV } from "../../../../util/consts";
import { ArticleListElement } from "../../_components/articleListElement";
+import { pagenationElement } from "../../_components/pagenationElement";
type PageType = {
searchParams: Record,
params: {
@@ -13,24 +16,30 @@ export async function generateMetadata(context: PageType) {
}
export default async function Page(context: PageType) {
const nowPageTagName = decodeURIComponent(context.params.tagName);
- const loadedData = await ArticleLoader.instance.loadData()
- const filterdArticles = loadedData.articles.filter(article => {
- if (article.tags.includes(nowPageTagName)) {
- return true;
- }
- if (article.breadLinks.includes(nowPageTagName)) {
- return true;
- }
- return false;
- });
+ const categoryTag = await ArticleLoader.instance.getCategoryTag();
+ const loadedData = await ArticleLoader.instance.getTagArticle(nowPageTagName);
+ const chunkdData = chunk(loadedData, PPV);
+ const displayData = chunkdData[0];
return (
タグ:{nowPageTagName} の記事一覧
-
全:{filterdArticles.length}件
- {ArticleListElement(filterdArticles, loadedData.categoryTag)}
+
全:{loadedData.length}件
+ {pagenationElement(1, chunkdData.length, getHrefBuilder(nowPageTagName))}
+ {ArticleListElement(displayData, categoryTag)}
+ {pagenationElement(1, chunkdData.length, getHrefBuilder(nowPageTagName))}
);
}
+function getHrefBuilder(tagName: string) {
+ return (page: number) => {
+ if (page == 1) {
+ return `/article/tag/${tagName}/`;
+ } else {
+ return `/article/tag/${tagName}/${page}/`;
+ }
+ }
+}
+
export async function generateStaticParams() {
const articleData = await ArticleLoader.instance.loadData();
const result: { tagName: string }[] = [];
diff --git a/src/util/arrayChunk.ts b/src/util/arrayChunk.ts
new file mode 100644
index 0000000..de1151c
--- /dev/null
+++ b/src/util/arrayChunk.ts
@@ -0,0 +1,10 @@
+export function chunk(list: T[], len: number) {
+ if (len <= 0) {
+ throw new Error();
+ }
+ const result: T[][] = [];
+ for (let i = 0; i < list.length; i += len) {
+ result.push(list.slice(i, i + len));
+ }
+ return result;
+}
\ No newline at end of file
diff --git a/src/util/articleLoader.ts b/src/util/articleLoader.ts
index f7c7e95..7ce98b3 100644
--- a/src/util/articleLoader.ts
+++ b/src/util/articleLoader.ts
@@ -26,6 +26,26 @@ export class ArticleLoader {
this.dataCache = loadedData;
return loadedData;
}
+ async getCategoryTag() {
+ const loadedData = await this._loadData();
+ return loadedData.categoryTag;
+ }
+ /**
+ * 指定のタグ、パンくずリストの記事一覧を取得
+ */
+ async getTagArticle(tagName: string) {
+ const loadedData = await this._loadData();
+ const filterdArticles = loadedData.articles.filter(article => {
+ if (article.tags.includes(tagName)) {
+ return true;
+ }
+ if (article.breadLinks.includes(tagName)) {
+ return true;
+ }
+ return false;
+ });
+ return filterdArticles;
+ }
private async _loadData() {
const articleJsonPath = process.env["AKIBA_SOUKEN_ARTICLE_JSON"]!;
const jsonStr = await readFile(articleJsonPath, { encoding: "utf-8" }).then(text => {
@@ -50,47 +70,6 @@ export class ArticleLoader {
categoryTag: categoryTagData,
};
}
- /**
- *
- * @returns [{tag:"タグ名",category:string,count:100}] の値。カテゴリに属していないタグはカテゴリが空文字。
- * カテゴリ自体を指す場合は {tag:"ホビー",category:"ホビー",count:100} の様に同じ値が入る事がある。
- * ソート順は未定義
- * @deprecated
- */
- // async getTagList() {
- // const loadedData = await this.loadData();
- // // 先にパンくずリストを全部見る
- // const breadcrumb = new Breadcrumb();
- // for (const a of loadedData.articles) {
- // breadcrumb.push(a.breadLinks);
- // }
- // // key:タグ名 , val:回数
- // const tagCount = new Map();
- // // パンくずリストに含まれないタグを調査
- // for (const a of loadedData.articles) {
- // for (const tag of a.tags) {
- // if (breadcrumb.strExists(tag)) {
- // continue;
- // }
- // const tagData = tagCount.get(tag);
- // if (tagData != null) {
- // tagCount.set(tag, tagData + 1);
- // } else {
- // tagCount.set(tag, 1);
- // }
- // }
- // }
- // const result: { tag: string, category: string, count: number }[] = [];
- // for (const [name, count] of tagCount) {
- // result.push({ tag: name, count: count, category: "" });
- // }
- // for (const b of breadcrumb.getFlatArray()) {
- // const breadcrumbName = b.breadcrumb[b.breadcrumb.length - 1];//パンくずリストの最後の項目
- // const category = b.breadcrumb[0];//カテゴリ名
- // result.push({ tag: breadcrumbName, count: b.count, category: category });
- // }
- // return result;
- // }
}
type TagName = string;
class CategoryTag {
@@ -165,13 +144,19 @@ class Article {
return this.tagsCache;
}
const tags: { name: string, category: string | "" }[] = [];
- for (const v of this.data.tags) {
- tags.push({ name: v, category: "" })
- };
const category = this.data.breadLinks[0];
+ // パンくずリストとタグに同じ文字が入っている場合がある。その場合はパンくずリスト優先
+ // 例: パンくずリスト:ホビー>コスプレ タグ:コスプレ/コミケ/独自取材
+
for (const v of this.data.breadLinks) {
tags.push({ name: v, category: category });
};
+ for (const v of this.data.tags) {
+ if (this.data.breadLinks.includes(v)) {
+ continue;
+ }
+ tags.push({ name: v, category: "" })
+ };
this.tagsCache = tags;
return tags;
}
diff --git a/src/util/consts.ts b/src/util/consts.ts
new file mode 100644
index 0000000..5dc77ba
--- /dev/null
+++ b/src/util/consts.ts
@@ -0,0 +1,4 @@
+export const PPV = Number(process.env["AKIBA_SOUKEN_AR_ITEM_PPV"] ?? "100");
+if (!Number.isInteger(PPV)) {
+ throw new Error(`AKIBA_SOUKEN_AR_ITEM_PPVに整数をセットして下さい`);
+}
--
cgit v1.2.3