diff --git a/__tests__/lib/exports/index.test.ts b/__tests__/lib/exports/index.test.ts
index df73fb068..f56d24361 100644
--- a/__tests__/lib/exports/index.test.ts
+++ b/__tests__/lib/exports/index.test.ts
@@ -14,6 +14,6 @@ describe('export tags', () => {
});
it('returns different types of export names', () => {
- expect(exports(weirdExportsMdx)).toStrictEqual(['Foo', 'bar', 'doSomethingFunction', 'YELLING']);
+ expect(exports(weirdExportsMdx)).toStrictEqual(['Foo', 'bar', 'doSomethingFunction', 'YELLING', 'SingleNewlinesAreAnnoying', 'x', 'MyClass']);
});
});
\ No newline at end of file
diff --git a/__tests__/lib/exports/input/weirdExports.mdx b/__tests__/lib/exports/input/weirdExports.mdx
index 3953dd587..8656cd25e 100644
--- a/__tests__/lib/exports/input/weirdExports.mdx
+++ b/__tests__/lib/exports/input/weirdExports.mdx
@@ -7,13 +7,16 @@ export function Foo() {
export const bar = () => {
return ;
}
-
export function doSomethingFunction(input) {
return input.trim();
}
export const
YELLING = () => {}
+export const SingleNewlinesAreAnnoying = () => "hey";
+export let x = 2;
+export class MyClass {
+}
## Hey there
\ No newline at end of file
diff --git a/lib/exports.ts b/lib/exports.ts
index ff072028b..ec9c1bc9d 100644
--- a/lib/exports.ts
+++ b/lib/exports.ts
@@ -3,19 +3,75 @@ import mdast from './mdast';
import { isMDXEsm } from '../processor/utils';
import { MdxjsEsm } from 'mdast-util-mdx';
-const EXPORT_NAME_REGEX = /export\s+(?:const|let|var|function)\s+(\w+)/;
+/* Example mdast structures to find first export name in a mdxjsEsm node:
+There are three types of export declarations that we need to consider:
+1. VARIABLE DECLARATION
+ "type": "mdxjsEsm",
+ "value": "export const Foo = () =>
Hello world
\nexport const Bar = () => hello darkness my old friend
",
+ "data": {
+ "estree": {
+ "type": "Program",
+ "body": [
+ {
+ "type": "ExportNamedDeclaration",
+ "declaration": {
+ "type": "VariableDeclaration",
+ "declarations": [
+ {
+ "type": "VariableDeclarator",
+ "id": {
+ "type": "Identifier",
+ "name": "Foo" // --------> This is the export name
+ },
+ ...
+
+2/3. FUNCTION DECLARATION & CLASS DECLARATION
+ "estree": {
+ "type": "Program",
+ "body": [
+ {
+ "type": "ExportNamedDeclaration",
+ "declaration": {
+ "type": "ClassDeclaration" | "FunctionDeclaration",
+ "id": {
+ "type": "Identifier",
+ "name": "Foo" // --------> This is the export name
+ },
+*/
const exports = (doc: string) => {
const set = new Set();
visit(mdast(doc), isMDXEsm, (node: MdxjsEsm) => {
- if (node.value?.match(EXPORT_NAME_REGEX)) {
- const [, name] = node.value.match(EXPORT_NAME_REGEX);
- set.add(name);
+ // Once inside an mdxjsEsm node, we need to check for one or more declared exports within data.estree.body
+ // This is because single newlines \n are not considered as a new block, so there may be more than one export statement in a single mdxjsEsm node
+ const body = node.data?.estree.body;
+ if (!body) return;
+
+ for (const child of body) {
+ if (child.type === 'ExportNamedDeclaration') {
+ // There are three types of ExportNamedDeclaration that we need to consider: VariableDeclaration, FunctionDeclaration, ClassDeclaration
+ const declaration = child.declaration;
+ // FunctionDeclaration and ClassDeclaration have the same structure
+ if (declaration.type !== 'VariableDeclaration') {
+ // Note: declaration.id.type is always 'Identifier' for FunctionDeclarations and ClassDeclarations
+ set.add(declaration.id.name);
+ }
+ else {
+ const declarations = declaration.declarations;
+ for (const declaration of declarations) {
+ const id = declaration.id;
+ if (id.type === 'Identifier') {
+ set.add(id.name);
+ }
+ }
+ }
+ }
}
+
});
return Array.from(set);
};
-export default exports;
+export default exports;
\ No newline at end of file