transform markdown through asset transformer
This commit is contained in:
24
packages/docs/src/asset-builder/transform-markdown.ts
Normal file
24
packages/docs/src/asset-builder/transform-markdown.ts
Normal 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",
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
import clsx from "clsx"
|
||||
import React from "react"
|
||||
import { LocalFileAsset } from "../asset-builder/asset.js"
|
||||
import { AppLink } from "../navigation/app-link"
|
||||
import { guideLinks } from "../navigation/guide-links"
|
||||
import { MainNavigation } from "../navigation/main-navigation"
|
||||
import { docsProseClass, linkClass, maxWidthContainer } from "../ui/components"
|
||||
|
||||
export default function GuidePage({ html }: { html: string }) {
|
||||
export function GuidePage({ url }: { url: string }) {
|
||||
return (
|
||||
<>
|
||||
<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>
|
||||
</nav>
|
||||
<section
|
||||
className={clsx(docsProseClass, "pb-8 flex-1 min-w-0")}
|
||||
dangerouslySetInnerHTML={{ __html: html }}
|
||||
/>
|
||||
<LocalFileAsset from={new URL(`${url}.md`, import.meta.url)}>
|
||||
{(asset) => (
|
||||
<section
|
||||
className={clsx(docsProseClass, "pb-8 flex-1 min-w-0")}
|
||||
dangerouslySetInnerHTML={{ __html: asset.content }}
|
||||
/>
|
||||
)}
|
||||
</LocalFileAsset>
|
||||
</main>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import packageJson from "reacord/package.json"
|
||||
import React from "react"
|
||||
import { renderMarkdownFile } from "../helpers/markdown"
|
||||
import { LocalFileAsset } from "../asset-builder/asset.js"
|
||||
import { MainNavigation } from "../navigation/main-navigation"
|
||||
import { maxWidthContainer } from "../ui/components"
|
||||
|
||||
const landingExample = await renderMarkdownFile(
|
||||
new URL("landing-example.md", import.meta.url).pathname,
|
||||
)
|
||||
|
||||
export function Landing() {
|
||||
return (
|
||||
<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">
|
||||
<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>
|
||||
<section
|
||||
className="mx-auto text-sm sm:text-base"
|
||||
dangerouslySetInnerHTML={{ __html: landingExample.html }}
|
||||
/>
|
||||
<LocalFileAsset from={new URL("landing-example.md", import.meta.url)}>
|
||||
{(asset) => (
|
||||
<section
|
||||
className="mx-auto text-sm sm:text-base"
|
||||
dangerouslySetInnerHTML={{ __html: asset.content }}
|
||||
/>
|
||||
)}
|
||||
</LocalFileAsset>
|
||||
<p className="text-2xl font-light">{packageJson.description}</p>
|
||||
<a
|
||||
href="/guides/getting-started"
|
||||
|
||||
@@ -11,9 +11,10 @@ import ssrPrepass from "react-ssr-prepass"
|
||||
import { AssetBuilderProvider } from "./asset-builder/asset-builder-context.js"
|
||||
import { AssetBuilder } from "./asset-builder/asset-builder.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 { fromProjectRoot } from "./constants"
|
||||
import GuidePage from "./guides/guide-page"
|
||||
import { GuidePage } from "./guides/guide-page"
|
||||
import { renderMarkdownFile } from "./helpers/markdown"
|
||||
import { Html } from "./html.js"
|
||||
import { Landing } from "./landing/landing"
|
||||
@@ -24,6 +25,7 @@ const port = process.env.PORT || 3000
|
||||
const assets = await AssetBuilder.create(fromProjectRoot(".asset-cache"), [
|
||||
transformEsbuild,
|
||||
transformPostCss,
|
||||
transformMarkdown,
|
||||
])
|
||||
|
||||
async function render(res: Response, element: React.ReactElement) {
|
||||
@@ -43,14 +45,14 @@ const router = Router()
|
||||
.use(assets.middleware())
|
||||
|
||||
.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,
|
||||
)
|
||||
await render(
|
||||
res,
|
||||
<AssetBuilderProvider value={assets}>
|
||||
<Html title={`${data.title} | Reacord`} description={data.description}>
|
||||
<GuidePage html={html} />
|
||||
<GuidePage url={req.params[0]} />
|
||||
</Html>
|
||||
</AssetBuilderProvider>,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user