1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2026-01-09 11:22:56 -05:00

custom <Link /> wrapper around next/link

This commit is contained in:
2022-01-30 10:33:40 -05:00
parent 2a29d713bb
commit 9f34cec930
35 changed files with 578 additions and 1009 deletions

View File

@@ -1,13 +1,12 @@
import classNames from "classnames"; import classNames from "classnames";
import CopyButton from "../CopyButton/CopyButton"; import CopyButton from "../CopyButton/CopyButton";
import type { ReactNode } from "react"; import type { PropsWithChildren } from "react";
import styles from "./CodeBlock.module.css"; import styles from "./CodeBlock.module.css";
type Props = { type Props = PropsWithChildren<{
children: ReactNode;
className?: string; className?: string;
}; }>;
const CodeBlock = ({ children, className, ...rest }: Props) => { const CodeBlock = ({ children, className, ...rest }: Props) => {
if (className?.split(" ").includes("code-highlight")) { if (className?.split(" ").includes("code-highlight")) {

View File

@@ -1,15 +1,11 @@
import { memo } from "react"; import { memo } from "react";
import Link from "next/link"; import css from "styled-jsx/css";
import type { ReactNode } from "react"; import classNames from "classnames";
import Link, { Props as CustomLinkProps } from "../Link/Link";
type Props = { type Props = CustomLinkProps & {
children: ReactNode;
href: string;
lightColor: string; lightColor: string;
darkColor: string; darkColor: string;
title?: string;
external?: boolean;
className?: string;
}; };
// spits out alpha'd version of given color in rgba() format within a linear-gradient (that's not really a gradient) // spits out alpha'd version of given color in rgba() format within a linear-gradient (that's not really a gradient)
@@ -25,28 +21,23 @@ const getLinearGradient = (hex: string, alpha = 0.4) => {
return `linear-gradient(${rgbaString},${rgbaString})`; return `linear-gradient(${rgbaString},${rgbaString})`;
}; };
const ColorfulLink = ({ href, lightColor, darkColor, external, className, ...rest }: Props) => { const ColorfulLink = ({ lightColor, darkColor, className, ...rest }: Props) => {
const { className: underlineClassName, styles: underlineStyles } = css.resolve`
a {
color: ${lightColor};
background-image: ${getLinearGradient(lightColor)};
}
:global([data-theme="dark"]) a {
color: ${darkColor};
background-image: ${getLinearGradient(darkColor)};
}
`;
return ( return (
<> <>
<Link href={href} passHref={true} prefetch={false}> <Link className={classNames(underlineClassName, className)} {...rest} />
<a
className={className}
target={external ? "_blank" : undefined}
rel={external ? "noopener noreferrer" : undefined}
{...rest}
/>
</Link>
<style jsx>{` {underlineStyles}
a {
color: ${lightColor};
background-image: ${getLinearGradient(lightColor)};
}
:global([data-theme="dark"]) a {
color: ${darkColor};
background-image: ${getLinearGradient(darkColor)};
}
`}</style>
</> </>
); );
}; };

View File

@@ -33,10 +33,6 @@
line-height: 1.75; line-height: 1.75;
} }
.markdown_tip a:first-of-type {
font-weight: 500;
}
.hcaptcha { .hcaptcha {
margin: 1em 0; margin: 1em 0;
} }

View File

@@ -3,6 +3,7 @@ import { useTheme } from "next-themes";
import classNames from "classnames/bind"; import classNames from "classnames/bind";
import { Formik, Form, Field } from "formik"; import { Formik, Form, Field } from "formik";
import HCaptcha from "@hcaptcha/react-hcaptcha"; import HCaptcha from "@hcaptcha/react-hcaptcha";
import Link from "../Link/Link";
import { SendIcon, CheckOcticon, XOcticon } from "../Icons"; import { SendIcon, CheckOcticon, XOcticon } from "../Icons";
import type { FormikHelpers } from "formik"; import type { FormikHelpers } from "formik";
@@ -126,18 +127,13 @@ const ContactForm = ({ className }: Props) => {
<div className={styles.markdown_tip}> <div className={styles.markdown_tip}>
Basic{" "} Basic{" "}
<a <Link href="https://commonmark.org/help/" title="Markdown reference sheet" style={{ fontWeight: 600 }}>
href="https://commonmark.org/help/"
title="Markdown reference sheet"
target="_blank"
rel="noopener noreferrer"
>
Markdown syntax Markdown syntax
</a>{" "} </Link>{" "}
is allowed here, e.g.: <strong>**bold**</strong>, <em>_italics_</em>, [ is allowed here, e.g.: <strong>**bold**</strong>, <em>_italics_</em>, [
<a href="https://jarv.is" target="_blank" rel="noopener noreferrer"> <Link href="https://jarv.is" forceNewWindow>
links links
</a> </Link>
](https://jarv.is), and <code>`code`</code>. ](https://jarv.is), and <code>`code`</code>.
</div> </div>

View File

@@ -3,28 +3,6 @@
line-height: 1.7; line-height: 1.7;
} }
.content a {
color: var(--link);
background-image: linear-gradient(var(--link-underline), var(--link-underline));
background-position: 0% 100%;
background-repeat: no-repeat;
background-size: 0% var(--link-underline-size);
padding-bottom: var(--link-underline-size);
/* background-size is for hover animation, color & border are for theme fading: */
transition: background-size 0.25s ease-in-out, color 0.25s ease, border 0.25s ease;
}
.content a:hover {
background-size: 100% var(--link-underline-size);
}
/* set an anchor's class to `no-underline` to disable all of the above */
.content :global(a.no-underline) {
background: none;
padding-bottom: 0;
transition: none;
}
@media screen and (max-width: 768px) { @media screen and (max-width: 768px) {
.content { .content {
font-size: 0.925em; font-size: 0.925em;

View File

@@ -1,12 +1,11 @@
import classNames from "classnames"; import classNames from "classnames";
import type { ReactNode } from "react"; import type { PropsWithChildren } from "react";
import styles from "./Content.module.css"; import styles from "./Content.module.css";
type Props = { type Props = PropsWithChildren<{
children: ReactNode;
className?: string; className?: string;
}; }>;
const Content = ({ className, ...rest }: Props) => <div className={classNames(styles.content, className)} {...rest} />; const Content = ({ className, ...rest }: Props) => <div className={classNames(styles.content, className)} {...rest} />;

View File

@@ -1,16 +1,16 @@
import Image from "../Image/Image"; import Image from "../Image/Image";
import innerText from "react-innertext"; import innerText from "react-innertext";
import classNames from "classnames"; import classNames from "classnames";
import type { ReactNode } from "react"; import type { PropsWithChildren } from "react";
import type { ImageProps as NextImageProps } from "next/image"; import type { ImageProps as NextImageProps } from "next/image";
import styles from "./Figure.module.css"; import styles from "./Figure.module.css";
type Props = Omit<NextImageProps, "alt"> & { type Props = Omit<NextImageProps, "alt"> &
children: ReactNode; PropsWithChildren<{
alt?: string; // becomes optional -- pulled from plaintext-ified caption if missing alt?: string; // becomes optional -- pulled from plaintext-ified caption if missing
className?: string; className?: string;
}; }>;
const Figure = ({ children, alt, className, ...imageProps }: Props) => { const Figure = ({ children, alt, className, ...imageProps }: Props) => {
return ( return (

View File

@@ -22,9 +22,10 @@
} }
.icon { .icon {
width: 1.3em; width: 1.25em;
height: 1.3em; height: 1.25em;
vertical-align: -0.2em; vertical-align: -0.25em;
margin: 0 0.075em;
} }
.nextjs:hover { .nextjs:hover {

View File

@@ -16,7 +16,7 @@ const Heading = ({ as: Component, id, className, children, ...rest }: Props) =>
{/* add anchor link to H2s and H3s. ID is already generated by rehype-slug. `#` character inserted via CSS. */} {/* add anchor link to H2s and H3s. ID is already generated by rehype-slug. `#` character inserted via CSS. */}
{id && (Component === "h2" || Component === "h3") && ( {id && (Component === "h2" || Component === "h3") && (
<a className={classNames("no-underline", styles.anchor)} href={`#${id}`} tabIndex={-1} aria-hidden="true" /> <a className={styles.anchor} href={`#${id}`} tabIndex={-1} aria-hidden="true" />
)} )}
</Component> </Component>
); );

View File

@@ -1,17 +1,18 @@
import Head from "next/head"; import Head from "next/head";
import { useTheme } from "next-themes"; import { useTheme } from "next-themes";
import classNames from "classnames";
import Header from "../Header/Header"; import Header from "../Header/Header";
import Footer from "../Footer/Footer"; import Footer from "../Footer/Footer";
import { themeColors } from "../../lib/config"; import { themeColors } from "../../lib/config";
import type { ReactNode } from "react"; import type { PropsWithChildren } from "react";
import styles from "./Layout.module.css"; import styles from "./Layout.module.css";
type Props = { type Props = PropsWithChildren<{
children: ReactNode; className?: string;
}; }>;
const Layout = ({ children }: Props) => { const Layout = ({ className, children }: Props) => {
const { resolvedTheme } = useTheme(); const { resolvedTheme } = useTheme();
return ( return (
@@ -23,7 +24,7 @@ const Layout = ({ children }: Props) => {
)} )}
<Header /> <Header />
<main className={styles.main}> <main className={classNames(styles.main, className)}>
<div className={styles.container}>{children}</div> <div className={styles.container}>{children}</div>
</main> </main>
<Footer /> <Footer />

View File

@@ -0,0 +1,14 @@
.link {
color: var(--link);
background-image: linear-gradient(var(--link-underline), var(--link-underline));
background-position: 0% 100%;
background-repeat: no-repeat;
background-size: 0% var(--link-underline-size);
padding-bottom: var(--link-underline-size);
/* background-size is for hover animation, color & border are for theme fading: */
transition: background-size 0.25s ease-in-out, color 0.25s ease, border 0.25s ease;
}
.link:hover {
background-size: 100% var(--link-underline-size);
}

49
components/Link/Link.tsx Normal file
View File

@@ -0,0 +1,49 @@
import NextLink from "next/link";
import classNames from "classnames";
import isAbsoluteUrl from "is-absolute-url";
import type { AnchorHTMLAttributes, PropsWithChildren } from "react";
import type { LinkProps } from "next/link";
import styles from "./Link.module.css";
export type Props = Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "href"> &
LinkProps &
PropsWithChildren<{
target?: string;
rel?: string;
forceNewWindow?: boolean;
className?: string;
}>;
const CustomLink = ({
href,
prefetch = false,
passHref = true,
target,
rel,
forceNewWindow,
className,
...rest
}: Props) => {
// this component auto-detects whether or not we should use a normal HTML anchor externally or next/link internally,
// can be overridden with `forceNewWindow={true}`.
if (forceNewWindow || isAbsoluteUrl(href.toString())) {
return (
<a
href={href.toString()}
target={target || "_blank"}
rel={rel || "noopener noreferrer"}
className={classNames(styles.link, className)}
{...rest}
/>
);
} else {
return (
<NextLink href={href} prefetch={prefetch} passHref={passHref}>
<a className={classNames(styles.link, className)} {...rest} />
</NextLink>
);
}
};
export default CustomLink;

View File

@@ -1,12 +1,11 @@
import classNames from "classnames"; import classNames from "classnames";
import type { ReactNode } from "react"; import type { PropsWithChildren } from "react";
import styles from "./List.module.css"; import styles from "./List.module.css";
type Props = { type Props = PropsWithChildren<{
children: ReactNode;
className?: string; className?: string;
}; }>;
export const UnorderedList = ({ className, ...rest }: Props) => ( export const UnorderedList = ({ className, ...rest }: Props) => (
<ul className={classNames(styles.unordered, className)} {...rest} /> <ul className={classNames(styles.unordered, className)} {...rest} />

View File

@@ -1,4 +1,3 @@
import Link from "next/link";
import { format } from "date-fns"; import { format } from "date-fns";
import HitCounter from "../HitCounter/HitCounter"; import HitCounter from "../HitCounter/HitCounter";
import { DateIcon, TagIcon, EditIcon, ViewsIcon } from "../Icons"; import { DateIcon, TagIcon, EditIcon, ViewsIcon } from "../Icons";
@@ -15,11 +14,7 @@ const NoteMeta = ({ slug, date, title, tags = [] }: Props) => (
<span> <span>
<DateIcon className={styles.icon} /> <DateIcon className={styles.icon} />
</span> </span>
<span title={format(new Date(date), "PPppp")}> <span title={format(new Date(date), "PPppp")}>{format(new Date(date), "MMMM d, yyyy")}</span>
<Link href={`/notes/${slug}/`}>
<a>{format(new Date(date), "MMMM d, yyyy")}</a>
</Link>
</span>
</div> </div>
{tags.length > 0 && ( {tags.length > 0 && (
@@ -36,19 +31,17 @@ const NoteMeta = ({ slug, date, title, tags = [] }: Props) => (
)} )}
<div> <div>
<span> <a
<EditIcon className={styles.icon} /> href={`https://github.com/${config.githubRepo}/blob/main/notes/${slug}.mdx`}
</span> target="_blank"
<span> rel="noopener noreferrer"
<a title={`Edit "${title}" on GitHub`}
href={`https://github.com/${config.githubRepo}/blob/main/notes/${slug}.mdx`} >
target="_blank" <span>
rel="noopener noreferrer" <EditIcon className={styles.icon} />
title={`Edit "${title}" on GitHub`} </span>
> <span>Improve This Post</span>
Improve This Post </a>
</a>
</span>
</div> </div>
<div className={styles.views}> <div className={styles.views}>

View File

@@ -5,10 +5,15 @@ import styles from "./NoteTitle.module.css";
type Props = Pick<NoteMetaType, "slug" | "htmlTitle">; type Props = Pick<NoteMetaType, "slug" | "htmlTitle">;
const NoteTitle = ({ slug, htmlTitle }: Props) => ( const NoteTitle = ({ slug, htmlTitle, ...rest }: Props) => (
<h1 className={styles.title}> <h1 className={styles.title}>
<Link href={`/notes/${slug}/`}> <Link
<a dangerouslySetInnerHTML={{ __html: htmlTitle }} /> href={{
pathname: "/notes/[slug]/",
query: { slug: slug },
}}
>
<a dangerouslySetInnerHTML={{ __html: htmlTitle }} {...rest} />
</Link> </Link>
</h1> </h1>
); );

View File

@@ -1,5 +1,5 @@
import Link from "next/link";
import { format } from "date-fns"; import { format } from "date-fns";
import Link from "../Link/Link";
import type { NoteMetaType } from "../../types"; import type { NoteMetaType } from "../../types";
import styles from "./NotesList.module.css"; import styles from "./NotesList.module.css";
@@ -21,10 +21,8 @@ const NotesList = ({ notesByYear }) => {
pathname: "/notes/[slug]/", pathname: "/notes/[slug]/",
query: { slug: slug }, query: { slug: slug },
}} }}
prefetch={false} dangerouslySetInnerHTML={{ __html: htmlTitle }}
> />
<a dangerouslySetInnerHTML={{ __html: htmlTitle }} />
</Link>
</span> </span>
</li> </li>
))} ))}

View File

@@ -8,13 +8,8 @@ type Props = {
className?: string; className?: string;
}; };
const OctocatLink = ({ repo, className }: Props) => ( const OctocatLink = ({ repo, className, ...rest }: Props) => (
<a <a className={styles.link} href={`https://github.com/${repo}`} target="_blank" rel="noopener noreferrer" {...rest}>
className={classNames("no-underline", styles.link)}
href={`https://github.com/${repo}`}
target="_blank"
rel="noopener noreferrer"
>
<OctocatOcticon fill="currentColor" className={classNames(styles.icon, className)} /> <OctocatOcticon fill="currentColor" className={classNames(styles.icon, className)} />
</a> </a>
); );

View File

@@ -2,23 +2,22 @@ import { useRouter } from "next/router";
import Link from "next/link"; import Link from "next/link";
import classNames from "classnames"; import classNames from "classnames";
import { baseUrl } from "../../lib/config"; import { baseUrl } from "../../lib/config";
import type { ReactNode } from "react"; import type { PropsWithChildren } from "react";
import styles from "./PageTitle.module.css"; import styles from "./PageTitle.module.css";
type Props = { type Props = PropsWithChildren<{
children: ReactNode;
className?: string; className?: string;
}; }>;
const PageTitle = ({ children, className }: Props) => { const PageTitle = ({ className, ...rest }: Props) => {
const router = useRouter(); const router = useRouter();
const canonical = `${baseUrl}${router.pathname}/`; const canonical = `${baseUrl}${router.pathname}/`;
return ( return (
<h1 className={classNames(styles.title, className)}> <h1 className={classNames(styles.title, className)}>
<Link href={canonical}> <Link href={canonical}>
<a>{children}</a> <a {...rest} />
</Link> </Link>
</h1> </h1>
); );

View File

@@ -1,5 +1,6 @@
import classNames from "classnames"; import classNames from "classnames";
import { intlFormat, formatDistanceToNowStrict } from "date-fns"; import { intlFormat, formatDistanceToNowStrict } from "date-fns";
import Link from "../Link/Link";
import { StarOcticon, ForkOcticon } from "../Icons"; import { StarOcticon, ForkOcticon } from "../Icons";
import type { RepoType } from "../../types"; import type { RepoType } from "../../types";
@@ -11,9 +12,9 @@ type Props = RepoType & {
const RepositoryCard = ({ name, url, description, language, stars, forks, updatedAt, className }: Props) => ( const RepositoryCard = ({ name, url, description, language, stars, forks, updatedAt, className }: Props) => (
<div className={classNames(styles.card, className)}> <div className={classNames(styles.card, className)}>
<a className={styles.name} href={url} target="_blank" rel="noopener noreferrer"> <Link className={styles.name} href={url}>
{name} {name}
</a> </Link>
{description && <p className={styles.description}>{description}</p>} {description && <p className={styles.description}>{description}</p>}
@@ -28,7 +29,6 @@ const RepositoryCard = ({ name, url, description, language, stars, forks, update
{stars > 0 && ( {stars > 0 && (
<div className={styles.meta_item}> <div className={styles.meta_item}>
<a <a
className="no-underline"
href={`${url}/stargazers`} href={`${url}/stargazers`}
title={`${stars.toLocaleString("en-US")} ${stars === 1 ? "star" : "stars"}`} title={`${stars.toLocaleString("en-US")} ${stars === 1 ? "star" : "stars"}`}
target="_blank" target="_blank"
@@ -43,7 +43,6 @@ const RepositoryCard = ({ name, url, description, language, stars, forks, update
{forks > 0 && ( {forks > 0 && (
<div className={styles.meta_item}> <div className={styles.meta_item}>
<a <a
className="no-underline"
href={`${url}/network/members`} href={`${url}/network/members`}
title={`${forks.toLocaleString("en-US")} ${forks === 1 ? "fork" : "forks"}`} title={`${forks.toLocaleString("en-US")} ${forks === 1 ? "fork" : "forks"}`}
target="_blank" target="_blank"

View File

@@ -1,16 +1,15 @@
import { useEffect, useRef } from "react"; import { useEffect, useRef } from "react";
import classNames from "classnames/bind"; import classNames from "classnames/bind";
import type { ReactNode } from "react"; import type { PropsWithChildren } from "react";
import styles from "./Wallpaper.module.css"; import styles from "./Wallpaper.module.css";
const cx = classNames.bind(styles); const cx = classNames.bind(styles);
type Props = { type Props = PropsWithChildren<{
image: string; image: string;
tile?: boolean; tile?: boolean;
className?: string; className?: string;
children: ReactNode; }>;
};
const Wallpaper = ({ image, tile, className, ...rest }: Props) => { const Wallpaper = ({ image, tile, className, ...rest }: Props) => {
const bgRef = useRef<HTMLDivElement>(null); const bgRef = useRef<HTMLDivElement>(null);

View File

@@ -5,6 +5,7 @@ export { default as Image } from "../components/Image/Image";
export { default as Figure } from "../components/Figure/Figure"; export { default as Figure } from "../components/Figure/Figure";
// These (mostly very small) components are direct replacements for HTML tags generated by remark: // These (mostly very small) components are direct replacements for HTML tags generated by remark:
export { default as a } from "../components/Link/Link";
export { default as code } from "../components/CodeBlock/CodeBlock"; export { default as code } from "../components/CodeBlock/CodeBlock";
export { default as blockquote } from "../components/Blockquote/Blockquote"; export { default as blockquote } from "../components/Blockquote/Blockquote";
export { default as hr } from "../components/HorizontalRule/HorizontalRule"; export { default as hr } from "../components/HorizontalRule/HorizontalRule";

View File

@@ -12,7 +12,6 @@ import { NOTES_DIR, baseUrl } from "./config";
// remark/rehype markdown plugins // remark/rehype markdown plugins
import remarkGfm from "remark-gfm"; import remarkGfm from "remark-gfm";
import rehypeExternalLinks from "rehype-external-links";
import rehypeSlug from "rehype-slug"; import rehypeSlug from "rehype-slug";
// note: 'common' only exports these languages: https://github.com/wooorm/refractor/blob/main/lib/common.js // note: 'common' only exports these languages: https://github.com/wooorm/refractor/blob/main/lib/common.js
// eslint-disable-next-line import/no-unresolved // eslint-disable-next-line import/no-unresolved
@@ -70,11 +69,7 @@ export const getNote = async (slug: string): Promise<NoteType> => {
parseFrontmatter: false, parseFrontmatter: false,
mdxOptions: { mdxOptions: {
remarkPlugins: [[remarkGfm, { singleTilde: false }]], remarkPlugins: [[remarkGfm, { singleTilde: false }]],
rehypePlugins: [ rehypePlugins: [[rehypeSlug], [rehypePrism, { ignoreMissing: true }]],
[rehypeExternalLinks, { target: "_blank", rel: ["noopener", "noreferrer"] }],
[rehypeSlug, {}],
[rehypePrism, { ignoreMissing: true }],
],
}, },
}); });

View File

@@ -43,6 +43,7 @@
"feed": "^4.2.2", "feed": "^4.2.2",
"formik": "^2.2.9", "formik": "^2.2.9",
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",
"is-absolute-url": "^4.0.1",
"markdown-to-jsx": "^7.1.6", "markdown-to-jsx": "^7.1.6",
"modern-normalize": "^1.1.0", "modern-normalize": "^1.1.0",
"next": "^12.0.9", "next": "^12.0.9",
@@ -63,20 +64,19 @@
"react-player": "^2.9.0", "react-player": "^2.9.0",
"react-tweet-embed": "^1.3.1", "react-tweet-embed": "^1.3.1",
"reading-time": "^1.5.0", "reading-time": "^1.5.0",
"rehype-external-links": "^1.0.1",
"rehype-prism-plus": "^1.3.1", "rehype-prism-plus": "^1.3.1",
"rehype-slug": "^5.0.1", "rehype-slug": "^5.0.1",
"remark-gfm": "^3.0.1", "remark-gfm": "^3.0.1",
"remove-markdown": "^0.3.0", "remove-markdown": "^0.3.0",
"sanitize-html": "^2.6.1", "sanitize-html": "^2.6.1",
"simple-icons": "^6.7.0", "simple-icons": "^6.8.0",
"swr": "^1.2.0", "swr": "^1.2.0",
"terser": "^5.10.0", "terser": "^5.10.0",
"twemoji": "github:twitter/twemoji#v13.1.0" "twemoji": "github:twitter/twemoji#v13.1.0"
}, },
"devDependencies": { "devDependencies": {
"@jakejarvis/eslint-config": "github:jakejarvis/eslint-config#main", "@jakejarvis/eslint-config": "github:jakejarvis/eslint-config#main",
"@svgr/webpack": "^6.2.0", "@svgr/webpack": "^6.2.1",
"@types/node": "*", "@types/node": "*",
"@types/prop-types": "^15.7.4", "@types/prop-types": "^15.7.4",
"@types/react": "^17.0.38", "@types/react": "^17.0.38",

View File

@@ -1,6 +1,7 @@
import { NextSeo } from "next-seo"; import { NextSeo } from "next-seo";
import Content from "../components/Content/Content"; import Content from "../components/Content/Content";
import PageTitle from "../components/PageTitle/PageTitle"; import PageTitle from "../components/PageTitle/PageTitle";
import Link from "../components/Link/Link";
import Image from "../components/Image/Image"; import Image from "../components/Image/Image";
import Blockquote from "../components/Blockquote/Blockquote"; import Blockquote from "../components/Blockquote/Blockquote";
import CodeBlock from "../components/CodeBlock/CodeBlock"; import CodeBlock from "../components/CodeBlock/CodeBlock";
@@ -23,20 +24,12 @@ const CLI = () => (
<Content> <Content>
<Blockquote> <Blockquote>
<p> <p>
The{" "} The <Link href="https://jarv.is/">Jake Jarvis</Link> CLI (aka the most useless Node module ever published, in
<a href="https://jarv.is/" target="_blank" rel="noopener noreferrer"> history, by anyone, ever).
Jake Jarvis
</a>{" "}
CLI (aka the most useless Node module ever published, in history, by anyone, ever).
</p> </p>
</Blockquote> </Blockquote>
<a <a href="https://www.npmjs.com/package/@jakejarvis/cli" target="_blank" rel="noopener noreferrer">
className="no-underline"
href="https://www.npmjs.com/package/@jakejarvis/cli"
target="_blank"
rel="noopener noreferrer"
>
<Image src={cliImg} alt="Terminal Screenshot" priority /> <Image src={cliImg} alt="Terminal Screenshot" priority />
</a> </a>
@@ -46,48 +39,32 @@ const CLI = () => (
<H2>Inspired by</H2> <H2>Inspired by</H2>
<ul> <ul>
<li> <li>
<a href="https://github.com/sindresorhus/sindresorhus-cli" target="_blank" rel="noopener noreferrer"> <Link href="https://github.com/sindresorhus/sindresorhus-cli">@sindresorhus/sindresorhus-cli</Link>
@sindresorhus/sindresorhus-cli
</a>
</li> </li>
<li> <li>
<a href="https://github.com/yg/ygcodes" target="_blank" rel="noopener noreferrer"> <Link href="https://github.com/yg/ygcodes">@yg/ygcodes</Link>
@yg/ygcodes
</a>
</li> </li>
</ul> </ul>
<H2>Built with</H2> <H2>Built with</H2>
<ul> <ul>
<li> <li>
<a href="https://github.com/vadimdemedes/ink" target="_blank" rel="noopener noreferrer"> <Link href="https://github.com/vadimdemedes/ink">ink</Link> - React for interactive command-line apps
ink
</a>{" "}
- React for interactive command-line apps
</li> </li>
<li> <li>
<a href="https://github.com/sindresorhus/meow" target="_blank" rel="noopener noreferrer"> <Link href="https://github.com/sindresorhus/meow">meow</Link> - CLI helper
meow
</a>{" "}
- CLI helper
</li> </li>
</ul> </ul>
<p> <p>
<a href="https://github.com/jakejarvis/jakejarvis/tree/main/cli" target="_blank" rel="noreferrer"> <Link href="https://github.com/jakejarvis/jakejarvis/tree/main/cli" target="_blank" rel="noreferrer">
View source on GitHub. View source on GitHub.
</a> </Link>
</p> </p>
<H2>License</H2> <H2>License</H2>
<p> <p>
MIT ©{" "} MIT © <Link href="https://jarv.is/">Jake Jarvis</Link>,{" "}
<a href="https://jarv.is/" target="_blank" rel="noopener noreferrer"> <Link href="https://sindresorhus.com">Sindre Sorhus</Link>
Jake Jarvis
</a>
,{" "}
<a href="https://sindresorhus.com" target="_blank" rel="noopener noreferrer">
Sindre Sorhus
</a>
</p> </p>
</Content> </Content>
</> </>

View File

@@ -1,6 +1,7 @@
import { NextSeo } from "next-seo"; import { NextSeo } from "next-seo";
import Content from "../components/Content/Content"; import Content from "../components/Content/Content";
import PageTitle from "../components/PageTitle/PageTitle"; import PageTitle from "../components/PageTitle/PageTitle";
import Link from "../components/Link/Link";
import ContactForm from "../components/ContactForm/ContactForm"; import ContactForm from "../components/ContactForm/ContactForm";
const Contact = () => ( const Contact = () => (
@@ -18,21 +19,15 @@ const Contact = () => (
<div className="wrapper"> <div className="wrapper">
<p> <p>
Fill out this quick form and I'll get back to you as soon as I can! You can also{" "} Fill out this quick form and I'll get back to you as soon as I can! You can also{" "}
<a href="mailto:jake@jarv.is">email me directly</a>, send me a{" "} <Link href="mailto:jake@jarv.is">email me directly</Link>, send me a{" "}
<a <Link href="https://twitter.com/messages/compose?recipient_id=229769022">direct message on Twitter</Link>, or{" "}
href="https://twitter.com/messages/compose?recipient_id=229769022" <Link href="sms:+1-617-917-3737">text me</Link>.
target="_blank"
rel="noopener nofollow noreferrer"
>
direct message on Twitter
</a>
, or <a href="sms:+1-617-917-3737">text me</a>.
</p> </p>
<p> <p>
🔐 You can grab my public key here:{" "} 🔐 You can grab my public key here:{" "}
<a href="/pubkey.asc" title="My Public PGP Key" target="_blank" rel="pgpkey authn noopener"> <Link href="/pubkey.asc" title="My Public PGP Key" rel="pgpkey authn noopener" forceNewWindow>
<code className="pubkey">6BF3 79D3 6F67 1480 2B0C 9CF2 51E6 9A39</code> <code className="pubkey">6BF3 79D3 6F67 1480 2B0C 9CF2 51E6 9A39</code>
</a> </Link>
. .
</p> </p>

View File

@@ -1,6 +1,7 @@
import { NextSeo } from "next-seo"; import { NextSeo } from "next-seo";
import Content from "../components/Content/Content"; import Content from "../components/Content/Content";
import PageTitle from "../components/PageTitle/PageTitle"; import PageTitle from "../components/PageTitle/PageTitle";
import Link from "../components/Link/Link";
import Video from "../components/Video/Video"; import Video from "../components/Video/Video";
import thumbnail from "../public/static/images/hillary/thumb.png"; import thumbnail from "../public/static/images/hillary/thumb.png";
@@ -26,17 +27,17 @@ const Hillary = () => (
<p className="copyright"> <p className="copyright">
Video is property of{" "} Video is property of{" "}
<a href="https://www.hillaryclinton.com/" target="_blank" rel="noopener noreferrer"> <Link href="https://www.hillaryclinton.com/" style={{ fontWeight: 700 }}>
Hillary for America Hillary for America
</a> </Link>
, the{" "} , the{" "}
<a href="https://democrats.org/" target="_blank" rel="noopener noreferrer"> <Link href="https://democrats.org/" style={{ fontWeight: 700 }}>
Democratic National Committee Democratic National Committee
</a> </Link>
, and{" "} , and{" "}
<a href="https://cnnpressroom.blogs.cnn.com/" target="_blank" rel="noopener noreferrer"> <Link href="https://cnnpressroom.blogs.cnn.com/" style={{ fontWeight: 700 }}>
CNN / WarnerMedia CNN / WarnerMedia
</a> </Link>
. &copy; 2016. . &copy; 2016.
</p> </p>
</Content> </Content>
@@ -49,10 +50,6 @@ const Hillary = () => (
margin: 1.25em 1em 0.5em; margin: 1.25em 1em 0.5em;
color: var(--medium-light); color: var(--medium-light);
} }
.copyright a {
font-weight: 700;
}
`}</style> `}</style>
</> </>
); );

View File

@@ -4,7 +4,7 @@ import ColorfulLink from "../components/ColorfulLink/ColorfulLink";
const Index = () => ( const Index = () => (
<> <>
<Content> <Content>
<div className="home"> <div>
<h1> <h1>
Hi there! I'm Jake. <span className="wave">👋</span> Hi there! I'm Jake. <span className="wave">👋</span>
</h1> </h1>
@@ -16,7 +16,6 @@ const Index = () => (
title='"Boston Accent Trailer - Late Night with Seth Meyers" on YouTube' title='"Boston Accent Trailer - Late Night with Seth Meyers" on YouTube'
lightColor="#fb4d42" lightColor="#fb4d42"
darkColor="#ff5146" darkColor="#ff5146"
external
> >
Boston Boston
</ColorfulLink> </ColorfulLink>
@@ -30,7 +29,6 @@ const Index = () => (
title='"The Brutal Lifecycle of JavaScript Frameworks" by Ian Allen' title='"The Brutal Lifecycle of JavaScript Frameworks" by Ian Allen'
lightColor="#1091b3" lightColor="#1091b3"
darkColor="#6fcbe3" darkColor="#6fcbe3"
external
> >
modern JS frameworks modern JS frameworks
</ColorfulLink>{" "} </ColorfulLink>{" "}
@@ -40,18 +38,11 @@ const Index = () => (
title="The best JS framework in the world by Eric Wastl" title="The best JS framework in the world by Eric Wastl"
lightColor="#f48024" lightColor="#f48024"
darkColor="#e18431" darkColor="#e18431"
external
> >
vanilla JavaScript vanilla JavaScript
</ColorfulLink>{" "} </ColorfulLink>{" "}
to make nifty{" "} to make nifty{" "}
<ColorfulLink <ColorfulLink href="https://jamstack.wtf/" title="WTF is JAMstack?" lightColor="#04a699" darkColor="#08bbac">
href="https://jamstack.wtf/"
title="WTF is JAMstack?"
lightColor="#04a699"
darkColor="#08bbac"
external
>
JAMstack sites JAMstack sites
</ColorfulLink>{" "} </ColorfulLink>{" "}
with dynamic{" "} with dynamic{" "}
@@ -60,7 +51,6 @@ const Index = () => (
title="Node.js Official Website" title="Node.js Official Website"
lightColor="#6fbc4e" lightColor="#6fbc4e"
darkColor="#84d95f" darkColor="#84d95f"
external
> >
Node.js Node.js
</ColorfulLink>{" "} </ColorfulLink>{" "}
@@ -70,7 +60,6 @@ const Index = () => (
title='"PHP in 2020" by Brent Roose' title='"PHP in 2020" by Brent Roose'
lightColor="#8892bf" lightColor="#8892bf"
darkColor="#a4afe3" darkColor="#a4afe3"
external
> >
PHP PHP
</ColorfulLink> </ColorfulLink>
@@ -80,7 +69,6 @@ const Index = () => (
title="Ruby Official Website" title="Ruby Official Website"
lightColor="#d34135" lightColor="#d34135"
darkColor="#f95a4d" darkColor="#f95a4d"
external
> >
Ruby Ruby
</ColorfulLink> </ColorfulLink>
@@ -90,7 +78,6 @@ const Index = () => (
title="Golang Official Website" title="Golang Official Website"
lightColor="#00acd7" lightColor="#00acd7"
darkColor="#2ad1fb" darkColor="#2ad1fb"
external
> >
Go Go
</ColorfulLink>{" "} </ColorfulLink>{" "}
@@ -104,7 +91,6 @@ const Index = () => (
title="jakejarvis/awesome-shodan-queries on GitHub" title="jakejarvis/awesome-shodan-queries on GitHub"
lightColor="#00b81a" lightColor="#00b81a"
darkColor="#57f06d" darkColor="#57f06d"
external
> >
application security application security
</ColorfulLink> </ColorfulLink>
@@ -114,7 +100,6 @@ const Index = () => (
title='"What is serverless computing?" on Cloudflare' title='"What is serverless computing?" on Cloudflare'
lightColor="#0098ec" lightColor="#0098ec"
darkColor="#43b9fb" darkColor="#43b9fb"
external
> >
serverless stacks serverless stacks
</ColorfulLink> </ColorfulLink>
@@ -124,7 +109,6 @@ const Index = () => (
title='"Automation" on xkcd' title='"Automation" on xkcd'
lightColor="#ff6200" lightColor="#ff6200"
darkColor="#f46c16" darkColor="#f46c16"
external
> >
DevOps automation DevOps automation
</ColorfulLink> </ColorfulLink>
@@ -171,7 +155,6 @@ const Index = () => (
title='"Student designs iPhone JoeyTracker app" on The Tufts Daily' title='"Student designs iPhone JoeyTracker app" on The Tufts Daily'
lightColor="#ff1b1b" lightColor="#ff1b1b"
darkColor="#f06060" darkColor="#f06060"
external
> >
have have
</ColorfulLink>{" "} </ColorfulLink>{" "}
@@ -188,7 +171,6 @@ const Index = () => (
title='"The Facebook Effect" by David Kirkpatrick (Google Books)' title='"The Facebook Effect" by David Kirkpatrick (Google Books)'
lightColor="#f2b702" lightColor="#f2b702"
darkColor="#ffcc2e" darkColor="#ffcc2e"
external
> >
featured featured
</ColorfulLink>{" "} </ColorfulLink>{" "}
@@ -197,7 +179,6 @@ const Index = () => (
title='"The new Facebook is on a roll" on CNN Money' title='"The new Facebook is on a roll" on CNN Money'
lightColor="#5ebd3e" lightColor="#5ebd3e"
darkColor="#78df55" darkColor="#78df55"
external
> >
by by
</ColorfulLink>{" "} </ColorfulLink>{" "}
@@ -206,7 +187,6 @@ const Index = () => (
title='"Middio: A YouTube Scraper for Major Label Music Videos" on Wired' title='"Middio: A YouTube Scraper for Major Label Music Videos" on Wired'
lightColor="#009cdf" lightColor="#009cdf"
darkColor="#29bfff" darkColor="#29bfff"
external
> >
various various
</ColorfulLink>{" "} </ColorfulLink>{" "}
@@ -215,7 +195,6 @@ const Index = () => (
title='"Fresh Faces in Tech: 10 Kid Entrepreneurs to Watch" on Gigaom' title='"Fresh Faces in Tech: 10 Kid Entrepreneurs to Watch" on Gigaom'
lightColor="#3e49bb" lightColor="#3e49bb"
darkColor="#7b87ff" darkColor="#7b87ff"
external
> >
media media
</ColorfulLink>{" "} </ColorfulLink>{" "}
@@ -224,7 +203,6 @@ const Index = () => (
title='"Your Next Client? The CEO&#39;s Son" on Advertising Age' title='"Your Next Client? The CEO&#39;s Son" on Advertising Age'
lightColor="#973999" lightColor="#973999"
darkColor="#db60dd" darkColor="#db60dd"
external
> >
outlets outlets
</ColorfulLink> </ColorfulLink>
@@ -238,7 +216,6 @@ const Index = () => (
title="Jake Jarvis on GitHub" title="Jake Jarvis on GitHub"
lightColor="#8d4eff" lightColor="#8d4eff"
darkColor="#a379f0" darkColor="#a379f0"
external
> >
GitHub GitHub
</ColorfulLink>{" "} </ColorfulLink>{" "}
@@ -248,7 +225,6 @@ const Index = () => (
title="Jake Jarvis on LinkedIn" title="Jake Jarvis on LinkedIn"
lightColor="#0073b1" lightColor="#0073b1"
darkColor="#3b9dd2" darkColor="#3b9dd2"
external
> >
LinkedIn LinkedIn
</ColorfulLink> </ColorfulLink>
@@ -258,12 +234,13 @@ const Index = () => (
</ColorfulLink>{" "} </ColorfulLink>{" "}
<sup className="monospace pgp_key"> <sup className="monospace pgp_key">
<ColorfulLink <ColorfulLink
className="no-underline"
href="/pubkey.asc" href="/pubkey.asc"
rel="pgpkey authn noopener"
title="My Public Key" title="My Public Key"
lightColor="#757575" lightColor="#757575"
darkColor="#959595" darkColor="#959595"
external style={{ background: "none" }}
forceNewWindow
> >
🔐 2B0C 9CF2 51E6 9A39 🔐 2B0C 9CF2 51E6 9A39
</ColorfulLink> </ColorfulLink>
@@ -274,7 +251,6 @@ const Index = () => (
title="Jake Jarvis on Twitter" title="Jake Jarvis on Twitter"
lightColor="#00acee" lightColor="#00acee"
darkColor="#3bc9ff" darkColor="#3bc9ff"
external
> >
Twitter Twitter
</ColorfulLink> </ColorfulLink>
@@ -293,32 +269,32 @@ const Index = () => (
</Content> </Content>
<style jsx>{` <style jsx>{`
.home { div {
font-size: 1.1em; font-size: 1.1em;
line-height: 1; line-height: 1;
} }
.home h1 { h1 {
margin: 0 0 0.5em -0.03em; margin: 0 0 0.5em -0.03em;
font-size: 1.8em; font-size: 1.8em;
font-weight: 500; font-weight: 500;
letter-spacing: -0.01em; letter-spacing: -0.01em;
} }
.home h2 { h2 {
margin: 0.5em 0 0.5em -0.03em; margin: 0.5em 0 0.5em -0.03em;
font-size: 1.35em; font-size: 1.35em;
font-weight: 400; font-weight: 400;
letter-spacing: -0.016em; letter-spacing: -0.016em;
line-height: 1.4; line-height: 1.4;
} }
.home p { p {
margin: 0.85em 0; margin: 0.85em 0;
letter-spacing: -0.004em; letter-spacing: -0.004em;
line-height: 1.7; line-height: 1.7;
} }
.home p:last-of-type { p:last-of-type {
margin-bottom: 0; margin-bottom: 0;
} }
.home .wave { .wave {
display: inline-block; display: inline-block;
margin-left: 0.1em; margin-left: 0.1em;
font-size: 1.2em; font-size: 1.2em;
@@ -327,18 +303,15 @@ const Index = () => (
transform-origin: 65% 80%; transform-origin: 65% 80%;
will-change: transform; will-change: transform;
} }
.home .pgp_key { .pgp_key {
margin: 0 0.15em; margin: 0 0.15em;
font-size: 0.65em; font-size: 0.65em;
word-spacing: -0.3em; word-spacing: -0.3em;
} }
.home .pgp_key :global(a) { .quiet {
background: none !important;
}
.home .quiet {
color: var(--medium-light); color: var(--medium-light);
} }
.home .birthday :global(a:hover) { .birthday :global(a:hover) {
/* magic wand cursor easter egg */ /* magic wand cursor easter egg */
cursor: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='30' style='font-size:24px'><text y='50%' transform='rotate(-70 0 0) translate(-20, 6)'>🪄</text></svg>") cursor: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='30' style='font-size:24px'><text y='50%' transform='rotate(-70 0 0) translate(-20, 6)'>🪄</text></svg>")
5 5, 5 5,
@@ -346,17 +319,18 @@ const Index = () => (
} }
@media screen and (max-width: 768px) { @media screen and (max-width: 768px) {
.home h1 { h1 {
font-size: 1.5em; font-size: 1.5em;
} }
.home h2 { h2 {
font-size: 1.2em; font-size: 1.2em;
} }
.home p { p {
font-size: 0.925em; font-size: 0.925em;
} }
} }
/* https://jarv.is/notes/css-waving-hand-emoji/ */
@keyframes wave { @keyframes wave {
0% { 0% {
transform: rotate(0deg); transform: rotate(0deg);

View File

@@ -1,6 +1,7 @@
import { NextSeo } from "next-seo"; import { NextSeo } from "next-seo";
import Content from "../components/Content/Content"; import Content from "../components/Content/Content";
import PageTitle from "../components/PageTitle/PageTitle"; import PageTitle from "../components/PageTitle/PageTitle";
import Link from "../components/Link/Link";
import Video from "../components/Video/Video"; import Video from "../components/Video/Video";
import thumbnail from "../public/static/images/leo/thumb.png"; import thumbnail from "../public/static/images/leo/thumb.png";
@@ -27,17 +28,13 @@ const Leo = () => (
<p className="copyright"> <p className="copyright">
Video is property of{" "} Video is property of{" "}
<a <Link href="https://web.archive.org/web/20070511004304/http://www.g4techtv.ca/" style={{ fontWeight: 700 }}>
href="https://web.archive.org/web/20070511004304/http://www.g4techtv.ca/"
target="_blank"
rel="noopener noreferrer"
>
G4techTV Canada G4techTV Canada
</a>{" "} </Link>{" "}
&amp;{" "} &amp;{" "}
<a href="https://leolaporte.com/" target="_blank" rel="noopener noreferrer"> <Link href="https://leolaporte.com/" style={{ fontWeight: 700 }}>
Leo Laporte Leo Laporte
</a> </Link>
. &copy; 2007 G4 Media, Inc. . &copy; 2007 G4 Media, Inc.
</p> </p>
</Content> </Content>
@@ -50,10 +47,6 @@ const Leo = () => (
margin: 1.25em 1em 0.5em; margin: 1.25em 1em 0.5em;
color: var(--medium-light); color: var(--medium-light);
} }
.copyright a {
font-weight: 700;
}
`}</style> `}</style>
</> </>
); );

View File

@@ -1,6 +1,7 @@
import { NextSeo } from "next-seo"; import { NextSeo } from "next-seo";
import Content from "../components/Content/Content"; import Content from "../components/Content/Content";
import PageTitle from "../components/PageTitle/PageTitle"; import PageTitle from "../components/PageTitle/PageTitle";
import Link from "../components/Link/Link";
import HorizontalRule from "../components/HorizontalRule/HorizontalRule"; import HorizontalRule from "../components/HorizontalRule/HorizontalRule";
import Blockquote from "../components/Blockquote/Blockquote"; import Blockquote from "../components/Blockquote/Blockquote";
import { H2, H3 } from "../components/Heading/Heading"; import { H2, H3 } from "../components/Heading/Heading";
@@ -19,18 +20,14 @@ const License = () => (
<Content> <Content>
<p> <p>
Unless otherwise noted, content on this website is published under the{" "} Unless otherwise noted, content on this website is published under the{" "}
<a href="https://creativecommons.org/licenses/by/4.0/" target="_blank" rel="noopener noreferrer"> <Link href="https://creativecommons.org/licenses/by/4.0/">
<strong>Creative Commons Attribution 4.0 International Public License</strong> <strong>Creative Commons Attribution 4.0 International Public License</strong>
</a>{" "} </Link>{" "}
(CC-BY-4.0), which means that you can copy, redistribute, remix, transform, and build upon the content for any (CC-BY-4.0), which means that you can copy, redistribute, remix, transform, and build upon the content for any
purpose as long as you give appropriate credit (such as a hyperlink to the original URL). purpose as long as you give appropriate credit (such as a hyperlink to the original URL).
</p> </p>
<p> <p>
The{" "} The <Link href="https://creativecommons.org/licenses/by/4.0/legalcode">full license</Link> is re-printed below.
<a href="https://creativecommons.org/licenses/by/4.0/legalcode" target="_blank" rel="noopener noreferrer">
full license
</a>{" "}
is re-printed below.
</p> </p>
<HorizontalRule /> <HorizontalRule />
@@ -39,7 +36,6 @@ const License = () => (
<p style={{ textAlign: "center", lineHeight: 0 }}> <p style={{ textAlign: "center", lineHeight: 0 }}>
<a <a
className="no-underline"
href="https://creativecommons.org/licenses/by/4.0/" href="https://creativecommons.org/licenses/by/4.0/"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
@@ -98,13 +94,9 @@ const License = () => (
our licenses so that the public can reuse the material as expected. Licensors should clearly mark any our licenses so that the public can reuse the material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-licensed material, or material used under an material not subject to the license. This includes other CC-licensed material, or material used under an
exception or limitation to copyright.{" "} exception or limitation to copyright.{" "}
<a <Link href="https://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors">
href="https://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors"
target="_blank"
rel="noopener noreferrer"
>
More considerations for licensors More considerations for licensors
</a> </Link>
. .
</p> </p>
</li> </li>
@@ -118,13 +110,9 @@ const License = () => (
restricted for other reasons, including because others have copyright or other rights in the material. A restricted for other reasons, including because others have copyright or other rights in the material. A
licensor may make special requests, such as asking that all changes be marked or described. Although not licensor may make special requests, such as asking that all changes be marked or described. Although not
required by our licenses, you are encouraged to respect those requests where reasonable.{" "} required by our licenses, you are encouraged to respect those requests where reasonable.{" "}
<a <Link href="https://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees">
href="https://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees"
target="_blank"
rel="noopener noreferrer"
>
More considerations for the public More considerations for the public
</a> </Link>
. .
</p> </p>
</li> </li>
@@ -461,30 +449,20 @@ const License = () => (
Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply
one of its public licenses to material it publishes and in those instances will be considered the "Licensor." one of its public licenses to material it publishes and in those instances will be considered the "Licensor."
The text of the Creative Commons public licenses is dedicated to the public domain under the{" "} The text of the Creative Commons public licenses is dedicated to the public domain under the{" "}
<a <Link href="https://creativecommons.org/publicdomain/zero/1.0/legalcode">
href="https://creativecommons.org/publicdomain/zero/1.0/legalcode"
target="_blank"
rel="noopener noreferrer"
>
<em>CC0 Public Domain Dedication</em> <em>CC0 Public Domain Dedication</em>
</a> </Link>
. Except for the limited purpose of indicating that material is shared under a Creative Commons public license . Except for the limited purpose of indicating that material is shared under a Creative Commons public license
or as otherwise permitted by the Creative Commons policies published at{" "} or as otherwise permitted by the Creative Commons policies published at{" "}
<a href="https://creativecommons.org/policies" target="_blank" rel="noopener noreferrer"> <Link href="https://creativecommons.org/policies">creativecommons.org/policies</Link>, Creative Commons does
creativecommons.org/policies not authorize the use of the trademark "Creative Commons" or any other trademark or logo of Creative Commons
</a> without its prior written consent including, without limitation, in connection with any unauthorized
, Creative Commons does not authorize the use of the trademark "Creative Commons" or any other trademark or modifications to any of its public licenses or any other arrangements, understandings, or agreements
logo of Creative Commons without its prior written consent including, without limitation, in connection with concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the
any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or public licenses.
agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part
of the public licenses.
</p> </p>
<p> <p>
Creative Commons may be contacted at{" "} Creative Commons may be contacted at <Link href="https://creativecommons.org/">creativecommons.org</Link>.
<a href="https://creativecommons.org/" target="_blank" rel="noopener noreferrer">
creativecommons.org
</a>
.
</p> </p>
</Blockquote> </Blockquote>
</Content> </Content>

View File

@@ -56,6 +56,7 @@ const Note = ({ frontMatter, source }: NoteType) => {
<NoteTitle slug={frontMatter.slug} htmlTitle={frontMatter.htmlTitle} /> <NoteTitle slug={frontMatter.slug} htmlTitle={frontMatter.htmlTitle} />
<Content> <Content>
{/* @ts-ignore */}
<MDXRemote {...source} components={{ ...mdxComponents }} /> <MDXRemote {...source} components={{ ...mdxComponents }} />
</Content> </Content>

View File

@@ -1,7 +1,7 @@
import Link from "next/link";
import { NextSeo } from "next-seo"; import { NextSeo } from "next-seo";
import Content from "../components/Content/Content"; import Content from "../components/Content/Content";
import PageTitle from "../components/PageTitle/PageTitle"; import PageTitle from "../components/PageTitle/PageTitle";
import Link from "../components/Link/Link";
import Figure from "../components/Figure/Figure"; import Figure from "../components/Figure/Figure";
import IFrame from "../components/IFrame/IFrame"; import IFrame from "../components/IFrame/IFrame";
import HorizontalRule from "../components/HorizontalRule/HorizontalRule"; import HorizontalRule from "../components/HorizontalRule/HorizontalRule";
@@ -40,9 +40,13 @@ const Previously = () => (
<Content> <Content>
<Figure src={img_wayback} alt="Timeline of this website's past." priority> <Figure src={img_wayback} alt="Timeline of this website's past." priority>
...the{" "} ...the{" "}
<a href="https://web.archive.org/web/20010501000000*/jakejarvis.com" target="_blank" rel="noopener noreferrer"> <Link
href="https://web.archive.org/web/20010501000000*/jakejarvis.com"
target="_blank"
rel="noopener noreferrer"
>
Cringey Chronicles&trade; Cringey Chronicles&trade;
</a>{" "} </Link>{" "}
of this website's past. of this website's past.
</Figure> </Figure>
@@ -55,13 +59,11 @@ const Previously = () => (
</code> </code>
...{" "} ...{" "}
<Link href="/y2k/" prefetch={false}> <Link href="/y2k/" prefetch={false}>
<a> Click for the{" "}
Click for the{" "} <strong>
<strong> <em>FULL</em>
<em>FULL</em> </strong>{" "}
</strong>{" "} experience anyway.
experience anyway.
</a>
</Link> </Link>
</p> </p>
@@ -73,9 +75,9 @@ const Previously = () => (
/> />
<p className="iframe_caption"> <p className="iframe_caption">
November 2001 ( November 2001 (
<a href="https://github.com/jakejarvis/my-first-website" target="_blank" rel="noopener noreferrer"> <Link href="https://github.com/jakejarvis/my-first-website" target="_blank" rel="noopener noreferrer">
archived source archived source
</a> </Link>
) )
</p> </p>
@@ -123,9 +125,9 @@ const Previously = () => (
<Figure src={img_2012_09} alt="September 2012"> <Figure src={img_2012_09} alt="September 2012">
September 2012 ( September 2012 (
<a href="https://github.com/jakejarvis/jarv.is/tree/v1" target="_blank" rel="noopener noreferrer"> <Link href="https://github.com/jakejarvis/jarv.is/tree/v1" target="_blank" rel="noopener noreferrer">
archived source archived source
</a> </Link>
) )
</Figure> </Figure>
@@ -133,9 +135,9 @@ const Previously = () => (
<Figure src={img_2018_04} alt="April 2018"> <Figure src={img_2018_04} alt="April 2018">
April 2018 ( April 2018 (
<a href="https://github.com/jakejarvis/jarv.is/tree/v2" target="_blank" rel="noopener noreferrer"> <Link href="https://github.com/jakejarvis/jarv.is/tree/v2" target="_blank" rel="noopener noreferrer">
archived source archived source
</a> </Link>
) )
</Figure> </Figure>
@@ -143,9 +145,9 @@ const Previously = () => (
<Figure src={img_2020_03} alt="March 2020"> <Figure src={img_2020_03} alt="March 2020">
March 2020 ( March 2020 (
<a href="https://github.com/jakejarvis/jarv.is/tree/v3" target="_blank" rel="noopener noreferrer"> <Link href="https://github.com/jakejarvis/jarv.is/tree/v3" target="_blank" rel="noopener noreferrer">
archived source archived source
</a> </Link>
) )
</Figure> </Figure>
</Content> </Content>

View File

@@ -1,7 +1,7 @@
import Link from "next/link";
import { NextSeo } from "next-seo"; import { NextSeo } from "next-seo";
import Content from "../components/Content/Content"; import Content from "../components/Content/Content";
import PageTitle from "../components/PageTitle/PageTitle"; import PageTitle from "../components/PageTitle/PageTitle";
import Link from "../components/Link/Link";
import Image from "../components/Image/Image"; import Image from "../components/Image/Image";
import IFrame from "../components/IFrame/IFrame"; import IFrame from "../components/IFrame/IFrame";
import { H2 } from "../components/Heading/Heading"; import { H2 } from "../components/Heading/Heading";
@@ -27,33 +27,23 @@ const Privacy = () => (
<p> <p>
Pages and first-party assets on this website are served by{" "} Pages and first-party assets on this website are served by{" "}
<a href="https://vercel.com/" target="_blank" rel="noopener noreferrer"> <Link href="https://vercel.com/">
<strong> Vercel</strong> <strong> Vercel</strong>
</a> </Link>
. Refer to their{" "} . Refer to their <Link href="https://vercel.com/legal/privacy-policy">privacy policy</Link> for more
<a href="https://vercel.com/legal/privacy-policy" target="_blank" rel="noopener noreferrer"> information.
privacy policy
</a>{" "}
for more information.
</p> </p>
<p> <p>
For a likely excessive level of privacy and security, this website is also mirrored on the{" "} For a likely excessive level of privacy and security, this website is also mirrored on the{" "}
<a href="https://www.torproject.org/" target="_blank" rel="noopener noreferrer"> <Link href="https://www.torproject.org/">🧅 Tor network</Link> at:
🧅 Tor network
</a>{" "}
at:
</p> </p>
<Blockquote> <Blockquote>
<p> <p>
<a <Link href="http://jarvis2i2vp4j4tbxjogsnqdemnte5xhzyi7hziiyzxwge3hzmh57zad.onion">
href="http://jarvis2i2vp4j4tbxjogsnqdemnte5xhzyi7hziiyzxwge3hzmh57zad.onion"
target="_blank"
rel="noopener noreferrer"
>
<strong>jarvis2i2vp4j4tbxjogsnqdemnte5xhzyi7hziiyzxwge3hzmh57zad.onion</strong> <strong>jarvis2i2vp4j4tbxjogsnqdemnte5xhzyi7hziiyzxwge3hzmh57zad.onion</strong>
</a> </Link>
</p> </p>
</Blockquote> </Blockquote>
@@ -61,53 +51,29 @@ const Privacy = () => (
<p> <p>
A very simple hit counter on each blog post tallies an aggregate number of pageviews (i.e.{" "} A very simple hit counter on each blog post tallies an aggregate number of pageviews (i.e.{" "}
<code>hits = hits + 1</code>) in a{" "} <code>hits = hits + 1</code>) in a <Link href="https://fauna.com/">Fauna</Link> database. Individual views and
<a href="https://fauna.com/" target="_blank" rel="noopener noreferrer"> identifying (or non-identifying) details are <strong>never stored or logged</strong>.
Fauna
</a>{" "}
database. Individual views and identifying (or non-identifying) details are{" "}
<strong>never stored or logged</strong>.
</p> </p>
<p> <p>
The{" "} The <Link href="https://github.com/jakejarvis/jarv.is/blob/main/pages/api/hits.ts">serverless function</Link>{" "}
<a
href="https://github.com/jakejarvis/jarv.is/blob/main/pages/api/hits.ts"
target="_blank"
rel="noopener noreferrer"
>
serverless function
</a>{" "}
and{" "} and{" "}
<a <Link href="https://github.com/jakejarvis/jarv.is/blob/main/components/HitCounter/HitCounter.tsx">
href="https://github.com/jakejarvis/jarv.is/blob/main/components/HitCounter/HitCounter.tsx"
target="_blank"
rel="noopener noreferrer"
>
client script client script
</a>{" "} </Link>{" "}
are open source, and{" "} are open source, and <Link href="https://github.com/jakejarvis/website-stats">snapshots of the database</Link>{" "}
<a href="https://github.com/jakejarvis/website-stats" target="_blank" rel="noopener noreferrer">
snapshots of the database
</a>{" "}
are public. are public.
</p> </p>
<Image src={faunaImg} alt="The entire database schema." /> <Image src={faunaImg} alt="The entire database schema." />
<p> <p>
<a href="https://usefathom.com/ref/ZEYG0O" target="_blank" rel="noopener noreferrer"> <Link href="https://usefathom.com/ref/ZEYG0O">
<strong>Fathom Analytics</strong> <strong>Fathom Analytics</strong>
</a> </Link>
, a <em>very</em>{" "} , a <em>very</em> <Link href="https://usefathom.com/privacy-focused-web-analytics">privacy-focused</Link>{" "}
<a href="https://usefathom.com/privacy-focused-web-analytics" target="_blank" rel="noopener noreferrer">
privacy-focused
</a>{" "}
service, is also used to gain insights into referrers, search terms, etc.{" "} service, is also used to gain insights into referrers, search terms, etc.{" "}
<strong>without collecting anything identifiable about you</strong>. (My{" "} <strong>without collecting anything identifiable about you</strong>. (My <Link href="/stats/">dashboard</Link>{" "}
<a href="/stats/" target="_blank" rel="noopener noreferrer">
dashboard
</a>{" "}
is completely public, too!) is completely public, too!)
</p> </p>
@@ -127,43 +93,25 @@ const Privacy = () => (
<ul> <ul>
<li> <li>
<a href="https://blog.codepen.io/documentation/privacy/" target="_blank" rel="noopener noreferrer"> <Link href="https://blog.codepen.io/documentation/privacy/">CodePen</Link>
CodePen
</a>
</li> </li>
<li> <li>
<a href="https://www.facebook.com/policy.php" target="_blank" rel="noopener noreferrer"> <Link href="https://www.facebook.com/policy.php">Facebook</Link>
Facebook
</a>
</li> </li>
<li> <li>
<a <Link href="https://docs.github.com/en/github/site-policy/github-privacy-statement">GitHub</Link>
href="https://docs.github.com/en/github/site-policy/github-privacy-statement"
target="_blank"
rel="noopener noreferrer"
>
GitHub
</a>
</li> </li>
<li> <li>
<a href="https://soundcloud.com/pages/privacy" target="_blank" rel="noopener noreferrer"> <Link href="https://soundcloud.com/pages/privacy">SoundCloud</Link>
SoundCloud
</a>
</li> </li>
<li> <li>
<a href="https://twitter.com/en/privacy" target="_blank" rel="noopener noreferrer"> <Link href="https://twitter.com/en/privacy">Twitter</Link>
Twitter
</a>
</li> </li>
<li> <li>
<a href="https://vimeo.com/privacy" target="_blank" rel="noopener noreferrer"> <Link href="https://vimeo.com/privacy">Vimeo</Link>
Vimeo
</a>
</li> </li>
<li> <li>
<a href="https://policies.google.com/privacy" target="_blank" rel="noopener noreferrer"> <Link href="https://policies.google.com/privacy">YouTube</Link>
YouTube
</a>
</li> </li>
</ul> </ul>
@@ -171,51 +119,27 @@ const Privacy = () => (
<p> <p>
Using{" "} Using{" "}
<a href="https://www.hcaptcha.com/" target="_blank" rel="noopener noreferrer"> <Link href="https://www.hcaptcha.com/">
<strong>hCaptcha</strong> <strong>hCaptcha</strong>
</a>{" "}
to fight bot spam on the{" "}
<Link href="/contact/" prefetch={false}>
<a>contact form</a>
</Link>{" "} </Link>{" "}
was an easy choice over seemingly unavoidable alternatives like{" "} to fight bot spam on the <Link href="/contact/">contact form</Link> was an easy choice over seemingly
<a href="https://developers.google.com/recaptcha/" target="_blank" rel="noopener noreferrer"> unavoidable alternatives like <Link href="https://developers.google.com/recaptcha/">reCAPTCHA</Link>.
reCAPTCHA
</a>
.
</p> </p>
<p> <p>
You can refer to hCaptcha's{" "} You can refer to hCaptcha's <Link href="https://www.hcaptcha.com/privacy">privacy policy</Link> and{" "}
<a href="https://www.hcaptcha.com/privacy" target="_blank" rel="noopener noreferrer"> <Link href="https://www.hcaptcha.com/terms">terms of service</Link> for more details. While some information is
privacy policy sent to the hCaptcha API about your behavior <strong>(on the contact page only)</strong>, at least you won't be
</a>{" "} helping a certain internet conglomerate{" "}
and{" "} <Link href="https://blog.cloudflare.com/moving-from-recaptcha-to-hcaptcha/">train their self-driving cars</Link>
<a href="https://www.hcaptcha.com/terms" target="_blank" rel="noopener noreferrer">
terms of service
</a>{" "}
for more details. While some information is sent to the hCaptcha API about your behavior{" "}
<strong>(on the contact page only)</strong>, at least you won't be helping a certain internet conglomerate{" "}
<a
href="https://blog.cloudflare.com/moving-from-recaptcha-to-hcaptcha/"
target="_blank"
rel="noopener noreferrer"
>
train their self-driving cars
</a>
. 🚗 . 🚗
</p> </p>
<p> <p>
I also enabled the setting to donate 100% of my{" "} I also enabled the setting to donate 100% of my{" "}
<a href="https://humanprotocol.org/?lng=en-US" target="_blank" rel="noopener noreferrer"> <Link href="https://humanprotocol.org/?lng=en-US">HMT token</Link> earnings to the{" "}
HMT token <Link href="https://wikimediafoundation.org/">Wikimedia Foundation</Link>, for what it's worth. (A few cents,
</a>{" "} probably... 💰)
earnings to the{" "}
<a href="https://wikimediafoundation.org/" target="_blank" rel="noopener noreferrer">
Wikimedia Foundation
</a>
, for what it's worth. (A few cents, probably... 💰)
</p> </p>
</Content> </Content>
</> </>

View File

@@ -2,6 +2,7 @@ import { graphql } from "@octokit/graphql";
import { NextSeo } from "next-seo"; import { NextSeo } from "next-seo";
import Content from "../components/Content/Content"; import Content from "../components/Content/Content";
import PageTitle from "../components/PageTitle/PageTitle"; import PageTitle from "../components/PageTitle/PageTitle";
import Link from "../components/Link/Link";
import RepositoryCard from "../components/RepositoryCard/RepositoryCard"; import RepositoryCard from "../components/RepositoryCard/RepositoryCard";
import type { GetStaticProps } from "next"; import type { GetStaticProps } from "next";
import type { RepoType } from "../types"; import type { RepoType } from "../types";
@@ -31,9 +32,7 @@ const Projects = ({ repos }: Props) => (
</div> </div>
<p className="view_more"> <p className="view_more">
<a href="https://github.com/jakejarvis?tab=repositories" target="_blank" rel="noopener noreferrer"> <Link href="https://github.com/jakejarvis?tab=repositories">View more on GitHub...</Link>
View more on GitHub...
</a>
</p> </p>
</Content> </Content>
@@ -57,6 +56,8 @@ const Projects = ({ repos }: Props) => (
.view_more { .view_more {
text-align: center; text-align: center;
margin-bottom: 0; margin-bottom: 0;
font-size: 1.1em;
font-weight: 500;
} }
`}</style> `}</style>
</> </>

File diff suppressed because it is too large Load Diff

View File

@@ -1409,31 +1409,31 @@
"@svgr/babel-plugin-transform-react-native-svg" "^6.0.0" "@svgr/babel-plugin-transform-react-native-svg" "^6.0.0"
"@svgr/babel-plugin-transform-svg-component" "^6.2.0" "@svgr/babel-plugin-transform-svg-component" "^6.2.0"
"@svgr/core@^6.2.0": "@svgr/core@^6.2.1":
version "6.2.0" version "6.2.1"
resolved "https://registry.yarnpkg.com/@svgr/core/-/core-6.2.0.tgz#187a7930695635382c1ab42f476a1d4d45a65994" resolved "https://registry.yarnpkg.com/@svgr/core/-/core-6.2.1.tgz#195de807a9f27f9e0e0d678e01084b05c54fdf61"
integrity sha512-n5PrYAPoTpWGykqa8U05/TVTHOrVR/TxrUJ5EWHP9Db6vR3qnqzwAVLiFT1+slA7zQoJTXafQb+akwThf9SxGw== integrity sha512-NWufjGI2WUyrg46mKuySfviEJ6IxHUOm/8a3Ph38VCWSp+83HBraCQrpEM3F3dB6LBs5x8OElS8h3C0oOJaJAA==
dependencies: dependencies:
"@svgr/plugin-jsx" "^6.2.0" "@svgr/plugin-jsx" "^6.2.1"
camelcase "^6.2.0" camelcase "^6.2.0"
cosmiconfig "^7.0.1" cosmiconfig "^7.0.1"
"@svgr/hast-util-to-babel-ast@^6.0.0": "@svgr/hast-util-to-babel-ast@^6.2.1":
version "6.0.0" version "6.2.1"
resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.0.0.tgz#423329ad866b6c169009cc82b5e28ffee80c857c" resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.2.1.tgz#ae065567b74cbe745afae617053adf9a764bea25"
integrity sha512-S+TxtCdDyRGafH1VG1t/uPZ87aOYOHzWL8kqz4FoSZcIbzWA6rnOmjNViNiDzqmEpzp2PW5o5mZfvC9DiVZhTQ== integrity sha512-pt7MMkQFDlWJVy9ULJ1h+hZBDGFfSCwlBNW1HkLnVi7jUhyEXUaGYWi1x6bM2IXuAR9l265khBT4Av4lPmaNLQ==
dependencies: dependencies:
"@babel/types" "^7.15.6" "@babel/types" "^7.15.6"
entities "^3.0.1" entities "^3.0.1"
"@svgr/plugin-jsx@^6.2.0": "@svgr/plugin-jsx@^6.2.1":
version "6.2.0" version "6.2.1"
resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-6.2.0.tgz#5e41a75b12b34cb66509e63e535606161770ff42" resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-6.2.1.tgz#5668f1d2aa18c2f1bb7a1fc9f682d3f9aed263bd"
integrity sha512-QJDEe7K5Hkd4Eewu4pcjiOKTCtjB47Ol6lDLXVhf+jEewi+EKJAaAmM+bNixfW6LSNEg8RwOYQN3GZcprqKfHw== integrity sha512-u+MpjTsLaKo6r3pHeeSVsh9hmGRag2L7VzApWIaS8imNguqoUwDq/u6U/NDmYs/KAsrmtBjOEaAAPbwNGXXp1g==
dependencies: dependencies:
"@babel/core" "^7.15.5" "@babel/core" "^7.15.5"
"@svgr/babel-preset" "^6.2.0" "@svgr/babel-preset" "^6.2.0"
"@svgr/hast-util-to-babel-ast" "^6.0.0" "@svgr/hast-util-to-babel-ast" "^6.2.1"
svg-parser "^2.0.2" svg-parser "^2.0.2"
"@svgr/plugin-svgo@^6.2.0": "@svgr/plugin-svgo@^6.2.0":
@@ -1445,18 +1445,18 @@
deepmerge "^4.2.2" deepmerge "^4.2.2"
svgo "^2.5.0" svgo "^2.5.0"
"@svgr/webpack@^6.2.0": "@svgr/webpack@^6.2.1":
version "6.2.0" version "6.2.1"
resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-6.2.0.tgz#00fafd32e1d59add7b554c40aa2e97e83f975686" resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-6.2.1.tgz#ef5d51c1b6be4e7537fb9f76b3f2b2e22b63c58d"
integrity sha512-KlLdGe93A8GDs19g8kjEmHwArgMAP6cUfegr2Nx+yDAYY32IPtjzm3SoqNP+I+cnOF1CToJu1clWTPEmdd8dXg== integrity sha512-h09ngMNd13hnePwgXa+Y5CgOjzlCvfWLHg+MBnydEedAnuLRzUHUJmGS3o2OsrhxTOOqEsPOFt5v/f6C5Qulcw==
dependencies: dependencies:
"@babel/core" "^7.15.5" "@babel/core" "^7.15.5"
"@babel/plugin-transform-react-constant-elements" "^7.14.5" "@babel/plugin-transform-react-constant-elements" "^7.14.5"
"@babel/preset-env" "^7.15.6" "@babel/preset-env" "^7.15.6"
"@babel/preset-react" "^7.14.5" "@babel/preset-react" "^7.14.5"
"@babel/preset-typescript" "^7.15.0" "@babel/preset-typescript" "^7.15.0"
"@svgr/core" "^6.2.0" "@svgr/core" "^6.2.1"
"@svgr/plugin-jsx" "^6.2.0" "@svgr/plugin-jsx" "^6.2.1"
"@svgr/plugin-svgo" "^6.2.0" "@svgr/plugin-svgo" "^6.2.0"
"@trysound/sax@0.2.0": "@trysound/sax@0.2.0":
@@ -2044,9 +2044,9 @@ camelcase@^6.2.0:
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
caniuse-lite@^1.0.30001283, caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001297, caniuse-lite@^1.0.30001299: caniuse-lite@^1.0.30001283, caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001297, caniuse-lite@^1.0.30001299:
version "1.0.30001303" version "1.0.30001304"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001303.tgz#9b168e4f43ccfc372b86f4bc5a551d9b909c95c9" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001304.tgz#38af55ed3fc8220cb13e35e6e7309c8c65a05559"
integrity sha512-/Mqc1oESndUNszJP0kx0UaQU9kEv9nNtJ7Kn8AdA0mNnH8eR1cj0kG+NbNuC1Wq/b21eA8prhKRA3bbkjONegQ== integrity sha512-bdsfZd6K6ap87AGqSHJP/s1V+U6Z5lyrcbBu3ovbCCf8cSYpwTtGrCBObMpJqwxfTbLW6YTIdbb1jEeTelcpYQ==
ccount@^1.0.0: ccount@^1.0.0:
version "1.1.0" version "1.1.0"
@@ -2541,9 +2541,9 @@ eastasianwidth@^0.2.0:
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
electron-to-chromium@^1.4.17: electron-to-chromium@^1.4.17:
version "1.4.56" version "1.4.57"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.56.tgz#f660fd2c6739b341d8922fe3a441a5a2804911a1" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.57.tgz#2b2766df76ac8dbc0a1d41249bc5684a31849892"
integrity sha512-0k/S0FQqRRpJbX7YUjwCcLZ8D42RqGKtaiq90adXBOYgTIWwLA/g3toO8k9yEpqU8iC4QyaWYYWSTBIna8WV4g== integrity sha512-FNC+P5K1n6pF+M0zIK+gFCoXcJhhzDViL3DRIGy2Fv5PohuSES1JHR7T+GlwxSxlzx4yYbsuzCZvHxcBSRCIOw==
emoji-regex@^8.0.0: emoji-regex@^8.0.0:
version "8.0.0" version "8.0.0"
@@ -3538,7 +3538,7 @@ internal-slot@^1.0.3:
has "^1.0.3" has "^1.0.3"
side-channel "^1.0.4" side-channel "^1.0.4"
is-absolute-url@^4.0.0: is-absolute-url@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-4.0.1.tgz#16e4d487d4fded05cfe0685e53ec86804a5e94dc" resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-4.0.1.tgz#16e4d487d4fded05cfe0685e53ec86804a5e94dc"
integrity sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A== integrity sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==
@@ -5681,22 +5681,10 @@ regjsparser@^0.7.0:
dependencies: dependencies:
jsesc "~0.5.0" jsesc "~0.5.0"
rehype-external-links@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/rehype-external-links/-/rehype-external-links-1.0.1.tgz#9e5d21c606b04d8098012e2d3c811919762d0ba2"
integrity sha512-SrMMtIO2tPLWDfvibhECAn9cuEMW6Fi40ZVK2UQSPTnDEv3LraLzGVyKGb/vrDlUy4RCYTcmm0rq/ss9nPqrsw==
dependencies:
"@types/hast" "^2.0.0"
extend "^3.0.0"
is-absolute-url "^4.0.0"
space-separated-tokens "^2.0.0"
unified "^10.0.0"
unist-util-visit "^4.0.0"
rehype-parse@^8.0.2: rehype-parse@^8.0.2:
version "8.0.3" version "8.0.4"
resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-8.0.3.tgz#a1947132a08a930d0c2b6fd2b3dbcc137457c07a" resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-8.0.4.tgz#3d17c9ff16ddfef6bbcc8e6a25a99467b482d688"
integrity sha512-RGw0CVt+0S6KdvpE8bbP2Db9WXclQcIX7A0ufM3QFqAhTo/ddJMQrrI2j3cijlRPZlGK8R3pRgC8U5HyV76IDw== integrity sha512-MJJKONunHjoTh4kc3dsM1v3C9kGrrxvA3U8PxZlP2SjH8RNUSrb+lF7Y0KVaUDnGH2QZ5vAn7ulkiajM9ifuqg==
dependencies: dependencies:
"@types/hast" "^2.0.0" "@types/hast" "^2.0.0"
hast-util-from-parse5 "^7.0.0" hast-util-from-parse5 "^7.0.0"
@@ -6022,10 +6010,10 @@ simple-git-hooks@^2.7.0:
resolved "https://registry.yarnpkg.com/simple-git-hooks/-/simple-git-hooks-2.7.0.tgz#121a5c3023663b8abcc5648c8bfe8619dc263705" resolved "https://registry.yarnpkg.com/simple-git-hooks/-/simple-git-hooks-2.7.0.tgz#121a5c3023663b8abcc5648c8bfe8619dc263705"
integrity sha512-nQe6ASMO9zn5/htIrU37xEIHGr9E6wikXelLbOeTcfsX2O++DHaVug7RSQoq+kO7DvZTH37WA5gW49hN9HTDmQ== integrity sha512-nQe6ASMO9zn5/htIrU37xEIHGr9E6wikXelLbOeTcfsX2O++DHaVug7RSQoq+kO7DvZTH37WA5gW49hN9HTDmQ==
simple-icons@^6.7.0: simple-icons@^6.8.0:
version "6.7.0" version "6.8.0"
resolved "https://registry.yarnpkg.com/simple-icons/-/simple-icons-6.7.0.tgz#45263b5cd624f26f8f11c8ce1cf814be07de41dc" resolved "https://registry.yarnpkg.com/simple-icons/-/simple-icons-6.8.0.tgz#ee837f4222dc00b600d90ec0025f52ea44c2c749"
integrity sha512-bEqOxIkVGTX/Dlq84bXM3ohzRkwE/kpUloSTNvKb7QDTR35ufxMthK3u6kZy2SbmbhFKSpM3Jc8tgAzgfzwV5w== integrity sha512-Ow1ISgCpRZuXa1xvwVqUrep6xqdtNmcgqd9pCtMgni7m1XmQI56EuSSJYAbyvCcoakXVcbtHFajtPXEd86iMCA==
sirv@^1.0.7: sirv@^1.0.7:
version "1.0.19" version "1.0.19"