/
mdx.ts
55 lines (47 loc) · 1.81 KB
/
mdx.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import { errorToString } from '@contentlayer/utils'
import { OT, pipe, T, Tagged } from '@contentlayer/utils/effect'
import * as mdxBundler from 'mdx-bundler'
import type { BundleMDXOptions } from 'mdx-bundler/dist/types'
import * as path from 'path'
import type { MDXOptions } from './plugin.js'
export const bundleMDX = ({
mdxString,
options,
contentDirPath,
}: {
mdxString: string
options?: MDXOptions
contentDirPath: string
}): T.Effect<OT.HasTracer, UnexpectedMDXError, string> =>
pipe(
T.gen(function* ($) {
// TODO should be fixed in `mdx-bundler`
if (mdxString.length === 0) {
return ''
}
const { rehypePlugins, remarkPlugins, cwd: cwd_, ...restOptions } = options ?? {}
const getCwdFromContentDirPath = () =>
// TODO don't use `process.cwd()` but instead `HasCwd`
path.isAbsolute(contentDirPath) ? contentDirPath : path.join(process.cwd(), contentDirPath)
const cwd = cwd_ ?? getCwdFromContentDirPath()
const mdxOptions: BundleMDXOptions<any> = {
mdxOptions: (opts) => {
opts.rehypePlugins = [...(opts.rehypePlugins ?? []), ...(rehypePlugins ?? [])]
opts.remarkPlugins = [...(opts.remarkPlugins ?? []), ...(remarkPlugins ?? [])]
return opts
},
cwd,
...restOptions,
}
const res = yield* $(T.tryPromise(() => mdxBundler.bundleMDX({ source: mdxString, ...mdxOptions })))
if (res.errors.length > 0) {
return yield* $(T.fail(res.errors))
}
return res.code
}),
T.mapError((error) => new UnexpectedMDXError({ error })),
OT.withSpan('@contentlayer/core/markdown:bundleMDX'),
)
export class UnexpectedMDXError extends Tagged('UnexpectedMDXError')<{ readonly error: unknown }> {
toString = () => `UnexpectedMDXError: ${errorToString(this.error)}`
}