mirror of
https://github.com/theoludwig/theoludwig.git
synced 2025-05-29 22:37:44 +02:00
chore: better Prettier config for easier reviews
This commit is contained in:
@ -1,10 +1,10 @@
|
||||
import { notFound } from 'next/navigation'
|
||||
import date from 'date-and-time'
|
||||
import { notFound } from "next/navigation"
|
||||
import date from "date-and-time"
|
||||
|
||||
import 'katex/dist/katex.min.css'
|
||||
import "katex/dist/katex.min.css"
|
||||
|
||||
import { getBlogPostBySlug } from '@/blog/blog'
|
||||
import { BlogPostContent } from '@/blog/BlogPostContent'
|
||||
import { getBlogPostBySlug } from "@/blog/blog"
|
||||
import { BlogPostContent } from "@/blog/BlogPostContent"
|
||||
|
||||
export interface BlogPostProps {
|
||||
slug: string
|
||||
@ -19,13 +19,13 @@ export const BlogPost = async (props: BlogPostProps): Promise<JSX.Element> => {
|
||||
}
|
||||
|
||||
return (
|
||||
<main className='break-wrap-words flex flex-1 flex-col flex-wrap items-center justify-center'>
|
||||
<div className='my-10 flex flex-col items-center text-center'>
|
||||
<h1 className='text-3xl font-semibold'>{blogPost.frontmatter.title}</h1>
|
||||
<p className='mt-2' data-cy='blog-post-date'>
|
||||
<main className="break-wrap-words flex flex-1 flex-col flex-wrap items-center justify-center">
|
||||
<div className="my-10 flex flex-col items-center text-center">
|
||||
<h1 className="text-3xl font-semibold">{blogPost.frontmatter.title}</h1>
|
||||
<p className="mt-2" data-cy="blog-post-date">
|
||||
{date.format(
|
||||
new Date(blogPost.frontmatter.publishedOn),
|
||||
'DD/MM/YYYY'
|
||||
"DD/MM/YYYY",
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
@ -1,9 +1,9 @@
|
||||
'use client'
|
||||
"use client"
|
||||
|
||||
import Giscus from '@giscus/react'
|
||||
import Giscus from "@giscus/react"
|
||||
|
||||
import { useTheme } from '@/theme/theme.client'
|
||||
import type { CookiesStore } from '@/utils/constants'
|
||||
import { useTheme } from "@/theme/theme.client"
|
||||
import type { CookiesStore } from "@/utils/constants"
|
||||
|
||||
interface BlogPostCommentsProps {
|
||||
cookiesStore: CookiesStore
|
||||
@ -16,18 +16,18 @@ export const BlogPostComments = (props: BlogPostCommentsProps): JSX.Element => {
|
||||
|
||||
return (
|
||||
<Giscus
|
||||
id='comments'
|
||||
repo='theoludwig/theoludwig'
|
||||
repoId='MDEwOlJlcG9zaXRvcnkzNTg5NDg1NDQ='
|
||||
category='General'
|
||||
categoryId='DIC_kwDOFWUewM4CQ_WK'
|
||||
mapping='pathname'
|
||||
reactionsEnabled='1'
|
||||
emitMetadata='0'
|
||||
inputPosition='top'
|
||||
id="comments"
|
||||
repo="theoludwig/theoludwig"
|
||||
repoId="MDEwOlJlcG9zaXRvcnkzNTg5NDg1NDQ="
|
||||
category="General"
|
||||
categoryId="DIC_kwDOFWUewM4CQ_WK"
|
||||
mapping="pathname"
|
||||
reactionsEnabled="1"
|
||||
emitMetadata="0"
|
||||
inputPosition="top"
|
||||
theme={theme}
|
||||
lang='en'
|
||||
loading='lazy'
|
||||
lang="en"
|
||||
loading="lazy"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
@ -1,37 +1,37 @@
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import { cookies } from 'next/headers'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faLink } from '@fortawesome/free-solid-svg-icons'
|
||||
import { MDXRemote } from 'next-mdx-remote/rsc'
|
||||
import { nodeTypes } from '@mdx-js/mdx'
|
||||
import rehypeRaw from 'rehype-raw'
|
||||
import remarkGfm from 'remark-gfm'
|
||||
import rehypeSlug from 'rehype-slug'
|
||||
import remarkMath from 'remark-math'
|
||||
import rehypeKatex from 'rehype-katex'
|
||||
import { getHighlighter } from 'shiki'
|
||||
import Image from "next/image"
|
||||
import Link from "next/link"
|
||||
import { cookies } from "next/headers"
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
||||
import { faLink } from "@fortawesome/free-solid-svg-icons"
|
||||
import { MDXRemote } from "next-mdx-remote/rsc"
|
||||
import { nodeTypes } from "@mdx-js/mdx"
|
||||
import rehypeRaw from "rehype-raw"
|
||||
import remarkGfm from "remark-gfm"
|
||||
import rehypeSlug from "rehype-slug"
|
||||
import remarkMath from "remark-math"
|
||||
import rehypeKatex from "rehype-katex"
|
||||
import { getHighlighter } from "shiki"
|
||||
|
||||
import 'katex/dist/katex.min.css'
|
||||
import "katex/dist/katex.min.css"
|
||||
|
||||
import { getTheme } from '@/theme/theme.server'
|
||||
import { remarkSyntaxHighlightingPlugin } from '@/blog/remarkSyntaxHighlightingPlugin'
|
||||
import { BlogPostComments } from '@/blog/BlogPostComments'
|
||||
import { getTheme } from "@/theme/theme.server"
|
||||
import { remarkSyntaxHighlightingPlugin } from "@/blog/remarkSyntaxHighlightingPlugin"
|
||||
import { BlogPostComments } from "@/blog/BlogPostComments"
|
||||
|
||||
const Heading = (
|
||||
props: React.DetailedHTMLProps<
|
||||
React.HTMLAttributes<HTMLHeadingElement>,
|
||||
HTMLHeadingElement
|
||||
>
|
||||
>,
|
||||
): JSX.Element => {
|
||||
const { children, id = '' } = props
|
||||
const { children, id = "" } = props
|
||||
return (
|
||||
<h2 {...props} className='group'>
|
||||
<h2 {...props} className="group">
|
||||
<Link
|
||||
href={`#${id}`}
|
||||
className='invisible !text-black group-hover:visible dark:!text-white'
|
||||
className="invisible !text-black group-hover:visible dark:!text-white"
|
||||
>
|
||||
<FontAwesomeIcon className='mr-2 inline h-4 w-4' icon={faLink} />
|
||||
<FontAwesomeIcon className="mr-2 inline h-4 w-4" icon={faLink} />
|
||||
</Link>
|
||||
{children}
|
||||
</h2>
|
||||
@ -43,7 +43,7 @@ export interface BlogPostContentProps {
|
||||
}
|
||||
|
||||
export const BlogPostContent = async (
|
||||
props: BlogPostContentProps
|
||||
props: BlogPostContentProps,
|
||||
): Promise<JSX.Element> => {
|
||||
const { content } = props
|
||||
|
||||
@ -51,12 +51,12 @@ export const BlogPostContent = async (
|
||||
const theme = getTheme()
|
||||
|
||||
const highlighter = await getHighlighter({
|
||||
theme: `${theme}-plus`
|
||||
theme: `${theme}-plus`,
|
||||
})
|
||||
|
||||
return (
|
||||
<div className='prose mb-10'>
|
||||
<div className='px-8'>
|
||||
<div className="prose mb-10">
|
||||
<div className="px-8">
|
||||
<MDXRemote
|
||||
source={content}
|
||||
options={{
|
||||
@ -64,14 +64,14 @@ export const BlogPostContent = async (
|
||||
remarkPlugins: [
|
||||
remarkGfm,
|
||||
[remarkSyntaxHighlightingPlugin, { highlighter }],
|
||||
remarkMath
|
||||
remarkMath,
|
||||
],
|
||||
rehypePlugins: [
|
||||
rehypeSlug,
|
||||
[rehypeRaw, { passThrough: nodeTypes }],
|
||||
rehypeKatex
|
||||
]
|
||||
}
|
||||
rehypeKatex,
|
||||
],
|
||||
},
|
||||
}}
|
||||
components={{
|
||||
h1: Heading,
|
||||
@ -81,27 +81,27 @@ export const BlogPostContent = async (
|
||||
h5: Heading,
|
||||
h6: Heading,
|
||||
img: (properties) => {
|
||||
const { src = '', alt = 'Blog Image' } = properties
|
||||
const source = src.replace('../../public/', '/')
|
||||
const { src = "", alt = "Blog Image" } = properties
|
||||
const source = src.replace("../../public/", "/")
|
||||
return (
|
||||
<span className='flex flex-col items-center justify-center'>
|
||||
<span className="flex flex-col items-center justify-center">
|
||||
<Image
|
||||
src={source}
|
||||
alt={alt}
|
||||
width={1000}
|
||||
height={1000}
|
||||
className='h-auto w-auto'
|
||||
className="h-auto w-auto"
|
||||
/>
|
||||
</span>
|
||||
)
|
||||
},
|
||||
a: (props) => {
|
||||
const { href = '' } = props
|
||||
if (href.startsWith('#')) {
|
||||
const { href = "" } = props
|
||||
if (href.startsWith("#")) {
|
||||
return <a {...props} />
|
||||
}
|
||||
return <a target='_blank' rel='noopener noreferrer' {...props} />
|
||||
}
|
||||
return <a target="_blank" rel="noopener noreferrer" {...props} />
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<BlogPostComments cookiesStore={cookiesStore.toString()} />
|
||||
|
@ -1,35 +1,35 @@
|
||||
import Link from 'next/link'
|
||||
import date from 'date-and-time'
|
||||
import Link from "next/link"
|
||||
import date from "date-and-time"
|
||||
|
||||
import { ShadowContainer } from '@/components/design/ShadowContainer'
|
||||
import { getBlogPosts } from '@/blog/blog'
|
||||
import { ShadowContainer } from "@/components/design/ShadowContainer"
|
||||
import { getBlogPosts } from "@/blog/blog"
|
||||
|
||||
export const BlogPosts = async (): Promise<JSX.Element> => {
|
||||
const posts = await getBlogPosts()
|
||||
|
||||
return (
|
||||
<div className='flex w-full items-center justify-center p-8'>
|
||||
<div className='w-[1600px]' data-cy='blog-posts'>
|
||||
<div className="flex w-full items-center justify-center p-8">
|
||||
<div className="w-[1600px]" data-cy="blog-posts">
|
||||
{posts.map((post, index) => {
|
||||
const postPublishedOn = date.format(
|
||||
new Date(post.frontmatter.publishedOn),
|
||||
'DD/MM/YYYY'
|
||||
"DD/MM/YYYY",
|
||||
)
|
||||
return (
|
||||
<Link
|
||||
href={`/blog/${post.slug}`}
|
||||
key={index}
|
||||
locale='en'
|
||||
locale="en"
|
||||
data-cy={post.slug}
|
||||
>
|
||||
<ShadowContainer className='cursor-pointer p-6 transition duration-200 ease-in-out hover:-translate-y-2'>
|
||||
<h2 data-cy='blog-post-title' className='text-xl font-semibold'>
|
||||
<ShadowContainer className="cursor-pointer p-6 transition duration-200 ease-in-out hover:-translate-y-2">
|
||||
<h2 data-cy="blog-post-title" className="text-xl font-semibold">
|
||||
{post.frontmatter.title}
|
||||
</h2>
|
||||
<p data-cy='blog-post-date' className='mt-2'>
|
||||
<p data-cy="blog-post-date" className="mt-2">
|
||||
{postPublishedOn}
|
||||
</p>
|
||||
<p data-cy='blog-post-description' className='mt-3'>
|
||||
<p data-cy="blog-post-description" className="mt-3">
|
||||
{post.frontmatter.description}
|
||||
</p>
|
||||
</ShadowContainer>
|
||||
|
22
blog/blog.ts
22
blog/blog.ts
@ -1,10 +1,10 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import fs from "node:fs"
|
||||
import path from "node:path"
|
||||
|
||||
import { cache } from 'react'
|
||||
import matter from 'gray-matter'
|
||||
import { cache } from "react"
|
||||
import matter from "gray-matter"
|
||||
|
||||
export const BLOG_POSTS_PATH = path.join(process.cwd(), 'blog', 'posts')
|
||||
export const BLOG_POSTS_PATH = path.join(process.cwd(), "blog", "posts")
|
||||
|
||||
export interface FrontMatter {
|
||||
title: string
|
||||
@ -23,13 +23,13 @@ export const getBlogPosts = cache(async (): Promise<BlogPost[]> => {
|
||||
const blogPosts = await fs.promises.readdir(BLOG_POSTS_PATH)
|
||||
const blogPostsWithTime = await Promise.all(
|
||||
blogPosts.map(async (blogPostFilename) => {
|
||||
const [slug, extension] = blogPostFilename.split('.')
|
||||
const [slug, extension] = blogPostFilename.split(".")
|
||||
if (slug == null || extension == null) {
|
||||
throw new Error('Invalid blog post filename.')
|
||||
throw new Error("Invalid blog post filename.")
|
||||
}
|
||||
const blogPostPath = path.join(BLOG_POSTS_PATH, `${slug}.${extension}`)
|
||||
const blogPostContent = await fs.promises.readFile(blogPostPath, {
|
||||
encoding: 'utf8'
|
||||
encoding: "utf8",
|
||||
})
|
||||
const { data, content } = matter(blogPostContent) as unknown as {
|
||||
data: FrontMatter
|
||||
@ -40,9 +40,9 @@ export const getBlogPosts = cache(async (): Promise<BlogPost[]> => {
|
||||
slug,
|
||||
content,
|
||||
frontmatter: data,
|
||||
time: date.getTime()
|
||||
time: date.getTime(),
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
const blogPostsSortedByPublicationDate = blogPostsWithTime
|
||||
.filter((post) => {
|
||||
@ -61,5 +61,5 @@ export const getBlogPostBySlug = cache(
|
||||
return blogPost.slug === slug && blogPost.frontmatter.isPublished
|
||||
})
|
||||
return blogPost
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@ -1,8 +1,8 @@
|
||||
---
|
||||
title: '🧼 Clean Code'
|
||||
title: "🧼 Clean Code"
|
||||
description: 'What is "Clean Code", what are "Design Patterns", and why is it so important today? Tips and tricks to make your code more readable and maintainable in the long term.'
|
||||
isPublished: true
|
||||
publishedOn: '2022-02-23T08:00:18.758Z'
|
||||
publishedOn: "2022-02-23T08:00:18.758Z"
|
||||
---
|
||||
|
||||
Hello! 👋
|
||||
@ -110,7 +110,7 @@ const transaction = charge(user, subscription)
|
||||
```typescript
|
||||
interface Car {
|
||||
carModel: string
|
||||
carColor: 'red' | 'blue' | 'yellow'
|
||||
carColor: "red" | "blue" | "yellow"
|
||||
}
|
||||
const printCar = (car: Car): void => {
|
||||
console.log(`${car.carModel} (${car.carColor})`)
|
||||
@ -122,7 +122,7 @@ const printCar = (car: Car): void => {
|
||||
```typescript
|
||||
interface Car {
|
||||
model: string
|
||||
color: 'red' | 'blue' | 'yellow'
|
||||
color: "red" | "blue" | "yellow"
|
||||
}
|
||||
const printCar = (car: Car): void => {
|
||||
console.log(`${car.model} (${car.color})`)
|
||||
@ -170,17 +170,17 @@ We have to keep it as simple as possible, not to implement features that are not
|
||||
### Example (bad way)
|
||||
|
||||
```typescript
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import fs from "node:fs"
|
||||
import path from "node:path"
|
||||
|
||||
const createFile = async (
|
||||
name: string,
|
||||
isTemporary: boolean = false
|
||||
isTemporary: boolean = false,
|
||||
): Promise<void> => {
|
||||
if (isTemporary) {
|
||||
return await fs.promises.writeFile(path.join('temporary', name), '')
|
||||
return await fs.promises.writeFile(path.join("temporary", name), "")
|
||||
}
|
||||
return await fs.promises.writeFile(name, '')
|
||||
return await fs.promises.writeFile(name, "")
|
||||
}
|
||||
```
|
||||
|
||||
@ -189,15 +189,15 @@ const createFile = async (
|
||||
### Example (good way)
|
||||
|
||||
```typescript
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import fs from "node:fs"
|
||||
import path from "node:path"
|
||||
|
||||
const createFile = async (name: string): Promise<void> => {
|
||||
await fs.promises.writeFile(name, '')
|
||||
await fs.promises.writeFile(name, "")
|
||||
}
|
||||
|
||||
const createTemporaryFile = async (name: string): Promise<void> => {
|
||||
await createFile(path.join('temporary', name))
|
||||
await createFile(path.join("temporary", name))
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
---
|
||||
title: '🗓️ Git version control: Ultimate Guide'
|
||||
description: 'What is `git`, what are the most used commands, best practices, and tips and tricks. The Ultimate guide to master `git` in your daily workflow.'
|
||||
title: "🗓️ Git version control: Ultimate Guide"
|
||||
description: "What is `git`, what are the most used commands, best practices, and tips and tricks. The Ultimate guide to master `git` in your daily workflow."
|
||||
isPublished: true
|
||||
publishedOn: '2022-10-27T14:33:07.465Z'
|
||||
publishedOn: "2022-10-27T14:33:07.465Z"
|
||||
---
|
||||
|
||||
Hello! 👋
|
||||
|
@ -1,8 +1,8 @@
|
||||
---
|
||||
title: '👋 Hello, world!'
|
||||
description: 'First post of the blog, introduction and explanation of how this blog is made.'
|
||||
title: "👋 Hello, world!"
|
||||
description: "First post of the blog, introduction and explanation of how this blog is made."
|
||||
isPublished: true
|
||||
publishedOn: '2022-02-20T08:00:18.758Z'
|
||||
publishedOn: "2022-02-20T08:00:18.758Z"
|
||||
---
|
||||
|
||||
Hello, world! 👋
|
||||
|
@ -1,8 +1,8 @@
|
||||
---
|
||||
title: '❌ Mistakes I made as a junior developer'
|
||||
description: 'Here are mistakes I made when I started, to prevent you from making the same mistakes.'
|
||||
title: "❌ Mistakes I made as a junior developer"
|
||||
description: "Here are mistakes I made when I started, to prevent you from making the same mistakes."
|
||||
isPublished: true
|
||||
publishedOn: '2022-03-14T07:42:52.989Z'
|
||||
publishedOn: "2022-03-14T07:42:52.989Z"
|
||||
---
|
||||
|
||||
Hello! 👋
|
||||
|
@ -1,8 +1,8 @@
|
||||
---
|
||||
title: '🧠 Programming Challenges'
|
||||
description: 'What are Programming Challenges and Competitive Programming and an introduction to Time/Space Complexity with Big O Notation.'
|
||||
title: "🧠 Programming Challenges"
|
||||
description: "What are Programming Challenges and Competitive Programming and an introduction to Time/Space Complexity with Big O Notation."
|
||||
isPublished: true
|
||||
publishedOn: '2023-05-21T10:20:18.837Z'
|
||||
publishedOn: "2023-05-21T10:20:18.837Z"
|
||||
---
|
||||
|
||||
Hello! 👋
|
||||
|
@ -1,8 +1,8 @@
|
||||
---
|
||||
title: '🟢 Thream v1.0.0'
|
||||
description: 'Your open source platform to stay close with your friends and communities, talk, chat, collaborate, share and have fun.'
|
||||
title: "🟢 Thream v1.0.0"
|
||||
description: "Your open source platform to stay close with your friends and communities, talk, chat, collaborate, share and have fun."
|
||||
isPublished: true
|
||||
publishedOn: '2022-04-11T10:24:55.206Z'
|
||||
publishedOn: "2022-04-11T10:24:55.206Z"
|
||||
---
|
||||
|
||||
Hello! 👋
|
||||
|
@ -1,7 +1,7 @@
|
||||
import type { Plugin, Transformer } from 'unified'
|
||||
import type { Literal, Node } from 'unist'
|
||||
import { visit } from 'unist-util-visit'
|
||||
import type { Highlighter } from 'shiki'
|
||||
import type { Plugin, Transformer } from "unified"
|
||||
import type { Literal, Node } from "unist"
|
||||
import { visit } from "unist-util-visit"
|
||||
import type { Highlighter } from "shiki"
|
||||
|
||||
export interface RemarkSyntaxHighlightingPluginOptions {
|
||||
highlighter: Highlighter
|
||||
@ -20,11 +20,11 @@ export const remarkSyntaxHighlightingPlugin: Plugin<
|
||||
Literal
|
||||
> = (options) => {
|
||||
const transformer: Transformer<RemarkSyntaxHighlightingNode> = (tree) => {
|
||||
visit<RemarkSyntaxHighlightingNode, string>(tree, 'code', (node) => {
|
||||
node.type = 'html'
|
||||
visit<RemarkSyntaxHighlightingNode, string>(tree, "code", (node) => {
|
||||
node.type = "html"
|
||||
node.children = undefined
|
||||
node.value = options.highlighter.codeToHtml(node.value, {
|
||||
lang: node.lang
|
||||
lang: node.lang,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user