Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
sistematico committed Dec 13, 2024
1 parent 8b1302a commit 3afc9c3
Show file tree
Hide file tree
Showing 18 changed files with 2,443 additions and 60 deletions.
123 changes: 123 additions & 0 deletions app/components/mdx.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import Link from 'next/link'
import Image from 'next/image'
import { MDXRemote, MDXRemoteProps } from 'next-mdx-remote/rsc'
import { highlight } from 'sugar-high'
import React from 'react'

interface TableData {
headers: string[];
rows: string[][];
}

function Table({ data }: { data: TableData }) {
let headers = data.headers.map((header, index) => (
<th key={index}>{header}</th>
))
let rows = data.rows.map((row, index) => (
<tr key={index}>
{row.map((cell, cellIndex) => (
<td key={cellIndex}>{cell}</td>
))}
</tr>
))

return (
<table>
<thead>
<tr>{headers}</tr>
</thead>
<tbody>{rows}</tbody>
</table>
)
}

function CustomLink(props: React.AnchorHTMLAttributes<HTMLAnchorElement>) {
let href = props.href

if (href && href.startsWith('/')) {
return (
<Link href={href} {...props}>
{props.children}
</Link>
)
}

if (href && href.startsWith('#')) {
return <a {...props} />
}

return <a target="_blank" rel="noopener noreferrer" {...props} />
}

interface RoundedImageProps {
alt: string;
src: string;
width?: number;
height?: number;
[key: string]: any;
}

function RoundedImage(props: RoundedImageProps) {
const { alt, ...rest } = props;
return <Image alt={alt} className="rounded-lg" {...rest} />
}

function Code({ children, ...props }: { children: React.ReactNode }) {
let codeHTML = highlight(children as string)
return <code dangerouslySetInnerHTML={{ __html: codeHTML }} {...props} />
}

function slugify(str: string) {
return str
.toString()
.toLowerCase()
.trim() // Remove whitespace from both ends of a string
.replace(/\s+/g, '-') // Replace spaces with -
.replace(/&/g, '-and-') // Replace & with 'and'
.replace(/[^\w\-]+/g, '') // Remove all non-word characters except for -
.replace(/\-\-+/g, '-') // Replace multiple - with single -
}

function createHeading(level: number) {
const Heading = ({ children }: { children: React.ReactNode }) => {
let slug = slugify(children as string)
return React.createElement(
`h${level}`,
{ id: slug },
[
React.createElement('a', {
href: `#${slug}`,
key: `link-${slug}`,
className: 'anchor',
}),
],
children
)
}

Heading.displayName = `Heading${level}`

return Heading
}

let components = {
h1: createHeading(1),
h2: createHeading(2),
h3: createHeading(3),
h4: createHeading(4),
h5: createHeading(5),
h6: createHeading(6),
Image: RoundedImage,
a: CustomLink,
code: Code,
Table,
}

export function CustomMDX(props: React.JSX.IntrinsicAttributes & MDXRemoteProps) {
return (
<MDXRemote
{...props}
components={{ ...components, ...(props.components || {}) }}
/>
)
}
36 changes: 36 additions & 0 deletions app/components/posts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Link from 'next/link'
import { formatDate, getBlogPosts } from '../posts/utils'

export function BlogPosts() {
let allBlogs = getBlogPosts()

return (
<div>
{allBlogs
.sort((a, b) => {
if (
new Date(a.metadata.publishedAt) > new Date(b.metadata.publishedAt)
) {
return -1
}
return 1
})
.map((post) => (
<Link
key={post.slug}
className="flex flex-col space-y-1 mb-4"
href={`/posts/${post.slug}`}
>
<div className="w-full flex flex-col md:flex-row space-x-0 md:space-x-2">
<p className="text-neutral-600 dark:text-neutral-400 w-[100px] tabular-nums">
{formatDate(post.metadata.publishedAt, false)}
</p>
<p className="text-neutral-900 dark:text-neutral-100 tracking-tight">
{post.metadata.title}
</p>
</div>
</Link>
))}
</div>
)
}
21 changes: 0 additions & 21 deletions app/globals.css

This file was deleted.

11 changes: 6 additions & 5 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import "./styles/main.css";

