mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2025-09-18 16:05:33 -04:00
fix post title encoding
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
|
import Image from "next/image";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import Link from "../Link";
|
import Link from "../Link";
|
||||||
import Image from "../Image";
|
|
||||||
import Menu from "../Menu";
|
import Menu from "../Menu";
|
||||||
import * as config from "../../lib/config";
|
import * as config from "../../lib/config";
|
||||||
import { MAX_WIDTH } from "../../lib/config/constants";
|
import { MAX_WIDTH } from "../../lib/config/constants";
|
||||||
|
5
components/Image/Image.module.css
Normal file
5
components/Image/Image.module.css
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.image {
|
||||||
|
display: block;
|
||||||
|
margin: 1em auto;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
@@ -1,11 +1,14 @@
|
|||||||
import NextImage from "next/image";
|
import NextImage from "next/image";
|
||||||
|
import clsx from "clsx";
|
||||||
import { MAX_WIDTH } from "../../lib/config/constants";
|
import { MAX_WIDTH } from "../../lib/config/constants";
|
||||||
import type { ComponentPropsWithoutRef } from "react";
|
import type { ComponentPropsWithoutRef } from "react";
|
||||||
import type { StaticImageData } from "next/image";
|
import type { StaticImageData } from "next/image";
|
||||||
|
|
||||||
|
import styles from "./Image.module.css";
|
||||||
|
|
||||||
export type ImageProps = ComponentPropsWithoutRef<typeof NextImage>;
|
export type ImageProps = ComponentPropsWithoutRef<typeof NextImage>;
|
||||||
|
|
||||||
const Image = ({ src, height, width, quality, placeholder, style, ...rest }: ImageProps) => {
|
const Image = ({ src, height, width, placeholder, className, ...rest }: ImageProps) => {
|
||||||
const constrainWidth = (width?: number | `${number}`) => {
|
const constrainWidth = (width?: number | `${number}`) => {
|
||||||
if (!width) return MAX_WIDTH;
|
if (!width) return MAX_WIDTH;
|
||||||
|
|
||||||
@@ -16,16 +19,11 @@ const Image = ({ src, height, width, quality, placeholder, style, ...rest }: Ima
|
|||||||
src,
|
src,
|
||||||
height,
|
height,
|
||||||
width: constrainWidth(width || (src as StaticImageData).width),
|
width: constrainWidth(width || (src as StaticImageData).width),
|
||||||
quality: quality || 75,
|
|
||||||
placeholder: placeholder || (typeof src === "string" ? "empty" : "blur"),
|
placeholder: placeholder || (typeof src === "string" ? "empty" : "blur"),
|
||||||
style: {
|
|
||||||
height: "auto",
|
|
||||||
...style,
|
|
||||||
},
|
|
||||||
...rest,
|
...rest,
|
||||||
};
|
};
|
||||||
|
|
||||||
return <NextImage {...imageProps} />;
|
return <NextImage className={clsx(styles.image, className)} {...imageProps} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Image;
|
export default Image;
|
||||||
|
@@ -3,7 +3,7 @@ export const siteName = "Jake Jarvis";
|
|||||||
export const siteLocale = "en-US";
|
export const siteLocale = "en-US";
|
||||||
export const timeZone = "America/New_York"; // https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
|
export const timeZone = "America/New_York"; // https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
|
||||||
export const onionDomain = "jarvis2i2vp4j4tbxjogsnqdemnte5xhzyi7hziiyzxwge3hzmh57zad.onion";
|
export const onionDomain = "jarvis2i2vp4j4tbxjogsnqdemnte5xhzyi7hziiyzxwge3hzmh57zad.onion";
|
||||||
export const shortDescription = "Front-End Web Developer in Boston; MA";
|
export const shortDescription = "Front-End Web Developer in Boston, MA";
|
||||||
export const longDescription =
|
export const longDescription =
|
||||||
"Hi there! I'm a frontend web developer based in Boston, Massachusetts specializing in the JAMstack, modern JavaScript frameworks, and progressive web apps.";
|
"Hi there! I'm a frontend web developer based in Boston, Massachusetts specializing in the JAMstack, modern JavaScript frameworks, and progressive web apps.";
|
||||||
export const license = "Creative Commons Attribution 4.0 International";
|
export const license = "Creative Commons Attribution 4.0 International";
|
||||||
|
@@ -2,6 +2,7 @@ import path from "path";
|
|||||||
import glob from "fast-glob";
|
import glob from "fast-glob";
|
||||||
import pMap from "p-map";
|
import pMap from "p-map";
|
||||||
import pMemoize from "p-memoize";
|
import pMemoize from "p-memoize";
|
||||||
|
import { decode } from "html-entities";
|
||||||
import { formatDate } from "./format-date";
|
import { formatDate } from "./format-date";
|
||||||
import { BASE_URL, POSTS_DIR } from "../config/constants";
|
import { BASE_URL, POSTS_DIR } from "../config/constants";
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ export const getFrontMatter = async (slug: string): Promise<FrontMatter> => {
|
|||||||
|
|
||||||
// allow *very* limited markdown to be used in post titles
|
// allow *very* limited markdown to be used in post titles
|
||||||
const parseTitle = async (title: string, allowedTags: string[] = []): Promise<string> => {
|
const parseTitle = async (title: string, allowedTags: string[] = []): Promise<string> => {
|
||||||
return String(
|
const newTitle = (
|
||||||
await unified()
|
await unified()
|
||||||
.use(remarkParse)
|
.use(remarkParse)
|
||||||
.use(remarkSmartypants, {
|
.use(remarkSmartypants, {
|
||||||
@@ -45,7 +46,10 @@ export const getFrontMatter = async (slug: string): Promise<FrontMatter> => {
|
|||||||
.use(rehypeSanitize, { tagNames: allowedTags })
|
.use(rehypeSanitize, { tagNames: allowedTags })
|
||||||
.use(rehypeStringify)
|
.use(rehypeStringify)
|
||||||
.process(title)
|
.process(title)
|
||||||
);
|
).toString();
|
||||||
|
|
||||||
|
// assume if we don't want any html titles then we don't want encoded html entities either
|
||||||
|
return allowedTags.length === 0 ? decode(newTitle) : newTitle;
|
||||||
};
|
};
|
||||||
|
|
||||||
// process title as both plain and stylized
|
// process title as both plain and stylized
|
||||||
@@ -57,8 +61,9 @@ export const getFrontMatter = async (slug: string): Promise<FrontMatter> => {
|
|||||||
// return both the parsed YAML front matter (with a few amendments) and the raw, unparsed markdown content
|
// return both the parsed YAML front matter (with a few amendments) and the raw, unparsed markdown content
|
||||||
return {
|
return {
|
||||||
...(frontmatter as Partial<FrontMatter>),
|
...(frontmatter as Partial<FrontMatter>),
|
||||||
// zero markdown title:
|
// plain title without html or markdown syntax:
|
||||||
title,
|
title,
|
||||||
|
// stylized title with limited html tags:
|
||||||
htmlTitle,
|
htmlTitle,
|
||||||
slug,
|
slug,
|
||||||
date: formatDate(frontmatter.date), // validate/normalize the date string provided from front matter
|
date: formatDate(frontmatter.date), // validate/normalize the date string provided from front matter
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
"fast-glob": "^3.3.3",
|
"fast-glob": "^3.3.3",
|
||||||
"feed": "^4.2.2",
|
"feed": "^4.2.2",
|
||||||
"geist": "^1.3.1",
|
"geist": "^1.3.1",
|
||||||
|
"html-entities": "^2.5.2",
|
||||||
"lucide-react": "0.481.0",
|
"lucide-react": "0.481.0",
|
||||||
"modern-normalize": "^3.0.1",
|
"modern-normalize": "^3.0.1",
|
||||||
"next": "15.3.0-canary.8",
|
"next": "15.3.0-canary.8",
|
||||||
|
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@@ -59,6 +59,9 @@ importers:
|
|||||||
geist:
|
geist:
|
||||||
specifier: ^1.3.1
|
specifier: ^1.3.1
|
||||||
version: 1.3.1(next@15.3.0-canary.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
|
version: 1.3.1(next@15.3.0-canary.8(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
|
||||||
|
html-entities:
|
||||||
|
specifier: ^2.5.2
|
||||||
|
version: 2.5.2
|
||||||
lucide-react:
|
lucide-react:
|
||||||
specifier: 0.481.0
|
specifier: 0.481.0
|
||||||
version: 0.481.0(react@19.0.0)
|
version: 0.481.0(react@19.0.0)
|
||||||
@@ -1944,6 +1947,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==}
|
resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==}
|
||||||
engines: {node: ^16.14.0 || >=18.0.0}
|
engines: {node: ^16.14.0 || >=18.0.0}
|
||||||
|
|
||||||
|
html-entities@2.5.2:
|
||||||
|
resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==}
|
||||||
|
|
||||||
html-escaper@2.0.2:
|
html-escaper@2.0.2:
|
||||||
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
|
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
|
||||||
|
|
||||||
@@ -5542,6 +5548,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
lru-cache: 10.4.3
|
lru-cache: 10.4.3
|
||||||
|
|
||||||
|
html-entities@2.5.2: {}
|
||||||
|
|
||||||
html-escaper@2.0.2: {}
|
html-escaper@2.0.2: {}
|
||||||
|
|
||||||
html-tags@3.3.1: {}
|
html-tags@3.3.1: {}
|
||||||
|
Reference in New Issue
Block a user