diff --git a/__tests__/lib/plain/custom-components.test.ts b/__tests__/lib/plain/custom-components.test.ts
new file mode 100644
index 000000000..34a5a5958
--- /dev/null
+++ b/__tests__/lib/plain/custom-components.test.ts
@@ -0,0 +1,33 @@
+import { hast, plain } from '../../../index';
+
+describe('plain compiler', () => {
+ it('should include the title of Accordion', () => {
+ const mdx = `
+
+ Body
+
+`;
+
+ expect(plain(hast(mdx))).toContain('Title Body');
+ });
+
+ it('should include the title of Card', () => {
+ const mdx = `
+
+ Body
+
+`;
+
+ expect(plain(hast(mdx))).toContain('Title Body');
+ });
+
+ it('should include the title of Tab', () => {
+ const mdx = `
+
+ Body
+
+`;
+
+ expect(plain(hast(mdx))).toContain('Title Body');
+ });
+});
diff --git a/lib/hast.ts b/lib/hast.ts
index 92c864166..9ec5ccec9 100644
--- a/lib/hast.ts
+++ b/lib/hast.ts
@@ -1,6 +1,6 @@
import astProcessor, { rehypePlugins, MdastOpts } from './ast-processor';
import remarkRehype from 'remark-rehype';
-import { injectComponents } from '../processor/transform';
+import { injectComponents, mdxToHast } from '../processor/transform';
import { MdastComponents } from '../types';
import mdast from './mdast';
@@ -10,7 +10,11 @@ const hast = (text: string, opts: MdastOpts = {}) => {
return memo;
}, {});
- const processor = astProcessor(opts).use(injectComponents({ components })).use(remarkRehype).use(rehypePlugins);
+ const processor = astProcessor(opts)
+ .use(injectComponents({ components }))
+ .use(mdxToHast)
+ .use(remarkRehype)
+ .use(rehypePlugins);
return processor.runSync(processor.parse(text));
};
diff --git a/lib/plain.ts b/lib/plain.ts
index 220814f93..9f775870b 100644
--- a/lib/plain.ts
+++ b/lib/plain.ts
@@ -21,32 +21,39 @@ function one(node: Nodes, opts: Options) {
if ('tagName' in node) {
if (STRIP_TAGS.includes(node.tagName)) return '';
- if (node.tagName === 'html-block') {
- if (!node.properties.html) return '';
- return all(hast(node.properties.html.toString()), opts);
- }
-
- if (node.tagName === 'rdme-callout') {
- const { icon, title } = node.properties;
-
- const children = node?.children?.slice(title ? 1 : 0);
- const body = children ? all({ type: 'root', children }, opts) : '';
-
- return [icon, ' ', title, title && body && ': ', body].filter(Boolean).join('');
- }
-
- if (node.tagName === 'readme-glossary-item') {
- return node.properties.term;
- }
-
- if (node.tagName === 'readme-variable') {
- const key = node.properties.variable.toString();
- const val = opts.variables[key];
- return val || `<<${key}>>`;
- }
-
- if (node.tagName === 'img') {
- return node.properties?.title || '';
+ switch (node.tagName) {
+ case 'html-block': {
+ if (!node.properties.html) return '';
+ return all(hast(node.properties.html.toString()), opts);
+ }
+ case 'rdme-callout': {
+ const { icon, title } = node.properties;
+
+ const children = node?.children?.slice(title ? 1 : 0);
+ const body = children ? all({ type: 'root', children }, opts) : '';
+
+ return [icon, ' ', title, title && body && ': ', body].filter(Boolean).join('');
+ }
+ case 'readme-glossary-item': {
+ return node.properties.term;
+ }
+ case 'readme-variable': {
+ const key = node.properties.variable.toString();
+ const val = opts.variables[key];
+ return val || `<<${key}>>`;
+ }
+ case 'img': {
+ return node.properties?.title || '';
+ }
+ case 'Accordion':
+ case 'Card':
+ case 'Tab': {
+ const title = node.properties?.title || '';
+ const children = node?.children;
+ const body = children ? all({ type: 'root', children }, opts) : '';
+
+ return [title, body].filter(Boolean).join(' ');
+ }
}
}
diff --git a/processor/transform/index.ts b/processor/transform/index.ts
index 7a9bc5898..a21491da0 100644
--- a/processor/transform/index.ts
+++ b/processor/transform/index.ts
@@ -4,24 +4,26 @@ import embedTransformer from './embeds';
import imageTransformer from './images';
import gemojiTransformer from './gemoji+';
+import compatabilityTransfomer from './compatability';
import divTransformer from './div';
import injectComponents from './inject-components';
+import mdxToHast from './mdx-to-hast';
+import mermaidTransformer from './mermaid';
import readmeComponentsTransformer from './readme-components';
import readmeToMdx from './readme-to-mdx';
-import variablesTransformer from './variables';
import tablesToJsx from './tables-to-jsx';
-import compatabilityTransfomer from './compatability';
-import mermaidTransformer from './mermaid';
+import variablesTransformer from './variables';
export {
compatabilityTransfomer,
divTransformer,
+ injectComponents,
+ mdxToHast,
+ mermaidTransformer,
readmeComponentsTransformer,
readmeToMdx,
- injectComponents,
- variablesTransformer,
tablesToJsx,
- mermaidTransformer,
+ variablesTransformer,
};
export const defaultTransforms = {
diff --git a/processor/transform/mdx-to-hast.ts b/processor/transform/mdx-to-hast.ts
new file mode 100644
index 000000000..f6a6c1544
--- /dev/null
+++ b/processor/transform/mdx-to-hast.ts
@@ -0,0 +1,27 @@
+import { visit } from 'unist-util-visit';
+import { MdxJsxFlowElement, MdxJsxTextElement } from 'mdast-util-mdx';
+import { Transform } from 'mdast-util-from-markdown';
+import { Parents } from 'mdast';
+import { getAttrs, isMDXElement } from '../utils';
+import * as Components from '../../components';
+
+const setData = (node: MdxJsxFlowElement | MdxJsxTextElement, index: number, parent: Parents) => {
+ if (!node.name) return;
+ if (!(node.name in Components)) return;
+
+ parent.children[index] = {
+ ...node,
+ data: {
+ hName: node.name,
+ hProperties: getAttrs(node),
+ },
+ };
+};
+
+const mdxToHast = (): Transform => tree => {
+ visit(tree, isMDXElement, setData);
+
+ return tree;
+};
+
+export default mdxToHast;