diff --git a/pages/components/middle/article_content.tsx b/pages/components/middle/article_content.tsx
index 4968c2a..50d272d 100644
--- a/pages/components/middle/article_content.tsx
+++ b/pages/components/middle/article_content.tsx
@@ -8,20 +8,23 @@ import LinkCard from './article_dom/linkcard'
import { cn } from '@/lib/utils'
import Br from './article_dom/br'
import Blockquote from './article_dom/blockquote'
-import { ParsedContent } from 'api-types'
+import { ParsedContent, TableOfContents } from 'api-types'
import { Suspense } from 'react'
import LoadingLinkcard from './loading_dom/loading_linkcard'
import BlogCard from './article_dom/blogcard'
import LoadingBlogCard from './loading_dom/loading_blogcard'
+import Table from './article_dom/table_of_contents'
export default async function ArticleContent({
contents,
articleID,
sample,
+ tableOfContents,
}: {
contents: ParsedContent[]
articleID: string
sample?: boolean
+ tableOfContents?: TableOfContents
}) {
const sampleFlag = sample || false
const sampleClassName = 'content-sample line-clamp-6 max-h-72'
@@ -43,7 +46,7 @@ export default async function ArticleContent({
// h1 ~ h5
// 正規表現でヒットさせる
if (tagName.match(/h[1-5]/)) {
- return
+ return
}
// hr
@@ -142,6 +145,13 @@ export default async function ArticleContent({
} else if (pOption === 'empty') {
// 空行の場合。改行をいれる
return
+ } else if (pOption === 'table_of_contents') {
+ if (tableOfContents) {
+ return
+ } else {
+ // 目次情報がない場合は何も表示しない
+ return <>>
+ }
}
// どれにも該当しない場合。ほぼないはずだが、新規の p_option が追加された場合必要になる
return
diff --git a/pages/components/middle/article_dom/h.tsx b/pages/components/middle/article_dom/h.tsx
index 9422269..cbcb453 100644
--- a/pages/components/middle/article_dom/h.tsx
+++ b/pages/components/middle/article_dom/h.tsx
@@ -1,16 +1,22 @@
// CMSデータの h1, h2... は、ブログ内のコンテンツに合わせたときタイトルを h1 とする都合でそれぞれ一つずつ下の階層に置換する
-export default function Hn({ tag, text }: { tag: string; text: string }) {
+export default function Hn({ tag, text, attrs }: { tag: string; text: string; attrs?: { [key: string]: string } }) {
+ const id = attrs?.id ? attrs.id : undefined
+
if (tag === 'h1') {
return (
-
{text}
+
+ {text}
+
)
}
if (tag === 'h2') {
return (
-
{text}
+
+ {text}
+
)
}
@@ -18,7 +24,9 @@ export default function Hn({ tag, text }: { tag: string; text: string }) {
return (
)
}
@@ -26,12 +34,18 @@ export default function Hn({ tag, text }: { tag: string; text: string }) {
return (
)
}
if (tag === 'h5') {
- return
{text}
+ return (
+
+ {text}
+
+ )
}
return
{text}
}
diff --git a/pages/components/middle/article_dom/table_of_contents.tsx b/pages/components/middle/article_dom/table_of_contents.tsx
new file mode 100644
index 0000000..ddbcbd2
--- /dev/null
+++ b/pages/components/middle/article_dom/table_of_contents.tsx
@@ -0,0 +1,63 @@
+import { TableOfContents } from 'api-types'
+
+export default function Table({ toc }: { toc: TableOfContents }) {
+ let beforeLevel = 0
+ return (
+
+
Contents
+
+ {toc.map((t, i) => {
+ if (t.level <= 1) {
+ const levelDown = beforeLevel > t.level
+ beforeLevel = t.level
+ return (
+
+ )
+ } else if (t.level === 2) {
+ const levelDown = beforeLevel > t.level
+ beforeLevel = t.level
+ return (
+
+ )
+ } else if (t.level === 3) {
+ const levelDown = beforeLevel > t.level
+ beforeLevel = t.level
+ return (
+
+ )
+ } else {
+ const levelDown = beforeLevel > t.level
+ beforeLevel = t.level
+ return (
+
+ )
+ }
+ })}
+
+
+ )
+}
diff --git a/pages/lib/api/workers.ts b/pages/lib/api/workers.ts
index 5671a75..de47c5d 100644
--- a/pages/lib/api/workers.ts
+++ b/pages/lib/api/workers.ts
@@ -1,5 +1,8 @@
import { getRequestContext } from '@cloudflare/next-on-pages'
import { categoryAPIResult, contentsAPIResult, infoAPIResult, OGPResult } from 'api-types'
+import { getNodeEnv } from '../env'
+
+const revalidateTime = getNodeEnv() === 'production' ? 60 : 0
async function getOGPData(targetURL: string) {
const { env } = getRequestContext()
@@ -11,7 +14,7 @@ async function getOGPData(targetURL: string) {
const request = new Request(url, { headers: { 'x-api-key': ogpAPIKey }, method: 'GET' })
- const res = await fetch(request)
+ const res = await fetch(request, { next: { revalidate: revalidateTime } })
const data = (await res.json()) as OGPResult
return data
@@ -28,7 +31,7 @@ async function getCMSContents(offset?: number, limit?: number) {
const request = new Request(url, { headers: { 'x-api-key': cmsAPIKey }, method: 'GET' })
- const res = await fetch(request)
+ const res = await fetch(request, { next: { revalidate: revalidateTime } })
const data = (await res.json()) as { contents: contentsAPIResult[]; total: number }
return data
@@ -45,7 +48,7 @@ async function getCMSContent(articleID: string, draftKey?: string) {
const request = new Request(url, { headers: { 'x-api-key': cmsAPIKey }, method: 'GET' })
- const res = await fetch(request)
+ const res = await fetch(request, { next: { revalidate: revalidateTime } })
const data = (await res.json()) as contentsAPIResult
return data
@@ -63,7 +66,7 @@ async function getCMSContentsWithTags(tagIDs: string[], offset?: number, limit?:
const request = new Request(url, { headers: { 'x-api-key': cmsAPIKey }, method: 'GET' })
- const res = await fetch(request)
+ const res = await fetch(request, { next: { revalidate: revalidateTime } })
const data = (await res.json()) as { contents: contentsAPIResult[]; total: number }
return data
@@ -78,7 +81,7 @@ async function getTags() {
const request = new Request(url, { headers: { 'x-api-key': cmsAPIKey }, method: 'GET' })
- const res = await fetch(request)
+ const res = await fetch(request, { next: { revalidate: revalidateTime } })
const data = (await res.json()) as categoryAPIResult[]
return data
@@ -93,7 +96,7 @@ async function getInfo() {
const request = new Request(url, { headers: { 'x-api-key': cmsAPIKey }, method: 'GET' })
- const res = await fetch(request)
+ const res = await fetch(request, { next: { revalidate: revalidateTime } })
const data = (await res.json()) as infoAPIResult[]
return data