Skip to content

Commit

Permalink
feat: add usemdxcomponents option (#848)
Browse files Browse the repository at this point in the history
Accepts a `components` opt that it passes into a custom `useMdxComponents` hook.
  • Loading branch information
kellyjosephprice authored Apr 3, 2024
1 parent b40b8fd commit 48351a2
Show file tree
Hide file tree
Showing 5 changed files with 2,852 additions and 1,544 deletions.
2 changes: 1 addition & 1 deletion __tests__/.eslintrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"extends": ["@readme/eslint-config/testing", "@readme/eslint-config/testing/jest"],
"extends": ["@readme/eslint-config/testing/jest.js", "@readme/eslint-config/testing/vitest.js"],
"rules": {
"testing-library/no-container": "off",
"testing-library/no-node-access": "off"
Expand Down
34 changes: 34 additions & 0 deletions __tests__/custom-components/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { compile, run } from '../../index';
import { renderToString } from 'react-dom/server';
import React from 'react';

describe('Custom Components', () => {
const Example = () => <div>It works!</div>;
const Composite = () => (
<>
<div>Does it work?</div>
<Example />
</>
);

it('renders custom components', () => {
const doc = `
<Example />
`;
const Page = run(compile(doc), { components: { Example } });
const output = renderToString(<Page />);

expect(output).toBe('<div data-reactroot="">It works!</div>');
});

it('renders custom components recursively', () => {
const doc = `
<Composite />
`;

const Page = run(compile(doc), { components: { Example, Composite } });
const output = renderToString(<Page />);

expect(output).toBe('<div>Does it work?</div><div>It works!</div>');
});
});
27 changes: 17 additions & 10 deletions index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import debug from 'debug';
import { remark } from 'remark';
import remarkMdx from 'remark-mdx';

import { createProcessor, compileSync, runSync } from '@mdx-js/mdx';
import { createProcessor, compileSync, runSync, RunOptions } from '@mdx-js/mdx';
import * as runtime from 'react/jsx-runtime';

import Variable from '@readme/variable';
Expand All @@ -14,10 +14,13 @@ import { options } from './options';
require('./styles/main.scss');

import calloutTransformer from './processor/transform/callouts';
import react from 'react';

const unimplemented = debug('mdx:unimplemented');

const { GlossaryItem } = Components;
type RunOpts = Omit<RunOptions, 'Fragment'> & {
components?: Record<string, React.Component>;
};

export { Components };

Expand All @@ -28,14 +31,16 @@ export const utils = {

BaseUrlContext,
getHref,
GlossaryContext: GlossaryItem.GlossaryContext,
GlossaryContext: Components.GlossaryItem.GlossaryContext,
VariablesContext: Variable.VariablesContext,
calloutIcons: {},
};

const useMDXComponents = () => ({
...Components,
});
const makeUseMDXComponents = (more: RunOpts['components']) => {
const components = { ...Components, ...more };

return () => components;
};

export const reactProcessor = (opts = {}) => {
return createProcessor({ remarkPlugins: [calloutTransformer], ...opts });
Expand All @@ -45,22 +50,24 @@ export const compile = (text: string, opts = {}) => {
return String(
compileSync(text, {
outputFormat: 'function-body',
providerImportSource: '@mdx-js/react',
providerImportSource: '#',
remarkPlugins: [calloutTransformer],
...opts,
})
}),
);
};

export const run = (code: string, opts = {}) => {
export const run = (code: string, _opts: RunOpts = {}) => {
// @ts-ignore
const Fragment = runtime.Fragment;

const { components, ...opts } = _opts;

const file = runSync(code, {
...runtime,
Fragment,
baseUrl: '',
useMDXComponents,
useMDXComponents: makeUseMDXComponents(components),
...opts,
});

Expand Down
Loading

0 comments on commit 48351a2

Please sign in to comment.