From ecfc86f5f5a8a42f6fe669cbdb9b11b8a5478420 Mon Sep 17 00:00:00 2001 From: Armand Abric Date: Tue, 19 Jan 2021 10:39:02 +0100 Subject: [PATCH] Specify language by post --- _posts/dynamic-routing.md | 1 + _posts/hello-world.md | 1 + _posts/preview.md | 1 + lib/api.ts | 12 ++++++--- package.json | 1 + pages/posts/[slug].tsx | 57 ++++++++++++++------------------------- types/post.ts | 33 +++++++++++++++++++++++ yarn.lock | 37 ++++++++++++++++++++++++- 8 files changed, 101 insertions(+), 42 deletions(-) diff --git a/_posts/dynamic-routing.md b/_posts/dynamic-routing.md index 44b0b31..be8c923 100644 --- a/_posts/dynamic-routing.md +++ b/_posts/dynamic-routing.md @@ -1,4 +1,5 @@ --- +lang: "fr" title: "Dynamic Routing and Static Generation" excerpt: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus." coverImage: "/assets/blog/dynamic-routing/cover.jpg" diff --git a/_posts/hello-world.md b/_posts/hello-world.md index e3fe9fe..435bf93 100644 --- a/_posts/hello-world.md +++ b/_posts/hello-world.md @@ -1,4 +1,5 @@ --- +lang: "fr" title: "Learn How to Pre-render Pages Using Static Generation with Next.js" excerpt: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus." coverImage: "/assets/blog/hello-world/cover.jpg" diff --git a/_posts/preview.md b/_posts/preview.md index 588bf9d..aeee235 100644 --- a/_posts/preview.md +++ b/_posts/preview.md @@ -1,4 +1,5 @@ --- +lang: "fr" title: "Preview Mode for Static Generation" excerpt: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Praesent elementum facilisis leo vel fringilla est ullamcorper eget. At imperdiet dui accumsan sit amet nulla facilities morbi tempus." coverImage: "/assets/blog/preview/cover.jpg" diff --git a/lib/api.ts b/lib/api.ts index ad8a2c2..541de49 100644 --- a/lib/api.ts +++ b/lib/api.ts @@ -1,7 +1,7 @@ import fs from "fs"; import { join } from "path"; import matter from "gray-matter"; -import { Post, PostSummary } from "../types/post"; +import { Post, PostSummary, guardPostPayload } from "../types/post"; const postsDirectory = join(process.cwd(), "_posts"); @@ -18,9 +18,9 @@ export function getPostBySlug(slug: string): Post { const fileContents = fs.readFileSync(fullPath, "utf8"); const { data: headers, content: contentInMarkdown } = matter(fileContents); - // TODO: Add a validation for each header fields - const post = { + const postPayload = { slug, + lang: headers.lang, title: headers.title, excerpt: headers.excerpt, coverImage: headers.coverImage, @@ -30,7 +30,9 @@ export function getPostBySlug(slug: string): Post { content: contentInMarkdown, }; - return post; + guardPostPayload(postPayload); + + return postPayload; } export function getPostByFilename(filename: string): Post { @@ -39,6 +41,7 @@ export function getPostByFilename(filename: string): Post { export function getPostSummaryByFilename(filename: string): PostSummary { const { + lang, slug, title, excerpt, @@ -49,6 +52,7 @@ export function getPostSummaryByFilename(filename: string): PostSummary { } = getPostByFilename(filename); const postSummary = { + lang, slug, title, excerpt, diff --git a/package.json b/package.json index 4aaa076..fa1abb2 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "date-fns": "^2.10.0", "feed": "^4.2.1", "gray-matter": "^4.0.2", + "joi": "^17.3.0", "next": "^10.0.5", "react": "^17.0.1", "react-dom": "^17.0.1", diff --git a/pages/posts/[slug].tsx b/pages/posts/[slug].tsx index d227947..2243557 100644 --- a/pages/posts/[slug].tsx +++ b/pages/posts/[slug].tsx @@ -1,55 +1,38 @@ -import { useRouter } from "next/router"; -import ErrorPage from "next/error"; +import Head from "next/head"; import Container from "../../components/container"; import PostBody from "../../components/post-body"; import Header from "../../components/header"; import PostHeader from "../../components/post-header"; import Layout from "../../components/layout"; import { getPostBySlug, getAllPostSummaries } from "../../lib/api"; -import PostTitle from "../../components/post-title"; -import Head from "next/head"; -import { CMS_NAME } from "../../lib/constants"; +import { BLOG_TITLE } from "../../lib/constants"; import markdownToHtml from "../../lib/markdownToHtml"; -import { Post as PostType, PostSummary } from "../../types/post"; +import { Post as PostType } from "../../types/post"; type Props = { post: PostType; - // morePosts: Array; - preview?: boolean; }; -const Post = ({ post, preview }: Props) => { - const router = useRouter(); - - if (!router.isFallback && !post?.slug) { - return ; - } - +const Post = ({ post }: Props) => { return ( - +
- {router.isFallback ? ( - Loading… - ) : ( - <> -
- - - {post.title} | Next.js Blog Example with {CMS_NAME} - - - - - -
- - )} +
+ + + {post.title} | {BLOG_TITLE} + + + + + +
); diff --git a/types/post.ts b/types/post.ts index 3ced7e6..6f3d13a 100644 --- a/types/post.ts +++ b/types/post.ts @@ -1,6 +1,8 @@ +import Joi from "joi"; import { Author } from "./author"; export interface PostSummary { + lang: "en" | "fr"; slug: string; title: string; excerpt: string; @@ -15,3 +17,34 @@ export interface PostSummary { export interface Post extends PostSummary { content: string; } + +const postSchema = Joi.object({ + lang: Joi.string().allow("en", "fr"), + slug: Joi.string() + .pattern(/^[a-zA-Z0-9\-]+$/) + .min(5), + title: Joi.string(), + content: Joi.string(), + excerpt: Joi.string(), + coverImage: Joi.string(), + ogImage: Joi.object({ + url: Joi.string(), + }) + .options({ presence: "required" }) + .unknown(false), + date: Joi.string().isoDate(), + author: Joi.object({ + name: Joi.string(), + picture: Joi.string(), + }) + .options({ presence: "required" }) + .unknown(false), +}) + .options({ presence: "required" }) + .unknown(false); + +export function guardPostPayload( + postPayload: any, +): asserts postPayload is Post { + Joi.assert(postPayload, postSchema); +} diff --git a/yarn.lock b/yarn.lock index 6459772..f50c8fa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -117,11 +117,18 @@ dependencies: "@hapi/hoek" "9.x.x" -"@hapi/hoek@9.x.x": +"@hapi/hoek@9.x.x", "@hapi/hoek@^9.0.0": version "9.1.1" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.1.1.tgz#9daf5745156fd84b8e9889a2dc721f0c58e894aa" integrity sha512-CAEbWH7OIur6jEOzaai83jq3FmKmv4PmX1JYfs9IrYcGEVI/lyL1EXJGCj7eFVJ0bg5QR8LMxBlEtA+xKiLpFw== +"@hapi/topo@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.0.0.tgz#c19af8577fa393a06e9c77b60995af959be721e7" + integrity sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw== + dependencies: + "@hapi/hoek" "^9.0.0" + "@jest/types@^25.5.0": version "25.5.0" resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.5.0.tgz#4d6a4793f7b9599fc3680877b856a97dbccf2a9d" @@ -176,6 +183,23 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/context-base/-/context-base-0.14.0.tgz#c67fc20a4d891447ca1a855d7d70fa79a3533001" integrity sha512-sDOAZcYwynHFTbLo6n8kIbLiVF3a3BLkrmehJUyEbT9F+Smbi47kLGS2gG2g0fjBLR/Lr1InPD7kXL7FaTqEkw== +"@sideway/address@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.0.tgz#0b301ada10ac4e0e3fa525c90615e0b61a72b78d" + integrity sha512-wAH/JYRXeIFQRsxerIuLjgUu2Xszam+O5xKeatJ4oudShOOirfmsQ1D6LL54XOU2tizpCYku+s1wmU0SYdpoSA== + dependencies: + "@hapi/hoek" "^9.0.0" + +"@sideway/formula@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" + integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== + +"@sideway/pinpoint@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" + integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== + "@types/classnames@^2.2.10": version "2.2.11" resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.11.tgz#2521cc86f69d15c5b90664e4829d84566052c1cf" @@ -2537,6 +2561,17 @@ jest-worker@24.9.0: merge-stream "^2.0.0" supports-color "^6.1.0" +joi@^17.3.0: + version "17.3.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.3.0.tgz#f1be4a6ce29bc1716665819ac361dfa139fff5d2" + integrity sha512-Qh5gdU6niuYbUIUV5ejbsMiiFmBdw8Kcp8Buj2JntszCkCfxJ9Cz76OtHxOZMPXrt5810iDIXs+n1nNVoquHgg== + dependencies: + "@hapi/hoek" "^9.0.0" + "@hapi/topo" "^5.0.0" + "@sideway/address" "^4.1.0" + "@sideway/formula" "^3.0.0" + "@sideway/pinpoint" "^2.0.0" + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"