mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2025-09-13 23:55:35 -04:00
simplify note parsing logic
This commit is contained in:
@@ -2,90 +2,106 @@ import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import TweetEmbed from "react-tweet-embed";
|
||||
import Gist from "react-gist";
|
||||
import getNodeText from "../lib/get-node-text";
|
||||
import Video from "./video/FullPageVideo";
|
||||
import CopyButton from "./clipboard/CopyButton";
|
||||
import getNodeText from "../lib/get-node-text";
|
||||
import { OctocatOcticon } from "./icons/octicons";
|
||||
|
||||
import type { LinkProps } from "next/link";
|
||||
import type { ImageProps } from "next/image";
|
||||
import type { ReactPlayerProps } from "react-player";
|
||||
|
||||
// The following components are all passed into <MDXProvider /> as replacement HTML tags or drop-in React components
|
||||
// available in .mdx files containing post content, since they're not directly aware of the components in this folder.
|
||||
const mdxComponents = {
|
||||
a: ({
|
||||
href,
|
||||
target,
|
||||
rel,
|
||||
className,
|
||||
children,
|
||||
}: LinkProps & {
|
||||
target?: string;
|
||||
rel?: string;
|
||||
className?: string;
|
||||
children?: unknown;
|
||||
}) => (
|
||||
<Link href={href} passHref={true}>
|
||||
<a className={className} target={target} rel={rel}>
|
||||
{children}
|
||||
</a>
|
||||
</Link>
|
||||
),
|
||||
img: (props: ImageProps) => {
|
||||
|
||||
const CustomLink = ({
|
||||
href,
|
||||
target,
|
||||
rel,
|
||||
className,
|
||||
children,
|
||||
}: LinkProps & {
|
||||
target?: string;
|
||||
rel?: string;
|
||||
className?: string;
|
||||
children?: unknown;
|
||||
}) => (
|
||||
<Link href={href} passHref={true}>
|
||||
<a className={className} target={target} rel={rel}>
|
||||
{children}
|
||||
</a>
|
||||
</Link>
|
||||
);
|
||||
|
||||
const CustomImg = (props: ImageProps) => {
|
||||
return (
|
||||
// height and width are part of the props, so they get automatically passed here with {...props}
|
||||
<div className={props.className}>
|
||||
{/* eslint-disable-next-line jsx-a11y/alt-text */}
|
||||
<Image {...props} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const CustomCode = (props: any) => {
|
||||
if (props.className?.split(" ").includes("hljs")) {
|
||||
return (
|
||||
// height and width are part of the props, so they get automatically passed here with {...props}
|
||||
<div className={props.className}>
|
||||
{/* eslint-disable-next-line jsx-a11y/alt-text */}
|
||||
<Image {...props} />
|
||||
<div>
|
||||
<CopyButton content={getNodeText(props.children)} />
|
||||
<code {...props}>{props.children}</code>
|
||||
<style jsx>{`
|
||||
div {
|
||||
position: relative;
|
||||
max-width: 100%;
|
||||
overflow-x: scroll;
|
||||
margin: 1em 0;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
code: (props: any) => {
|
||||
if (props.className?.split(" ").includes("hljs")) {
|
||||
return (
|
||||
<div>
|
||||
<CopyButton content={getNodeText(props.children)} />
|
||||
<code {...props}>{props.children}</code>
|
||||
<style jsx>{`
|
||||
div {
|
||||
position: relative;
|
||||
max-width: 100%;
|
||||
overflow-x: scroll;
|
||||
margin: 1em 0;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return <code {...props}>{props.children}</code>;
|
||||
}
|
||||
},
|
||||
video: (props: ReactPlayerProps) => <Video {...props} />,
|
||||
tweet: (props: { id: string }) => (
|
||||
<TweetEmbed
|
||||
id={props.id}
|
||||
options={{
|
||||
dnt: true,
|
||||
align: "center",
|
||||
}}
|
||||
/>
|
||||
),
|
||||
gist: (props: { id: string; file?: string }) => <Gist {...props} />,
|
||||
octocat: (props: { repo: string }) => (
|
||||
<a className="no-underline" href={`https://github.com/${props.repo}`} target="_blank" rel="noopener noreferrer">
|
||||
<OctocatOcticon verticalAlign="text-top" fill="currentColor" />
|
||||
<style jsx>{`
|
||||
a {
|
||||
margin: 0 0.3em;
|
||||
color: var(--text);
|
||||
}
|
||||
} else {
|
||||
return <code {...props}>{props.children}</code>;
|
||||
}
|
||||
};
|
||||
|
||||
a:hover {
|
||||
color: var(--link);
|
||||
}
|
||||
`}</style>
|
||||
</a>
|
||||
),
|
||||
const CustomVideo = (props: ReactPlayerProps) => <Video {...props} />;
|
||||
|
||||
const CustomTweet = (props: { id: string }) => (
|
||||
<TweetEmbed
|
||||
id={props.id}
|
||||
options={{
|
||||
dnt: true,
|
||||
align: "center",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
const CustomGist = (props: { id: string; file?: string }) => <Gist {...props} />;
|
||||
|
||||
const CustomGitHubLink = (props: { repo: string }) => (
|
||||
<a className="no-underline" href={`https://github.com/${props.repo}`} target="_blank" rel="noopener noreferrer">
|
||||
<OctocatOcticon verticalAlign="text-top" fill="currentColor" />
|
||||
<style jsx>{`
|
||||
a {
|
||||
margin: 0 0.3em;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--link);
|
||||
}
|
||||
`}</style>
|
||||
</a>
|
||||
);
|
||||
|
||||
const mdxComponents = {
|
||||
a: CustomLink,
|
||||
img: CustomImg,
|
||||
code: CustomCode,
|
||||
video: CustomVideo,
|
||||
tweet: CustomTweet,
|
||||
gist: CustomGist,
|
||||
octocat: CustomGitHubLink,
|
||||
};
|
||||
|
||||
export default mdxComponents;
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import Link from "next/link";
|
||||
import { format, parseISO } from "date-fns";
|
||||
import groupBy from "lodash.groupby";
|
||||
|
||||
import styles from "./List.module.scss";
|
||||
|
||||
@@ -9,15 +10,16 @@ type NoteProps = {
|
||||
slug: string;
|
||||
};
|
||||
|
||||
const List = ({ notesByYear }) => {
|
||||
const List = ({ notes }) => {
|
||||
const notesByYear = groupBy(notes, "year");
|
||||
const sections = [];
|
||||
|
||||
Object.entries(notesByYear).forEach(([year, notes]: [string, NoteProps[]]) => {
|
||||
Object.entries(notesByYear).forEach(([year, yearNotes]: [string, NoteProps[]]) => {
|
||||
sections.push(
|
||||
<section key={year} className={styles.section}>
|
||||
<h2 className={styles.year}>{year}</h2>
|
||||
<ul className={styles.list}>
|
||||
{notes.map((note) => (
|
||||
{yearNotes.map((note) => (
|
||||
<li key={note.slug} className={styles.row}>
|
||||
<span className={styles.date}>{format(parseISO(note.date), "MMM d")}</span>
|
||||
<span>
|
||||
|
@@ -1,37 +1,40 @@
|
||||
import { Feed } from "feed";
|
||||
import { getAllNotes } from "./parse-notes";
|
||||
import * as config from "./config";
|
||||
|
||||
export const buildFeed = (notes: any[]) => {
|
||||
export const buildFeed = () => {
|
||||
const baseURL = config.baseURL || "http://localhost:3000"; // necessary for local testing
|
||||
const feed = new Feed({
|
||||
id: `${config.baseURL}/`,
|
||||
link: `${config.baseURL}/`,
|
||||
id: `${baseURL}/`,
|
||||
link: `${baseURL}/`,
|
||||
title: config.siteName,
|
||||
description: config.longDescription,
|
||||
copyright: "https://creativecommons.org/licenses/by/4.0/",
|
||||
updated: new Date(),
|
||||
image: `${config.baseURL}/static/images/me.jpg`,
|
||||
image: `${baseURL}/static/images/me.jpg`,
|
||||
feedLinks: {
|
||||
rss: `${config.baseURL}/feed.xml`,
|
||||
atom: `${config.baseURL}/feed.atom`,
|
||||
rss: `${baseURL}/feed.xml`,
|
||||
atom: `${baseURL}/feed.atom`,
|
||||
},
|
||||
author: {
|
||||
name: config.authorName,
|
||||
link: config.baseURL,
|
||||
link: baseURL,
|
||||
email: "jake@jarv.is",
|
||||
},
|
||||
});
|
||||
|
||||
notes.forEach((note: { title: any; slug: any; description: any; image: any; date: string | number | Date }) => {
|
||||
const notes = getAllNotes();
|
||||
notes.forEach((note: any) => {
|
||||
feed.addItem({
|
||||
title: note.title,
|
||||
link: `${config.baseURL}/notes/${note.slug}/`,
|
||||
guid: `${config.baseURL}/notes/${note.slug}/`,
|
||||
link: `${baseURL}/notes/${note.slug}/`,
|
||||
guid: `${baseURL}/notes/${note.slug}/`,
|
||||
description: note.description,
|
||||
image: note.image ? `${config.baseURL}${note.image}` : "",
|
||||
image: note.image ? `${baseURL}${note.image}` : "",
|
||||
author: [
|
||||
{
|
||||
name: config.authorName,
|
||||
link: config.baseURL,
|
||||
link: baseURL,
|
||||
},
|
||||
],
|
||||
date: new Date(note.date),
|
||||
|
@@ -27,4 +27,7 @@ export const facebookAppId = "3357248167622283";
|
||||
export const webmentionId = "jarv.is";
|
||||
export const monetization = "$ilp.uphold.com/BJp6d2FrEB69";
|
||||
|
||||
// Next.js constants
|
||||
export const NOTES_DIR = "notes";
|
||||
|
||||
// ...note / TODO: there is still a metric poop ton of this kind of info hard-coded.
|
||||
|
@@ -1,38 +1,29 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import matter from "gray-matter";
|
||||
import { format, parseISO } from "date-fns";
|
||||
import { NOTES_DIR } from "./config";
|
||||
|
||||
export const NOTES_PATH = path.join(process.cwd(), "notes");
|
||||
export const getNoteData = (file: string) => {
|
||||
const slug = file.replace(/\.mdx$/, "");
|
||||
const fullPath = path.join(process.cwd(), NOTES_DIR, `${slug}.mdx`);
|
||||
const contents = fs.readFileSync(fullPath, "utf8");
|
||||
const { data } = matter(contents);
|
||||
|
||||
export const getNoteSlugs = () => fs.readdirSync(NOTES_PATH);
|
||||
|
||||
// Return all md(x) files in NOTES_PATH
|
||||
export const notePaths = getNoteSlugs().filter((notePath) => /\.mdx?$/.test(notePath));
|
||||
|
||||
export const getNoteBySlug = (slug, fields = []) => {
|
||||
const realSlug = slug.replace(/\.mdx$/, "");
|
||||
const fullPath = path.join(NOTES_PATH, `${realSlug}.mdx`);
|
||||
const fileContents = fs.readFileSync(fullPath, "utf8");
|
||||
const { data, content } = matter(fileContents);
|
||||
|
||||
const items = {};
|
||||
|
||||
// Ensure only the minimal needed data is exposed
|
||||
fields.forEach((field) => {
|
||||
if (field === "slug") {
|
||||
items[field] = realSlug;
|
||||
} else if (field === "content") {
|
||||
items[field] = content;
|
||||
} else if (typeof data[field] !== "undefined") {
|
||||
items[field] = data[field];
|
||||
}
|
||||
});
|
||||
|
||||
return items;
|
||||
return {
|
||||
...data,
|
||||
slug: slug,
|
||||
date: parseISO(data.date).toISOString(), // validate/normalize the date string provided from front matter
|
||||
year: parseInt(format(parseISO(data.date), "yyyy")),
|
||||
};
|
||||
};
|
||||
|
||||
export const getAllNotes = (fields = []) =>
|
||||
getNoteSlugs()
|
||||
.map((slug) => getNoteBySlug(slug, fields))
|
||||
// all .mdx files in NOTES_DIR
|
||||
export const getNoteFiles = () =>
|
||||
fs.readdirSync(path.join(process.cwd(), NOTES_DIR)).filter((notePath) => /\.mdx$/.test(notePath));
|
||||
|
||||
export const getAllNotes = () =>
|
||||
getNoteFiles()
|
||||
.map((file) => getNoteData(file))
|
||||
// sort notes by date in descending order
|
||||
.sort((note1: any, note2: any) => (note1.date > note2.date ? -1 : 1));
|
||||
|
@@ -8,7 +8,7 @@ tags:
|
||||
- Coronavirus
|
||||
- Public Health
|
||||
- GitHub
|
||||
image: "images/covid19dashboards.png"
|
||||
image: "/static/images/notes/coronavirus-open-source/covid19dashboards.png"
|
||||
---
|
||||
|
||||
We're all quickly learning that worldwide pandemics can bring out both [the best](https://www.vox.com/culture/2020/3/13/21179293/coronavirus-italy-covid19-music-balconies-sing) and [the worst](https://twitter.com/9NewsAUS/status/1236088663093608448) of humanity. But one thing has become readily apparent to me — outside of the large teams of medical professionals risking their lives right this minute, the open source community stands alone in its ability to rapidly organize in the midst of chaos to give back to the world and, in this case, make it safer for all of us.
|
||||
|
@@ -8,7 +8,7 @@ tags:
|
||||
- Subdomain Takeover
|
||||
- Bug Bounty
|
||||
- Tutorial
|
||||
image: "images/hackerone-2.png"
|
||||
image: "/static/images/notes/finding-candidates-subdomain-takeovers/hackerone-2.png"
|
||||
---
|
||||
|
||||
A **subdomain takeover** occurs when a subdomain (like _example_.jarv.is) points to a shared hosting account that is abandoned by its owner, leaving the endpoint available to claim for yourself.
|
||||
|
@@ -8,7 +8,7 @@ tags:
|
||||
- Continuous Integration
|
||||
- Docker
|
||||
- Open Source
|
||||
image: "images/actions-flow.png"
|
||||
image: "/static/images/notes/github-actions/actions-flow.png"
|
||||
---
|
||||
|
||||
<img
|
||||
|
@@ -14,7 +14,7 @@
|
||||
"url": "https://github.com/jakejarvis/jarv.is.git"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"dev": "NODE_OPTIONS='--inspect' next dev",
|
||||
"build": "next build",
|
||||
"postbuild": "next-sitemap",
|
||||
"start": "next start",
|
||||
@@ -85,7 +85,7 @@
|
||||
"eslint-config-next": "~12.0.7",
|
||||
"eslint-config-prettier": "~8.3.0",
|
||||
"eslint-plugin-prettier": "~4.0.0",
|
||||
"lint-staged": "^12.1.4",
|
||||
"lint-staged": "^12.1.5",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"postcss": "^8.4.5",
|
||||
"postcss-focus": "^5.0.1",
|
||||
|
@@ -1,14 +1,12 @@
|
||||
import { getAllNotes } from "../lib/parse-notes";
|
||||
import { buildFeed } from "../lib/build-feed";
|
||||
import type { GetServerSideProps } from "next";
|
||||
|
||||
const AtomPage = () => null;
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||
const notes = getAllNotes(["title", "date", "image", "slug", "description"]);
|
||||
const feed = buildFeed(notes);
|
||||
|
||||
const feed = buildFeed();
|
||||
const { res } = context;
|
||||
|
||||
res.setHeader("content-type", "application/atom+xml");
|
||||
res.write(feed.atom1());
|
||||
res.end();
|
||||
|
@@ -1,14 +1,12 @@
|
||||
import { getAllNotes } from "../lib/parse-notes";
|
||||
import { buildFeed } from "../lib/build-feed";
|
||||
import type { GetServerSideProps } from "next";
|
||||
|
||||
const RssPage = () => null;
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||
const notes = getAllNotes(["title", "date", "image", "slug", "description"]);
|
||||
const feed = buildFeed(notes);
|
||||
|
||||
const feed = buildFeed();
|
||||
const { res } = context;
|
||||
|
||||
res.setHeader("content-type", "application/rss+xml");
|
||||
res.write(feed.rss2());
|
||||
res.end();
|
||||
|
@@ -8,8 +8,8 @@ import Layout from "../../components/Layout";
|
||||
import Container from "../../components/Container";
|
||||
import Content from "../../components/Content";
|
||||
import Meta from "../../components/notes/Meta";
|
||||
import { notePaths, NOTES_PATH } from "../../lib/parse-notes";
|
||||
import mdxComponents from "../../components/mdxComponents";
|
||||
import { getNoteFiles } from "../../lib/parse-notes";
|
||||
import * as config from "../../lib/config";
|
||||
import type { GetStaticProps, GetStaticPaths } from "next";
|
||||
|
||||
@@ -59,7 +59,9 @@ const Note = ({ source, frontMatter, slug }) => (
|
||||
<Container>
|
||||
<Meta {...frontMatter} slug={slug} />
|
||||
<Content>
|
||||
<MDXRemote {...source} components={mdxComponents} />
|
||||
<div className="markdown">
|
||||
<MDXRemote {...source} components={mdxComponents} />
|
||||
</div>
|
||||
</Content>
|
||||
</Container>
|
||||
</Layout>
|
||||
@@ -67,7 +69,7 @@ const Note = ({ source, frontMatter, slug }) => (
|
||||
);
|
||||
|
||||
export const getStaticProps: GetStaticProps = async ({ params }) => {
|
||||
const filePath = path.join(NOTES_PATH, `${params.slug}.mdx`);
|
||||
const filePath = path.join(process.cwd(), config.NOTES_DIR, `${params.slug}.mdx`);
|
||||
const source = fs.readFileSync(filePath);
|
||||
|
||||
const { content, data } = matter(source);
|
||||
@@ -98,7 +100,7 @@ export const getStaticProps: GetStaticProps = async ({ params }) => {
|
||||
};
|
||||
|
||||
export const getStaticPaths: GetStaticPaths = async () => {
|
||||
const paths = notePaths
|
||||
const paths = getNoteFiles()
|
||||
// Remove file extensions for page paths
|
||||
.map((notePath) => notePath.replace(/\.mdx?$/, ""))
|
||||
// Map the path into the static paths object required by Next.js
|
||||
|
@@ -1,28 +1,23 @@
|
||||
import { format, parseISO } from "date-fns";
|
||||
import groupBy from "lodash.groupby";
|
||||
import Layout from "../../components/Layout";
|
||||
import Container from "../../components/Container";
|
||||
import List from "../../components/notes/List";
|
||||
import { getAllNotes } from "../../lib/parse-notes";
|
||||
import type { GetStaticProps } from "next";
|
||||
|
||||
const Notes = ({ notesByYear }) => (
|
||||
const Notes = ({ notes }) => (
|
||||
<Layout>
|
||||
<Container title="Notes" description="Recent posts by Jake Jarvis.">
|
||||
<List notesByYear={notesByYear} />
|
||||
<List notes={notes} />
|
||||
</Container>
|
||||
</Layout>
|
||||
);
|
||||
|
||||
export const getStaticProps: GetStaticProps = async () => {
|
||||
const allNotes = getAllNotes(["date", "slug", "title"]);
|
||||
|
||||
// parse year of each note
|
||||
allNotes.map((note: any) => (note.year = parseInt(format(parseISO(note.date), "yyyy"))));
|
||||
const notes = getAllNotes();
|
||||
|
||||
return {
|
||||
props: {
|
||||
notesByYear: groupBy(allNotes, "year"),
|
||||
notes,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@@ -1,8 +1,10 @@
|
||||
@use "sass:meta";
|
||||
|
||||
// hacky way to assign different HLJS themes to light/dark mode
|
||||
@include meta.load-css("../node_modules/highlight.js/styles/stackoverflow-light.css");
|
||||
.markdown {
|
||||
@include meta.load-css("../node_modules/highlight.js/styles/stackoverflow-light.css");
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
[data-theme="dark"] .markdown {
|
||||
@include meta.load-css("../node_modules/highlight.js/styles/stackoverflow-dark.css");
|
||||
}
|
||||
|
22
yarn.lock
22
yarn.lock
@@ -2586,7 +2586,7 @@ eslint-import-resolver-typescript@^2.4.0:
|
||||
resolve "^1.20.0"
|
||||
tsconfig-paths "^3.9.0"
|
||||
|
||||
eslint-module-utils@^2.7.1:
|
||||
eslint-module-utils@^2.7.2:
|
||||
version "2.7.2"
|
||||
resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.2.tgz#1d0aa455dcf41052339b63cada8ab5fd57577129"
|
||||
integrity sha512-zquepFnWCY2ISMFwD/DqzaM++H+7PDzOpUvotJWm/y1BAFt5R4oeULgdrTejKqLkz7MA/tgstsUMNYc7wNdTrg==
|
||||
@@ -2595,23 +2595,23 @@ eslint-module-utils@^2.7.1:
|
||||
find-up "^2.1.0"
|
||||
|
||||
eslint-plugin-import@^2.25.2:
|
||||
version "2.25.3"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.3.tgz#a554b5f66e08fb4f6dc99221866e57cfff824766"
|
||||
integrity sha512-RzAVbby+72IB3iOEL8clzPLzL3wpDrlwjsTBAQXgyp5SeTqqY+0bFubwuo+y/HLhNZcXV4XqTBO4LGsfyHIDXg==
|
||||
version "2.25.4"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz#322f3f916a4e9e991ac7af32032c25ce313209f1"
|
||||
integrity sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==
|
||||
dependencies:
|
||||
array-includes "^3.1.4"
|
||||
array.prototype.flat "^1.2.5"
|
||||
debug "^2.6.9"
|
||||
doctrine "^2.1.0"
|
||||
eslint-import-resolver-node "^0.3.6"
|
||||
eslint-module-utils "^2.7.1"
|
||||
eslint-module-utils "^2.7.2"
|
||||
has "^1.0.3"
|
||||
is-core-module "^2.8.0"
|
||||
is-glob "^4.0.3"
|
||||
minimatch "^3.0.4"
|
||||
object.values "^1.1.5"
|
||||
resolve "^1.20.0"
|
||||
tsconfig-paths "^3.11.0"
|
||||
tsconfig-paths "^3.12.0"
|
||||
|
||||
eslint-plugin-jsx-a11y@^6.5.1:
|
||||
version "6.5.1"
|
||||
@@ -3729,10 +3729,10 @@ lines-and-columns@^1.1.6:
|
||||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
|
||||
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
|
||||
|
||||
lint-staged@^12.1.4:
|
||||
version "12.1.4"
|
||||
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-12.1.4.tgz#a92ec8509f13018caaafade61d515c2d5873316e"
|
||||
integrity sha512-RgDz9nsFsE0/5eL9Vat0AvCuk0+j5mEuzBIVfrRH5FRtt5wibYe8zTjZs2nuqLFrLAGQGYnj8+HJxolcj08i/A==
|
||||
lint-staged@^12.1.5:
|
||||
version "12.1.5"
|
||||
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-12.1.5.tgz#e05582fc39aed5cb13b9dd1dfb8330407246d809"
|
||||
integrity sha512-WyKb+0sNKDTd1LwwAfTBPp0XmdaKkAOEbg4oHE4Kq2+oQVchg/VAcjVQtSqZih1izNsTURjc2EkhG/syRQUXdA==
|
||||
dependencies:
|
||||
cli-truncate "^3.1.0"
|
||||
colorette "^2.0.16"
|
||||
@@ -5591,7 +5591,7 @@ trough@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/trough/-/trough-2.0.2.tgz#94a3aa9d5ce379fc561f6244905b3f36b7458d96"
|
||||
integrity sha512-FnHq5sTMxC0sk957wHDzRnemFnNBvt/gSY99HzK8F7UP5WAbvP70yX5bd7CjEQkN+TjdxwI7g7lJ6podqrG2/w==
|
||||
|
||||
tsconfig-paths@^3.11.0, tsconfig-paths@^3.9.0:
|
||||
tsconfig-paths@^3.12.0, tsconfig-paths@^3.9.0:
|
||||
version "3.12.0"
|
||||
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz#19769aca6ee8f6a1a341e38c8fa45dd9fb18899b"
|
||||
integrity sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==
|
||||
|
Reference in New Issue
Block a user