const geistSans = Geist({
variable: "--font-geist-sans",
Expand All @@ -13,8 +13,9 @@ const geistMono = Geist_Mono({
});

export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
title: "Paxá",
description: "Full-stack developer, designer, and writer.",
icons: "https://paxa.dev/images/favicon.png"
};

export default function RootLayout({
Expand All @@ -25,9 +26,9 @@ export default function RootLayout({
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased flex flex-col items-center justify-center mx-auto mt-2 lg:mt-8 mb-20 lg:mb-40`}
className={`${geistSans.variable} ${geistMono.variable} antialiased flex items-center justify-center mx-auto h-full`}
>
<main className="flex-auto min-w-0 mt-2 md:mt-6 flex flex-col px-6 sm:px-4 md:px-0 max-w-[640px] w-full">
<main className="flex flex-col flex-auto min-w-0 max-w-[640px] w-full">
{children}
</main>
</body>
Expand Down
2 changes: 1 addition & 1 deletion app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export default function Home() {
return (
<Image
className="dark:invert"
src="/next.svg"
src="/images/logo.svg"
alt="Next.js logo"
width={180}
height={38}
Expand Down
98 changes: 98 additions & 0 deletions app/posts/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { notFound } from 'next/navigation'
import { CustomMDX } from '../../components/mdx'
import { formatDate, getBlogPosts } from '../../posts/utils'
import { baseUrl } from '../../sitemap'

export async function generateStaticParams() {
let posts = await getBlogPosts()

return posts.map((post) => ({
slug: post.slug,
}))
}

export async function generateMetadata({ params }: { params: { slug: string } }) {
let post = await getBlogPosts().find((post) => post.slug === params.slug)
if (!post) {
return
}

let {
title,
publishedAt: publishedTime,
summary: description,
image,
} = post.metadata
let ogImage = image
? image
: `${baseUrl}/og?title=${encodeURIComponent(title)}`

return {
title,
description,
openGraph: {
title,
description,
type: 'article',
publishedTime,
url: `${baseUrl}/posts/${post.slug}`,
images: [
{
url: ogImage,
},
],
},
twitter: {
card: 'summary_large_image',
title,
description,
images: [ogImage],
},
}
}

export default async function Blog({ params }: { params: { slug: string } }) {
let post = await getBlogPosts().find((post) => post.slug === params.slug)

if (!post) {
notFound()
}

return (
<section>
<script
type="application/ld+json"
suppressHydrationWarning
dangerouslySetInnerHTML={{
__html: JSON.stringify({
'@context': 'https://schema.org',
'@type': 'BlogPosting',
headline: post.metadata.title,
datePublished: post.metadata.publishedAt,
dateModified: post.metadata.publishedAt,
description: post.metadata.summary,
image: post.metadata.image
? `${baseUrl}${post.metadata.image}`
: `/og?title=${encodeURIComponent(post.metadata.title)}`,
url: `${baseUrl}/blog/${post.slug}`,
author: {
'@type': 'Person',
name: 'My Portfolio',
},
}),
}}
/>
<h1 className="title font-semibold text-2xl tracking-tighter">
{post.metadata.title}
</h1>
<div className="flex justify-between items-center mt-2 mb-8 text-sm">
<p className="text-sm text-neutral-600 dark:text-neutral-400">
{formatDate(post.metadata.publishedAt)}
</p>
</div>
<article className="prose">
<CustomMDX source={post.content} />
</article>
</section>
)
}
39 changes: 39 additions & 0 deletions app/posts/content/vim.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
title: 'Embracing Vim: The Unsung Hero of Code Editors'
publishedAt: '2024-04-09'
summary: 'Discover why Vim, with its steep learning curve, remains a beloved tool among developers for editing code efficiently and effectively.'
---

In the world of software development, where the latest and greatest tools frequently capture the spotlight, Vim stands out as a timeless classic. Despite its age and initial complexity, Vim has managed to retain a devoted following of developers who swear by its efficiency, versatility, and power.

This article delves into the reasons behind Vim's enduring appeal and why it continues to be a great tool for coding in the modern era.

## Efficiency and Speed

At the heart of Vim's philosophy is the idea of minimizing keystrokes to achieve maximum efficiency.

Unlike other text editors where the mouse is often relied upon for navigation and text manipulation, Vim's keyboard-centric design allows developers to perform virtually all coding tasks without leaving the home row. This not only speeds up coding but also reduces the risk of repetitive strain injuries.

## Highly Customizable

Vim can be extensively customized to suit any developer's preferences and workflow. With a vibrant ecosystem of plugins and a robust scripting language, users can tailor the editor to their specific needs, whether it's programming in Python, writing in Markdown, or managing projects.

This level of customization ensures that Vim remains relevant and highly functional for a wide range of programming tasks and languages.

## Ubiquity and Portability

Vim is virtually everywhere. It's available on all major platforms, and because it's lightweight and terminal-based, it can be used on remote servers through SSH, making it an indispensable tool for sysadmins and developers working in a cloud-based environment.

The ability to use the same editor across different systems without a graphical interface is a significant advantage for those who need to maintain a consistent workflow across multiple environments.

## Vibrant Community

Despite—or perhaps because of—its learning curve, Vim has cultivated a passionate and active community. Online forums, dedicated websites, and plugins abound, offering support, advice, and improvements.

This community not only helps newcomers climb the steep learning curve but also continually contributes to Vim's evolution, ensuring it remains adaptable and up-to-date with the latest programming trends and technologies.

## Conclusion

Vim is not just a text editor; it's a way of approaching coding with efficiency and thoughtfulness. Its steep learning curve is a small price to pay for the speed, flexibility, and control it offers.

For those willing to invest the time to master its commands, Vim proves to be an invaluable tool that enhances productivity and enjoyment in coding. In an age of ever-changing development tools, the continued popularity of Vim is a testament to its enduring value and utility.
15 changes: 15 additions & 0 deletions app/posts/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { BlogPosts } from '../components/posts'

export const metadata = {
title: 'Blog',
description: 'Read my blog.',
}

export default function Page() {
return (
<section>
<h1 className="font-semibold text-2xl mb-8 tracking-tighter">My Blog</h1>
<BlogPosts />
</section>
)
}
Loading

0 comments on commit 3afc9c3

Please sign in to comment.