transform markdown through asset transformer

This commit is contained in:
MapleLeaf
2022-01-08 14:55:53 -06:00
parent 7379402e80
commit b6c5c41706
4 changed files with 48 additions and 17 deletions

View File

@@ -0,0 +1,24 @@
import grayMatter from "gray-matter"
import MarkdownIt from "markdown-it"
import prism from "markdown-it-prism"
import { readFile } from "node:fs/promises"
import type { AssetTransformer } from "./asset-builder.js"
const renderer = new MarkdownIt({
html: true,
linkify: true,
}).use(prism)
export const transformMarkdown: AssetTransformer = {
async transform(inputFile) {
if (!/\.md$/.test(inputFile)) return
const { data, content } = grayMatter(await readFile(inputFile, "utf8"))
const html = renderer.render(content)
return {
content: html,
type: "text/html",
}
},
}

View File

@@ -1,11 +1,12 @@
import clsx from "clsx" import clsx from "clsx"
import React from "react" import React from "react"
import { LocalFileAsset } from "../asset-builder/asset.js"
import { AppLink } from "../navigation/app-link" import { AppLink } from "../navigation/app-link"
import { guideLinks } from "../navigation/guide-links" import { guideLinks } from "../navigation/guide-links"
import { MainNavigation } from "../navigation/main-navigation" import { MainNavigation } from "../navigation/main-navigation"
import { docsProseClass, linkClass, maxWidthContainer } from "../ui/components" import { docsProseClass, linkClass, maxWidthContainer } from "../ui/components"
export default function GuidePage({ html }: { html: string }) { export function GuidePage({ url }: { url: string }) {
return ( return (
<> <>
<header className="bg-slate-700/30 shadow sticky top-0 backdrop-blur-sm transition z-10 flex"> <header className="bg-slate-700/30 shadow sticky top-0 backdrop-blur-sm transition z-10 flex">
@@ -24,10 +25,14 @@ export default function GuidePage({ html }: { html: string }) {
))} ))}
</ul> </ul>
</nav> </nav>
<LocalFileAsset from={new URL(`${url}.md`, import.meta.url)}>
{(asset) => (
<section <section
className={clsx(docsProseClass, "pb-8 flex-1 min-w-0")} className={clsx(docsProseClass, "pb-8 flex-1 min-w-0")}
dangerouslySetInnerHTML={{ __html: html }} dangerouslySetInnerHTML={{ __html: asset.content }}
/> />
)}
</LocalFileAsset>
</main> </main>
</> </>
) )

View File

@@ -1,13 +1,9 @@
import packageJson from "reacord/package.json" import packageJson from "reacord/package.json"
import React from "react" import React from "react"
import { renderMarkdownFile } from "../helpers/markdown" import { LocalFileAsset } from "../asset-builder/asset.js"
import { MainNavigation } from "../navigation/main-navigation" import { MainNavigation } from "../navigation/main-navigation"
import { maxWidthContainer } from "../ui/components" import { maxWidthContainer } from "../ui/components"
const landingExample = await renderMarkdownFile(
new URL("landing-example.md", import.meta.url).pathname,
)
export function Landing() { export function Landing() {
return ( return (
<div className="flex flex-col min-w-0 min-h-screen text-center"> <div className="flex flex-col min-w-0 min-h-screen text-center">
@@ -17,10 +13,14 @@ export function Landing() {
<div className="px-4 pb-8 flex flex-1"> <div className="px-4 pb-8 flex flex-1">
<main className="px-4 py-6 rounded-lg shadow bg-slate-800 space-y-5 m-auto w-full max-w-xl"> <main className="px-4 py-6 rounded-lg shadow bg-slate-800 space-y-5 m-auto w-full max-w-xl">
<h1 className="text-6xl font-light">reacord</h1> <h1 className="text-6xl font-light">reacord</h1>
<LocalFileAsset from={new URL("landing-example.md", import.meta.url)}>
{(asset) => (
<section <section
className="mx-auto text-sm sm:text-base" className="mx-auto text-sm sm:text-base"
dangerouslySetInnerHTML={{ __html: landingExample.html }} dangerouslySetInnerHTML={{ __html: asset.content }}
/> />
)}
</LocalFileAsset>
<p className="text-2xl font-light">{packageJson.description}</p> <p className="text-2xl font-light">{packageJson.description}</p>
<a <a
href="/guides/getting-started" href="/guides/getting-started"

View File

@@ -11,9 +11,10 @@ import ssrPrepass from "react-ssr-prepass"
import { AssetBuilderProvider } from "./asset-builder/asset-builder-context.js" import { AssetBuilderProvider } from "./asset-builder/asset-builder-context.js"
import { AssetBuilder } from "./asset-builder/asset-builder.js" import { AssetBuilder } from "./asset-builder/asset-builder.js"
import { transformEsbuild } from "./asset-builder/transform-esbuild.js" import { transformEsbuild } from "./asset-builder/transform-esbuild.js"
import { transformMarkdown } from "./asset-builder/transform-markdown.js"
import { transformPostCss } from "./asset-builder/transform-postcss.js" import { transformPostCss } from "./asset-builder/transform-postcss.js"
import { fromProjectRoot } from "./constants" import { fromProjectRoot } from "./constants"
import GuidePage from "./guides/guide-page" import { GuidePage } from "./guides/guide-page"
import { renderMarkdownFile } from "./helpers/markdown" import { renderMarkdownFile } from "./helpers/markdown"
import { Html } from "./html.js" import { Html } from "./html.js"
import { Landing } from "./landing/landing" import { Landing } from "./landing/landing"
@@ -24,6 +25,7 @@ const port = process.env.PORT || 3000
const assets = await AssetBuilder.create(fromProjectRoot(".asset-cache"), [ const assets = await AssetBuilder.create(fromProjectRoot(".asset-cache"), [
transformEsbuild, transformEsbuild,
transformPostCss, transformPostCss,
transformMarkdown,
]) ])
async function render(res: Response, element: React.ReactElement) { async function render(res: Response, element: React.ReactElement) {
@@ -43,14 +45,14 @@ const router = Router()
.use(assets.middleware()) .use(assets.middleware())
.get("/guides/*", async (req: Request<{ 0: string }>, res) => { .get("/guides/*", async (req: Request<{ 0: string }>, res) => {
const { html, data } = await renderMarkdownFile( const { data } = await renderMarkdownFile(
new URL(`guides/${req.params[0]}.md`, import.meta.url).pathname, new URL(`guides/${req.params[0]}.md`, import.meta.url).pathname,
) )
await render( await render(
res, res,
<AssetBuilderProvider value={assets}> <AssetBuilderProvider value={assets}>
<Html title={`${data.title} | Reacord`} description={data.description}> <Html title={`${data.title} | Reacord`} description={data.description}>
<GuidePage html={html} /> <GuidePage url={req.params[0]} />
</Html> </Html>
</AssetBuilderProvider>, </AssetBuilderProvider>,
) )