chore: sync with v0.3.4
This commit is contained in:
commit
644acb788b
@ -2,6 +2,10 @@
|
||||
|
||||
# Tailwind Nextjs Starter Blog
|
||||
|
||||
[![GitHub Repo stars](https://img.shields.io/github/stars/timlrx/tailwind-nextjs-starter-blog?style=social)](https://GitHub.com/timlrx/tailwind-nextjs-starter-blog/stargazers/)
|
||||
[![GitHub forks](https://img.shields.io/github/forks/timlrx/tailwind-nextjs-starter-blog?style=social)](https://GitHub.com/timlrx/tailwind-nextjs-starter-blog/network/)
|
||||
[![Twitter URL](https://img.shields.io/twitter/url?style=social&url=https%3A%2F%2Ftwitter.com%2Ftimlrxx)](https://twitter.com/timlrxx)
|
||||
|
||||
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/timlrx/tailwind-nextjs-starter-blog)
|
||||
|
||||
This is a [Next.js](https://nextjs.org/), [Tailwind CSS](https://tailwindcss.com/) blogging starter template. Comes out of the box configured with the latest technologies to make technical writing a breeze. Easily configurable and customizable. Perfect as a replacement to existing Jekyll and Hugo individual blogs.
|
||||
|
36
components/Pagination.js
Normal file
36
components/Pagination.js
Normal file
@ -0,0 +1,36 @@
|
||||
import Link from '@/components/Link'
|
||||
|
||||
export default function Pagination({ totalPages, currentPage }) {
|
||||
const prevPage = parseInt(currentPage) - 1 > 0
|
||||
const nextPage = parseInt(currentPage) + 1 <= parseInt(totalPages)
|
||||
|
||||
return (
|
||||
<div className="pt-6 pb-8 space-y-2 md:space-y-5">
|
||||
<nav className="flex justify-between">
|
||||
{!prevPage && (
|
||||
<button rel="previous" className="cursor-auto disabled:opacity-50" disabled={!prevPage}>
|
||||
Previous
|
||||
</button>
|
||||
)}
|
||||
{prevPage && (
|
||||
<Link href={currentPage - 1 === 1 ? `/blog/` : `/blog/page/${currentPage - 1}`}>
|
||||
<button rel="previous">Previous</button>
|
||||
</Link>
|
||||
)}
|
||||
<span>
|
||||
{currentPage} of {totalPages}
|
||||
</span>
|
||||
{!nextPage && (
|
||||
<button rel="next" className="cursor-auto disabled:opacity-50" disabled={!nextPage}>
|
||||
Next
|
||||
</button>
|
||||
)}
|
||||
{nextPage && (
|
||||
<Link href={`/blog/page/${currentPage + 1}`}>
|
||||
<button rel="next">Next</button>
|
||||
</Link>
|
||||
)}
|
||||
</nav>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -2,16 +2,21 @@ import Link from '@/components/Link'
|
||||
import Tag from '@/components/Tag'
|
||||
import siteMetadata from '@/data/siteMetadata'
|
||||
import { useState } from 'react'
|
||||
import Pagination from '@/components/Pagination'
|
||||
|
||||
const postDateTemplate = { year: 'numeric', month: 'long', day: 'numeric' }
|
||||
|
||||
export default function ListLayout({ posts, title }) {
|
||||
export default function ListLayout({ posts, title, initialDisplayPosts = [], pagination }) {
|
||||
const [searchValue, setSearchValue] = useState('')
|
||||
const filteredBlogPosts = posts.filter((frontMatter) => {
|
||||
const searchContent = frontMatter.title + frontMatter.summary + frontMatter.tags.join(' ')
|
||||
return searchContent.toLowerCase().includes(searchValue.toLowerCase())
|
||||
})
|
||||
|
||||
// If initialDisplayPosts exist, display it if no searchValue is specified
|
||||
const displayPosts =
|
||||
initialDisplayPosts.length > 0 && !searchValue ? initialDisplayPosts : filteredBlogPosts
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="divide-y">
|
||||
@ -45,7 +50,7 @@ export default function ListLayout({ posts, title }) {
|
||||
</div>
|
||||
<ul>
|
||||
{!filteredBlogPosts.length && 'No posts found.'}
|
||||
{filteredBlogPosts.map((frontMatter) => {
|
||||
{displayPosts.map((frontMatter) => {
|
||||
const { slug, date, title, summary, tags } = frontMatter
|
||||
return (
|
||||
<li key={slug} className="py-4">
|
||||
@ -81,6 +86,9 @@ export default function ListLayout({ posts, title }) {
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
{pagination && pagination.totalPages > 1 && !searchValue && (
|
||||
<Pagination currentPage={pagination.currentPage} totalPages={pagination.totalPages} />
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -42,8 +42,8 @@ export function dateSortDesc(a, b) {
|
||||
}
|
||||
|
||||
export async function getFileBySlug(type, slug) {
|
||||
const mdxPath = path.join(root, 'data', type, `${slug.join('/')}.mdx`)
|
||||
const mdPath = path.join(root, 'data', type, `${slug.join('/')}.md`)
|
||||
const mdxPath = path.join(root, 'data', type, `${slug}.mdx`)
|
||||
const mdPath = path.join(root, 'data', type, `${slug}.md`)
|
||||
const source = fs.existsSync(mdxPath)
|
||||
? fs.readFileSync(mdxPath, 'utf8')
|
||||
: fs.readFileSync(mdPath, 'utf8')
|
||||
@ -80,7 +80,6 @@ export async function getFileBySlug(type, slug) {
|
||||
return {
|
||||
mdxSource,
|
||||
frontMatter: {
|
||||
wordCount: content.split(/\s+/gu).length,
|
||||
readingTime: readingTime(content),
|
||||
slug: slug || null,
|
||||
fileName: fs.existsSync(mdxPath) ? `${slug}.mdx` : `${slug}.md`,
|
||||
|
141
package-lock.json
generated
141
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tailwind-nextjs-starter-blog",
|
||||
"version": "0.3.2",
|
||||
"version": "0.3.4",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@ -1208,9 +1208,9 @@
|
||||
}
|
||||
},
|
||||
"@hapi/accept": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/accept/-/accept-5.0.1.tgz",
|
||||
"integrity": "sha512-fMr4d7zLzsAXo28PRRQPXR1o2Wmu+6z+VY1UzDp0iFo13Twj8WePakwXBiqn3E1aAlTpSNzCXdnnQXFhst8h8Q==",
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/accept/-/accept-5.0.2.tgz",
|
||||
"integrity": "sha512-CmzBx/bXUR8451fnZRuZAJRlzgm0Jgu5dltTX/bszmR2lheb9BpyN47Q1RbaGTsvFzn0PXAEs+lXDKfshccYZw==",
|
||||
"requires": {
|
||||
"@hapi/boom": "9.x.x",
|
||||
"@hapi/hoek": "9.x.x"
|
||||
@ -1239,16 +1239,6 @@
|
||||
"unist-util-visit": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"@mdx-js/loader": {
|
||||
"version": "1.6.22",
|
||||
"resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-1.6.22.tgz",
|
||||
"integrity": "sha512-9CjGwy595NaxAYp0hF9B/A0lH6C8Rms97e2JS9d3jVUtILn6pT5i5IV965ra3lIWc7Rs1GG1tBdVF7dCowYe6Q==",
|
||||
"requires": {
|
||||
"@mdx-js/mdx": "1.6.22",
|
||||
"@mdx-js/react": "1.6.22",
|
||||
"loader-utils": "2.0.0"
|
||||
}
|
||||
},
|
||||
"@mdx-js/mdx": {
|
||||
"version": "1.6.22",
|
||||
"resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz",
|
||||
@ -1329,33 +1319,28 @@
|
||||
"integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA=="
|
||||
},
|
||||
"@next/bundle-analyzer": {
|
||||
"version": "10.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-10.2.0.tgz",
|
||||
"integrity": "sha512-vJI5zer6fp9vtDal/IxwyT3rigu/+nACdKIJHyzls+fz1joyHAKU15Xxz0rsak3cwvE6MozFjoJTrawDV8eQDQ==",
|
||||
"version": "10.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@next/bundle-analyzer/-/bundle-analyzer-10.2.3.tgz",
|
||||
"integrity": "sha512-vEfQhGWgJugZOlSUlj3DZWs/KsK0SO2SPKoHSZ7KkzpruKzc/e45G0oUh0rffzdhasMQZM1TuSBkxO+1UcnDNw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"webpack-bundle-analyzer": "4.3.0"
|
||||
}
|
||||
},
|
||||
"@next/env": {
|
||||
"version": "10.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-10.2.0.tgz",
|
||||
"integrity": "sha512-tsWBsn1Rb6hXRaHc/pWMCpZ4Ipkf3OCbZ54ef5ukgIyEvzzGdGFXQshPP2AF7yb+8yMpunWs7vOMZW3e8oPF6A=="
|
||||
},
|
||||
"@next/mdx": {
|
||||
"version": "10.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@next/mdx/-/mdx-10.2.0.tgz",
|
||||
"integrity": "sha512-2AwN5Q4Av6McSpVKps2dDGdKEEUdme0cjdmo0iNuBFdBPzMBMeMyIMrT9T/QPCDUtqeB747f6Zkf/Xt2uVwzBg=="
|
||||
"version": "10.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-10.2.3.tgz",
|
||||
"integrity": "sha512-uBOjRBjsWC4C8X3DfmWWP6ekwLnf2JCCwQX9KVnJtJkqfDsv1yQPakdOEwvJzXQc3JC/v5KKffYPVmV2wHXCgQ=="
|
||||
},
|
||||
"@next/polyfill-module": {
|
||||
"version": "10.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@next/polyfill-module/-/polyfill-module-10.2.0.tgz",
|
||||
"integrity": "sha512-Nl3GexIUXsmuggkUqrRFyE/2k7UI44JaVzSywtXEyHzxpZm2a5bdMaWuC89pgLiFDDOqmbqyLAbtwm5lNxa7Eg=="
|
||||
"version": "10.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@next/polyfill-module/-/polyfill-module-10.2.3.tgz",
|
||||
"integrity": "sha512-OkeY4cLhzfYbXxM4fd+6V4s5pTPuyfKSlavItfNRA6PpS7t1/R6YjO7S7rB8tu1pbTGuDHGIdE1ioDv15bAbDQ=="
|
||||
},
|
||||
"@next/react-dev-overlay": {
|
||||
"version": "10.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@next/react-dev-overlay/-/react-dev-overlay-10.2.0.tgz",
|
||||
"integrity": "sha512-PRIAoWog41hLN4iJ8dChKp4ysOX0Q8yiNQ/cwzyqEd3EjugkDV5OiKl3mumGKaApJaIra1MX6j1wgQRuLhuWMA==",
|
||||
"version": "10.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@next/react-dev-overlay/-/react-dev-overlay-10.2.3.tgz",
|
||||
"integrity": "sha512-E6g2jws4YW94l0lMMopBVKIZK2mEHfSBvM0d9dmzKG9L/A/kEq6LZCB4SiwGJbNsAdlk2y3USDa0oNbpA+m5Kw==",
|
||||
"requires": {
|
||||
"@babel/code-frame": "7.12.11",
|
||||
"anser": "1.4.9",
|
||||
@ -1432,9 +1417,9 @@
|
||||
}
|
||||
},
|
||||
"@next/react-refresh-utils": {
|
||||
"version": "10.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@next/react-refresh-utils/-/react-refresh-utils-10.2.0.tgz",
|
||||
"integrity": "sha512-3I31K9B4hEQRl7yQ44Umyz+szHtuMJrNdwsgJGhoEnUCXSBRHp5wv5Zv8eDa2NewSbe53b2C0oOpivrzmdBakw=="
|
||||
"version": "10.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@next/react-refresh-utils/-/react-refresh-utils-10.2.3.tgz",
|
||||
"integrity": "sha512-qtBF56vPC6d6a8p7LYd0iRjW89fhY80kAIzmj+VonvIGjK/nymBjcFUhbKiMFqlhsarCksnhwX+Zmn95Dw9qvA=="
|
||||
},
|
||||
"@nodelib/fs.scandir": {
|
||||
"version": "2.1.4",
|
||||
@ -1473,9 +1458,9 @@
|
||||
"integrity": "sha512-sDOAZcYwynHFTbLo6n8kIbLiVF3a3BLkrmehJUyEbT9F+Smbi47kLGS2gG2g0fjBLR/Lr1InPD7kXL7FaTqEkw=="
|
||||
},
|
||||
"@polka/url": {
|
||||
"version": "1.0.0-next.12",
|
||||
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.12.tgz",
|
||||
"integrity": "sha512-6RglhutqrGFMO1MNUXp95RBuYIuc8wTnMAV5MUhLmjTOy78ncwOw7RgeQ/HeymkKXRhZd0s2DNrM1rL7unk3MQ==",
|
||||
"version": "1.0.0-next.15",
|
||||
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.15.tgz",
|
||||
"integrity": "sha512-15spi3V28QdevleWBNXE4pIls3nFZmBbUGrW9IVPwiQczuSb9n76TCB4bsk8TSel+I1OkHEdPhu5QKMfY6rQHA==",
|
||||
"dev": true
|
||||
},
|
||||
"@svgr/babel-plugin-add-jsx-attribute": {
|
||||
@ -1648,9 +1633,9 @@
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "15.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.2.tgz",
|
||||
"integrity": "sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA=="
|
||||
"version": "15.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.6.1.tgz",
|
||||
"integrity": "sha512-7EIraBEyRHEe7CH+Fm1XvgqU6uwZN8Q7jppJGcqjROMT29qhAuuOxYB1uEY5UMYQKEmA5D+5tBnhdaPXSsLONA=="
|
||||
},
|
||||
"@types/parse-json": {
|
||||
"version": "4.0.0",
|
||||
@ -1806,11 +1791,6 @@
|
||||
"@babel/runtime-corejs3": "^7.10.2"
|
||||
}
|
||||
},
|
||||
"array-filter": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz",
|
||||
"integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM="
|
||||
},
|
||||
"array-flatten": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
@ -1913,12 +1893,9 @@
|
||||
}
|
||||
},
|
||||
"available-typed-arrays": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz",
|
||||
"integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==",
|
||||
"requires": {
|
||||
"array-filter": "^1.0.0"
|
||||
}
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.4.tgz",
|
||||
"integrity": "sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA=="
|
||||
},
|
||||
"axe-core": {
|
||||
"version": "4.2.0",
|
||||
@ -2995,7 +2972,8 @@
|
||||
"emojis-list": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
|
||||
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q=="
|
||||
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
|
||||
"dev": true
|
||||
},
|
||||
"encodeurl": {
|
||||
"version": "1.0.2",
|
||||
@ -4127,9 +4105,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz",
|
||||
"integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==",
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
}
|
||||
@ -4719,6 +4697,7 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
@ -5198,9 +5177,9 @@
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.1.22",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.22.tgz",
|
||||
"integrity": "sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ=="
|
||||
"version": "3.1.23",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
|
||||
"integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw=="
|
||||
},
|
||||
"native-url": {
|
||||
"version": "0.3.4",
|
||||
@ -5223,23 +5202,23 @@
|
||||
"dev": true
|
||||
},
|
||||
"next": {
|
||||
"version": "10.2.0",
|
||||
"resolved": "https://registry.npmjs.org/next/-/next-10.2.0.tgz",
|
||||
"integrity": "sha512-PKDKCSF7s82xudu3kQhOEaokxggpbLEWouEUtzP6OqV0YqKYHF+Ff+BFLycEem8ixtTM2M6ElN0VRJcskJfxPQ==",
|
||||
"version": "10.2.3",
|
||||
"resolved": "https://registry.npmjs.org/next/-/next-10.2.3.tgz",
|
||||
"integrity": "sha512-dkM1mIfnORtGyzw/Yme8RdqNxlCMZyi4Lqj56F01/yHbe1ZtOaJ0cyqqRB4RGiPhjGGh0319f8ddjDyO1605Ow==",
|
||||
"requires": {
|
||||
"@babel/runtime": "7.12.5",
|
||||
"@hapi/accept": "5.0.1",
|
||||
"@next/env": "10.2.0",
|
||||
"@next/polyfill-module": "10.2.0",
|
||||
"@next/react-dev-overlay": "10.2.0",
|
||||
"@next/react-refresh-utils": "10.2.0",
|
||||
"@hapi/accept": "5.0.2",
|
||||
"@next/env": "10.2.3",
|
||||
"@next/polyfill-module": "10.2.3",
|
||||
"@next/react-dev-overlay": "10.2.3",
|
||||
"@next/react-refresh-utils": "10.2.3",
|
||||
"@opentelemetry/api": "0.14.0",
|
||||
"assert": "2.0.0",
|
||||
"ast-types": "0.13.2",
|
||||
"browserify-zlib": "0.2.0",
|
||||
"browserslist": "4.16.1",
|
||||
"browserslist": "4.16.6",
|
||||
"buffer": "5.6.0",
|
||||
"caniuse-lite": "^1.0.30001179",
|
||||
"caniuse-lite": "^1.0.30001228",
|
||||
"chalk": "2.4.2",
|
||||
"chokidar": "3.5.1",
|
||||
"constants-browserify": "1.0.0",
|
||||
@ -5279,18 +5258,6 @@
|
||||
"watchpack": "2.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"browserslist": {
|
||||
"version": "4.16.1",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.1.tgz",
|
||||
"integrity": "sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==",
|
||||
"requires": {
|
||||
"caniuse-lite": "^1.0.30001173",
|
||||
"colorette": "^1.2.1",
|
||||
"electron-to-chromium": "^1.3.634",
|
||||
"escalade": "^3.1.1",
|
||||
"node-releases": "^1.1.69"
|
||||
}
|
||||
},
|
||||
"postcss": {
|
||||
"version": "8.2.13",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.13.tgz",
|
||||
@ -6926,12 +6893,12 @@
|
||||
}
|
||||
},
|
||||
"sirv": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.11.tgz",
|
||||
"integrity": "sha512-SR36i3/LSWja7AJNRBz4fF/Xjpn7lQFI30tZ434dIy+bitLYSP+ZEenHg36i23V2SGEz+kqjksg0uOGZ5LPiqg==",
|
||||
"version": "1.0.12",
|
||||
"resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.12.tgz",
|
||||
"integrity": "sha512-+jQoCxndz7L2tqQL4ZyzfDhky0W/4ZJip3XoOuxyQWnAwMxindLl3Xv1qT4x1YX/re0leShvTm8Uk0kQspGhBg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@polka/url": "^1.0.0-next.9",
|
||||
"@polka/url": "^1.0.0-next.15",
|
||||
"mime": "^2.3.1",
|
||||
"totalist": "^1.0.0"
|
||||
}
|
||||
@ -7988,9 +7955,9 @@
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"ws": {
|
||||
"version": "7.4.5",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz",
|
||||
"integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==",
|
||||
"version": "7.4.6",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
|
||||
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
|
||||
"dev": true
|
||||
},
|
||||
"xtend": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tailwind-nextjs-starter-blog",
|
||||
"version": "0.3.2",
|
||||
"version": "0.3.4",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "cross-env TAILWIND_MODE=watch next-remote-watch ./data",
|
||||
@ -12,15 +12,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@mapbox/rehype-prism": "^0.6.0",
|
||||
"@mdx-js/loader": "^1.6.22",
|
||||
"@mdx-js/react": "^1.6.22",
|
||||
"@next/mdx": "10.2.0",
|
||||
"@tailwindcss/forms": "^0.3.2",
|
||||
"@tailwindcss/typography": "^0.4.0",
|
||||
"autoprefixer": "^10.2.5",
|
||||
"gray-matter": "^4.0.2",
|
||||
"image-size": "1.0.0",
|
||||
"next": "10.2.0",
|
||||
"next": "10.2.3",
|
||||
"next-mdx-remote": "^3.0.1",
|
||||
"next-seo": "4.24.0",
|
||||
"next-themes": "^0.0.14",
|
||||
@ -38,7 +35,7 @@
|
||||
"tailwindcss": "^2.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "10.2.0",
|
||||
"@next/bundle-analyzer": "10.2.3",
|
||||
"@svgr/webpack": "^5.5.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^7.17.0",
|
||||
|
@ -1,26 +1,22 @@
|
||||
import '@/css/tailwind.css'
|
||||
|
||||
import { MDXProvider } from '@mdx-js/react'
|
||||
import { ThemeProvider } from 'next-themes'
|
||||
import { DefaultSeo } from 'next-seo'
|
||||
import Head from 'next/head'
|
||||
|
||||
import { SEO } from '@/components/SEO'
|
||||
import LayoutWrapper from '@/components/LayoutWrapper'
|
||||
import { MDXComponents } from '@/components/MDXComponents'
|
||||
|
||||
export default function App({ Component, pageProps }) {
|
||||
return (
|
||||
<ThemeProvider attribute="class">
|
||||
<MDXProvider components={MDXComponents}>
|
||||
<Head>
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
||||
</Head>
|
||||
<DefaultSeo {...SEO} />
|
||||
<LayoutWrapper>
|
||||
<Component {...pageProps} />
|
||||
</LayoutWrapper>
|
||||
</MDXProvider>
|
||||
<Head>
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
||||
</Head>
|
||||
<DefaultSeo {...SEO} />
|
||||
<LayoutWrapper>
|
||||
<Component {...pageProps} />
|
||||
</LayoutWrapper>
|
||||
</ThemeProvider>
|
||||
)
|
||||
}
|
||||
|
@ -27,38 +27,10 @@ class MyDocument extends Document {
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="https://cdn.jsdelivr.net/npm/katex@0.13.0/dist/fonts/KaTeX_Main-Regular.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="https://cdn.jsdelivr.net/npm/katex@0.13.0/dist/fonts/KaTeX_Math-Italic.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="https://cdn.jsdelivr.net/npm/katex@0.13.0/dist/fonts/KaTeX_Size2-Regular.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
<link
|
||||
rel="preload"
|
||||
href="https://cdn.jsdelivr.net/npm/katex@0.13.0/dist/fonts/KaTeX_Size4-Regular.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/katex@0.13.0/dist/katex.min.css"
|
||||
integrity="sha384-t5CR+zwDAROtph0PXGte6ia8heboACF9R5l/DiY+WZ3P2lxNgvJkQk5n7GPvLMYw"
|
||||
href="https://cdn.jsdelivr.net/npm/katex@0.13.11/dist/katex.min.css"
|
||||
integrity="sha384-Um5gpz1odJg5Z4HAmzPtgZKdTBHZdw8S29IecapCSB31ligYPhHQZMIlWLYQGVoc"
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
</Head>
|
||||
|
@ -3,13 +3,20 @@ import siteMetadata from '@/data/siteMetadata'
|
||||
import ListLayout from '@/layouts/ListLayout'
|
||||
import { PageSeo } from '@/components/SEO'
|
||||
|
||||
export const POSTS_PER_PAGE = 10
|
||||
|
||||
export async function getStaticProps() {
|
||||
const posts = await getAllFilesFrontMatter('blog')
|
||||
const initialDisplayPosts = posts.slice(0, POSTS_PER_PAGE)
|
||||
const pagination = {
|
||||
currentPage: 1,
|
||||
totalPages: Math.ceil(posts.length / POSTS_PER_PAGE),
|
||||
}
|
||||
|
||||
return { props: { posts } }
|
||||
return { props: { initialDisplayPosts, posts, pagination } }
|
||||
}
|
||||
|
||||
export default function Blog({ posts }) {
|
||||
export default function Blog({ posts, initialDisplayPosts, pagination }) {
|
||||
return (
|
||||
<>
|
||||
<PageSeo
|
||||
@ -17,7 +24,12 @@ export default function Blog({ posts }) {
|
||||
description={siteMetadata.description}
|
||||
url={`${siteMetadata.siteUrl}/blog`}
|
||||
/>
|
||||
<ListLayout posts={posts} title="All Posts" />
|
||||
<ListLayout
|
||||
posts={posts}
|
||||
initialDisplayPosts={initialDisplayPosts}
|
||||
pagination={pagination}
|
||||
title="All Posts"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ export async function getStaticProps({ params }) {
|
||||
const postIndex = allPosts.findIndex((post) => formatSlug(post.slug) === params.slug.join('/'))
|
||||
const prev = allPosts[postIndex + 1] || null
|
||||
const next = allPosts[postIndex - 1] || null
|
||||
const post = await getFileBySlug('blog', params.slug)
|
||||
const post = await getFileBySlug('blog', params.slug.join('/'))
|
||||
const authorList = post.frontMatter.authors || ['default']
|
||||
const authorPromise = authorList.map(async (author) => {
|
||||
const authorResults = await getFileBySlug('authors', [author])
|
||||
|
60
pages/blog/page/[page].js
Normal file
60
pages/blog/page/[page].js
Normal file
@ -0,0 +1,60 @@
|
||||
import { PageSeo } from '@/components/SEO'
|
||||
import siteMetadata from '@/data/siteMetadata'
|
||||
import { getAllFilesFrontMatter } from '@/lib/mdx'
|
||||
import ListLayout from '@/layouts/ListLayout'
|
||||
import { POSTS_PER_PAGE } from '../../blog'
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const totalPosts = await getAllFilesFrontMatter('blog')
|
||||
const totalPages = Math.ceil(totalPosts.length / POSTS_PER_PAGE)
|
||||
const paths = Array.from({ length: totalPages }, (_, i) => ({
|
||||
params: { page: (i + 1).toString() },
|
||||
}))
|
||||
|
||||
return {
|
||||
paths,
|
||||
fallback: false,
|
||||
}
|
||||
}
|
||||
|
||||
export async function getStaticProps(context) {
|
||||
const {
|
||||
params: { page },
|
||||
} = context
|
||||
const posts = await getAllFilesFrontMatter('blog')
|
||||
const pageNumber = parseInt(page)
|
||||
const initialDisplayPosts = posts.slice(
|
||||
POSTS_PER_PAGE * (pageNumber - 1),
|
||||
POSTS_PER_PAGE * pageNumber
|
||||
)
|
||||
const pagination = {
|
||||
currentPage: pageNumber,
|
||||
totalPages: Math.ceil(posts.length / POSTS_PER_PAGE),
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
posts,
|
||||
initialDisplayPosts,
|
||||
pagination,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default function PostPage({ posts, initialDisplayPosts, pagination }) {
|
||||
return (
|
||||
<>
|
||||
<PageSeo
|
||||
title={siteMetadata.title}
|
||||
description={siteMetadata.description}
|
||||
url={`${siteMetadata.siteUrl}/blog/${pagination.currentPage}`}
|
||||
/>
|
||||
<ListLayout
|
||||
posts={posts}
|
||||
initialDisplayPosts={initialDisplayPosts}
|
||||
pagination={pagination}
|
||||
title="All Posts"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user