mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2025-09-13 23:45:30 -04:00
start extracting types to shared .d.ts file
This commit is contained in:
@@ -11,6 +11,6 @@ module.exports = {
|
|||||||
rules: {
|
rules: {
|
||||||
"react/no-unescaped-entities": "off",
|
"react/no-unescaped-entities": "off",
|
||||||
"@typescript-eslint/ban-ts-comment": "off",
|
"@typescript-eslint/ban-ts-comment": "off",
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "warn",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
import styles from "./Content.module.css";
|
import styles from "./Content.module.css";
|
||||||
|
import type { ReactNode } from "react";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: unknown;
|
children: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Content = ({ children }: Props) => <div className={styles.content}>{children}</div>;
|
const Content = ({ children }: Props) => <div className={styles.content}>{children}</div>;
|
||||||
|
@@ -2,11 +2,10 @@ import { useState, useEffect } from "react";
|
|||||||
import copy from "copy-to-clipboard";
|
import copy from "copy-to-clipboard";
|
||||||
import innerText from "react-innertext";
|
import innerText from "react-innertext";
|
||||||
import { CopyOcticon, CheckOcticon } from "../icons/octicons";
|
import { CopyOcticon, CheckOcticon } from "../icons/octicons";
|
||||||
|
import type { ReactNode } from "react";
|
||||||
|
|
||||||
import styles from "./CopyButton.module.css";
|
import styles from "./CopyButton.module.css";
|
||||||
|
|
||||||
import type { ReactNode } from "react";
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
source: ReactNode;
|
source: ReactNode;
|
||||||
timeout?: number;
|
timeout?: number;
|
||||||
|
@@ -1,6 +1,12 @@
|
|||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
|
import type { ReactNode } from "react";
|
||||||
|
|
||||||
const CustomCode = (props: any) => {
|
type Props = {
|
||||||
|
className?: string;
|
||||||
|
children: ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CustomCode = (props: Props) => {
|
||||||
if (props.className?.split(" ").includes("hljs")) {
|
if (props.className?.split(" ").includes("hljs")) {
|
||||||
const CopyButton = dynamic(() => import("../clipboard/CopyButton"));
|
const CopyButton = dynamic(() => import("../clipboard/CopyButton"));
|
||||||
|
|
||||||
|
@@ -1,19 +1,13 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
|
import type { NoteMetaType } from "../../types";
|
||||||
|
|
||||||
import styles from "./List.module.css";
|
import styles from "./List.module.css";
|
||||||
|
|
||||||
type NoteProps = {
|
|
||||||
title: string;
|
|
||||||
htmlTitle?: string;
|
|
||||||
date: string;
|
|
||||||
slug: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const List = ({ notesByYear }) => {
|
const List = ({ notesByYear }) => {
|
||||||
const sections = [];
|
const sections = [];
|
||||||
|
|
||||||
Object.entries(notesByYear).forEach(([year, notes]: [string, NoteProps[]]) => {
|
Object.entries(notesByYear).forEach(([year, notes]: [string, NoteMetaType[]]) => {
|
||||||
sections.push(
|
sections.push(
|
||||||
<section key={year} className={styles.section}>
|
<section key={year} className={styles.section}>
|
||||||
<h2 className={styles.year}>{year}</h2>
|
<h2 className={styles.year}>{year}</h2>
|
||||||
|
@@ -3,18 +3,11 @@ import { format } from "date-fns";
|
|||||||
import Hits from "../hits/Hits";
|
import Hits from "../hits/Hits";
|
||||||
import { DateIcon, TagIcon, EditIcon, ViewsIcon } from "../icons";
|
import { DateIcon, TagIcon, EditIcon, ViewsIcon } from "../icons";
|
||||||
import * as config from "../../lib/config";
|
import * as config from "../../lib/config";
|
||||||
|
import type { NoteMetaType } from "../../types";
|
||||||
|
|
||||||
import styles from "./Meta.module.css";
|
import styles from "./Meta.module.css";
|
||||||
|
|
||||||
export type Props = {
|
const Meta = ({ title, htmlTitle, date, slug, tags = [] }: NoteMetaType) => (
|
||||||
title: string;
|
|
||||||
htmlTitle?: string;
|
|
||||||
date: string;
|
|
||||||
slug: string;
|
|
||||||
tags?: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
const Meta = ({ title, htmlTitle = "", date, slug, tags = [] }: Props) => (
|
|
||||||
<>
|
<>
|
||||||
<div className={styles.meta}>
|
<div className={styles.meta}>
|
||||||
<div className={styles.date}>
|
<div className={styles.date}>
|
||||||
|
@@ -23,7 +23,7 @@ export const buildFeed = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const notes = getAllNotes();
|
const notes = getAllNotes();
|
||||||
notes.forEach((note: any) => {
|
notes.forEach((note) => {
|
||||||
feed.addItem({
|
feed.addItem({
|
||||||
guid: note.permalink,
|
guid: note.permalink,
|
||||||
link: note.permalink,
|
link: note.permalink,
|
||||||
|
@@ -14,6 +14,8 @@ import rehypeSlug from "rehype-slug";
|
|||||||
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
import rehypeAutolinkHeadings from "rehype-autolink-headings";
|
||||||
import rehypeHighlight from "rehype-highlight";
|
import rehypeHighlight from "rehype-highlight";
|
||||||
|
|
||||||
|
import type { NoteMetaType, NoteType } from "../types";
|
||||||
|
|
||||||
// returns all .mdx files in NOTES_DIR (without .mdx extension)
|
// returns all .mdx files in NOTES_DIR (without .mdx extension)
|
||||||
export const getNoteSlugs = () =>
|
export const getNoteSlugs = () =>
|
||||||
fs
|
fs
|
||||||
@@ -22,14 +24,14 @@ export const getNoteSlugs = () =>
|
|||||||
.map((noteFile) => noteFile.replace(/\.mdx$/, ""));
|
.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 = (slug: string) => {
|
export const getNoteData = (slug: string): { frontMatter: NoteMetaType; content: string } => {
|
||||||
const fullPath = path.join(process.cwd(), NOTES_DIR, `${slug}.mdx`);
|
const fullPath = path.join(process.cwd(), NOTES_DIR, `${slug}.mdx`);
|
||||||
const rawContent = fs.readFileSync(fullPath, "utf8");
|
const rawContent = fs.readFileSync(fullPath, "utf8");
|
||||||
const { data, content } = matter(rawContent);
|
const { data, content } = matter(rawContent);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
frontMatter: {
|
frontMatter: {
|
||||||
...data,
|
...(data as NoteMetaType),
|
||||||
htmlTitle: sanitizeHtml(marked.parseInline(data.title), { allowedTags: ["code"] }),
|
htmlTitle: sanitizeHtml(marked.parseInline(data.title), { allowedTags: ["code"] }),
|
||||||
slug,
|
slug,
|
||||||
permalink: `${baseUrl}/notes/${slug}/`,
|
permalink: `${baseUrl}/notes/${slug}/`,
|
||||||
@@ -40,7 +42,7 @@ export const getNoteData = (slug: string) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getNote = async (slug: string) => {
|
export const getNote = async (slug: string): Promise<NoteType> => {
|
||||||
// https://github.com/kentcdodds/mdx-bundler#nextjs-esbuild-enoent
|
// https://github.com/kentcdodds/mdx-bundler#nextjs-esbuild-enoent
|
||||||
process.env.ESBUILD_BINARY_PATH =
|
process.env.ESBUILD_BINARY_PATH =
|
||||||
process.platform === "win32"
|
process.platform === "win32"
|
||||||
@@ -90,4 +92,4 @@ export const getNote = async (slug: string) => {
|
|||||||
export const getAllNotes = () =>
|
export const getAllNotes = () =>
|
||||||
getNoteSlugs()
|
getNoteSlugs()
|
||||||
.map((slug) => getNoteData(slug).frontMatter)
|
.map((slug) => getNoteData(slug).frontMatter)
|
||||||
.sort((note1: any, note2: any) => (note1.date > note2.date ? -1 : 1));
|
.sort((note1: NoteMetaType, note2: NoteMetaType) => (note1.date > note2.date ? -1 : 1));
|
||||||
|
@@ -95,8 +95,10 @@ const getSiteStats = async (client) => {
|
|||||||
pages,
|
pages,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
pages.map((page: any) => {
|
pages.map((page: any) => {
|
||||||
// match URLs from RSS feed with db to populate some metadata
|
// match URLs from RSS feed with db to populate some metadata
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const match: any = notes.find((note) => `notes/${note.slug}` === page.slug);
|
const match: any = notes.find((note) => `notes/${note.slug}` === page.slug);
|
||||||
if (match) {
|
if (match) {
|
||||||
page.title = match.title;
|
page.title = match.title;
|
||||||
|
@@ -2,16 +2,16 @@ import Link from "next/link";
|
|||||||
import isAbsoluteUrl from "is-absolute-url";
|
import isAbsoluteUrl from "is-absolute-url";
|
||||||
import hexRgb from "hex-rgb";
|
import hexRgb from "hex-rgb";
|
||||||
import { WaveIcon, LockIcon } from "../components/icons";
|
import { WaveIcon, LockIcon } from "../components/icons";
|
||||||
|
import type { ReactNode } from "react";
|
||||||
|
|
||||||
type ColorLinkProps = {
|
type ColorLinkProps = {
|
||||||
children: unknown;
|
children: ReactNode;
|
||||||
href: string;
|
href: string;
|
||||||
lightColor: string;
|
lightColor: string;
|
||||||
darkColor: string;
|
darkColor: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
external?: boolean;
|
external?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ColorLink = ({ href, title, lightColor, darkColor, external = false, children }: ColorLinkProps) => {
|
const ColorLink = ({ href, title, lightColor, darkColor, external = false, children }: ColorLinkProps) => {
|
||||||
external = external || isAbsoluteUrl(href);
|
external = external || isAbsoluteUrl(href);
|
||||||
|
|
||||||
|
@@ -11,10 +11,11 @@ import CustomCode from "../../components/embeds/Code";
|
|||||||
import { getNote, getNoteSlugs } from "../../lib/parse-notes";
|
import { getNote, getNoteSlugs } from "../../lib/parse-notes";
|
||||||
import * as config from "../../lib/config";
|
import * as config from "../../lib/config";
|
||||||
import type { GetStaticProps, GetStaticPaths } from "next";
|
import type { GetStaticProps, GetStaticPaths } from "next";
|
||||||
|
import type { NoteType } from "../../types";
|
||||||
|
|
||||||
const Comments = dynamic(() => import("../../components/notes/Comments"), { ssr: false });
|
const Comments = dynamic(() => import("../../components/notes/Comments"), { ssr: false });
|
||||||
|
|
||||||
const Note = ({ frontMatter, mdxSource }) => {
|
const Note = ({ frontMatter, mdxSource }: NoteType) => {
|
||||||
const customComponents = {
|
const customComponents = {
|
||||||
a: CustomLink,
|
a: CustomLink,
|
||||||
code: CustomCode,
|
code: CustomCode,
|
||||||
|
17
types/index.d.ts
vendored
Normal file
17
types/index.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
export type NoteMetaType = {
|
||||||
|
title: string;
|
||||||
|
htmlTitle?: string;
|
||||||
|
date: string;
|
||||||
|
slug: string;
|
||||||
|
permalink: string;
|
||||||
|
description?: string;
|
||||||
|
image?: string;
|
||||||
|
tags?: string[];
|
||||||
|
readingMins?: number;
|
||||||
|
noComments?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type NoteType = {
|
||||||
|
frontMatter: NoteMetaType;
|
||||||
|
mdxSource: string;
|
||||||
|
};
|
Reference in New Issue
Block a user