sync with pliny dev
This commit is contained in:
parent
d61487efa4
commit
20704c9f75
@ -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
|
||||
|
||||
|
@ -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>
|
||||
</>
|
||||
)
|
||||
|
@ -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>
|
||||
</>
|
||||
)}
|
||||
|
@ -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"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
@ -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"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
@ -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 { 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>
|
||||
|
@ -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 { 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} />
|
||||
}
|
||||
|
@ -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',
|
||||
|
@ -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',
|
||||
},
|
||||
},
|
||||
// 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
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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...')
|
||||
|
Loading…
x
Reference in New Issue
Block a user