diff --git a/.eslintrc.json b/.eslintrc.json
index 4d765f28..d1ab569b 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,3 +1,7 @@
{
- "extends": ["next/core-web-vitals", "prettier"]
+ "plugins": ["prettier"],
+ "extends": ["next/core-web-vitals", "prettier"],
+ "rules": {
+ "prettier/prettier": "error"
+ }
}
diff --git a/.gitignore b/.gitignore
index 838f8d37..371118f4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,3 +34,4 @@ yarn-error.log*
.vercel
/public/posts
+.idea/
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index b58b603f..00000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Editor-based HTTP Client requests
-/httpRequests/
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 42b77934..00000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/unicorn-utterances.iml b/.idea/unicorn-utterances.iml
deleted file mode 100644
index 0c8867d7..00000000
--- a/.idea/unicorn-utterances.iml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7f..00000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 00000000..69a88e3b
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1 @@
+{}
diff --git a/package-lock.json b/package-lock.json
index 534301b8..c0135c60 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -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": {
"version": "7.27.1",
"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",
"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": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz",
@@ -5433,6 +5448,15 @@
"integrity": "sha512-FM/zAKgWTxj40rH03VxzIPdXmj39SwSjwG0heUcNFwI+EMZJnY93yAiKXM3dObIKAM5TA88werc8T/EwhB45eg==",
"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": {
"version": "26.6.2",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz",
diff --git a/package.json b/package.json
index 095fea4d..5447b34c 100644
--- a/package.json
+++ b/package.json
@@ -49,6 +49,7 @@
"eslint": "^7.32.0",
"eslint-config-next": "12.0.4",
"eslint-config-prettier": "^8.3.0",
+ "eslint-plugin-prettier": "^4.0.0",
"prettier": "^2.5.0"
}
}
diff --git a/src/components/seo.tsx b/src/components/seo.tsx
index 5a0f73a6..98f323bf 100644
--- a/src/components/seo.tsx
+++ b/src/components/seo.tsx
@@ -1,147 +1,177 @@
-import React from "react";
-import Head from "next/head";
-import {siteMetadata, siteUrl} from "../api/get-site-config";
-import {UnicornInfo} from "../types";
-
-interface SEOProps {
- description?: string;
- lang?: string;
- title: string;
- unicornsData?: UnicornInfo[];
- keywords?: string[];
- publishedTime?: string;
- editedTime?: string;
- type?: "article" | "profile";
- pathName?: string;
- canonical?: string;
-}
-
-type MetaSEOProps = SEOProps & {
- metaDescription: string
- metaKeywords: string
- metaImage: string
-}
-
-const GoogleAnalytics = () => {
- return <>
-
-
- >
-}
-
-const FacebookSEO = (props: MetaSEOProps) => {
- const {
- pathName,
- metaDescription,
- title,
- metaImage,
- type,
- unicornsData,
- publishedTime,
- editedTime,
- keywords
- } = props;
- return <>
-
-
-
-
-
-
- {
- type === 'article' ?
- :
- type === 'profile' ?
- :
-
- }
- {
- type === 'profile' ?
- [
- ,
- ,
-
- ]
- : null
- }
- {
- type !== 'article' ? null : [
- ,
- uni.name).join(',')}/>,
- publishedTime ? : null,
- editedTime ? : null,
- ...keywords!.map(keyword => )
- ]
- }
- >
-}
-
-
-const TwitterSingleAuthor = (props: MetaSEOProps) => {
- const socialUnicorn = props.unicornsData!.find((uni) => uni.socials);
- const uniTwitter =
- socialUnicorn && socialUnicorn.socials && socialUnicorn.socials.twitter;
- if (uniTwitter) {
- return
- }
- return null
-}
-
-const TwitterSEO = (props: MetaSEOProps) => {
- const {metaDescription, title, metaImage, type, unicornsData} = props;
- return <>
-
-
-
-
-
- {
- type === 'article' ?
- [
- unicornsData!.length === 1 ?
- :
- null
- ]
- : null
- }
- >
-}
-
-export const SEO: React.FC = (
- 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
- {title ? `${title} | ${siteMetadata.title}` : siteMetadata.title}
-
- {canonical ? : null}
-
-
-
-
-
-
- {children}
-
-}
+import React from "react";
+import Head from "next/head";
+import { siteMetadata, siteUrl } from "../api/get-site-config";
+import { UnicornInfo } from "../types";
+
+interface SEOProps {
+ description?: string;
+ lang?: string;
+ title: string;
+ unicornsData?: UnicornInfo[];
+ keywords?: string[];
+ publishedTime?: string;
+ editedTime?: string;
+ type?: "article" | "profile";
+ pathName?: string;
+ canonical?: string;
+}
+
+type MetaSEOProps = SEOProps & {
+ metaDescription: string;
+ metaKeywords: string;
+ metaImage: string;
+};
+
+const GoogleAnalytics = () => {
+ return (
+ <>
+
+
+ >
+ );
+};
+
+const FacebookSEO = (props: MetaSEOProps) => {
+ const {
+ pathName,
+ metaDescription,
+ title,
+ metaImage,
+ type,
+ unicornsData,
+ publishedTime,
+ editedTime,
+ keywords,
+ } = props;
+ return (
+ <>
+
+
+
+
+
+
+ {type === "article" ? (
+
+ ) : type === "profile" ? (
+
+ ) : (
+
+ )}
+ {type === "profile"
+ ? [
+ ,
+ ,
+ ,
+ ]
+ : null}
+ {type !== "article"
+ ? null
+ : [
+ ,
+ uni.name).join(",")}
+ />,
+ publishedTime ? (
+
+ ) : null,
+ editedTime ? (
+
+ ) : null,
+ ...keywords!.map((keyword) => (
+
+ )),
+ ]}
+ >
+ );
+};
+
+const TwitterSingleAuthor = (props: MetaSEOProps) => {
+ const socialUnicorn = props.unicornsData!.find((uni) => uni.socials);
+ const uniTwitter =
+ socialUnicorn && socialUnicorn.socials && socialUnicorn.socials.twitter;
+ if (uniTwitter) {
+ return ;
+ }
+ return null;
+};
+
+const TwitterSEO = (props: MetaSEOProps) => {
+ const { metaDescription, title, metaImage, type, unicornsData } = props;
+ return (
+ <>
+
+
+
+
+
+ {type === "article"
+ ? [
+ unicornsData!.length === 1 ? (
+
+ ) : null,
+ ]
+ : null}
+ >
+ );
+};
+
+export const SEO: React.FC = (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 (
+
+
+ {title ? `${title} | ${siteMetadata.title}` : siteMetadata.title}
+
+
+ {canonical ? : null}
+
+
+
+
+
+
+ {children}
+
+ );
+};
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx
index 6ac887c0..0ee799e0 100644
--- a/src/pages/_app.tsx
+++ b/src/pages/_app.tsx
@@ -1,6 +1,6 @@
-import { AppProps } from 'next/app'
-import '../styles/index.css'
+import { AppProps } from "next/app";
+import "../styles/index.css";
export default function MyApp({ Component, pageProps }: AppProps) {
- return
+ return ;
}
diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx
index 0622df2d..3059a9c1 100644
--- a/src/pages/_document.tsx
+++ b/src/pages/_document.tsx
@@ -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 {
render() {
return (
-
-
-
-
+
+
+
+
- )
+ );
}
}
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
index 12a19faa..7714d4b3 100644
--- a/src/pages/index.tsx
+++ b/src/pages/index.tsx
@@ -1,51 +1,50 @@
-import {getAllPosts} from '../api/api'
-import Post from '../types/post'
-import React from 'react'
-import Link from 'next/link';
+import { getAllPosts } from "../api/api";
+import Post from "../types/post";
+import React from "react";
+import Link from "next/link";
type Props = {
- allPosts: Post[]
-}
+ allPosts: Post[];
+};
-const Index = ({allPosts}: Props) => {
- return (
- <>
-
- {allPosts.map(
- post =>
- -
-
-
{post.published}
-
- )}
-
- >
- )
-}
+const Index = ({ allPosts }: Props) => {
+ return (
+ <>
+
+ {allPosts.map((post) => (
+ -
+
+
{post.published}
+
+ ))}
+
+ >
+ );
+};
-export default Index
+export default Index;
export const getStaticProps = async () => {
- let allPosts = getAllPosts({
- title: true,
- published: true,
- slug: true,
- author: true,
- excerpt: true
- } as const)
+ let allPosts = getAllPosts({
+ title: true,
+ published: true,
+ slug: true,
+ author: true,
+ excerpt: true,
+ } as const);
- // sort posts by date in descending order
- allPosts = allPosts.sort((post1, post2) => {
- const date1 = new Date(post1.published);
- const date2 = new Date(post2.published);
- return (date1 > date2 ? -1 : 1);
- })
+ // sort posts by date in descending order
+ allPosts = allPosts.sort((post1, post2) => {
+ const date1 = new Date(post1.published);
+ const date2 = new Date(post2.published);
+ return date1 > date2 ? -1 : 1;
+ });
- return {
- props: {allPosts},
- }
-}
+ return {
+ props: { allPosts },
+ };
+};
diff --git a/src/pages/posts/[slug].tsx b/src/pages/posts/[slug].tsx
index 3bfc3227..0877ac18 100644
--- a/src/pages/posts/[slug].tsx
+++ b/src/pages/posts/[slug].tsx
@@ -1,98 +1,109 @@
// import { useRouter } from 'next/router'
// import ErrorPage from 'next/error'
-import {getPostBySlug, getAllPosts, postsDirectory} from '../../api/api'
-import * as React from 'react';
+import { getPostBySlug, getAllPosts, postsDirectory } from "../../api/api";
+import * as React from "react";
import markdownToHtml from "../../utils/markdownToHtml";
-import {useMarkdownRenderer} from "../../hooks/useMarkdownRenderer";
-import 'react-medium-image-zoom/dist/styles.css'
+import { useMarkdownRenderer } from "../../hooks/useMarkdownRenderer";
+import "react-medium-image-zoom/dist/styles.css";
type Props = {
- markdownHTML: string
- slug: string
- postsDirectory: string
- wordCount: number
- seriesPosts: any[]
-}
+ markdownHTML: string;
+ slug: string;
+ postsDirectory: string;
+ wordCount: number;
+ seriesPosts: any[];
+};
-const Post = ({markdownHTML, slug, postsDirectory, wordCount, seriesPosts}: Props) => {
- const result = useMarkdownRenderer({
- markdownHTML,
- slug,
- postsDirectory
- });
+const Post = ({
+ markdownHTML,
+ slug,
+ postsDirectory,
+ wordCount,
+ seriesPosts,
+}: Props) => {
+ const result = useMarkdownRenderer({
+ markdownHTML,
+ slug,
+ postsDirectory,
+ });
- return (
- <>
- Word count: {wordCount}
- {JSON.stringify(seriesPosts)}
- <>{result}>
- >
- )
-}
+ return (
+ <>
+ Word count: {wordCount}
+ {JSON.stringify(seriesPosts)}
+ <>{result}>
+ >
+ );
+};
-export default Post
+export default Post;
type Params = {
- params: {
- slug: string
- }
-}
+ params: {
+ slug: string;
+ };
+};
const seriesPostCacheKey = {};
-export async function getStaticProps({params}: Params) {
- const post = getPostBySlug(params.slug, {
+export async function getStaticProps({ params }: Params) {
+ 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,
slug: true,
- content: true,
- wordCount: true,
series: true,
- order: true
- } as const)
+ order: true,
+ } as const,
+ seriesPostCacheKey
+ );
- const isStr = (val: any): val is string => typeof val === 'string';
- const markdown = isStr(post.content) ? post.content : '';
- const slug = isStr(post.slug) ? post.slug : '';
+ seriesPosts = allPosts
+ .filter((filterPost) => filterPost.series === post.series)
+ .sort((sortPost) => Number(sortPost.order) - Number(post.order));
+ }
- let seriesPosts: any[] = [];
- if (post.series && post.order) {
- const allPosts = getAllPosts({
- title: true,
- slug: true,
- series: true,
- order: true,
- } as const, seriesPostCacheKey)
+ const markdownHTML = await markdownToHtml(slug, markdown);
- seriesPosts = allPosts.filter(filterPost => filterPost.series === post.series).sort(sortPost => Number(sortPost.order) - Number(post.order));
- }
-
- const markdownHTML = await markdownToHtml(slug, markdown);
-
- return {
- props: {
- markdownHTML,
- slug: slug,
- postsDirectory,
- wordCount: post.wordCount,
- seriesPosts
- }
- }
+ return {
+ props: {
+ markdownHTML,
+ slug: slug,
+ postsDirectory,
+ wordCount: post.wordCount,
+ seriesPosts,
+ },
+ };
}
export async function getStaticPaths() {
- const posts = getAllPosts({'slug': true})
-
- const paths = posts.map((post) => {
- return {
- params: {
- slug: post.slug,
- },
- }
- });
+ const posts = getAllPosts({ slug: true });
+ const paths = posts.map((post) => {
return {
- paths,
- fallback: false,
- }
+ params: {
+ slug: post.slug,
+ },
+ };
+ });
+
+ return {
+ paths,
+ fallback: false,
+ };
}