upstream #1

Merged
jblu merged 1007 commits from upstream into main 2024-11-04 22:35:57 -06:00
11 changed files with 306 additions and 21 deletions
Showing only changes of commit 133c19e7fb - Show all commits

View File

@ -43,6 +43,7 @@ I wanted it to be nearly as feature-rich as popular blogging templates like [bea
- Support for multiple authors - Support for multiple authors
- Blog templates - Blog templates
- Support for nested routing of blog posts - Support for nested routing of blog posts
- Supports [giscus](https://github.com/laymonage/giscus), [utterances](https://github.com/utterance/utterances) or disqus
- Projects page - Projects page
- SEO friendly with RSS feed, sitemaps and more! - SEO friendly with RSS feed, sitemaps and more!

View File

@ -0,0 +1,37 @@
import React, { useState } from 'react'
import siteMetadata from '@/data/siteMetadata'
const Disqus = ({ frontMatter }) => {
const [enableLoadComments, setEnabledLoadComments] = useState(true)
const COMMENTS_ID = 'disqus_thread'
function LoadComments() {
setEnabledLoadComments(false)
window.disqus_config = function () {
this.page.url = window.location.href
this.page.identifier = frontMatter.slug
}
if (window.DISQUS === undefined) {
const script = document.createElement('script')
script.src = 'https://' + siteMetadata.comment.disqus.shortname + '.disqus.com/embed.js'
script.setAttribute('data-timestamp', +new Date())
script.setAttribute('crossorigin', 'anonymous')
script.async = true
document.body.appendChild(script)
} else {
window.DISQUS.reset({ reload: true })
}
}
return (
<div className="pt-6 pb-6 text-center text-gray-700 dark:text-gray-300">
{enableLoadComments && <button onClick={LoadComments}>Load Comments</button>}
<div className="disqus-frame" id={COMMENTS_ID} />
</div>
)
}
export default Disqus

View File

@ -0,0 +1,50 @@
import React, { useState } from 'react'
import { useTheme } from 'next-themes'
import siteMetadata from '@/data/siteMetadata'
const Giscus = ({ mapping }) => {
const [enableLoadComments, setEnabledLoadComments] = useState(true)
const { theme, resolvedTheme } = useTheme()
const commentsTheme =
siteMetadata.comment.giscusConfig.themeURL === ''
? theme === 'dark' || resolvedTheme === 'dark'
? siteMetadata.comment.giscusConfig.darkTheme
: siteMetadata.comment.giscusConfig.theme
: siteMetadata.comment.giscusConfig.themeURL
const COMMENTS_ID = 'comments-container'
function LoadComments() {
setEnabledLoadComments(false)
const script = document.createElement('script')
script.src = 'https://giscus.app/client.js'
script.setAttribute('data-repo', siteMetadata.comment.giscusConfig.repo)
script.setAttribute('data-repo-id', siteMetadata.comment.giscusConfig.repositoryId)
script.setAttribute('data-category', siteMetadata.comment.giscusConfig.category)
script.setAttribute('data-category-id', siteMetadata.comment.giscusConfig.categoryId)
script.setAttribute('data-mapping', mapping)
script.setAttribute('data-reactions-enabled', siteMetadata.comment.giscusConfig.reactions)
script.setAttribute('data-emit-metadata', siteMetadata.comment.giscusConfig.metadata)
script.setAttribute('data-theme', commentsTheme)
script.setAttribute('crossorigin', 'anonymous')
script.async = true
const comments = document.getElementById(COMMENTS_ID)
if (comments) comments.appendChild(script)
return () => {
const comments = document.getElementById(COMMENTS_ID)
if (comments) comments.innerHTML = ''
}
}
return (
<div className="pt-6 pb-6 text-center text-gray-700 dark:text-gray-300">
{enableLoadComments && <button onClick={LoadComments}>Load Comments</button>}
<div className="giscus-frame" id={COMMENTS_ID} />
</div>
)
}
export default Giscus

View File

@ -0,0 +1,45 @@
import React, { useState } from 'react'
import { useTheme } from 'next-themes'
import siteMetadata from '@/data/siteMetadata'
const Utterances = ({ issueTerm }) => {
const [enableLoadComments, setEnabledLoadComments] = useState(true)
const { theme, resolvedTheme } = useTheme()
const commentsTheme =
theme === 'dark' || resolvedTheme === 'dark'
? siteMetadata.comment.utterancesConfig.darkTheme
: siteMetadata.comment.utterancesConfig.theme
const COMMENTS_ID = 'comments-container'
function LoadComments() {
setEnabledLoadComments(false)
const script = document.createElement('script')
script.src = 'https://utteranc.es/client.js'
script.setAttribute('repo', siteMetadata.comment.utterancesConfig.repo)
script.setAttribute('issue-term', issueTerm)
script.setAttribute('label', siteMetadata.comment.utterancesConfig.label)
script.setAttribute('theme', commentsTheme)
script.setAttribute('crossorigin', 'anonymous')
script.async = true
const comments = document.getElementById(COMMENTS_ID)
if (comments) comments.appendChild(script)
return () => {
const comments = document.getElementById(COMMENTS_ID)
if (comments) comments.innerHTML = ''
}
}
// Added `relative` to fix a weird bug with `utterances-frame` position
return (
<div className="pt-6 pb-6 text-center text-gray-700 dark:text-gray-300">
{enableLoadComments && <button onClick={LoadComments}>Load Comments</button>}
<div className="utterances-frame relative" id={COMMENTS_ID} />
</div>
)
}
export default Utterances

View File

@ -0,0 +1,54 @@
import siteMetadata from '@/data/siteMetadata'
import dynamic from 'next/dynamic'
const UtterancesComponent = dynamic(
() => {
return import('@/components/comments/Utterances')
},
{ ssr: false }
)
const GiscusComponent = dynamic(
() => {
return import('@/components/comments/Giscus')
},
{ ssr: false }
)
const DisqusComponent = dynamic(
() => {
return import('@/components/comments/Disqus')
},
{ ssr: false }
)
const Comments = ({ frontMatter }) => {
let term
switch (
siteMetadata.comment.giscusConfig.mapping ||
siteMetadata.comment.utterancesConfig.issueTerm
) {
case 'pathname':
term = frontMatter.slug
break
case 'url':
term = window.location.href
break
case 'title':
term = frontMatter.title
break
}
return (
<>
{siteMetadata.comment && siteMetadata.comment.provider === 'giscus' && (
<GiscusComponent mapping={term} />
)}
{siteMetadata.comment && siteMetadata.comment.provider === 'utterances' && (
<UtterancesComponent issueTerm={term} />
)}
{siteMetadata.comment && siteMetadata.comment.provider === 'disqus' && (
<DisqusComponent frontMatter={frontMatter} />
)}
</>
)
}
export default Comments

View File

@ -1,7 +1,7 @@
--- ---
title: 'Introducing Tailwind Nexjs Starter Blog' title: 'Introducing Tailwind Nexjs Starter Blog'
date: '2021-01-12' date: '2021-01-12'
lastmod: '2021-07-11' lastmod: '2021-07-18'
tags: ['next-js', 'tailwind', 'guide'] tags: ['next-js', 'tailwind', 'guide']
draft: false draft: false
summary: 'Looking for a performant, out of the box template, with all the best in web technology to support your blogging needs? Checkout the Tailwind Nextjs Starter Blog template.' summary: 'Looking for a performant, out of the box template, with all the best in web technology to support your blogging needs? Checkout the Tailwind Nextjs Starter Blog template.'
@ -48,6 +48,7 @@ I wanted it to be nearly as feature-rich as popular blogging templates like [bea
- Support for multiple authors - Support for multiple authors
- Blog templates - Blog templates
- Support for nested routing of blog posts - Support for nested routing of blog posts
- Supports [giscus](https://github.com/laymonage/giscus), [utterances](https://github.com/utterance/utterances) or disqus
- Projects page - Projects page
- SEO friendly with RSS feed, sitemaps and more! - SEO friendly with RSS feed, sitemaps and more!

View File

@ -1,6 +1,6 @@
--- ---
title: 'New features in v1' title: 'New features in v1'
date: '2021-07-11' date: '2021-07-18'
tags: ['next-js', 'tailwind', 'guide'] tags: ['next-js', 'tailwind', 'guide']
draft: false draft: false
summary: 'An overview of the new features released in v1 - code block copy, multiple authors, frontmatter layout and more' summary: 'An overview of the new features released in v1 - code block copy, multiple authors, frontmatter layout and more'
@ -15,6 +15,7 @@ A post on the new features introduced in v1.0. New features:
- [Xdm MDX compiler](#xdm-mdx-compiler) - [Xdm MDX compiler](#xdm-mdx-compiler)
- [Layouts](#layouts) - [Layouts](#layouts)
- [Multiple authors](#multiple-authors) - [Multiple authors](#multiple-authors)
- [Blog comments system](#blog-comments-system)
- [Copy button for code blocks](#copy-button-for-code-blocks) - [Copy button for code blocks](#copy-button-for-code-blocks)
- [Line highlighting and line numbers](#line-highlighting-and-line-numbers) - [Line highlighting and line numbers](#line-highlighting-and-line-numbers)
@ -140,6 +141,52 @@ export const MDXLayoutRenderer = ({ layout, mdxSource, ...rest }) => {
Use the component is a page where you want to accept a layout name to map to the desired layout. Use the component is a page where you want to accept a layout name to map to the desired layout.
You need to pass the layout name from the layout folder (it has to be an exact match) and the mdxSource content which is an output of the `seralize` function from the `next-mdx-remote` library. You need to pass the layout name from the layout folder (it has to be an exact match) and the mdxSource content which is an output of the `seralize` function from the `next-mdx-remote` library.
## Blog comments system
We added support for [giscus](https://github.com/laymonage/giscus), [utterances](https://github.com/utterance/utterances) or disqus.
To enable, simply configure `siteMetadata.js` comments property with the desired provider and settings as specified in the config file.
```js
comment: {
provider: '', // supported providers: giscus, utterances, disqus
giscusConfig: {
repo: '', // username/repoName
// Visit the link below and copy/paste the 'repositoryId', 'category' and 'categoryId'
// https://giscus.app/api/discussions/categories?repo={username}%2F{repoName}
repositoryId: '',
category: [],
categoryId: '',
mapping: '', // supported options: pathname, url, title
reactions: '', // Emoji reactions: 1 = enable / 0 = disable
// Send discussion metadata periodically to the parent window: 1 = enable / 0 = disable
metadata: '',
// theme example: light, dark, dark_dimmed, dark_high_contrast
// transparent_dark, preferred_color_scheme, custom
theme: '',
// theme when dark mode
darkTheme: '',
// If the theme option above is set to 'custom`
// please provide a link below to your custom theme css file.
// example: https://giscus.app/themes/custom_example.css
themeURL: '',
},
utterancesConfig: {
repo: '', // username/repoName
issueTerm: '', // supported options: pathname, url, title
label: '', // label (optional): Comment 💬
// theme example: github-light, github-dark, preferred-color-scheme
// github-dark-orange, icy-dark, dark-blue, photon-dark, boxy-light
theme: '',
// theme when dark mode
darkTheme: '',
},
disqus: {
// https://help.disqus.com/en/articles/1717111-what-s-a-shortname
shortname: '',
},
}
```
## Multiple authors ## Multiple authors
Information on authors is now split from `siteMetadata.json` and stored in its own `data/authors` folder as a markdown file. Minimally, you will need to have a `default.md` file with authorship information. You can create additional files as required and the file name will be used as the reference to the author. Information on authors is now split from `siteMetadata.json` and stored in its own `data/authors` folder as a markdown file. Minimally, you will need to have a `default.md` file with authorship information. You can create additional files as required and the file name will be used as the reference to the author.

65
data/siteMetadata.js Normal file
View File

@ -0,0 +1,65 @@
const siteMetadata = {
title: 'Next.js Starter Blog',
author: 'Tails Azimuth',
headerTitle: 'TailwindBlog',
description: 'A blog created with Next.js and Tailwind.css',
language: 'en-us',
siteUrl: 'https://tailwind-nextjs-starter-blog.vercel.app',
siteRepo: 'https://github.com/timlrx/tailwind-nextjs-starter-blog',
siteLogo: '/static/images/logo.png',
image: '/static/images/avatar.png',
socialBanner: '/static/images/twitter-card.png',
email: 'address@yoursite.com',
github: 'https://github.com',
twitter: 'https://twitter.com/Twitter',
facebook: 'https://facebook.com',
youtube: 'https://youtube.com',
linkedin: 'https://www.linkedin.com',
locale: 'en-US',
comment: {
provider: 'giscus', // supported providers: giscus, utterances, disqus
giscusConfig: {
repo: 'timlrx/tailwind-nextjs-starter-blog', // username/repoName
// Visit the link below and copy/paste the 'repositoryId', 'category' and 'categoryId'
// https://giscus.app/api/discussions/categories?repo={username}%2F{repoName}
repositoryId: 'MDEwOlJlcG9zaXRvcnkzMjgxMjEyNjA=',
category: [
{ emoji: '📣', id: 'MDE4OkRpc2N1c3Npb25DYXRlZ29yeTMzMDM4NDYw', name: 'Announcements' },
{ emoji: '💬', id: 'MDE4OkRpc2N1c3Npb25DYXRlZ29yeTMzMDM4NDYx', name: 'General' },
{ emoji: '🙏', id: 'MDE4OkRpc2N1c3Npb25DYXRlZ29yeTMzMDM4NDYy', name: 'Q&A' },
{ emoji: '💡', id: 'MDE4OkRpc2N1c3Npb25DYXRlZ29yeTMzMDM4NDYz', name: 'Ideas' },
{ emoji: '🙌', id: 'MDE4OkRpc2N1c3Npb25DYXRlZ29yeTMzMDM4NDY0', name: 'Show and tell' },
],
categoryId: 'MDE4OkRpc2N1c3Npb25DYXRlZ29yeTMzMDM4NDYw',
mapping: 'pathname', // supported options: pathname, url, title
reactions: '1', // Emoji reactions: 1 = enable / 0 = disable
// Send discussion metadata periodically to the parent window: 1 = enable / 0 = disable
metadata: '0',
// theme example: light, dark, dark_dimmed, dark_high_contrast
// transparent_dark, preferred_color_scheme, custom
theme: 'light',
// theme when dark mode
darkTheme: 'transparent_dark',
// If the theme option above is set to 'custom`
// please provide a link below to your custom theme css file.
// example: https://giscus.app/themes/custom_example.css
themeURL: '',
},
utterancesConfig: {
repo: '', // username/repoName
issueTerm: '', // supported options: pathname, url, title
label: '', // label (optional): Comment 💬
// theme example: github-light, github-dark, preferred-color-scheme
// github-dark-orange, icy-dark, dark-blue, photon-dark, boxy-light
theme: '',
// theme when dark mode
darkTheme: '',
},
disqus: {
// https://help.disqus.com/en/articles/1717111-what-s-a-shortname
shortname: '',
},
},
}
module.exports = siteMetadata

View File

@ -1,19 +0,0 @@
{
"title": "Next.js Starter Blog",
"author": "Tails Azimuth",
"headerTitle": "TailwindBlog",
"description": "A blog created with Next.js and Tailwind.css",
"language": "en-us",
"siteUrl": "https://tailwind-nextjs-starter-blog.vercel.app",
"siteRepo": "https://github.com/timlrx/tailwind-nextjs-starter-blog",
"siteLogo": "/static/images/logo.png",
"image": "/static/images/avatar.png",
"socialBanner": "/static/images/twitter-card.png",
"email": "address@yoursite.com",
"github": "https://github.com",
"twitter": "https://twitter.com/Twitter",
"facebook": "https://facebook.com",
"youtube": "https://youtube.com",
"linkedin": "https://www.linkedin.com",
"locale": "en-US"
}

View File

@ -5,6 +5,7 @@ import { BlogSeo } from '@/components/SEO'
import Image from '@/components/Image' import Image from '@/components/Image'
import Tag from '@/components/Tag' import Tag from '@/components/Tag'
import siteMetadata from '@/data/siteMetadata' import siteMetadata from '@/data/siteMetadata'
import Comments from '@/components/comments'
const editUrl = (fileName) => `${siteMetadata.siteRepo}/blob/master/data/blog/${fileName}` const editUrl = (fileName) => `${siteMetadata.siteRepo}/blob/master/data/blog/${fileName}`
const discussUrl = (slug) => const discussUrl = (slug) =>
@ -91,6 +92,7 @@ export default function PostLayout({ frontMatter, authorDetails, next, prev, chi
{``} {``}
<Link href={editUrl(fileName)}>{'View on GitHub'}</Link> <Link href={editUrl(fileName)}>{'View on GitHub'}</Link>
</div> </div>
<Comments frontMatter={frontMatter} />
</div> </div>
<footer> <footer>
<div className="text-sm font-medium leading-5 divide-gray-200 xl:divide-y dark:divide-gray-700 xl:col-start-1 xl:row-start-2"> <div className="text-sm font-medium leading-5 divide-gray-200 xl:divide-y dark:divide-gray-700 xl:col-start-1 xl:row-start-2">

View File

@ -4,6 +4,7 @@ import SectionContainer from '@/components/SectionContainer'
import { BlogSeo } from '@/components/SEO' import { BlogSeo } from '@/components/SEO'
import siteMetadata from '@/data/siteMetadata' import siteMetadata from '@/data/siteMetadata'
import formatDate from '@/lib/utils/formatDate' import formatDate from '@/lib/utils/formatDate'
import Comments from '@/components/comments'
export default function PostLayout({ frontMatter, authorDetails, next, prev, children }) { export default function PostLayout({ frontMatter, authorDetails, next, prev, children }) {
const { date, title } = frontMatter const { date, title } = frontMatter
@ -35,6 +36,7 @@ export default function PostLayout({ frontMatter, authorDetails, next, prev, chi
<div className="divide-y divide-gray-200 dark:divide-gray-700 xl:pb-0 xl:col-span-3 xl:row-span-2"> <div className="divide-y divide-gray-200 dark:divide-gray-700 xl:pb-0 xl:col-span-3 xl:row-span-2">
<div className="pt-10 pb-8 prose dark:prose-dark max-w-none">{children}</div> <div className="pt-10 pb-8 prose dark:prose-dark max-w-none">{children}</div>
</div> </div>
<Comments frontMatter={frontMatter} />
<footer> <footer>
<div className="flex flex-col text-sm font-medium sm:flex-row sm:justify-between sm:text-base"> <div className="flex flex-col text-sm font-medium sm:flex-row sm:justify-between sm:text-base">
{prev && ( {prev && (