upstream #1
@ -3,7 +3,7 @@ import Link from '@/components/Link'
|
|||||||
import Tag from '@/components/Tag'
|
import Tag from '@/components/Tag'
|
||||||
import siteMetadata from '@/data/siteMetadata'
|
import siteMetadata from '@/data/siteMetadata'
|
||||||
import { formatDate } from 'pliny/utils/formatDate'
|
import { formatDate } from 'pliny/utils/formatDate'
|
||||||
import { NewsletterForm } from 'pliny/ui/NewsletterForm'
|
import NewsletterForm from 'pliny/ui/NewsletterForm'
|
||||||
|
|
||||||
const MAX_DISPLAY = 5
|
const MAX_DISPLAY = 5
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Authors, allAuthors } from 'contentlayer/generated'
|
import { Authors, allAuthors } from 'contentlayer/generated'
|
||||||
import { Mdx } from '@/components/MDXComponents'
|
import { MDXLayoutRenderer } from 'pliny/mdx-components'
|
||||||
import AuthorLayout from '@/layouts/AuthorLayout'
|
import AuthorLayout from '@/layouts/AuthorLayout'
|
||||||
import { coreContent } from 'pliny/utils/contentlayer'
|
import { coreContent } from 'pliny/utils/contentlayer'
|
||||||
import { genPageMetadata } from 'app/seo'
|
import { genPageMetadata } from 'app/seo'
|
||||||
@ -13,7 +13,7 @@ export default function Page() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AuthorLayout content={mainContent}>
|
<AuthorLayout content={mainContent}>
|
||||||
<Mdx code={author.body.code} />
|
<MDXLayoutRenderer code={author.body.code} />
|
||||||
</AuthorLayout>
|
</AuthorLayout>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import PageTitle from '@/components/PageTitle'
|
import PageTitle from '@/components/PageTitle'
|
||||||
import { Mdx } from '@/components/MDXComponents'
|
import { components } from '@/components/MDXComponents'
|
||||||
|
import { MDXLayoutRenderer } from 'pliny/mdx-components'
|
||||||
import { sortedBlogPost, coreContent } from 'pliny/utils/contentlayer'
|
import { sortedBlogPost, coreContent } from 'pliny/utils/contentlayer'
|
||||||
import { allBlogs, allAuthors } from 'contentlayer/generated'
|
import { allBlogs, allAuthors } from 'contentlayer/generated'
|
||||||
import type { Authors, Blog } from 'contentlayer/generated'
|
import type { Authors, Blog } from 'contentlayer/generated'
|
||||||
@ -104,7 +105,7 @@ export default async function Page({ params }: { params: { slug: string[] } }) {
|
|||||||
{JSON.stringify(jsonLd)}
|
{JSON.stringify(jsonLd)}
|
||||||
</script>
|
</script>
|
||||||
<PostLayout content={mainContent} authorDetails={authorDetails} next={next} prev={prev}>
|
<PostLayout content={mainContent} authorDetails={authorDetails} next={next} prev={prev}>
|
||||||
<Mdx code={post.body.code} toc={post.toc} />
|
<MDXLayoutRenderer code={post.body.code} components={components} toc={post.toc} />
|
||||||
</PostLayout>
|
</PostLayout>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -21,14 +21,11 @@ export default function BlogPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<ListLayout
|
||||||
{/* <PageSEO title={`Blog - ${siteMetadata.author}`} description={siteMetadata.description} /> */}
|
posts={posts}
|
||||||
<ListLayout
|
initialDisplayPosts={initialDisplayPosts}
|
||||||
posts={posts}
|
pagination={pagination}
|
||||||
initialDisplayPosts={initialDisplayPosts}
|
title="All Posts"
|
||||||
pagination={pagination}
|
/>
|
||||||
title="All Posts"
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// import { PageSEO } from '@/components/SEO'
|
|
||||||
import siteMetadata from '@/data/siteMetadata'
|
|
||||||
import ListLayout from '@/layouts/ListLayout'
|
import ListLayout from '@/layouts/ListLayout'
|
||||||
import { allCoreContent, sortedBlogPost } from 'pliny/utils/contentlayer'
|
import { allCoreContent, sortedBlogPost } from 'pliny/utils/contentlayer'
|
||||||
import { allBlogs } from 'contentlayer/generated'
|
import { allBlogs } from 'contentlayer/generated'
|
||||||
@ -28,14 +26,11 @@ export default function Page({ params }: { params: { page: string } }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<ListLayout
|
||||||
{/* <PageSEO title={siteMetadata.title} description={siteMetadata.description} /> */}
|
posts={allCoreContent(posts)}
|
||||||
<ListLayout
|
initialDisplayPosts={allCoreContent(initialDisplayPosts)}
|
||||||
posts={allCoreContent(posts)}
|
pagination={pagination}
|
||||||
initialDisplayPosts={allCoreContent(initialDisplayPosts)}
|
title="All Posts"
|
||||||
pagination={pagination}
|
/>
|
||||||
title="All Posts"
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
|
|
||||||
.task-list-item::before {
|
|
||||||
@apply hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-list-item {
|
|
||||||
@apply list-none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footnotes {
|
|
||||||
@apply mt-12 border-t border-gray-200 pt-8 dark:border-gray-700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.data-footnote-backref {
|
|
||||||
@apply no-underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.csl-entry {
|
|
||||||
@apply my-5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* https://stackoverflow.com/questions/61083813/how-to-avoid-internal-autofill-selected-style-to-be-applied */
|
|
||||||
input:-webkit-autofill,
|
|
||||||
input:-webkit-autofill:focus {
|
|
||||||
transition: background-color 600000s 0s, color 600000s 0s;
|
|
||||||
}
|
|
@ -1,8 +1,10 @@
|
|||||||
import './globals.css'
|
import 'css/tailwind.css'
|
||||||
|
import 'css/prism.css'
|
||||||
|
import 'pliny/search/algolia.css'
|
||||||
|
|
||||||
import { Inter } from 'next/font/google'
|
import { Inter } from 'next/font/google'
|
||||||
import { Analytics } from 'pliny/analytics'
|
import { Analytics, AnalyticsConfig } from 'pliny/analytics'
|
||||||
import { SearchProvider } from 'pliny/search'
|
import { SearchProvider, SearchConfig } from 'pliny/search'
|
||||||
import Header from '@/components/Header'
|
import Header from '@/components/Header'
|
||||||
import SectionContainer from '@/components/SectionContainer'
|
import SectionContainer from '@/components/SectionContainer'
|
||||||
import Footer from '@/components/Footer'
|
import Footer from '@/components/Footer'
|
||||||
@ -68,13 +70,13 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
|||||||
<link rel="alternate" type="application/rss+xml" href="/feed.xml" />
|
<link rel="alternate" type="application/rss+xml" href="/feed.xml" />
|
||||||
<body className="bg-white text-black antialiased dark:bg-gray-900 dark:text-white">
|
<body className="bg-white text-black antialiased dark:bg-gray-900 dark:text-white">
|
||||||
<ThemeProviders>
|
<ThemeProviders>
|
||||||
{/* <Analytics analyticsConfig={siteMetadata.analytics} /> */}
|
<Analytics analyticsConfig={siteMetadata.analytics as AnalyticsConfig} />
|
||||||
<SectionContainer>
|
<SectionContainer>
|
||||||
<div className="flex h-screen flex-col justify-between font-sans">
|
<div className="flex h-screen flex-col justify-between font-sans">
|
||||||
{/* <SearchProvider searchConfig={siteMetadata.search}> */}
|
<SearchProvider searchConfig={siteMetadata.search as SearchConfig}>
|
||||||
<Header />
|
<Header />
|
||||||
<main className="mb-auto">{children}</main>
|
<main className="mb-auto">{children}</main>
|
||||||
{/* </SearchProvider> */}
|
</SearchProvider>
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
</SectionContainer>
|
</SectionContainer>
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
// dot notation breaks RSC - https://github.com/vercel/next.js/issues/51593
|
|
||||||
// temporarily workaround to re-export
|
|
||||||
import { BlogNewsletterForm } from 'pliny/ui/NewsletterForm'
|
|
||||||
|
|
||||||
export default BlogNewsletterForm
|
|
17
components/Comments.tsx
Normal file
17
components/Comments.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { Comments as CommentsComponent } from 'pliny/comments'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import siteMetadata from '@/data/siteMetadata'
|
||||||
|
|
||||||
|
export default function Comments({ slug }: { slug: string }) {
|
||||||
|
const [loadComments, setLoadComments] = useState(false)
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{!loadComments && <button onClick={() => setLoadComments(true)}>Load Comments</button>}
|
||||||
|
{siteMetadata.comments && loadComments && (
|
||||||
|
<CommentsComponent commentsConfig={siteMetadata.comments} slug={slug} />
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
@ -1,30 +1,14 @@
|
|||||||
import React from 'react'
|
import TOCInline from 'pliny/ui/TOCInline'
|
||||||
import { useMDXComponent } from 'next-contentlayer/hooks'
|
|
||||||
import { ComponentMap } from 'pliny/mdx-components'
|
|
||||||
import { TOCInline } from 'pliny/ui/TOCInline'
|
|
||||||
import Pre from './Pre'
|
import Pre from './Pre'
|
||||||
import BlogNewsletterForm from './BlogNewsletterForm'
|
import BlogNewsletterForm from 'pliny/ui/NewsletterForm'
|
||||||
// import { BlogNewsletterForm } from 'pliny/ui/NewsletterForm'
|
import type { MDXComponents } from 'mdx/types'
|
||||||
|
|
||||||
import Image from './Image'
|
import Image from './Image'
|
||||||
import CustomLink from './Link'
|
import CustomLink from './Link'
|
||||||
|
|
||||||
interface MdxProps {
|
export const components: MDXComponents = {
|
||||||
code: string
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
[key: string]: any
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MDXComponents: ComponentMap = {
|
|
||||||
Image,
|
Image,
|
||||||
TOCInline,
|
TOCInline,
|
||||||
a: CustomLink,
|
a: CustomLink,
|
||||||
pre: Pre,
|
pre: Pre,
|
||||||
BlogNewsletterForm,
|
BlogNewsletterForm,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Mdx({ code, ...rest }: MdxProps) {
|
|
||||||
const Component = useMDXComponent(code)
|
|
||||||
|
|
||||||
return <Component components={{ ...MDXComponents }} {...rest} />
|
|
||||||
}
|
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
remarkCodeTitles,
|
remarkCodeTitles,
|
||||||
remarkImgToJsx,
|
remarkImgToJsx,
|
||||||
extractTocHeadings,
|
extractTocHeadings,
|
||||||
} from 'pliny/mdx-plugins.js'
|
} from 'pliny/mdx-plugins/index.js'
|
||||||
// Rehype packages
|
// Rehype packages
|
||||||
import rehypeSlug from 'rehype-slug'
|
import rehypeSlug from 'rehype-slug'
|
||||||
import rehypeAutolinkHeadings from 'rehype-autolink-headings'
|
import rehypeAutolinkHeadings from 'rehype-autolink-headings'
|
||||||
@ -20,6 +20,7 @@ import rehypeCitation from 'rehype-citation'
|
|||||||
import rehypePrismPlus from 'rehype-prism-plus'
|
import rehypePrismPlus from 'rehype-prism-plus'
|
||||||
import rehypePresetMinify from 'rehype-preset-minify'
|
import rehypePresetMinify from 'rehype-preset-minify'
|
||||||
import siteMetadata from './data/siteMetadata'
|
import siteMetadata from './data/siteMetadata'
|
||||||
|
import { allCoreContent } from 'pliny/utils/contentlayer.js'
|
||||||
|
|
||||||
const root = process.cwd()
|
const root = process.cwd()
|
||||||
|
|
||||||
@ -60,6 +61,19 @@ function createTagCount(allBlogs) {
|
|||||||
writeFileSync('./app/tag-data.json', JSON.stringify(tagCount))
|
writeFileSync('./app/tag-data.json', JSON.stringify(tagCount))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createSearchIndex(allBlogs) {
|
||||||
|
if (
|
||||||
|
siteMetadata?.search?.provider === 'kbar' &&
|
||||||
|
siteMetadata.search.kbarConfig.searchDocumentsPath
|
||||||
|
) {
|
||||||
|
writeFileSync(
|
||||||
|
`public/${siteMetadata.search.kbarConfig.searchDocumentsPath}`,
|
||||||
|
JSON.stringify(allCoreContent(allBlogs))
|
||||||
|
)
|
||||||
|
console.log('Local search index generated...')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const Blog = defineDocumentType(() => ({
|
export const Blog = defineDocumentType(() => ({
|
||||||
name: 'Blog',
|
name: 'Blog',
|
||||||
filePathPattern: 'blog/**/*.mdx',
|
filePathPattern: 'blog/**/*.mdx',
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
|
|
||||||
.light .DocSearch {
|
|
||||||
--docsearch-primary-color: theme(colors.primary.600);
|
|
||||||
--docsearch-highlight-color: theme(colors.primary.600);
|
|
||||||
--docsearch-searchbox-shadow: inset 0 0 0 2px theme(colors.primary.600);
|
|
||||||
--docsearch-muted-color: theme(colors.gray.500);
|
|
||||||
--docsearch-container-background: theme(colors.gray.400 / 80%);
|
|
||||||
/* Modal */
|
|
||||||
--docsearch-modal-background: theme(colors.gray.200);
|
|
||||||
/* Search box */
|
|
||||||
--docsearch-searchbox-background: theme(colors.gray.100);
|
|
||||||
--docsearch-searchbox-focus-background: theme(colors.gray.100);
|
|
||||||
/* Hit */
|
|
||||||
--docsearch-hit-color: theme(colors.gray.700);
|
|
||||||
--docsearch-hit-shadow: none;
|
|
||||||
--docsearch-hit-active-color: theme(colors.gray.800);
|
|
||||||
--docsearch-hit-background: theme(colors.gray.100);
|
|
||||||
/* Footer */
|
|
||||||
--docsearch-footer-background: theme(colors.gray.100);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark .DocSearch {
|
|
||||||
--docsearch-primary-color: theme(colors.primary.600);
|
|
||||||
--docsearch-highlight-color: theme(colors.primary.600);
|
|
||||||
--docsearch-searchbox-shadow: inset 0 0 0 2px theme(colors.primary.600);
|
|
||||||
--docsearch-text-color: theme(colors.gray.200);
|
|
||||||
--docsearch-muted-color: theme(colors.gray.400);
|
|
||||||
--docsearch-container-background: theme(colors.gray.900 / 80%);
|
|
||||||
/* Modal */
|
|
||||||
--docsearch-modal-background: theme(colors.gray.900);
|
|
||||||
--docsearch-modal-shadow: inset 1px 1px 0 0 rgb(44, 46, 64),
|
|
||||||
0 3px 8px 0 rgb(0, 3, 9);
|
|
||||||
/* Search box */
|
|
||||||
--docsearch-searchbox-background: theme(colors.gray.800);
|
|
||||||
--docsearch-searchbox-focus-background: theme(colors.gray.800);
|
|
||||||
/* Hit */
|
|
||||||
--docsearch-hit-color: theme(colors.gray.200);
|
|
||||||
--docsearch-hit-shadow: none;
|
|
||||||
--docsearch-hit-active-color: theme(colors.gray.100);
|
|
||||||
--docsearch-hit-background: theme(colors.gray.800);
|
|
||||||
/* Footer */
|
|
||||||
--docsearch-footer-background: theme(colors.gray.900);
|
|
||||||
--docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, 0.5),
|
|
||||||
0 -4px 8px 0 rgba(0, 0, 0, 0.2);
|
|
||||||
--docsearch-key-gradient: linear-gradient(-26.5deg,
|
|
||||||
theme(colors.gray.800) 0%,
|
|
||||||
theme(colors.gray.900) 100%);
|
|
||||||
--docsearch-key-shadow: inset 0 -2px 0 0 rgb(40, 45, 85),
|
|
||||||
inset 0 0 1px 1px rgb(81, 87, 125), 0 2px 2px 0 rgba(3, 4, 9, 0.3);
|
|
||||||
--docsearch-logo-color: theme(colors.gray.300);
|
|
||||||
}
|
|
||||||
|
|
||||||
.light .DocSearch-Input {
|
|
||||||
@apply hover:ring-0 ring-0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark .DocSearch-Input {
|
|
||||||
@apply hover:ring-0 ring-0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.DocSearch-Container {
|
|
||||||
@apply backdrop-blur;
|
|
||||||
}
|
|
@ -65,20 +65,20 @@ const siteMetadata = {
|
|||||||
lang: 'en',
|
lang: 'en',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// search: {
|
search: {
|
||||||
// provider: 'kbar', // kbar or algolia
|
// provider: 'kbar', // kbar or algolia
|
||||||
// kbarConfig: {
|
// kbarConfig: {
|
||||||
// searchDocumentsPath: 'search.json', // path to load documents to search
|
// searchDocumentsPath: 'search.json', // path to load documents to search
|
||||||
// },
|
// },
|
||||||
// provider: 'algolia',
|
provider: 'algolia',
|
||||||
// algoliaConfig: {
|
algoliaConfig: {
|
||||||
// // The application ID provided by Algolia
|
// The application ID provided by Algolia
|
||||||
// appId: 'R2IYF7ETH7',
|
appId: 'R2IYF7ETH7',
|
||||||
// // Public API key: it is safe to commit it
|
// Public API key: it is safe to commit it
|
||||||
// apiKey: '599cec31baffa4868cae4e79f180729b',
|
apiKey: '599cec31baffa4868cae4e79f180729b',
|
||||||
// indexName: 'docsearch',
|
indexName: 'docsearch',
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = siteMetadata
|
module.exports = siteMetadata
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useState, ReactNode } from 'react'
|
import { ReactNode } from 'react'
|
||||||
import { Comments } from 'pliny/comments'
|
|
||||||
import { CoreContent } from 'pliny/utils/contentlayer'
|
import { CoreContent } from 'pliny/utils/contentlayer'
|
||||||
import type { Blog, Authors } from 'contentlayer/generated'
|
import type { Blog, Authors } from 'contentlayer/generated'
|
||||||
|
import Comments from '@/components/Comments'
|
||||||
import Link from '@/components/Link'
|
import Link from '@/components/Link'
|
||||||
import PageTitle from '@/components/PageTitle'
|
import PageTitle from '@/components/PageTitle'
|
||||||
import SectionContainer from '@/components/SectionContainer'
|
import SectionContainer from '@/components/SectionContainer'
|
||||||
@ -33,7 +33,6 @@ interface LayoutProps {
|
|||||||
export default function PostLayout({ content, authorDetails, next, prev, children }: LayoutProps) {
|
export default function PostLayout({ content, authorDetails, next, prev, children }: LayoutProps) {
|
||||||
const { filePath, path, slug, date, title, tags } = content
|
const { filePath, path, slug, date, title, tags } = content
|
||||||
const basePath = path.split('/')[0]
|
const basePath = path.split('/')[0]
|
||||||
// const [loadComments, setLoadComments] = useState(false)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SectionContainer>
|
<SectionContainer>
|
||||||
@ -107,10 +106,7 @@ export default function PostLayout({ content, authorDetails, next, prev, childre
|
|||||||
className="pb-6 pt-6 text-center text-gray-700 dark:text-gray-300"
|
className="pb-6 pt-6 text-center text-gray-700 dark:text-gray-300"
|
||||||
id="comment"
|
id="comment"
|
||||||
>
|
>
|
||||||
{/* {!loadComments && (
|
<Comments slug={slug} />
|
||||||
<button onClick={() => setLoadComments(true)}>Load Comments</button>
|
|
||||||
)}
|
|
||||||
{loadComments && <Comments commentsConfig={siteMetadata.comments} slug={slug} />} */}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { useState, ReactNode } from 'react'
|
import { ReactNode } from 'react'
|
||||||
import { Comments } from 'pliny/comments'
|
|
||||||
import { formatDate } from 'pliny/utils/formatDate'
|
import { formatDate } from 'pliny/utils/formatDate'
|
||||||
import { CoreContent } from 'pliny/utils/contentlayer'
|
import { CoreContent } from 'pliny/utils/contentlayer'
|
||||||
import type { Blog } from 'contentlayer/generated'
|
import type { Blog } from 'contentlayer/generated'
|
||||||
|
import Comments from '@/components/Comments'
|
||||||
import Link from '@/components/Link'
|
import Link from '@/components/Link'
|
||||||
import PageTitle from '@/components/PageTitle'
|
import PageTitle from '@/components/PageTitle'
|
||||||
import SectionContainer from '@/components/SectionContainer'
|
import SectionContainer from '@/components/SectionContainer'
|
||||||
@ -17,8 +17,6 @@ interface LayoutProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function PostLayout({ content, next, prev, children }: LayoutProps) {
|
export default function PostLayout({ content, next, prev, children }: LayoutProps) {
|
||||||
const [loadComments, setLoadComments] = useState(false)
|
|
||||||
|
|
||||||
const { path, slug, date, title } = content
|
const { path, slug, date, title } = content
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -47,10 +45,7 @@ export default function PostLayout({ content, next, prev, children }: LayoutProp
|
|||||||
</div>
|
</div>
|
||||||
{siteMetadata.comments && (
|
{siteMetadata.comments && (
|
||||||
<div className="pb-6 pt-6 text-center text-gray-700 dark:text-gray-300" id="comment">
|
<div className="pb-6 pt-6 text-center text-gray-700 dark:text-gray-300" id="comment">
|
||||||
{!loadComments && (
|
<Comments slug={slug} />
|
||||||
<button onClick={() => setLoadComments(true)}>Load Comments</button>
|
|
||||||
)}
|
|
||||||
{loadComments && <Comments commentsConfig={siteMetadata.comments} slug={slug} />}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<footer>
|
<footer>
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
"next": "13.4.9",
|
"next": "13.4.9",
|
||||||
"next-contentlayer": "0.3.4",
|
"next-contentlayer": "0.3.4",
|
||||||
"next-themes": "^0.2.1",
|
"next-themes": "^0.2.1",
|
||||||
"pliny": "0.0.10",
|
"pliny": "0.1.0-beta.3",
|
||||||
"postcss": "^8.4.24",
|
"postcss": "^8.4.24",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
|
@ -1,7 +1,60 @@
|
|||||||
import { generateRSS } from 'pliny/utils/generate-rss.js'
|
import { writeFileSync, mkdirSync } from 'fs'
|
||||||
|
import path from 'path'
|
||||||
|
// import { generateRSS } from 'pliny/utils/generate-rss.js'
|
||||||
|
import GithubSlugger from 'github-slugger'
|
||||||
import siteMetadata from '../data/siteMetadata.js'
|
import siteMetadata from '../data/siteMetadata.js'
|
||||||
|
import tagData from '../app/tag-data.json' assert { type: 'json' }
|
||||||
import { allBlogs } from '../.contentlayer/generated/index.mjs'
|
import { allBlogs } from '../.contentlayer/generated/index.mjs'
|
||||||
|
|
||||||
|
const generateRssItem = (config, post) => `
|
||||||
|
<item>
|
||||||
|
<guid>${config.siteUrl}/blog/${post.slug}</guid>
|
||||||
|
<title>${escape(post.title)}</title>
|
||||||
|
<link>${config.siteUrl}/blog/${post.slug}</link>
|
||||||
|
${post.summary && `<description>${escape(post.summary)}</description>`}
|
||||||
|
<pubDate>${new Date(post.date).toUTCString()}</pubDate>
|
||||||
|
<author>${config.email} (${config.author})</author>
|
||||||
|
${post.tags && post.tags.map((t) => `<category>${t}</category>`).join('')}
|
||||||
|
</item>
|
||||||
|
`
|
||||||
|
|
||||||
|
const generateRss = (config, posts, page = 'feed.xml') => `
|
||||||
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||||
|
<channel>
|
||||||
|
<title>${escape(config.title)}</title>
|
||||||
|
<link>${config.siteUrl}/blog</link>
|
||||||
|
<description>${escape(config.description)}</description>
|
||||||
|
<language>${config.language}</language>
|
||||||
|
<managingEditor>${config.email} (${config.author})</managingEditor>
|
||||||
|
<webMaster>${config.email} (${config.author})</webMaster>
|
||||||
|
<lastBuildDate>${new Date(posts[0].date).toUTCString()}</lastBuildDate>
|
||||||
|
<atom:link href="${config.siteUrl}/${page}" rel="self" type="application/rss+xml"/>
|
||||||
|
${posts.map((post) => generateRssItem(config, post)).join('')}
|
||||||
|
</channel>
|
||||||
|
</rss>
|
||||||
|
`
|
||||||
|
|
||||||
|
async function generateRSS(config, allBlogs) {
|
||||||
|
const publishPosts = allBlogs.filter((post) => post.draft !== true)
|
||||||
|
// RSS for blog post
|
||||||
|
if (publishPosts.length > 0) {
|
||||||
|
const rss = generateRss(config, publishPosts)
|
||||||
|
writeFileSync('./public/feed.xml', rss)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (publishPosts.length > 0) {
|
||||||
|
for (const tag of Object.keys(tagData)) {
|
||||||
|
const filteredPosts = allBlogs.filter((post) =>
|
||||||
|
post.tags.map((t) => GithubSlugger.slug(t)).includes(tag)
|
||||||
|
)
|
||||||
|
const rss = generateRss(config, filteredPosts, `tags/${tag}/feed.xml`)
|
||||||
|
const rssPath = path.join('public', 'tags', tag)
|
||||||
|
mkdirSync(rssPath, { recursive: true })
|
||||||
|
writeFileSync(path.join(rssPath, 'feed.xml'), rss)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const rss = () => {
|
const rss = () => {
|
||||||
generateRSS(siteMetadata, allBlogs)
|
generateRSS(siteMetadata, allBlogs)
|
||||||
console.log('RSS feed generated...')
|
console.log('RSS feed generated...')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user