mirror of
https://github.com/LukeHagar/unicorn-utterances.git
synced 2025-12-06 04:21:55 +00:00
chore: add prettier to linting
This commit is contained in:
@@ -1,3 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": ["next/core-web-vitals", "prettier"]
|
"plugins": ["prettier"],
|
||||||
|
"extends": ["next/core-web-vitals", "prettier"],
|
||||||
|
"rules": {
|
||||||
|
"prettier/prettier": "error"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -34,3 +34,4 @@ yarn-error.log*
|
|||||||
.vercel
|
.vercel
|
||||||
|
|
||||||
/public/posts
|
/public/posts
|
||||||
|
.idea/
|
||||||
|
|||||||
5
.idea/.gitignore
generated
vendored
5
.idea/.gitignore
generated
vendored
@@ -1,5 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Editor-based HTTP Client requests
|
|
||||||
/httpRequests/
|
|
||||||
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/unicorn-utterances.iml" filepath="$PROJECT_DIR$/.idea/unicorn-utterances.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
12
.idea/unicorn-utterances.iml
generated
12
.idea/unicorn-utterances.iml
generated
@@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="WEB_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager">
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
||||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
1
.prettierrc.json
Normal file
1
.prettierrc.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
24
package-lock.json
generated
24
package-lock.json
generated
@@ -2362,6 +2362,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"eslint-plugin-prettier": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"prettier-linter-helpers": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"eslint-plugin-react": {
|
"eslint-plugin-react": {
|
||||||
"version": "7.27.1",
|
"version": "7.27.1",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.27.1.tgz",
|
||||||
@@ -2554,6 +2563,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||||
},
|
},
|
||||||
|
"fast-diff": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"fast-glob": {
|
"fast-glob": {
|
||||||
"version": "3.2.7",
|
"version": "3.2.7",
|
||||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz",
|
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz",
|
||||||
@@ -5433,6 +5448,15 @@
|
|||||||
"integrity": "sha512-FM/zAKgWTxj40rH03VxzIPdXmj39SwSjwG0heUcNFwI+EMZJnY93yAiKXM3dObIKAM5TA88werc8T/EwhB45eg==",
|
"integrity": "sha512-FM/zAKgWTxj40rH03VxzIPdXmj39SwSjwG0heUcNFwI+EMZJnY93yAiKXM3dObIKAM5TA88werc8T/EwhB45eg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"prettier-linter-helpers": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fast-diff": "^1.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"pretty-format": {
|
"pretty-format": {
|
||||||
"version": "26.6.2",
|
"version": "26.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz",
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
"eslint": "^7.32.0",
|
"eslint": "^7.32.0",
|
||||||
"eslint-config-next": "12.0.4",
|
"eslint-config-next": "12.0.4",
|
||||||
"eslint-config-prettier": "^8.3.0",
|
"eslint-config-prettier": "^8.3.0",
|
||||||
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
"prettier": "^2.5.0"
|
"prettier": "^2.5.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,147 +1,177 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import {siteMetadata, siteUrl} from "../api/get-site-config";
|
import { siteMetadata, siteUrl } from "../api/get-site-config";
|
||||||
import {UnicornInfo} from "../types";
|
import { UnicornInfo } from "../types";
|
||||||
|
|
||||||
interface SEOProps {
|
interface SEOProps {
|
||||||
description?: string;
|
description?: string;
|
||||||
lang?: string;
|
lang?: string;
|
||||||
title: string;
|
title: string;
|
||||||
unicornsData?: UnicornInfo[];
|
unicornsData?: UnicornInfo[];
|
||||||
keywords?: string[];
|
keywords?: string[];
|
||||||
publishedTime?: string;
|
publishedTime?: string;
|
||||||
editedTime?: string;
|
editedTime?: string;
|
||||||
type?: "article" | "profile";
|
type?: "article" | "profile";
|
||||||
pathName?: string;
|
pathName?: string;
|
||||||
canonical?: string;
|
canonical?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
type MetaSEOProps = SEOProps & {
|
type MetaSEOProps = SEOProps & {
|
||||||
metaDescription: string
|
metaDescription: string;
|
||||||
metaKeywords: string
|
metaKeywords: string;
|
||||||
metaImage: string
|
metaImage: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
const GoogleAnalytics = () => {
|
const GoogleAnalytics = () => {
|
||||||
return <>
|
return (
|
||||||
<link rel="preconnect" href="https://www.google.com"/>
|
<>
|
||||||
<link rel="preconnect" href="https://marketingplatform.google.com"/>
|
<link rel="preconnect" href="https://www.google.com" />
|
||||||
</>
|
<link rel="preconnect" href="https://marketingplatform.google.com" />
|
||||||
}
|
</>
|
||||||
|
);
|
||||||
const FacebookSEO = (props: MetaSEOProps) => {
|
};
|
||||||
const {
|
|
||||||
pathName,
|
const FacebookSEO = (props: MetaSEOProps) => {
|
||||||
metaDescription,
|
const {
|
||||||
title,
|
pathName,
|
||||||
metaImage,
|
metaDescription,
|
||||||
type,
|
title,
|
||||||
unicornsData,
|
metaImage,
|
||||||
publishedTime,
|
type,
|
||||||
editedTime,
|
unicornsData,
|
||||||
keywords
|
publishedTime,
|
||||||
} = props;
|
editedTime,
|
||||||
return <>
|
keywords,
|
||||||
<meta property="og:url" content={siteMetadata.siteUrl + (pathName || "")}/>
|
} = props;
|
||||||
<meta property="og:site_name" content={siteMetadata.title}/>
|
return (
|
||||||
<meta property="og:title" content={title}/>
|
<>
|
||||||
<meta property="og:locale" content="en_US"/>
|
<meta
|
||||||
<meta property="og:description"
|
property="og:url"
|
||||||
content={metaDescription}/>
|
content={siteMetadata.siteUrl + (pathName || "")}
|
||||||
<meta property="og:image" content={metaImage}/>
|
/>
|
||||||
{
|
<meta property="og:site_name" content={siteMetadata.title} />
|
||||||
type === 'article' ?
|
<meta property="og:title" content={title} />
|
||||||
<meta property="og:type" content="article"/> :
|
<meta property="og:locale" content="en_US" />
|
||||||
type === 'profile' ?
|
<meta property="og:description" content={metaDescription} />
|
||||||
<meta property="og:type" content="profile"/> :
|
<meta property="og:image" content={metaImage} />
|
||||||
<meta property="og:type" content="blog"/>
|
{type === "article" ? (
|
||||||
}
|
<meta property="og:type" content="article" />
|
||||||
{
|
) : type === "profile" ? (
|
||||||
type === 'profile' ?
|
<meta property="og:type" content="profile" />
|
||||||
[
|
) : (
|
||||||
<meta key="firstName" property="profile:firstName" content={unicornsData![0].firstName}/>,
|
<meta property="og:type" content="blog" />
|
||||||
<meta key="lastName" property="profile:lastName" content={unicornsData![0].lastName}/>,
|
)}
|
||||||
<meta key="username" property="profile:username" content={unicornsData![0].id}/>
|
{type === "profile"
|
||||||
]
|
? [
|
||||||
: null
|
<meta
|
||||||
}
|
key="firstName"
|
||||||
{
|
property="profile:firstName"
|
||||||
type !== 'article' ? null : [
|
content={unicornsData![0].firstName}
|
||||||
<meta key="section" property="article:section" content="Technology"/>,
|
/>,
|
||||||
<meta key="author" property="article:author" content={unicornsData!.map((uni) => uni.name).join(',')}/>,
|
<meta
|
||||||
publishedTime ? <meta key="published_time" property="article:published_time" content={publishedTime}/> : null,
|
key="lastName"
|
||||||
editedTime ? <meta key="modified_time" property="article:modified_time" content={editedTime}/> : null,
|
property="profile:lastName"
|
||||||
...keywords!.map(keyword => <meta key={keyword} property="article:tag" content={keyword}/>)
|
content={unicornsData![0].lastName}
|
||||||
]
|
/>,
|
||||||
}
|
<meta
|
||||||
</>
|
key="username"
|
||||||
}
|
property="profile:username"
|
||||||
|
content={unicornsData![0].id}
|
||||||
|
/>,
|
||||||
const TwitterSingleAuthor = (props: MetaSEOProps) => {
|
]
|
||||||
const socialUnicorn = props.unicornsData!.find((uni) => uni.socials);
|
: null}
|
||||||
const uniTwitter =
|
{type !== "article"
|
||||||
socialUnicorn && socialUnicorn.socials && socialUnicorn.socials.twitter;
|
? null
|
||||||
if (uniTwitter) {
|
: [
|
||||||
return <meta property="twitter:creator" content={`@${uniTwitter}`}/>
|
<meta
|
||||||
}
|
key="section"
|
||||||
return null
|
property="article:section"
|
||||||
}
|
content="Technology"
|
||||||
|
/>,
|
||||||
const TwitterSEO = (props: MetaSEOProps) => {
|
<meta
|
||||||
const {metaDescription, title, metaImage, type, unicornsData} = props;
|
key="author"
|
||||||
return <>
|
property="article:author"
|
||||||
<meta name="twitter:title" content={title}/>
|
content={unicornsData!.map((uni) => uni.name).join(",")}
|
||||||
<meta name="twitter:description"
|
/>,
|
||||||
content={metaDescription}/>
|
publishedTime ? (
|
||||||
<meta name="twitter:card" content="summary_large_image"/>
|
<meta
|
||||||
<meta name="twitter:site" content={siteMetadata.twitterHandle}/>
|
key="published_time"
|
||||||
<meta name="twitter:image" content={metaImage}/>
|
property="article:published_time"
|
||||||
{
|
content={publishedTime}
|
||||||
type === 'article' ?
|
/>
|
||||||
[
|
) : null,
|
||||||
unicornsData!.length === 1 ?
|
editedTime ? (
|
||||||
<TwitterSingleAuthor key="singleAuthor" {...props}/> :
|
<meta
|
||||||
null
|
key="modified_time"
|
||||||
]
|
property="article:modified_time"
|
||||||
: null
|
content={editedTime}
|
||||||
}
|
/>
|
||||||
</>
|
) : null,
|
||||||
}
|
...keywords!.map((keyword) => (
|
||||||
|
<meta key={keyword} property="article:tag" content={keyword} />
|
||||||
export const SEO: React.FC<SEOProps> = (
|
)),
|
||||||
props
|
]}
|
||||||
) => {
|
</>
|
||||||
const {
|
);
|
||||||
description = "",
|
};
|
||||||
children,
|
|
||||||
title,
|
const TwitterSingleAuthor = (props: MetaSEOProps) => {
|
||||||
keywords,
|
const socialUnicorn = props.unicornsData!.find((uni) => uni.socials);
|
||||||
canonical,
|
const uniTwitter =
|
||||||
} = props;
|
socialUnicorn && socialUnicorn.socials && socialUnicorn.socials.twitter;
|
||||||
|
if (uniTwitter) {
|
||||||
const metaDescription = description || siteMetadata.description;
|
return <meta property="twitter:creator" content={`@${uniTwitter}`} />;
|
||||||
const metaKeywords = keywords ? keywords.join(',') : siteMetadata.keywords;
|
}
|
||||||
const metaImage = `${siteUrl}/share-banner.png`;
|
return null;
|
||||||
|
};
|
||||||
const metaProps = {
|
|
||||||
metaDescription,
|
const TwitterSEO = (props: MetaSEOProps) => {
|
||||||
metaKeywords,
|
const { metaDescription, title, metaImage, type, unicornsData } = props;
|
||||||
metaImage
|
return (
|
||||||
}
|
<>
|
||||||
|
<meta name="twitter:title" content={title} />
|
||||||
return <Head>
|
<meta name="twitter:description" content={metaDescription} />
|
||||||
<title>{title ? `${title} | ${siteMetadata.title}` : siteMetadata.title}</title>
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
<link rel="icon" href="/favicon.ico"/>
|
<meta name="twitter:site" content={siteMetadata.twitterHandle} />
|
||||||
{canonical ? <link rel="canonical" href={canonical}/> : null}
|
<meta name="twitter:image" content={metaImage} />
|
||||||
<meta property="name" content={siteMetadata.title}/>
|
{type === "article"
|
||||||
<meta name="description"
|
? [
|
||||||
content={metaDescription}/>
|
unicornsData!.length === 1 ? (
|
||||||
<meta property="keywords"
|
<TwitterSingleAuthor key="singleAuthor" {...props} />
|
||||||
content={metaKeywords}/>
|
) : null,
|
||||||
<GoogleAnalytics/>
|
]
|
||||||
<FacebookSEO {...props} {...metaProps}/>
|
: null}
|
||||||
<TwitterSEO {...props} {...metaProps}/>
|
</>
|
||||||
{children}
|
);
|
||||||
</Head>
|
};
|
||||||
}
|
|
||||||
|
export const SEO: React.FC<SEOProps> = (props) => {
|
||||||
|
const { description = "", children, title, keywords, canonical } = props;
|
||||||
|
|
||||||
|
const metaDescription = description || siteMetadata.description;
|
||||||
|
const metaKeywords = keywords ? keywords.join(",") : siteMetadata.keywords;
|
||||||
|
const metaImage = `${siteUrl}/share-banner.png`;
|
||||||
|
|
||||||
|
const metaProps = {
|
||||||
|
metaDescription,
|
||||||
|
metaKeywords,
|
||||||
|
metaImage,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Head>
|
||||||
|
<title>
|
||||||
|
{title ? `${title} | ${siteMetadata.title}` : siteMetadata.title}
|
||||||
|
</title>
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
{canonical ? <link rel="canonical" href={canonical} /> : null}
|
||||||
|
<meta property="name" content={siteMetadata.title} />
|
||||||
|
<meta name="description" content={metaDescription} />
|
||||||
|
<meta property="keywords" content={metaKeywords} />
|
||||||
|
<GoogleAnalytics />
|
||||||
|
<FacebookSEO {...props} {...metaProps} />
|
||||||
|
<TwitterSEO {...props} {...metaProps} />
|
||||||
|
{children}
|
||||||
|
</Head>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { AppProps } from 'next/app'
|
import { AppProps } from "next/app";
|
||||||
import '../styles/index.css'
|
import "../styles/index.css";
|
||||||
|
|
||||||
export default function MyApp({ Component, pageProps }: AppProps) {
|
export default function MyApp({ Component, pageProps }: AppProps) {
|
||||||
return <Component {...pageProps} />
|
return <Component {...pageProps} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
import Document, { Html, Head, Main, NextScript } from 'next/document'
|
import Document, { Html, Head, Main, NextScript } from "next/document";
|
||||||
|
|
||||||
export default class MyDocument extends Document {
|
export default class MyDocument extends Document {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Html lang="en">
|
<Html lang="en">
|
||||||
<Head >
|
<Head>
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=Work+Sans&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Work+Sans&display=swap"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=Archivo&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Archivo&display=swap"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=Roboto+Mono&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Roboto+Mono&display=swap"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
</Head>
|
</Head>
|
||||||
<body>
|
<body>
|
||||||
<Main />
|
<Main />
|
||||||
<NextScript />
|
<NextScript />
|
||||||
</body>
|
</body>
|
||||||
</Html>
|
</Html>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,51 +1,50 @@
|
|||||||
import {getAllPosts} from '../api/api'
|
import { getAllPosts } from "../api/api";
|
||||||
import Post from '../types/post'
|
import Post from "../types/post";
|
||||||
import React from 'react'
|
import React from "react";
|
||||||
import Link from 'next/link';
|
import Link from "next/link";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
allPosts: Post[]
|
allPosts: Post[];
|
||||||
}
|
};
|
||||||
|
|
||||||
const Index = ({allPosts}: Props) => {
|
const Index = ({ allPosts }: Props) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ul>
|
<ul>
|
||||||
{allPosts.map(
|
{allPosts.map((post) => (
|
||||||
post =>
|
<li key={post.slug}>
|
||||||
<li key={post.slug}>
|
<h2>
|
||||||
<h2>
|
<Link href={`/posts/[slug]`} as={`/posts/${post.slug}`}>
|
||||||
<Link href={`/posts/[slug]`} as={`/posts/${post.slug}`}>
|
<a>{post.title}</a>
|
||||||
<a>{post.title}</a>
|
</Link>
|
||||||
</Link>
|
</h2>
|
||||||
</h2>
|
<p>{post.published}</p>
|
||||||
<p>{post.published}</p>
|
</li>
|
||||||
</li>
|
))}
|
||||||
)}
|
</ul>
|
||||||
</ul>
|
</>
|
||||||
</>
|
);
|
||||||
)
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default Index
|
export default Index;
|
||||||
|
|
||||||
export const getStaticProps = async () => {
|
export const getStaticProps = async () => {
|
||||||
let allPosts = getAllPosts({
|
let allPosts = getAllPosts({
|
||||||
title: true,
|
title: true,
|
||||||
published: true,
|
published: true,
|
||||||
slug: true,
|
slug: true,
|
||||||
author: true,
|
author: true,
|
||||||
excerpt: true
|
excerpt: true,
|
||||||
} as const)
|
} as const);
|
||||||
|
|
||||||
// sort posts by date in descending order
|
// sort posts by date in descending order
|
||||||
allPosts = allPosts.sort((post1, post2) => {
|
allPosts = allPosts.sort((post1, post2) => {
|
||||||
const date1 = new Date(post1.published);
|
const date1 = new Date(post1.published);
|
||||||
const date2 = new Date(post2.published);
|
const date2 = new Date(post2.published);
|
||||||
return (date1 > date2 ? -1 : 1);
|
return date1 > date2 ? -1 : 1;
|
||||||
})
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {allPosts},
|
props: { allPosts },
|
||||||
}
|
};
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,98 +1,109 @@
|
|||||||
// import { useRouter } from 'next/router'
|
// import { useRouter } from 'next/router'
|
||||||
// import ErrorPage from 'next/error'
|
// import ErrorPage from 'next/error'
|
||||||
import {getPostBySlug, getAllPosts, postsDirectory} from '../../api/api'
|
import { getPostBySlug, getAllPosts, postsDirectory } from "../../api/api";
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
|
|
||||||
import markdownToHtml from "../../utils/markdownToHtml";
|
import markdownToHtml from "../../utils/markdownToHtml";
|
||||||
import {useMarkdownRenderer} from "../../hooks/useMarkdownRenderer";
|
import { useMarkdownRenderer } from "../../hooks/useMarkdownRenderer";
|
||||||
import 'react-medium-image-zoom/dist/styles.css'
|
import "react-medium-image-zoom/dist/styles.css";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
markdownHTML: string
|
markdownHTML: string;
|
||||||
slug: string
|
slug: string;
|
||||||
postsDirectory: string
|
postsDirectory: string;
|
||||||
wordCount: number
|
wordCount: number;
|
||||||
seriesPosts: any[]
|
seriesPosts: any[];
|
||||||
}
|
};
|
||||||
|
|
||||||
const Post = ({markdownHTML, slug, postsDirectory, wordCount, seriesPosts}: Props) => {
|
const Post = ({
|
||||||
const result = useMarkdownRenderer({
|
markdownHTML,
|
||||||
markdownHTML,
|
slug,
|
||||||
slug,
|
postsDirectory,
|
||||||
postsDirectory
|
wordCount,
|
||||||
});
|
seriesPosts,
|
||||||
|
}: Props) => {
|
||||||
|
const result = useMarkdownRenderer({
|
||||||
|
markdownHTML,
|
||||||
|
slug,
|
||||||
|
postsDirectory,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h1>Word count: {wordCount}</h1>
|
<h1>Word count: {wordCount}</h1>
|
||||||
{JSON.stringify(seriesPosts)}
|
{JSON.stringify(seriesPosts)}
|
||||||
<>{result}</>
|
<>{result}</>
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Post
|
export default Post;
|
||||||
|
|
||||||
type Params = {
|
type Params = {
|
||||||
params: {
|
params: {
|
||||||
slug: string
|
slug: string;
|
||||||
}
|
};
|
||||||
}
|
};
|
||||||
|
|
||||||
const seriesPostCacheKey = {};
|
const seriesPostCacheKey = {};
|
||||||
|
|
||||||
export async function getStaticProps({params}: Params) {
|
export async function getStaticProps({ params }: Params) {
|
||||||
const post = getPostBySlug(params.slug, {
|
const post = getPostBySlug(params.slug, {
|
||||||
|
title: true,
|
||||||
|
slug: true,
|
||||||
|
content: true,
|
||||||
|
wordCount: true,
|
||||||
|
series: true,
|
||||||
|
order: true,
|
||||||
|
} as const);
|
||||||
|
|
||||||
|
const isStr = (val: any): val is string => typeof val === "string";
|
||||||
|
const markdown = isStr(post.content) ? post.content : "";
|
||||||
|
const slug = isStr(post.slug) ? post.slug : "";
|
||||||
|
|
||||||
|
let seriesPosts: any[] = [];
|
||||||
|
if (post.series && post.order) {
|
||||||
|
const allPosts = getAllPosts(
|
||||||
|
{
|
||||||
title: true,
|
title: true,
|
||||||
slug: true,
|
slug: true,
|
||||||
content: true,
|
|
||||||
wordCount: true,
|
|
||||||
series: true,
|
series: true,
|
||||||
order: true
|
order: true,
|
||||||
} as const)
|
} as const,
|
||||||
|
seriesPostCacheKey
|
||||||
|
);
|
||||||
|
|
||||||
const isStr = (val: any): val is string => typeof val === 'string';
|
seriesPosts = allPosts
|
||||||
const markdown = isStr(post.content) ? post.content : '';
|
.filter((filterPost) => filterPost.series === post.series)
|
||||||
const slug = isStr(post.slug) ? post.slug : '';
|
.sort((sortPost) => Number(sortPost.order) - Number(post.order));
|
||||||
|
}
|
||||||
|
|
||||||
let seriesPosts: any[] = [];
|
const markdownHTML = await markdownToHtml(slug, markdown);
|
||||||
if (post.series && post.order) {
|
|
||||||
const allPosts = getAllPosts({
|
|
||||||
title: true,
|
|
||||||
slug: true,
|
|
||||||
series: true,
|
|
||||||
order: true,
|
|
||||||
} as const, seriesPostCacheKey)
|
|
||||||
|
|
||||||
seriesPosts = allPosts.filter(filterPost => filterPost.series === post.series).sort(sortPost => Number(sortPost.order) - Number(post.order));
|
return {
|
||||||
}
|
props: {
|
||||||
|
markdownHTML,
|
||||||
const markdownHTML = await markdownToHtml(slug, markdown);
|
slug: slug,
|
||||||
|
postsDirectory,
|
||||||
return {
|
wordCount: post.wordCount,
|
||||||
props: {
|
seriesPosts,
|
||||||
markdownHTML,
|
},
|
||||||
slug: slug,
|
};
|
||||||
postsDirectory,
|
|
||||||
wordCount: post.wordCount,
|
|
||||||
seriesPosts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const posts = getAllPosts({'slug': true})
|
const posts = getAllPosts({ slug: true });
|
||||||
|
|
||||||
const paths = posts.map((post) => {
|
|
||||||
return {
|
|
||||||
params: {
|
|
||||||
slug: post.slug,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
const paths = posts.map((post) => {
|
||||||
return {
|
return {
|
||||||
paths,
|
params: {
|
||||||
fallback: false,
|
slug: post.slug,
|
||||||
}
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
paths,
|
||||||
|
fallback: false,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user