1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2025-04-26 13:18:26 -04:00

consolidate mdx file parsing

This commit is contained in:
Jake Jarvis 2022-01-03 17:53:47 -05:00
parent d2b71887b4
commit 3864a57d1a
Signed by: jake
GPG Key ID: 2B0C9CF251E69A39
9 changed files with 59 additions and 68 deletions

View File

@ -1,6 +1,5 @@
import Link from "next/link";
import { format, parseISO } from "date-fns";
import groupBy from "lodash.groupby";
import { format } from "date-fns";
import styles from "./List.module.scss";
@ -10,18 +9,17 @@ type NoteProps = {
slug: string;
};
const List = ({ notes }) => {
const notesByYear = groupBy(notes, "year");
const List = ({ notesByYear }) => {
const sections = [];
Object.entries(notesByYear).forEach(([year, yearNotes]: [string, NoteProps[]]) => {
Object.entries(notesByYear).forEach(([year, notes]: [string, NoteProps[]]) => {
sections.push(
<section key={year} className={styles.section}>
<h2 className={styles.year}>{year}</h2>
<ul className={styles.list}>
{yearNotes.map((note) => (
{notes.map((note) => (
<li key={note.slug} className={styles.row}>
<span className={styles.date}>{format(parseISO(note.date), "MMM d")}</span>
<span className={styles.date}>{format(new Date(note.date), "MMM d")}</span>
<span>
<Link href={`/notes/${note.slug}/`} prefetch={false}>
<a>{note.title}</a>

View File

@ -1,5 +1,5 @@
import Link from "next/link";
import { format, parseISO } from "date-fns";
import { format } from "date-fns";
import Hits from "../hits/Hits";
import { DateIcon, TagIcon, EditIcon, ViewsIcon } from "../icons";
import * as config from "../../lib/config";
@ -20,8 +20,8 @@ const Meta = ({ title, date, slug, tags = [] }: Props) => (
<span>
<DateIcon className={`icon ${styles.icon}`} />
</span>
<span title={format(parseISO(date), "PPppp")}>
<Link href={`/notes/${slug}/`}>{format(parseISO(date), "MMMM d, yyyy")}</Link>
<span title={format(new Date(date), "PPppp")}>
<Link href={`/notes/${slug}/`}>{format(new Date(date), "MMMM d, yyyy")}</Link>
</span>
</div>
{tags.length > 0 && (

View File

@ -1,4 +1,4 @@
import { intlFormat, formatDistanceToNowStrict, parseISO } from "date-fns";
import { intlFormat, formatDistanceToNowStrict } from "date-fns";
import { StarOcticon, ForkOcticon } from "../icons/octicons";
import styles from "./RepoCard.module.scss";
@ -69,7 +69,7 @@ const RepoCard = ({ name, url, description, language, stars, forks, updatedAt }:
<div
className={styles.meta_item}
title={intlFormat(
parseISO(updatedAt),
new Date(updatedAt),
{
year: "numeric",
month: "short",
@ -83,7 +83,7 @@ const RepoCard = ({ name, url, description, language, stars, forks, updatedAt }:
}
)}
>
<span>Updated {formatDistanceToNowStrict(parseISO(updatedAt), { addSuffix: true })}</span>
<span>Updated {formatDistanceToNowStrict(new Date(updatedAt), { addSuffix: true })}</span>
</div>
</div>
</div>

View File

@ -1,30 +1,33 @@
import fs from "fs";
import path from "path";
import matter from "gray-matter";
import { format, parseISO } from "date-fns";
import * as config from "./config";
import { NOTES_DIR, baseUrl } from "./config";
export const getNoteData = (file: string) => {
const slug = file.replace(/\.mdx$/, "");
const fullPath = path.join(process.cwd(), config.NOTES_DIR, `${slug}.mdx`);
const contents = fs.readFileSync(fullPath, "utf8");
const { data } = matter(contents);
export const getNoteData = (slug: string) => {
const fullPath = path.join(process.cwd(), NOTES_DIR, `${slug}.mdx`);
const rawContent = fs.readFileSync(fullPath, "utf8");
const { data, content } = matter(rawContent);
return {
...data,
slug,
permalink: `${config.baseUrl}/notes/${slug}/`,
date: parseISO(data.date).toISOString(), // validate/normalize the date string provided from front matter
year: parseInt(format(parseISO(data.date), "yyyy")), // parse years here so it's easier to group them on list page
frontMatter: {
...data,
slug,
permalink: `${baseUrl}/notes/${slug}/`,
date: new Date(data.date).toISOString(), // validate/normalize the date string provided from front matter
},
content,
};
};
// all .mdx files in NOTES_DIR
export const getNoteFiles = () =>
fs.readdirSync(path.join(process.cwd(), config.NOTES_DIR)).filter((notePath) => /\.mdx$/.test(notePath));
export const getNoteSlugs = () =>
fs
.readdirSync(path.join(process.cwd(), NOTES_DIR))
.filter((file) => /\.mdx$/.test(file))
.map((noteFile) => noteFile.replace(/\.mdx$/, ""));
export const getAllNotes = () =>
getNoteFiles()
.map((file) => getNoteData(file))
getNoteSlugs()
.map((slug) => getNoteData(slug).frontMatter)
// sort notes by date in descending order
.sort((note1: any, note2: any) => (note1.date > note2.date ? -1 : 1));

View File

@ -43,7 +43,6 @@
"hex-rgb": "^5.0.0",
"highlight.js": "^11.3.1",
"is-absolute-url": "^4.0.1",
"lodash.groupby": "^4.6.0",
"modern-normalize": "github:sindresorhus/modern-normalize#1fc6b5a86676b7ac8abc62d04d6080f92debc70f",
"next": "v12.0.8-canary.14",
"next-mdx-remote": "^3.0.8",

View File

@ -14,7 +14,7 @@ type ColorLinkProps = {
external?: boolean;
};
const ColorLink = ({ children, href, lightColor, darkColor, title, external = false }: ColorLinkProps) => {
const ColorLink = ({ href, title, lightColor, darkColor, external = false, children }: ColorLinkProps) => {
external = external || isAbsoluteUrl(href);
// spits out an alpha color in rgb() that's compatible with linear-gradient()

View File

@ -1,7 +1,3 @@
import fs from "fs";
import path from "path";
import matter from "gray-matter";
import { parseISO } from "date-fns";
import { MDXRemote } from "next-mdx-remote";
import { serialize } from "next-mdx-remote/serialize";
import { NextSeo, ArticleJsonLd } from "next-seo";
@ -10,7 +6,7 @@ import Container from "../../components/Container";
import Content from "../../components/Content";
import Meta from "../../components/notes/Meta";
import mdxComponents from "../../components/mdxComponents";
import { getNoteFiles } from "../../lib/parse-notes";
import { getNoteData, getNoteSlugs } from "../../lib/parse-notes";
import * as config from "../../lib/config";
import type { GetStaticProps, GetStaticPaths } from "next";
@ -72,12 +68,9 @@ const Note = ({ frontMatter, source }) => (
);
export const getStaticProps: GetStaticProps = async ({ params }) => {
const filePath = path.join(process.cwd(), config.NOTES_DIR, `${params.slug}.mdx`);
const rawSource = fs.readFileSync(filePath);
const { data, content } = matter(rawSource);
const { frontMatter, content } = getNoteData(params.slug as string);
const mdxSource = await serialize(content, {
scope: data,
const source = await serialize(content, {
mdxOptions: {
// remarkPlugins: [],
rehypePlugins: [
@ -94,23 +87,14 @@ export const getStaticProps: GetStaticProps = async ({ params }) => {
return {
props: {
frontMatter: {
...data,
slug: params.slug,
permalink: `${config.baseUrl}/notes/${params.slug}/`,
date: parseISO(data.date).toISOString(), // validate/normalize the date string provided from front matter
},
source: mdxSource,
frontMatter,
source,
},
};
};
export const getStaticPaths: GetStaticPaths = async () => {
const paths = getNoteFiles()
// Remove file extensions for page paths
.map((notePath) => notePath.replace(/\.mdx?$/, ""))
// Map the path into the static paths object required by Next.js
.map((slug) => ({ params: { slug } }));
const paths = getNoteSlugs().map((slug) => ({ params: { slug } }));
return {
paths,

View File

@ -1,23 +1,29 @@
import { format } from "date-fns";
import Layout from "../../components/Layout";
import Container from "../../components/Container";
import List from "../../components/notes/List";
import { getAllNotes } from "../../lib/parse-notes";
import type { GetStaticProps } from "next";
const Notes = ({ notes }) => (
const Notes = ({ notesByYear }) => (
<Layout>
<Container title="Notes" description="Recent posts by Jake Jarvis.">
<List notes={notes} />
<List notesByYear={notesByYear} />
</Container>
</Layout>
);
export const getStaticProps: GetStaticProps = async () => {
const notes = getAllNotes();
// parse the year of each note and group them together
const notesByYear = {};
getAllNotes().map((note) => {
const year = parseInt(format(new Date(note.date), "yyyy"));
(notesByYear[year] || (notesByYear[year] = [])).push(note);
});
return {
props: {
notes,
notesByYear,
},
};
};

View File

@ -3807,11 +3807,6 @@ lodash.debounce@^4.0.8:
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
lodash.groupby@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.groupby/-/lodash.groupby-4.6.0.tgz#0b08a1dcf68397c397855c3239783832df7403d1"
integrity sha1-Cwih3PaDl8OXhVwyOXg4Mt90A9E=
lodash.merge@^4.6.2:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
@ -4419,7 +4414,7 @@ path-key@^3.0.0, path-key@^3.1.0:
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
path-parse@^1.0.6:
path-parse@^1.0.6, path-parse@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
@ -4871,12 +4866,13 @@ resolve-from@^5.0.0:
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
resolve@^1.10.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.3.2:
version "1.20.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
version "1.21.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.21.0.tgz#b51adc97f3472e6a5cf4444d34bc9d6b9037591f"
integrity sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA==
dependencies:
is-core-module "^2.2.0"
path-parse "^1.0.6"
is-core-module "^2.8.0"
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
resolve@^2.0.0-next.3:
version "2.0.0-next.3"
@ -5462,6 +5458,11 @@ supports-color@^9.2.1:
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.2.1.tgz#599dc9d45acf74c6176e0d880bab1d7d718fe891"
integrity sha512-Obv7ycoCTG51N7y175StI9BlAXrmgZrFhZOb0/PyjHBher/NmsdBgbbQ1Inhq+gIhz6+7Gb+jWF2Vqi7Mf1xnQ==
supports-preserve-symlinks-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
svg-parser@^2.0.2:
version "2.0.4"
resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5"