Skip to content

Commit

Permalink
feat: Migrate from mdx-bundler to react-markdown (#141)
Browse files Browse the repository at this point in the history
* Backport RenderMarkdown.tsx

* More code transferred

* Add broken pre component

* Fix CodeBlock

* Move Highlight component
  • Loading branch information
lachlancollins authored Jan 19, 2024
1 parent 15f2363 commit a67d702
Show file tree
Hide file tree
Showing 21 changed files with 657 additions and 637 deletions.
50 changes: 24 additions & 26 deletions app/components/CodeBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
useState,
type FC,
type HTMLAttributes,
type ReactElement,
} from 'react'
import { useState, type ReactNode } from 'react'
import invariant from 'tiny-invariant'
import type { Language } from 'prism-react-renderer'
import { Highlight, Prism } from 'prism-react-renderer'
Expand All @@ -29,14 +24,20 @@ function isLanguageSupported(lang: string): lang is Language {
return lang in Prism.languages
}

export const CodeBlock: FC<HTMLAttributes<HTMLPreElement>> = ({ children }) => {
type Props = {
children: ReactNode
}

export const CodeBlock = ({ children }: Props) => {
invariant(!!children, 'children is required')
const [copied, setCopied] = useState(false)
const child = children as ReactElement
const className = child.props?.className || ''
const child = Array.isArray(children) ? children[0] : children
const className = child.props.className || ''
const userLang = getLanguageFromClassName(className)
const lang = isLanguageSupported(userLang) ? userLang : 'bash'
const code = child.props.children || ''
const code = Array.isArray(child.props.children)
? child.props.children[0]
: child.props.children
return (
<div className="w-full max-w-full relative">
<button
Expand All @@ -54,19 +55,16 @@ export const CodeBlock: FC<HTMLAttributes<HTMLPreElement>> = ({ children }) => {
<FaCopy className="text-gray-500 group-hover:text-gray-100 dark:group-hover:text-gray-200 transition duration-200" />
)}
</button>
<Highlight code={code.trim()} language={lang}>
{({ className, tokens, getLineProps, getTokenProps }) => (
<div className="relative not-prose">
<div
className="absolute bg-white text-sm z-10 border border-gray-300 px-2 rounded-md -top-3 right-2
<div className="relative not-prose">
<div
className="absolute bg-white text-sm z-10 border border-gray-300 px-2 rounded-md -top-3 right-2
dark:bg-gray-600 dark:border-0"
>
{lang}
</div>
<div
className="rounded-md font-normal w-full border border-gray-200
dark:border-0"
>
>
{lang}
</div>
<div className="rounded-md font-normal w-full border border-gray-200 dark:border-0">
<Highlight code={code.trim()} language={lang}>
{({ className, tokens, getLineProps, getTokenProps }) => (
<pre className={`overflow-scroll ${className}`} style={{}}>
<code className={className} style={{}}>
{tokens.map((line, i) => (
Expand All @@ -82,10 +80,10 @@ export const CodeBlock: FC<HTMLAttributes<HTMLPreElement>> = ({ children }) => {
))}
</code>
</pre>
</div>
</div>
)}
</Highlight>
)}
</Highlight>
</div>
</div>
</div>
)
}
8 changes: 4 additions & 4 deletions app/components/Doc.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { FaEdit } from 'react-icons/fa'
import { DocTitle } from '~/components/DocTitle'
import { Mdx } from '~/components/Mdx'
import { RenderMarkdown } from '~/components/RenderMarkdown'

export function Doc({
title,
code,
content,
repo,
branch,
filePath,
}: {
title: string
code: string
content: string
repo: string
branch: string
filePath: string
Expand All @@ -22,7 +22,7 @@ export function Doc({
<div className="h-px bg-gray-500 opacity-20" />
<div className="h-4" />
<div className="prose prose-gray prose-md dark:prose-invert max-w-none">
<Mdx code={code} />
<RenderMarkdown>{content}</RenderMarkdown>
</div>
<div className="h-12" />
<div className="w-full h-px bg-gray-500 opacity-30" />
Expand Down
39 changes: 24 additions & 15 deletions app/components/Mdx.tsx → app/components/RenderMarkdown.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import * as React from 'react'
import { getMDXComponent } from 'mdx-bundler/client'
import { CodeBlock } from '~/components/CodeBlock'
import { MarkdownLink } from '~/components/MarkdownLink'
import type { MDXComponents } from 'mdx/types'
import type { FC, HTMLProps } from 'react'
import ReactMarkdown from 'react-markdown'
import rehypeSlug from 'rehype-slug'
import remarkGfm from 'remark-gfm'
import rehypeRaw from 'rehype-raw'

const CustomHeading = ({
Comp,
id,
...props
}: React.HTMLProps<HTMLHeadingElement> & {
}: HTMLProps<HTMLHeadingElement> & {
Comp: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
}) => {
if (id) {
Expand All @@ -23,7 +25,7 @@ const CustomHeading = ({

const makeHeading =
(type: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6') =>
(props: React.HTMLProps<HTMLHeadingElement>) =>
(props: HTMLProps<HTMLHeadingElement>) =>
(
<CustomHeading
Comp={type}
Expand All @@ -32,7 +34,7 @@ const makeHeading =
/>
)

const markdownComponents = {
const defaultComponents: Record<string, FC> = {
a: MarkdownLink,
pre: CodeBlock,
h1: makeHeading('h1'),
Expand All @@ -53,14 +55,21 @@ const markdownComponents = {
},
}

export function Mdx({
code,
components,
}: {
code: string
components?: MDXComponents
}) {
const Doc = React.useMemo(() => getMDXComponent(code), [code])
type Props = {
children: string
components?: Record<string, FC>
}

export const RenderMarkdown = (props: Props) => {
const { components, children } = props

return <Doc components={{ ...markdownComponents, ...components }} />
return (
<ReactMarkdown
plugins={[remarkGfm]}
rehypePlugins={[rehypeSlug, rehypeRaw]}
components={{ ...defaultComponents, ...components }}
>
{children}
</ReactMarkdown>
)
}
14 changes: 4 additions & 10 deletions app/routes/blog.$.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import { useLoaderData } from '@remix-run/react'
import type { LoaderFunctionArgs, MetaFunction } from '@remix-run/node'
import { json } from '@remix-run/node'
import {
extractFrontMatter,
fetchRepoFile,
markdownToMdx,
} from '~/utils/documents.server'
import { extractFrontMatter, fetchRepoFile } from '~/utils/documents.server'
import { DefaultErrorBoundary } from '~/components/DefaultErrorBoundary'
import removeMarkdown from 'remove-markdown'
import { seo } from '~/utils/seo'
Expand All @@ -31,13 +27,11 @@ export const loader = async (context: LoaderFunctionArgs) => {
const frontMatter = extractFrontMatter(file)
const description = removeMarkdown(frontMatter.excerpt ?? '')

const mdx = await markdownToMdx(frontMatter.content)

return json({
title: frontMatter.data.title,
description,
published: frontMatter.data.published,
code: mdx.code,
content: frontMatter.content,
filePath,
})
}
Expand All @@ -52,12 +46,12 @@ export const meta: MetaFunction = ({ data }) => {
export const ErrorBoundary = DefaultErrorBoundary

export default function RouteReactTableDocs() {
const { title, code, filePath } = useLoaderData<typeof loader>()
const { title, content, filePath } = useLoaderData<typeof loader>()

return (
<Doc
title={title}
code={code}
content={content}
repo={'tanstack/tanstack.com'}
branch={'main'}
filePath={filePath}
Expand Down
24 changes: 10 additions & 14 deletions app/routes/blog._index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import * as React from 'react'
import { useLoaderData, Link } from '@remix-run/react'
import { json } from '@remix-run/node'
import {
extractFrontMatter,
fetchRepoFile,
markdownToMdx,
} from '~/utils/documents.server'
import { extractFrontMatter, fetchRepoFile } from '~/utils/documents.server'
import { getPostList } from '~/utils/blog'
import { DocTitle } from '~/components/DocTitle'
import { Mdx } from '~/components/Mdx'
import { RenderMarkdown } from '~/components/RenderMarkdown'
import { format } from 'date-fns'
import { DefaultErrorBoundary } from '~/components/DefaultErrorBoundary'
import { Footer } from '~/components/Footer'
Expand All @@ -33,14 +29,12 @@ export const loader = async () => {

const frontMatter = extractFrontMatter(file)

const mdx = await markdownToMdx(frontMatter.excerpt ?? '')

return [
info.id,
{
title: frontMatter.data.title,
published: frontMatter.data.published,
exerptCode: mdx.code,
excerpt: frontMatter.excerpt,
},
]
})
Expand All @@ -54,7 +48,7 @@ export const ErrorBoundary = DefaultErrorBoundary
export default function RouteReactTableDocs() {
const frontMatters = useLoaderData<typeof loader>() as [
string,
{ title: string; published: string; exerptCode: string }
{ title: string; published: string; excerpt: string }
][]

return (
Expand All @@ -67,9 +61,10 @@ export default function RouteReactTableDocs() {
<div className="h-4" />
</div>
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-4">
{frontMatters.map(([id, { title, published, exerptCode }]) => {
{frontMatters.map(([id, { title, published, excerpt }]) => {
return (
<Link
key={id}
to={`${id}`}
className={`flex flex-col gap-4 justify-between
border-2 border-transparent rounded-lg p-4 md:p-8
Expand All @@ -86,12 +81,13 @@ export default function RouteReactTableDocs() {
</div>
) : null}
<div className={`text-sm mt-2 text-black dark:text-white`}>
<Mdx
code={exerptCode}
<RenderMarkdown
components={{
a: (props) => <span {...props} />,
}}
/>
>
{excerpt}
</RenderMarkdown>
</div>
</div>
<div>
Expand Down
4 changes: 2 additions & 2 deletions app/routes/form.$version.docs.$.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ export const meta: MetaFunction<typeof loader> = ({ data }) => {
export const ErrorBoundary = DefaultErrorBoundary

export default function RouteDocs() {
const { title, code, filePath } = useLoaderData<typeof loader>()
const { title, content, filePath } = useLoaderData<typeof loader>()
const { version } = useParams()
const branch = getBranch(version)
return (
<Doc
title={title}
code={code}
content={content}
repo={repo}
branch={branch}
filePath={filePath}
Expand Down
14 changes: 4 additions & 10 deletions app/routes/query.$version.docs.$framework.$.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import type { LoaderFunctionArgs, MetaFunction } from '@remix-run/node'
import { json, redirect } from '@remix-run/node'
import {
extractFrontMatter,
fetchRepoFile,
markdownToMdx,
} from '~/utils/documents.server'
import { extractFrontMatter, fetchRepoFile } from '~/utils/documents.server'
import { repo, getBranch } from '~/routes/query'
import { DefaultErrorBoundary } from '~/components/DefaultErrorBoundary'
import { seo } from '~/utils/seo'
Expand Down Expand Up @@ -58,14 +54,12 @@ export const loader = async (context: LoaderFunctionArgs) => {
const frontMatter = extractFrontMatter(file)
const description = removeMarkdown(frontMatter.excerpt ?? '')

const mdx = await markdownToMdx(frontMatter.content)

return json(
{
title: frontMatter.data?.title,
description,
filePath,
code: mdx.code,
content: frontMatter.content,
},
{
headers: {
Expand All @@ -85,14 +79,14 @@ export const meta: MetaFunction = ({ data }) => {
export const ErrorBoundary = DefaultErrorBoundary

export default function RouteDocs() {
const { title, code, filePath } = useLoaderData<typeof loader>()
const { title, content, filePath } = useLoaderData<typeof loader>()
const { version } = useParams()
const branch = getBranch(version)

return (
<Doc
title={title}
code={code}
content={content}
repo={repo}
branch={branch}
filePath={filePath}
Expand Down
4 changes: 2 additions & 2 deletions app/routes/ranger.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { LoaderFunction, MetaFunction } from '@remix-run/node'
import type { LoaderFunctionArgs, MetaFunction } from '@remix-run/node'
import { redirect } from '@remix-run/node'
import { Outlet } from '@remix-run/react'
import { Scarf } from '~/components/Scarf'
Expand All @@ -12,7 +12,7 @@ export const meta: MetaFunction = () => {
})
}

export const loader: LoaderFunction = async (context) => {
export const loader = async (context: LoaderFunctionArgs) => {
if (!context.request.url.includes('/ranger/v')) {
return redirect(`${new URL(context.request.url).origin}/ranger/v1`)
}
Expand Down
Loading

1 comment on commit a67d702

@vercel
Copy link

@vercel vercel bot commented on a67d702 Jan 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.