sync with pliny dev

This commit is contained in:
Timothy Lin 2023-07-16 18:52:51 +08:00
parent d61487efa4
commit 20704c9f75
18 changed files with 356 additions and 684 deletions

View File

@ -3,7 +3,7 @@ import Link from '@/components/Link'
import Tag from '@/components/Tag'
import siteMetadata from '@/data/siteMetadata'
import { formatDate } from 'pliny/utils/formatDate'
import { NewsletterForm } from 'pliny/ui/NewsletterForm'
import NewsletterForm from 'pliny/ui/NewsletterForm'
const MAX_DISPLAY = 5

View File

@ -1,5 +1,5 @@
import { Authors, allAuthors } from 'contentlayer/generated'
import { Mdx } from '@/components/MDXComponents'
import { MDXLayoutRenderer } from 'pliny/mdx-components'
import AuthorLayout from '@/layouts/AuthorLayout'
import { coreContent } from 'pliny/utils/contentlayer'
import { genPageMetadata } from 'app/seo'
@ -13,7 +13,7 @@ export default function Page() {
return (
<>
<AuthorLayout content={mainContent}>
<Mdx code={author.body.code} />
<MDXLayoutRenderer code={author.body.code} />
</AuthorLayout>
</>
)

View File

@ -1,5 +1,6 @@
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 { allBlogs, allAuthors } 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)}
</script>
<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>
</>
)}

View File

@ -21,14 +21,11 @@ export default function BlogPage() {
}
return (
<>
{/* <PageSEO title={`Blog - ${siteMetadata.author}`} description={siteMetadata.description} /> */}
<ListLayout
posts={posts}
initialDisplayPosts={initialDisplayPosts}
pagination={pagination}
title="All Posts"
/>
</>
<ListLayout
posts={posts}
initialDisplayPosts={initialDisplayPosts}
pagination={pagination}
title="All Posts"
/>
)
}

View File

@ -1,5 +1,3 @@
// import { PageSEO } from '@/components/SEO'
import siteMetadata from '@/data/siteMetadata'
import ListLayout from '@/layouts/ListLayout'
import { allCoreContent, sortedBlogPost } from 'pliny/utils/contentlayer'
import { allBlogs } from 'contentlayer/generated'
@ -28,14 +26,11 @@ export default function Page({ params }: { params: { page: string } }) {
}
return (
<>
{/* <PageSEO title={siteMetadata.title} description={siteMetadata.description} /> */}
<ListLayout
posts={allCoreContent(posts)}
initialDisplayPosts={allCoreContent(initialDisplayPosts)}
pagination={pagination}
title="All Posts"
/>
</>
<ListLayout
posts={allCoreContent(posts)}
initialDisplayPosts={allCoreContent(initialDisplayPosts)}
pagination={pagination}
title="All Posts"
/>
)
}

View File

@ -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;
}

View File

@ -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 { Analytics } from 'pliny/analytics'
import { SearchProvider } from 'pliny/search'
import { Analytics, AnalyticsConfig } from 'pliny/analytics'
import { SearchProvider, SearchConfig } from 'pliny/search'
import Header from '@/components/Header'
import SectionContainer from '@/components/SectionContainer'
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" />
<body className="bg-white text-black antialiased dark:bg-gray-900 dark:text-white">
<ThemeProviders>
{/* <Analytics analyticsConfig={siteMetadata.analytics} /> */}
<Analytics analyticsConfig={siteMetadata.analytics as AnalyticsConfig} />
<SectionContainer>
<div className="flex h-screen flex-col justify-between font-sans">
{/* <SearchProvider searchConfig={siteMetadata.search}> */}
<Header />
<main className="mb-auto">{children}</main>
{/* </SearchProvider> */}
<SearchProvider searchConfig={siteMetadata.search as SearchConfig}>
<Header />
<main className="mb-auto">{children}</main>
</SearchProvider>
<Footer />
</div>
</SectionContainer>

View File

@ -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
View 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} />
)}
</>
)
}

View File

