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

parse markdown in titles at build time

This commit is contained in:
Jake Jarvis 2022-01-10 08:37:30 -05:00
parent 58321a3844
commit 972a25abc6
Signed by: jake
GPG Key ID: 2B0C9CF251E69A39
7 changed files with 89 additions and 51 deletions

View File

@ -1,28 +0,0 @@
const Octocat = (props: { repo: string }) => {
return (
<a
className="no-underline"
href={`https://github.com/${props.repo}`}
target="_blank"
rel="noopener noreferrer"
style={{ margin: "0 0.3em", color: "var(--text)" }}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
width="1em"
height="1em"
aria-hidden="true"
className="icon"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"
></path>
</svg>
</a>
);
};
export default Octocat;

View File

@ -1,11 +1,11 @@
import Link from "next/link";
import Markdown from "markdown-to-jsx";
import { format } from "date-fns";
import styles from "./List.module.css";
type NoteProps = {
title: string;
htmlTitle?: string;
date: string;
slug: string;
};
@ -29,9 +29,7 @@ const List = ({ notesByYear }) => {
}}
prefetch={false}
>
<a>
<Markdown options={{ disableParsingRawHTML: true, forceInline: true }}>{note.title}</Markdown>
</a>
<a dangerouslySetInnerHTML={{ __html: note.htmlTitle }} />
</Link>
</span>
</li>

View File

