1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2025-04-26 17:48:30 -04:00

clean up note types

This commit is contained in:
Jake Jarvis 2022-04-30 18:01:33 -04:00
parent a2921d106e
commit d718555001
Signed by: jake
GPG Key ID: 2B0C9CF251E69A39
10 changed files with 49 additions and 39 deletions

View File

@ -6,7 +6,7 @@ import NoteTitle from "../NoteTitle";
import { DateIcon, TagIcon, EditIcon, ViewsIcon } from "../Icons"; import { DateIcon, TagIcon, EditIcon, ViewsIcon } from "../Icons";
import { styled } from "../../lib/styles/stitches.config"; import { styled } from "../../lib/styles/stitches.config";
import * as config from "../../lib/config"; import * as config from "../../lib/config";
import type { NoteType } from "../../types"; import type { NoteFrontMatter } from "../../types";
const Wrapper = styled("div", { const Wrapper = styled("div", {
display: "inline-flex", display: "inline-flex",
@ -56,7 +56,7 @@ const Tag = styled("span", {
}, },
}); });
export type NoteMetaProps = Pick<NoteType["frontMatter"], "slug" | "date" | "title" | "htmlTitle" | "tags">; export type NoteMetaProps = Pick<NoteFrontMatter, "slug" | "date" | "title" | "htmlTitle" | "tags">;
const NoteMeta = ({ slug, date, title, htmlTitle, tags = [] }: NoteMetaProps) => ( const NoteMeta = ({ slug, date, title, htmlTitle, tags = [] }: NoteMetaProps) => (
<> <>

View File

@ -1,7 +1,7 @@
import NextLink from "next/link"; import NextLink from "next/link";
import { styled } from "../../lib/styles/stitches.config"; import { styled } from "../../lib/styles/stitches.config";
import type { ComponentProps } from "react"; import type { ComponentProps } from "react";
import type { NoteType } from "../../types"; import type { NoteFrontMatter } from "../../types";
const Title = styled("h1", { const Title = styled("h1", {
margin: "0.3em 0 0.5em -1px", // misaligned left margin, super nitpicky margin: "0.3em 0 0.5em -1px", // misaligned left margin, super nitpicky
@ -23,7 +23,7 @@ const Link = styled("a", {
textDecoration: "none", textDecoration: "none",
}); });
export type NoteTitleProps = Pick<NoteType["frontMatter"], "slug" | "htmlTitle"> & ComponentProps<typeof Title>; export type NoteTitleProps = Pick<NoteFrontMatter, "slug" | "htmlTitle"> & ComponentProps<typeof Title>;
const NoteTitle = ({ slug, htmlTitle, ...rest }: NoteTitleProps) => ( const NoteTitle = ({ slug, htmlTitle, ...rest }: NoteTitleProps) => (
<Title {...rest}> <Title {...rest}>

View File

@ -1,7 +1,7 @@
import Link from "../Link"; import Link from "../Link";
import Time from "../Time"; import Time from "../Time";
import { styled } from "../../lib/styles/stitches.config"; import { styled } from "../../lib/styles/stitches.config";
import type { NoteType } from "../../types"; import type { NoteFrontMatter } from "../../types";
const Section = styled("section", { const Section = styled("section", {
fontSize: "1.1em", fontSize: "1.1em",
@ -54,13 +54,13 @@ const PostDate = styled(Time, {
}); });
export type NotesListProps = { export type NotesListProps = {
notesByYear: Record<string, NoteType["frontMatter"][]>; notesByYear: Record<string, NoteFrontMatter[]>;
}; };
const NotesList = ({ notesByYear }: NotesListProps) => { const NotesList = ({ notesByYear }: NotesListProps) => {
const sections = []; const sections = [];
Object.entries(notesByYear).forEach(([year, notes]: [string, NoteType["frontMatter"][]]) => { Object.entries(notesByYear).forEach(([year, notes]: [string, NoteFrontMatter[]]) => {
sections.push( sections.push(
<Section key={year}> <Section key={year}>
<Year>{year}</Year> <Year>{year}</Year>

View File

@ -3,7 +3,7 @@ import RelativeTime from "../RelativeTime";
import { StarOcticon, ForkOcticon } from "../Icons"; import { StarOcticon, ForkOcticon } from "../Icons";
import { commafy } from "../../lib/helpers/format-number"; import { commafy } from "../../lib/helpers/format-number";
import { styled } from "../../lib/styles/stitches.config"; import { styled } from "../../lib/styles/stitches.config";
import type { RepositoryType } from "../../types"; import type { Repository } from "../../types";
const Wrapper = styled("div", { const Wrapper = styled("div", {
width: "100%", width: "100%",
@ -68,7 +68,7 @@ const LanguageCircle = styled("span", {
verticalAlign: "text-top", verticalAlign: "text-top",
}); });
export type RepositoryCardProps = RepositoryType & { export type RepositoryCardProps = Repository & {
className?: string; className?: string;
}; };

View File

@ -1,4 +1,6 @@
// Next.js constants (not needed in frontend) // Next.js constants (not needed in frontend)
// directory containing .mdx files relative to project root
export const NOTES_DIR = "./notes"; export const NOTES_DIR = "./notes";
// normalize the timestamp saved when building/deploying (see next.config.js) and fall back to right now: // normalize the timestamp saved when building/deploying (see next.config.js) and fall back to right now:

View File

@ -19,20 +19,27 @@ import remarkGfm from "remark-gfm";
import rehypeSlug from "rehype-slug"; import rehypeSlug from "rehype-slug";
import rehypePrism from "rehype-prism-plus"; import rehypePrism from "rehype-prism-plus";
import type { NoteType } from "../../types"; import type { Note, NoteFrontMatter } from "../../types";
const ABSOLUTE_NOTES_DIR = path.join(process.cwd(), NOTES_DIR);
// returns all .mdx files in NOTES_DIR (without .mdx extension) // returns all .mdx files in NOTES_DIR (without .mdx extension)
export const getNoteSlugs = async (): Promise<string[]> => { export const getNoteSlugs = async (): Promise<string[]> => {
// get all files in NOTES_DIR // get all files in NOTES_DIR
const files = await fs.readdir(path.join(process.cwd(), NOTES_DIR)); const files = await fs.readdir(ABSOLUTE_NOTES_DIR);
// narrow to only the .mdx files and strip the .mdx extension // narrow to only the .mdx files and strip the .mdx extension
return files.filter((file) => /\.mdx$/.test(file)).map((noteFile) => noteFile.replace(/\.mdx$/, "")); return files.filter((file) => /\.mdx$/.test(file)).map((noteFile) => noteFile.replace(/\.mdx$/, ""));
}; };
// returns front matter and/or *raw* markdown contents of a given slug // returns front matter and/or *raw* markdown contents of a given slug
export const getNoteData = async (slug: string): Promise<Omit<NoteType, "source"> & { content: string }> => { export const getNoteData = async (
const fullPath = path.join(process.cwd(), NOTES_DIR, `${slug}.mdx`); slug: string
): Promise<{
frontMatter: NoteFrontMatter;
content: string;
}> => {
const fullPath = path.join(ABSOLUTE_NOTES_DIR, `${slug}.mdx`);
const rawContent = await fs.readFile(fullPath, "utf8"); const rawContent = await fs.readFile(fullPath, "utf8");
const { data, content } = matter(rawContent); const { data, content } = matter(rawContent);
@ -52,7 +59,7 @@ export const getNoteData = async (slug: string): Promise<Omit<NoteType, "source"
// return both the parsed YAML front matter (with a few amendments) and the raw, unparsed markdown content // return both the parsed YAML front matter (with a few amendments) and the raw, unparsed markdown content
return { return {
frontMatter: { frontMatter: {
...(data as Omit<NoteType["frontMatter"], "slug" | "title" | "htmlTitle" | "permalink" | "date" | "readingMins">), ...(data as Partial<NoteFrontMatter>),
// zero markdown title: // zero markdown title:
title: removeMarkdown(data.title), title: removeMarkdown(data.title),
// parsed markdown title: // parsed markdown title:
@ -67,7 +74,7 @@ export const getNoteData = async (slug: string): Promise<Omit<NoteType, "source"
}; };
// fully parses MDX into JS and returns *everything* about a note // fully parses MDX into JS and returns *everything* about a note
export const getNote = async (slug: string): Promise<NoteType> => { export const getNote = async (slug: string): Promise<Note> => {
const { frontMatter, content } = await getNoteData(slug); const { frontMatter, content } = await getNoteData(slug);
const source = await serialize(content, { const source = await serialize(content, {
parseFrontmatter: false, parseFrontmatter: false,
@ -99,7 +106,7 @@ export const getNote = async (slug: string): Promise<NoteType> => {
}; };
// returns the front matter of ALL notes, sorted reverse chronologically // returns the front matter of ALL notes, sorted reverse chronologically
export const getAllNotes = async (): Promise<NoteType["frontMatter"][]> => { export const getAllNotes = async (): Promise<NoteFrontMatter[]> => {
const slugs = await getNoteSlugs(); const slugs = await getNoteSlugs();
// for each slug, query its front matter // for each slug, query its front matter
@ -108,9 +115,7 @@ export const getAllNotes = async (): Promise<NoteType["frontMatter"][]> => {
}); });
// sort the results by date // sort the results by date
const sorted = data.sort((note1: NoteType["frontMatter"], note2: NoteType["frontMatter"]) => const sorted = data.sort((note1, note2) => (note1.date > note2.date ? -1 : 1));
note1.date > note2.date ? -1 : 1
);
return sorted; return sorted;
}; };

View File

@ -10,9 +10,9 @@ import { getNote, getNoteSlugs } from "../../lib/helpers/parse-notes";
import * as config from "../../lib/config"; import * as config from "../../lib/config";
import { articleJsonLd } from "../../lib/config/seo"; import { articleJsonLd } from "../../lib/config/seo";
import type { GetStaticProps, GetStaticPaths } from "next"; import type { GetStaticProps, GetStaticPaths } from "next";
import type { NoteType } from "../../types"; import type { Note, NoteFrontMatter } from "../../types";
const Note = ({ frontMatter, source }: NoteType) => { const Note = ({ frontMatter, source }: Note) => {
return ( return (
<> <>
<NextSeo <NextSeo
@ -74,7 +74,7 @@ const Note = ({ frontMatter, source }: NoteType) => {
); );
}; };
export const getStaticProps: GetStaticProps = async ({ params }: { params: Pick<NoteType["frontMatter"], "slug"> }) => { export const getStaticProps: GetStaticProps = async ({ params }: { params: Pick<NoteFrontMatter, "slug"> }) => {
const { frontMatter, source } = await getNote(params.slug); const { frontMatter, source } = await getNote(params.slug);
return { return {

View File

@ -8,7 +8,7 @@ import { OctocatOcticon } from "../components/Icons";
import { styled } from "../lib/styles/stitches.config"; import { styled } from "../lib/styles/stitches.config";
import { authorSocial } from "../lib/config"; import { authorSocial } from "../lib/config";
import type { GetStaticProps } from "next"; import type { GetStaticProps } from "next";
import type { RepositoryType } from "../types"; import type { Repository } from "../types";
const Wrapper = styled("div", { const Wrapper = styled("div", {
display: "flex", display: "flex",
@ -54,7 +54,7 @@ const Projects = ({ repos }) => (
<Content> <Content>
<Wrapper> <Wrapper>
{repos.map((repo: RepositoryType) => ( {repos.map((repo: Repository) => (
<Card key={repo.name} {...repo} /> <Card key={repo.name} {...repo} />
))} ))}
</Wrapper> </Wrapper>
@ -111,7 +111,7 @@ export const getStaticProps: GetStaticProps = async () => {
} }
); );
const repos: RepositoryType[] = user.repositories.edges.map(({ node: repo }) => ({ const repos: Repository[] = user.repositories.edges.map(({ node: repo }) => ({
name: repo.name, name: repo.name,
url: repo.url, url: repo.url,
description: repo.description, description: repo.description,

29
types/note.d.ts vendored
View File

@ -1,18 +1,21 @@
import type { MDXRemoteSerializeResult } from "next-mdx-remote"; import type { MDXRemoteSerializeResult } from "next-mdx-remote";
export type NoteType = { export type NoteFrontMatter = {
frontMatter: { slug: string;
slug: string; permalink: string;
permalink: string; date: string;
date: string; title: string;
title: string; htmlTitle?: string;
htmlTitle?: string; description?: string;
description?: string; image?: string;
image?: string; tags?: string[];
tags?: string[]; readingMins?: number;
readingMins?: number; noComments?: boolean;
noComments?: boolean; };
};
export type Note = {
// yaml metadata
frontMatter: NoteFrontMatter;
// the final, compiled JSX by next-mdx-remote; see lib/helpers/parse-notes.ts // the final, compiled JSX by next-mdx-remote; see lib/helpers/parse-notes.ts
source: MDXRemoteSerializeResult; source: MDXRemoteSerializeResult;

View File

@ -1,4 +1,4 @@
export type RepositoryType = { export type Repository = {
name: string; name: string;
url: string; url: string;
description?: string; description?: string;