@ -1,30 +1,14 @@
import React from 'react'
import { useMDXComponent } from 'next-contentlayer/hooks'
import { ComponentMap } from 'pliny/mdx-components'
import { TOCInline } from 'pliny/ui/TOCInline'
import TOCInline from 'pliny/ui/TOCInline'
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 CustomLink from './Link'
interface MdxProps {
code: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any
}
export const MDXComponents: ComponentMap = {
export const components: MDXComponents = {
Image,
TOCInline,
a: CustomLink,
pre: Pre,
BlogNewsletterForm,
}
export function Mdx({ code, ...rest }: MdxProps) {
const Component = useMDXComponent(code)
return <Component components={{ ...MDXComponents }} {...rest} />
}

View File

@ -11,7 +11,7 @@ import {
remarkCodeTitles,
remarkImgToJsx,
extractTocHeadings,
} from 'pliny/mdx-plugins.js'
} from 'pliny/mdx-plugins/index.js'
// Rehype packages
import rehypeSlug from 'rehype-slug'
import rehypeAutolinkHeadings from 'rehype-autolink-headings'
@ -20,6 +20,7 @@ import rehypeCitation from 'rehype-citation'
import rehypePrismPlus from 'rehype-prism-plus'
import rehypePresetMinify from 'rehype-preset-minify'
import siteMetadata from './data/siteMetadata'
import { allCoreContent } from 'pliny/utils/contentlayer.js'
const root = process.cwd()
@ -60,6 +61,19 @@ function createTagCount(allBlogs) {
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(() => ({
name: 'Blog',
filePathPattern: 'blog/**/*.mdx',

View File

@ -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;
}

View File

@ -65,20 +65,20 @@ const siteMetadata = {
lang: 'en',
},
},
// search: {
// provider: 'kbar', // kbar or algolia
// kbarConfig: {
// searchDocumentsPath: 'search.json', // path to load documents to search
// },
// provider: 'algolia',
// algoliaConfig: {
// // The application ID provided by Algolia
// appId: 'R2IYF7ETH7',
// // Public API key: it is safe to commit it
// apiKey: '599cec31baffa4868cae4e79f180729b',
// indexName: 'docsearch',
// },
// },
search: {
// provider: 'kbar', // kbar or algolia
// kbarConfig: {
// searchDocumentsPath: 'search.json', // path to load documents to search
// },
provider: 'algolia',
algoliaConfig: {
// The application ID provided by Algolia
appId: 'R2IYF7ETH7',
// Public API key: it is safe to commit it
apiKey: '599cec31baffa4868cae4e79f180729b',
indexName: 'docsearch',
},
},
}
module.exports = siteMetadata

View File

@ -1,7 +1,7 @@
import { useState, ReactNode } from 'react'
import { Comments } from 'pliny/comments'
import { ReactNode } from 'react'
import { CoreContent } from 'pliny/utils/contentlayer'
import type { Blog, Authors } from 'contentlayer/generated'
import Comments from '@/components/Comments'
import Link from '@/components/Link'
import PageTitle from '@/components/PageTitle'
import SectionContainer from '@/components/SectionContainer'
@ -33,7 +33,6 @@ interface LayoutProps {
export default function PostLayout({ content, authorDetails, next, prev, children }: LayoutProps) {
const { filePath, path, slug, date, title, tags } = content
const basePath = path.split('/')[0]
// const [loadComments, setLoadComments] = useState(false)
return (
<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"
id="comment"
>
{/* {!loadComments && (
<button onClick={() => setLoadComments(true)}>Load Comments</button>
)}
{loadComments && <Comments commentsConfig={siteMetadata.comments} slug={slug} />} */}
<Comments slug={slug} />
</div>
)}
</div>

View File

@ -1,8 +1,8 @@
import { useState, ReactNode } from 'react'
import { Comments } from 'pliny/comments'
import { ReactNode } from 'react'
import { formatDate } from 'pliny/utils/formatDate'
import { CoreContent } from 'pliny/utils/contentlayer'
import type { Blog } from 'contentlayer/generated'
import Comments from '@/components/Comments'
import Link from '@/components/Link'
import PageTitle from '@/components/PageTitle'
import SectionContainer from '@/components/SectionContainer'
@ -17,8 +17,6 @@ interface LayoutProps {
}
export default function PostLayout({ content, next, prev, children }: LayoutProps) {
const [loadComments, setLoadComments] = useState(false)
const { path, slug, date, title } = content
return (
@ -47,10 +45,7 @@ export default function PostLayout({ content, next, prev, children }: LayoutProp
</div>
{siteMetadata.comments && (
<div className="pb-6 pt-6 text-center text-gray-700 dark:text-gray-300" id="comment">
{!loadComments && (
<button onClick={() => setLoadComments(true)}>Load Comments</button>
)}
{loadComments && <Comments commentsConfig={siteMetadata.comments} slug={slug} />}
<Comments slug={slug} />
</div>
)}
<footer>

View File

@ -24,7 +24,7 @@
"next": "13.4.9",
"next-contentlayer": "0.3.4",
"next-themes": "^0.2.1",
"pliny": "0.0.10",
"pliny": "0.1.0-beta.3",
"postcss": "^8.4.24",
"react": "18.2.0",
"react-dom": "18.2.0",
@ -79,4 +79,4 @@
]
},
"packageManager": "yarn@3.6.1"
}
}

View File

@ -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 tagData from '../app/tag-data.json' assert { type: 'json' }
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 = () => {
generateRSS(siteMetadata, allBlogs)
console.log('RSS feed generated...')

715
yarn.lock

File diff suppressed because it is too large Load Diff