@ -1,6 +1,5 @@
import Link from "next/link";
import { format } from "date-fns";
import Markdown from "markdown-to-jsx";
import Hits from "../hits/Hits";
import { DateIcon, TagIcon, EditIcon, ViewsIcon } from "../icons";
import * as config from "../../lib/config";
@ -9,12 +8,13 @@ import styles from "./Meta.module.css";
export type Props = {
title: string;
htmlTitle?: string;
date: string;
slug: string;
tags?: string[];
};
const Meta = ({ title, date, slug, tags = [] }: Props) => (
const Meta = ({ title, htmlTitle = "", date, slug, tags = [] }: Props) => (
<>
<div className={styles.meta}>
<div className={styles.date}>
@ -62,9 +62,7 @@ const Meta = ({ title, date, slug, tags = [] }: Props) => (
<h1 className={styles.title}>
<Link href={`/notes/${slug}/`}>
<a>
<Markdown options={{ disableParsingRawHTML: true, forceInline: true }}>{title}</Markdown>
</a>
<a dangerouslySetInnerHTML={{ __html: htmlTitle }} />
</Link>
</h1>
</>

View File

@ -1,6 +1,8 @@
import fs from "fs";
import path from "path";
import matter from "gray-matter";
import { marked } from "marked";
import sanitizeHtml from "sanitize-html";
import { bundleMDX } from "mdx-bundler";
import readingTime from "reading-time";
import { NOTES_DIR, baseUrl } from "./config";
@ -28,10 +30,11 @@ export const getNoteData = (slug: string) => {
return {
frontMatter: {
...data,
htmlTitle: sanitizeHtml(marked.parseInline(data.title), { allowedTags: ["code"] }),
slug,
permalink: `${baseUrl}/notes/${slug}/`,
date: new Date(data.date).toISOString(), // validate/normalize the date string provided from front matter
readingTime: readingTime(content).minutes,
readingMins: Math.ceil(readingTime(content).minutes),
},
content,
};
@ -39,11 +42,10 @@ export const getNoteData = (slug: string) => {
export const getNote = async (slug: string) => {
// https://github.com/kentcdodds/mdx-bundler#nextjs-esbuild-enoent
if (process.platform === "win32") {
process.env.ESBUILD_BINARY_PATH = path.join(process.cwd(), "node_modules", "esbuild", "esbuild.exe");
} else {
process.env.ESBUILD_BINARY_PATH = path.join(process.cwd(), "node_modules", "esbuild", "bin", "esbuild");
}
process.env.ESBUILD_BINARY_PATH =
process.platform === "win32"
? path.join(process.cwd(), "node_modules", "esbuild", "esbuild.exe")
: path.join(process.cwd(), "node_modules", "esbuild", "bin", "esbuild");
const { frontMatter, content } = getNoteData(slug);
const { code: mdxSource } = await bundleMDX({

View File

@ -13,7 +13,33 @@ image: "/static/images/notes/coronavirus-open-source/covid19dashboards.png"
import Image from "./components/embeds/Image";
import Video from "./components/embeds/Video";
import Octocat from "./components/embeds/Octocat";
export const Octocat = (props) => {
return (
<a
className="no-underline"
href={`https://github.com/${props.repo}`}
target="_blank"
rel="noopener noreferrer"
style={{ margin: "0 0.3em", color: "var(--text)" }}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
width="1em"
height="1em"
aria-hidden="true"
className="icon"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"
/>
</svg>
</a>
);
};
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.

View File

@ -43,7 +43,7 @@
"html-escaper": "^3.0.3",
"is-absolute-url": "^4.0.1",
"is-email-like": "^2.0.0",
"markdown-to-jsx": "^7.1.5",
"marked": "^4.0.9",
"mdx-bundler": "^8.0.1",
"modern-normalize": "github:sindresorhus/modern-normalize#1fc6b5a86676b7ac8abc62d04d6080f92debc70f",
"next": "v12.0.8-canary.19",
@ -67,6 +67,7 @@
"rehype-highlight": "^5.0.2",
"rehype-slug": "^5.0.1",
"remark-gfm": "^3.0.1",
"sanitize-html": "^2.6.1",
"styled-jsx": "^4.0.1",
"swr": "^1.1.2"
},
@ -74,10 +75,12 @@
"@jakejarvis/eslint-config": "github:jakejarvis/eslint-config#main",
"@svgr/webpack": "^6.1.2",
"@types/html-escaper": "^3.0.0",
"@types/marked": "^4.0.1",
"@types/prop-types": "^15.7.4",
"@types/react": "^17.0.38",
"@types/react-dom": "^17.0.11",
"@types/react-is": "^17.0.3",
"@types/sanitize-html": "^2.6.1",
"autoprefixer": "^10.4.2",
"cross-env": "^7.0.3",
"esbuild": "^0.14.11",

View File

@ -1496,6 +1496,11 @@
dependencies:
"@types/node" "*"
"@types/marked@^4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/marked/-/marked-4.0.1.tgz#d588a7bbc4d6551c5e75249bc106ffda96ae33c5"
integrity sha512-ZigEmCWdNUU7IjZEuQ/iaimYdDHWHfTe3kg8ORfKjyGYd9RWumPoOJRQXB0bO+XLkNwzCthW3wUIQtANaEZ1ag==
"@types/mdast@^3.0.0", "@types/mdast@^3.0.3":
version "3.0.10"
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af"
@ -1583,6 +1588,13 @@
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065"
integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==
"@types/sanitize-html@^2.6.1":
version "2.6.1"
resolved "https://registry.yarnpkg.com/@types/sanitize-html/-/sanitize-html-2.6.1.tgz#970193524df719f716c5bcf8db579859c446cd17"
integrity sha512-+JLlZdJkIHdgvlFnMorJeLv5WIORNcI+jHsAoPBWMnhGx5Rbz/D1QN5D4qvmoA7fooDlEVy6zlioWSgqbU0KeQ==
dependencies:
htmlparser2 "^6.0.0"
"@types/scheduler@*":
version "0.16.2"
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
@ -2442,14 +2454,14 @@ domelementtype@^2.0.1, domelementtype@^2.2.0:
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57"
integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==
domhandler@^4.2.0, domhandler@^4.3.0:
domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626"
integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==
dependencies:
domelementtype "^2.2.0"
domutils@^2.8.0:
domutils@^2.5.2, domutils@^2.8.0:
version "2.8.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135"
integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==
@ -3503,6 +3515,16 @@ html-tags@^3.1.0:
resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140"
integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==
htmlparser2@^6.0.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7"
integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==
dependencies:
domelementtype "^2.0.1"
domhandler "^4.0.0"
domutils "^2.5.2"
entities "^2.0.0"
http-cache-semantics@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390"
@ -4106,10 +4128,10 @@ markdown-table@^3.0.0:
resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.2.tgz#9b59eb2c1b22fe71954a65ff512887065a7bb57c"
integrity sha512-y8j3a5/DkJCmS5x4dMCQL+OR0+2EAq3DOtio1COSHsmW2BGXnNCK3v12hJt1LrUz5iZH5g0LmuYOjDdI+czghA==
markdown-to-jsx@^7.1.5:
version "7.1.5"
resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-7.1.5.tgz#caf72ad8a8c34a2bb692c4d17e44aabbe4eb19fd"
integrity sha512-YQEMMMCX3PYOWtUAQu8Fmz5/sH09s17eyQnDubwaAo8sWmnRTT1og96EFv1vL59l4nWfmtF3L91pqkuheVqRlA==
marked@^4.0.9:
version "4.0.9"
resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.9.tgz#96862d67bd31b4770917f01c93e1d9b3cc73ed96"
integrity sha512-HmoFvQwFLxNESeGupeOC+6CLb5WzcCWQmqvVetsErmrI3vrZ6gBumty5IP0ynLPR0zYSoVY7ITC1GffsYIGkog==
mathml-tag-names@^2.1.3:
version "2.1.3"
@ -5147,6 +5169,11 @@ parse-json@^5.0.0:
json-parse-even-better-errors "^2.3.0"
lines-and-columns "^1.1.6"
parse-srcset@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1"
integrity sha1-8r0iH2zJcKk42IVWq8WJyqqiveE=
path-exists@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
@ -5719,6 +5746,18 @@ safe-buffer@~5.2.0:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
sanitize-html@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.6.1.tgz#5d37c08e189c61c0631560a889b10d9d155d000e"
integrity sha512-DzjSz3H5qDntD7s1TcWCSoRPmNR8UmA+y+xZQOvWgjATe2Br9ZW73+vD3Pj6Snrg0RuEuJdXgrKvnYuiuixRkA==
dependencies:
deepmerge "^4.2.2"
escape-string-regexp "^4.0.0"
htmlparser2 "^6.0.0"
is-plain-object "^5.0.0"
parse-srcset "^1.0.2"
postcss "^8.3.11"
sax@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"