diff --git a/astro.config.mjs b/astro.config.mjs index 88c5a60..d655cc8 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -7,6 +7,7 @@ import remarkEmoji from "remark-emoji"; import tailwind from "@astrojs/tailwind"; import icon from "astro-icon"; +import { remarkReadingTime } from "./src/remark/remark-reading-time"; // https://astro.build/config export default defineConfig({ @@ -17,7 +18,7 @@ export default defineConfig({ site: "https://daichendt.one", integrations: [ mdx({ - remarkPlugins: [remarkEmoji], + remarkPlugins: [remarkEmoji, remarkReadingTime], }), sitemap(), tailwind(), diff --git a/package.json b/package.json index 06aecfe..23fcbb2 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,8 @@ "@iconify-json/simple-icons": "^1.2.14", "astro": "^5.0.3", "astro-icon": "^1.1.4", + "mdast-util-to-string": "^4.0.0", + "reading-time": "^1.5.0", "sharp": "^0.33.5", "tailwindcss": "^3.4.16" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2d8f018..8ef3329 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,12 @@ importers: astro-icon: specifier: ^1.1.4 version: 1.1.4 + mdast-util-to-string: + specifier: ^4.0.0 + version: 4.0.0 + reading-time: + specifier: ^1.5.0 + version: 1.5.0 sharp: specifier: ^0.33.5 version: 0.33.5 @@ -1874,6 +1880,9 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + reading-time@1.5.0: + resolution: {integrity: sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==} + recma-build-jsx@1.0.0: resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==} @@ -4491,6 +4500,8 @@ snapshots: dependencies: picomatch: 2.3.1 + reading-time@1.5.0: {} + recma-build-jsx@1.0.0: dependencies: '@types/estree': 1.0.6 diff --git a/src/layouts/BlogPost.astro b/src/layouts/BlogPost.astro index 95b45eb..80ea1e6 100644 --- a/src/layouts/BlogPost.astro +++ b/src/layouts/BlogPost.astro @@ -6,7 +6,8 @@ import { Picture } from "astro:assets"; type Props = CollectionEntry<"blog">["data"]; -const { title, description, pubDate, updatedDate, heroImage } = Astro.props; +const { title, description, pubDate, updatedDate, heroImage, readingTime } = + Astro.props; --- @@ -32,6 +33,7 @@ const { title, description, pubDate, updatedDate, heroImage } = Astro.props; }

{title}

+

{readingTime}


@@ -55,9 +57,8 @@ const { title, description, pubDate, updatedDate, heroImage } = Astro.props; box-shadow: var(--box-shadow); } .prose { - width: 768px; - max-width: calc(100% - 2em); color: rgb(var(--gray-dark)); + text-wrap: pretty; } .title { margin-bottom: 1em; diff --git a/src/pages/blog/[...slug].astro b/src/pages/blog/[...slug].astro index 17ee772..1addaef 100644 --- a/src/pages/blog/[...slug].astro +++ b/src/pages/blog/[...slug].astro @@ -7,6 +7,7 @@ import Ul from "../../components/Ul.astro"; import Ol from "../../components/Ol.astro"; import Li from "../../components/Li.astro"; import Link from "../../components/Link.astro"; +import { getEntry } from "astro:content"; export async function getStaticPaths() { const posts = await getCollection("blog"); @@ -18,7 +19,8 @@ export async function getStaticPaths() { type Props = CollectionEntry<"blog">; const post = Astro.props; -const { Content } = await render(post); +const { Content, remarkPluginFrontmatter } = await render(post); +const readingTime = remarkPluginFrontmatter.minutesRead; const components = { ul: Ul, @@ -29,6 +31,6 @@ const components = { }; --- - + diff --git a/src/remark/remark-reading-time.ts b/src/remark/remark-reading-time.ts new file mode 100644 index 0000000..68a25fe --- /dev/null +++ b/src/remark/remark-reading-time.ts @@ -0,0 +1,12 @@ +import getReadingTime from "reading-time"; +import { toString } from "mdast-util-to-string"; + +export function remarkReadingTime() { + return function (tree: any, { data }: { data: any }) { + const textOnPage = toString(tree); + const readingTime = getReadingTime(textOnPage); + // readingTime.text will give us minutes read as a friendly string, + // i.e. "3 min read" + data.astro.frontmatter.minutesRead = readingTime.text; + }; +} diff --git a/src/styles/global.css b/src/styles/global.css index abbba76..6f14da9 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -93,6 +93,9 @@ ol:not(ul ol, ol ol) { margin-bottom: 2em; } +.footnotes { + margin-left: 2rem; +} .footnotes ol { list-style: outside; }