diff --git a/__tests__/lib/exports/index.test.ts b/__tests__/lib/exports/index.test.ts
new file mode 100644
index 000000000..df73fb068
--- /dev/null
+++ b/__tests__/lib/exports/index.test.ts
@@ -0,0 +1,19 @@
+import singleExportMdx from './input/singleExport.mdx?raw';
+import multipleExportsMdx from './input/multipleExports.mdx?raw';
+import weirdExportsMdx from './input/weirdExports.mdx?raw';
+import { exports } from '../../../lib';
+
+describe('export tags', () => {
+ it('returns a single export name', () => {
+
+ expect(exports(singleExportMdx)).toStrictEqual(['Foo']);
+ });
+ it('returns multiple export names', () => {
+
+ expect(exports(multipleExportsMdx)).toStrictEqual(['Foo', 'Bar']);
+ });
+ it('returns different types of export names', () => {
+
+ expect(exports(weirdExportsMdx)).toStrictEqual(['Foo', 'bar', 'doSomethingFunction', 'YELLING']);
+ });
+});
\ No newline at end of file
diff --git a/__tests__/lib/exports/input/multipleExports.mdx b/__tests__/lib/exports/input/multipleExports.mdx
new file mode 100644
index 000000000..42ecc9b8d
--- /dev/null
+++ b/__tests__/lib/exports/input/multipleExports.mdx
@@ -0,0 +1,12 @@
+import React from 'react';
+
+export const Foo = () => {
+ return
Hello World
;
+}
+
+export const Bar = () => {
+ return ;
+}
+
+## Hey there
+
\ No newline at end of file
diff --git a/__tests__/lib/exports/input/singleExport.mdx b/__tests__/lib/exports/input/singleExport.mdx
new file mode 100644
index 000000000..e75889939
--- /dev/null
+++ b/__tests__/lib/exports/input/singleExport.mdx
@@ -0,0 +1,8 @@
+import React from 'react';
+
+export const Foo = () => {
+ return Hello World
;
+}
+
+## Hey there
+
\ No newline at end of file
diff --git a/__tests__/lib/exports/input/weirdExports.mdx b/__tests__/lib/exports/input/weirdExports.mdx
new file mode 100644
index 000000000..3953dd587
--- /dev/null
+++ b/__tests__/lib/exports/input/weirdExports.mdx
@@ -0,0 +1,19 @@
+import React from 'react';
+
+export function Foo() {
+ return Hello World
;
+}
+
+export const bar = () => {
+ return ;
+}
+
+export function doSomethingFunction(input) {
+ return input.trim();
+}
+
+export const
+YELLING = () => {}
+
+## Hey there
+
\ No newline at end of file
diff --git a/__tests__/lib/hast.test.ts b/__tests__/lib/hast.test.ts
index 3cf95bd71..1cade7566 100644
--- a/__tests__/lib/hast.test.ts
+++ b/__tests__/lib/hast.test.ts
@@ -1,4 +1,4 @@
-import { hast, hastFromHtml } from '../../lib';
+import { hast } from '../../lib';
import { h } from 'hastscript';
describe('hast transformer', () => {
@@ -19,6 +19,7 @@ describe('hast transformer', () => {
h('h2', { id: 'its-coming-from-within-the-component' }, "It's coming from within the component!"),
);
+ // @ts-ignore
expect(hast(md, { components })).toStrictEqualExceptPosition(expected);
});
});
diff --git a/__tests__/lib/mdast/__snapshots__/index.test.ts.snap b/__tests__/lib/mdast/__snapshots__/index.test.ts.snap
new file mode 100644
index 000000000..596918126
--- /dev/null
+++ b/__tests__/lib/mdast/__snapshots__/index.test.ts.snap
@@ -0,0 +1,544 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`mdast transformer > parses exports 1`] = `
+{
+ "children": [
+ {
+ "data": {
+ "estree": Node {
+ "body": [
+ Node {
+ "end": 26,
+ "loc": {
+ "end": {
+ "column": 26,
+ "line": 1,
+ "offset": 26,
+ },
+ "start": {
+ "column": 0,
+ "line": 1,
+ "offset": 0,
+ },
+ },
+ "range": [
+ 0,
+ 26,
+ ],
+ "source": Node {
+ "end": 25,
+ "loc": {
+ "end": {
+ "column": 25,
+ "line": 1,
+ "offset": 25,
+ },
+ "start": {
+ "column": 18,
+ "line": 1,
+ "offset": 18,
+ },
+ },
+ "range": [
+ 18,
+ 25,
+ ],
+ "raw": ""react"",
+ "start": 18,
+ "type": "Literal",
+ "value": "react",
+ },
+ "specifiers": [
+ Node {
+ "end": 12,
+ "loc": {
+ "end": {
+ "column": 12,
+ "line": 1,
+ "offset": 12,
+ },
+ "start": {
+ "column": 7,
+ "line": 1,
+ "offset": 7,
+ },
+ },
+ "local": Node {
+ "end": 12,
+ "loc": {
+ "end": {
+ "column": 12,
+ "line": 1,
+ "offset": 12,
+ },
+ "start": {
+ "column": 7,
+ "line": 1,
+ "offset": 7,
+ },
+ },
+ "name": "React",
+ "range": [
+ 7,
+ 12,
+ ],
+ "start": 7,
+ "type": "Identifier",
+ },
+ "range": [
+ 7,
+ 12,
+ ],
+ "start": 7,
+ "type": "ImportDefaultSpecifier",
+ },
+ ],
+ "start": 0,
+ "type": "ImportDeclaration",
+ },
+ ],
+ "comments": [],
+ "end": 26,
+ "loc": {
+ "end": {
+ "column": 26,
+ "line": 1,
+ "offset": 26,
+ },
+ "start": {
+ "column": 0,
+ "line": 1,
+ "offset": 0,
+ },
+ },
+ "range": [
+ 0,
+ 26,
+ ],
+ "sourceType": "module",
+ "start": 0,
+ "type": "Program",
+ },
+ },
+ "position": {
+ "end": {
+ "column": 27,
+ "line": 1,
+ "offset": 26,
+ },
+ "start": {
+ "column": 1,
+ "line": 1,
+ "offset": 0,
+ },
+ },
+ "type": "mdxjsEsm",
+ "value": "import React from "react";",
+ },
+ {
+ "data": {
+ "estree": Node {
+ "body": [
+ Node {
+ "declaration": Node {
+ "declarations": [
+ Node {
+ "end": 89,
+ "id": Node {
+ "end": 44,
+ "loc": {
+ "end": {
+ "column": 16,
+ "line": 3,
+ "offset": 44,
+ },
+ "start": {
+ "column": 13,
+ "line": 3,
+ "offset": 41,
+ },
+ },
+ "name": "Foo",
+ "range": [
+ 41,
+ 44,
+ ],
+ "start": 41,
+ "type": "Identifier",
+ },
+ "init": Node {
+ "async": false,
+ "body": Node {
+ "body": [
+ Node {
+ "argument": Node {
+ "children": [
+ Node {
+ "end": 80,
+ "loc": {
+ "end": {
+ "column": 25,
+ "line": 4,
+ "offset": 80,
+ },
+ "start": {
+ "column": 14,
+ "line": 4,
+ "offset": 69,
+ },
+ },
+ "range": [
+ 69,
+ 80,
+ ],
+ "raw": "Hello World",
+ "start": 69,
+ "type": "JSXText",
+ "value": "Hello World",
+ },
+ ],
+ "closingElement": Node {
+ "end": 86,
+ "loc": {
+ "end": {
+ "column": 31,
+ "line": 4,
+ "offset": 86,
+ },
+ "start": {
+ "column": 25,
+ "line": 4,
+ "offset": 80,
+ },
+ },
+ "name": Node {
+ "end": 85,
+ "loc": {
+ "end": {
+ "column": 30,
+ "line": 4,
+ "offset": 85,
+ },
+ "start": {
+ "column": 27,
+ "line": 4,
+ "offset": 82,
+ },
+ },
+ "name": "div",
+ "range": [
+ 82,
+ 85,
+ ],
+ "start": 82,
+ "type": "JSXIdentifier",
+ },
+ "range": [
+ 80,
+ 86,
+ ],
+ "start": 80,
+ "type": "JSXClosingElement",
+ },
+ "end": 86,
+ "loc": {
+ "end": {
+ "column": 31,
+ "line": 4,
+ "offset": 86,
+ },
+ "start": {
+ "column": 9,
+ "line": 4,
+ "offset": 64,
+ },
+ },
+ "openingElement": Node {
+ "attributes": [],
+ "end": 69,
+ "loc": {
+ "end": {
+ "column": 14,
+ "line": 4,
+ "offset": 69,
+ },
+ "start": {
+ "column": 9,
+ "line": 4,
+ "offset": 64,
+ },
+ },
+ "name": Node {
+ "end": 68,
+ "loc": {
+ "end": {
+ "column": 13,
+ "line": 4,
+ "offset": 68,
+ },
+ "start": {
+ "column": 10,
+ "line": 4,
+ "offset": 65,
+ },
+ },
+ "name": "div",
+ "range": [
+ 65,
+ 68,
+ ],
+ "start": 65,
+ "type": "JSXIdentifier",
+ },
+ "range": [
+ 64,
+ 69,
+ ],
+ "selfClosing": false,
+ "start": 64,
+ "type": "JSXOpeningElement",
+ },
+ "range": [
+ 64,
+ 86,
+ ],
+ "start": 64,
+ "type": "JSXElement",
+ },
+ "end": 87,
+ "loc": {
+ "end": {
+ "column": 32,
+ "line": 4,
+ "offset": 87,
+ },
+ "start": {
+ "column": 2,
+ "line": 4,
+ "offset": 57,
+ },
+ },
+ "range": [
+ 57,
+ 87,
+ ],
+ "start": 57,
+ "type": "ReturnStatement",
+ },
+ ],
+ "end": 89,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 5,
+ "offset": 89,
+ },
+ "start": {
+ "column": 25,
+ "line": 3,
+ "offset": 53,
+ },
+ },
+ "range": [
+ 53,
+ 89,
+ ],
+ "start": 53,
+ "type": "BlockStatement",
+ },
+ "end": 89,
+ "expression": false,
+ "generator": false,
+ "id": null,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 5,
+ "offset": 89,
+ },
+ "start": {
+ "column": 19,
+ "line": 3,
+ "offset": 47,
+ },
+ },
+ "params": [],
+ "range": [
+ 47,
+ 89,
+ ],
+ "start": 47,
+ "type": "ArrowFunctionExpression",
+ },
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 5,
+ "offset": 89,
+ },
+ "start": {
+ "column": 13,
+ "line": 3,
+ "offset": 41,
+ },
+ },
+ "range": [
+ 41,
+ 89,
+ ],
+ "start": 41,
+ "type": "VariableDeclarator",
+ },
+ ],
+ "end": 89,
+ "kind": "const",
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 5,
+ "offset": 89,
+ },
+ "start": {
+ "column": 7,
+ "line": 3,
+ "offset": 35,
+ },
+ },
+ "range": [
+ 35,
+ 89,
+ ],
+ "start": 35,
+ "type": "VariableDeclaration",
+ },
+ "end": 89,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 5,
+ "offset": 89,
+ },
+ "start": {
+ "column": 0,
+ "line": 3,
+ "offset": 28,
+ },
+ },
+ "range": [
+ 28,
+ 89,
+ ],
+ "source": null,
+ "specifiers": [],
+ "start": 28,
+ "type": "ExportNamedDeclaration",
+ },
+ ],
+ "comments": [],
+ "end": 89,
+ "loc": {
+ "end": {
+ "column": 1,
+ "line": 5,
+ "offset": 89,
+ },
+ "start": {
+ "column": 0,
+ "line": 3,
+ "offset": 28,
+ },
+ },
+ "range": [
+ 28,
+ 89,
+ ],
+ "sourceType": "module",
+ "start": 28,
+ "type": "Program",
+ },
+ },
+ "position": {
+ "end": {
+ "column": 2,
+ "line": 5,
+ "offset": 89,
+ },
+ "start": {
+ "column": 1,
+ "line": 3,
+ "offset": 28,
+ },
+ },
+ "type": "mdxjsEsm",
+ "value": "export const Foo = () => {
+ return Hello World
;
+}",
+ },
+ {
+ "children": [
+ {
+ "position": {
+ "end": {
+ "column": 13,
+ "line": 7,
+ "offset": 103,
+ },
+ "start": {
+ "column": 4,
+ "line": 7,
+ "offset": 94,
+ },
+ },
+ "type": "text",
+ "value": "Hey there",
+ },
+ ],
+ "depth": 2,
+ "position": {
+ "end": {
+ "column": 14,
+ "line": 7,
+ "offset": 104,
+ },
+ "start": {
+ "column": 1,
+ "line": 7,
+ "offset": 91,
+ },
+ },
+ "type": "heading",
+ },
+ {
+ "attributes": [],
+ "children": [],
+ "name": "Foo",
+ "position": {
+ "end": {
+ "column": 8,
+ "line": 8,
+ "offset": 112,
+ },
+ "start": {
+ "column": 1,
+ "line": 8,
+ "offset": 105,
+ },
+ },
+ "type": "mdxJsxFlowElement",
+ },
+ ],
+ "position": {
+ "end": {
+ "column": 8,
+ "line": 8,
+ "offset": 112,
+ },
+ "start": {
+ "column": 1,
+ "line": 1,
+ "offset": 0,
+ },
+ },
+ "type": "root",
+}
+`;
diff --git a/__tests__/lib/mdast/esm/in.mdx b/__tests__/lib/mdast/esm/in.mdx
new file mode 100644
index 000000000..e75889939
--- /dev/null
+++ b/__tests__/lib/mdast/esm/in.mdx
@@ -0,0 +1,8 @@
+import React from 'react';
+
+export const Foo = () => {
+ return Hello World
;
+}
+
+## Hey there
+
\ No newline at end of file
diff --git a/__tests__/lib/mdast/esm/out.json b/__tests__/lib/mdast/esm/out.json
new file mode 100644
index 000000000..bfabd053a
--- /dev/null
+++ b/__tests__/lib/mdast/esm/out.json
@@ -0,0 +1,538 @@
+{
+ "type": "root",
+ "children": [
+ {
+ "type": "mdxjsEsm",
+ "value": "import React from 'react';",
+ "position": {
+ "start": {
+ "line": 1,
+ "column": 1,
+ "offset": 0
+ },
+ "end": {
+ "line": 1,
+ "column": 27,
+ "offset": 26
+ }
+ },
+ "data": {
+ "estree": {
+ "type": "Program",
+ "start": 0,
+ "end": 26,
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 0,
+ "offset": 0
+ },
+ "end": {
+ "line": 1,
+ "column": 26,
+ "offset": 26
+ }
+ },
+ "body": [
+ {
+ "type": "ImportDeclaration",
+ "start": 0,
+ "end": 26,
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 0,
+ "offset": 0
+ },
+ "end": {
+ "line": 1,
+ "column": 26,
+ "offset": 26
+ }
+ },
+ "specifiers": [
+ {
+ "type": "ImportDefaultSpecifier",
+ "start": 7,
+ "end": 12,
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 7,
+ "offset": 7
+ },
+ "end": {
+ "line": 1,
+ "column": 12,
+ "offset": 12
+ }
+ },
+ "local": {
+ "type": "Identifier",
+ "start": 7,
+ "end": 12,
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 7,
+ "offset": 7
+ },
+ "end": {
+ "line": 1,
+ "column": 12,
+ "offset": 12
+ }
+ },
+ "name": "React",
+ "range": [
+ 7,
+ 12
+ ]
+ },
+ "range": [
+ 7,
+ 12
+ ]
+ }
+ ],
+ "source": {
+ "type": "Literal",
+ "start": 18,
+ "end": 25,
+ "loc": {
+ "start": {
+ "line": 1,
+ "column": 18,
+ "offset": 18
+ },
+ "end": {
+ "line": 1,
+ "column": 25,
+ "offset": 25
+ }
+ },
+ "value": "react",
+ "raw": "'react'",
+ "range": [
+ 18,
+ 25
+ ]
+ },
+ "range": [
+ 0,
+ 26
+ ]
+ }
+ ],
+ "sourceType": "module",
+ "comments": [],
+ "range": [
+ 0,
+ 26
+ ]
+ }
+ }
+ },
+ {
+ "type": "mdxjsEsm",
+ "value": "export const Foo = () => {\n return Hello World
;\n}",
+ "position": {
+ "start": {
+ "line": 3,
+ "column": 1,
+ "offset": 28
+ },
+ "end": {
+ "line": 5,
+ "column": 2,
+ "offset": 89
+ }
+ },
+ "data": {
+ "estree": {
+ "type": "Program",
+ "start": 28,
+ "end": 89,
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 0,
+ "offset": 28
+ },
+ "end": {
+ "line": 5,
+ "column": 1,
+ "offset": 89
+ }
+ },
+ "body": [
+ {
+ "type": "ExportNamedDeclaration",
+ "start": 28,
+ "end": 89,
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 0,
+ "offset": 28
+ },
+ "end": {
+ "line": 5,
+ "column": 1,
+ "offset": 89
+ }
+ },
+ "declaration": {
+ "type": "VariableDeclaration",
+ "start": 35,
+ "end": 89,
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 7,
+ "offset": 35
+ },
+ "end": {
+ "line": 5,
+ "column": 1,
+ "offset": 89
+ }
+ },
+ "declarations": [
+ {
+ "type": "VariableDeclarator",
+ "start": 41,
+ "end": 89,
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 13,
+ "offset": 41
+ },
+ "end": {
+ "line": 5,
+ "column": 1,
+ "offset": 89
+ }
+ },
+ "id": {
+ "type": "Identifier",
+ "start": 41,
+ "end": 44,
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 13,
+ "offset": 41
+ },
+ "end": {
+ "line": 3,
+ "column": 16,
+ "offset": 44
+ }
+ },
+ "name": "Foo",
+ "range": [
+ 41,
+ 44
+ ]
+ },
+ "init": {
+ "type": "ArrowFunctionExpression",
+ "start": 47,
+ "end": 89,
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 19,
+ "offset": 47
+ },
+ "end": {
+ "line": 5,
+ "column": 1,
+ "offset": 89
+ }
+ },
+ "id": null,
+ "expression": false,
+ "generator": false,
+ "async": false,
+ "params": [],
+ "body": {
+ "type": "BlockStatement",
+ "start": 53,
+ "end": 89,
+ "loc": {
+ "start": {
+ "line": 3,
+ "column": 25,
+ "offset": 53
+ },
+ "end": {
+ "line": 5,
+ "column": 1,
+ "offset": 89
+ }
+ },
+ "body": [
+ {
+ "type": "ReturnStatement",
+ "start": 57,
+ "end": 87,
+ "loc": {
+ "start": {
+ "line": 4,
+ "column": 2,
+ "offset": 57
+ },
+ "end": {
+ "line": 4,
+ "column": 32,
+ "offset": 87
+ }
+ },
+ "argument": {
+ "type": "JSXElement",
+ "start": 64,
+ "end": 86,
+ "loc": {
+ "start": {
+ "line": 4,
+ "column": 9,
+ "offset": 64
+ },
+ "end": {
+ "line": 4,
+ "column": 31,
+ "offset": 86
+ }
+ },
+ "openingElement": {
+ "type": "JSXOpeningElement",
+ "start": 64,
+ "end": 69,
+ "loc": {
+ "start": {
+ "line": 4,
+ "column": 9,
+ "offset": 64
+ },
+ "end": {
+ "line": 4,
+ "column": 14,
+ "offset": 69
+ }
+ },
+ "attributes": [],
+ "name": {
+ "type": "JSXIdentifier",
+ "start": 65,
+ "end": 68,
+ "loc": {
+ "start": {
+ "line": 4,
+ "column": 10,
+ "offset": 65
+ },
+ "end": {
+ "line": 4,
+ "column": 13,
+ "offset": 68
+ }
+ },
+ "name": "div",
+ "range": [
+ 65,
+ 68
+ ]
+ },
+ "selfClosing": false,
+ "range": [
+ 64,
+ 69
+ ]
+ },
+ "closingElement": {
+ "type": "JSXClosingElement",
+ "start": 80,
+ "end": 86,
+ "loc": {
+ "start": {
+ "line": 4,
+ "column": 25,
+ "offset": 80
+ },
+ "end": {
+ "line": 4,
+ "column": 31,
+ "offset": 86
+ }
+ },
+ "name": {
+ "type": "JSXIdentifier",
+ "start": 82,
+ "end": 85,
+ "loc": {
+ "start": {
+ "line": 4,
+ "column": 27,
+ "offset": 82
+ },
+ "end": {
+ "line": 4,
+ "column": 30,
+ "offset": 85
+ }
+ },
+ "name": "div",
+ "range": [
+ 82,
+ 85
+ ]
+ },
+ "range": [
+ 80,
+ 86
+ ]
+ },
+ "children": [
+ {
+ "type": "JSXText",
+ "start": 69,
+ "end": 80,
+ "loc": {
+ "start": {
+ "line": 4,
+ "column": 14,
+ "offset": 69
+ },
+ "end": {
+ "line": 4,
+ "column": 25,
+ "offset": 80
+ }
+ },
+ "value": "Hello World",
+ "raw": "Hello World",
+ "range": [
+ 69,
+ 80
+ ]
+ }
+ ],
+ "range": [
+ 64,
+ 86
+ ]
+ },
+ "range": [
+ 57,
+ 87
+ ]
+ }
+ ],
+ "range": [
+ 53,
+ 89
+ ]
+ },
+ "range": [
+ 47,
+ 89
+ ]
+ },
+ "range": [
+ 41,
+ 89
+ ]
+ }
+ ],
+ "kind": "const",
+ "range": [
+ 35,
+ 89
+ ]
+ },
+ "specifiers": [],
+ "source": null,
+ "range": [
+ 28,
+ 89
+ ]
+ }
+ ],
+ "sourceType": "module",
+ "comments": [],
+ "range": [
+ 28,
+ 89
+ ]
+ }
+ }
+ },
+ {
+ "type": "heading",
+ "depth": 2,
+ "children": [
+ {
+ "type": "text",
+ "value": "Hey there",
+ "position": {
+ "start": {
+ "line": 7,
+ "column": 4,
+ "offset": 94
+ },
+ "end": {
+ "line": 7,
+ "column": 13,
+ "offset": 103
+ }
+ }
+ }
+ ],
+ "position": {
+ "start": {
+ "line": 7,
+ "column": 1,
+ "offset": 91
+ },
+ "end": {
+ "line": 7,
+ "column": 14,
+ "offset": 104
+ }
+ }
+ },
+ {
+ "type": "mdxJsxFlowElement",
+ "name": "Foo",
+ "attributes": [],
+ "children": [],
+ "position": {
+ "start": {
+ "line": 8,
+ "column": 1,
+ "offset": 105
+ },
+ "end": {
+ "line": 8,
+ "column": 8,
+ "offset": 112
+ }
+ }
+ }
+ ],
+ "position": {
+ "start": {
+ "line": 1,
+ "column": 1,
+ "offset": 0
+ },
+ "end": {
+ "line": 8,
+ "column": 8,
+ "offset": 112
+ }
+ }
+}
diff --git a/__tests__/lib/mdast/index.test.ts b/__tests__/lib/mdast/index.test.ts
index 43ca8519b..572579486 100644
--- a/__tests__/lib/mdast/index.test.ts
+++ b/__tests__/lib/mdast/index.test.ts
@@ -15,6 +15,9 @@ import variablesWithSpacesJson from './variables-with-spaces/out.json';
import inlineImagesMdx from './images/inline/in.mdx?raw';
import inlineImagesJson from './images/inline/out.json';
+import esmMdx from './esm/in.mdx?raw';
+import esmJson from './esm/out.json';
+
describe('mdast transformer', async () => {
it('parses null attributes', () => {
// @ts-ignore
@@ -40,4 +43,9 @@ describe('mdast transformer', async () => {
// @ts-ignore
expect(mdast(inlineImagesMdx)).toStrictEqualExceptPosition(inlineImagesJson);
});
+
+ it('parses esm (imports and exports)', () => {
+ // @ts-ignore
+ expect(mdast(esmMdx)).toStrictEqualExceptPosition(esmJson);
+ });
});
diff --git a/lib/exports.ts b/lib/exports.ts
new file mode 100644
index 000000000..ff072028b
--- /dev/null
+++ b/lib/exports.ts
@@ -0,0 +1,21 @@
+import { visit } from 'unist-util-visit';
+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+)/;
+
+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);
+ }
+ });
+
+ return Array.from(set);
+};
+
+export default exports;
diff --git a/lib/index.ts b/lib/index.ts
index 17e935e51..e56289ba1 100644
--- a/lib/index.ts
+++ b/lib/index.ts
@@ -2,11 +2,12 @@ export type { MdastOpts } from './ast-processor';
export { default as astProcessor, remarkPlugins } from './ast-processor';
export { default as compile } from './compile';
+export { default as exports } from './exports';
export { default as hast } from './hast';
export { default as mdast } from './mdast';
export { default as mdastV6 } from './mdastV6';
export { default as mdx } from './mdx';
+export { default as migrate } from './migrate';
export { default as plain } from './plain';
export { default as run } from './run';
export { default as tags } from './tags';
-export { default as migrate } from './migrate';
diff --git a/lib/tags.ts b/lib/tags.ts
index 73dec329a..9cf094e50 100644
--- a/lib/tags.ts
+++ b/lib/tags.ts
@@ -7,7 +7,7 @@ const tags = (doc: string) => {
const set = new Set();
visit(mdast(doc), isMDXElement, (node: MdxJsxFlowElement | MdxJsxTextElement) => {
- if (node.name.match(/^[A-Z]/)) {
+ if (node.name?.match(/^[A-Z]/)) {
set.add(node.name);
}
});
diff --git a/processor/utils.ts b/processor/utils.ts
index 54c9e3e99..981396e1c 100644
--- a/processor/utils.ts
+++ b/processor/utils.ts
@@ -1,5 +1,5 @@
import type { Node } from 'mdast';
-import type { MdxJsxFlowElement, MdxJsxTextElement, MdxFlowExpression } from 'mdast-util-mdx';
+import type { MdxJsxFlowElement, MdxJsxTextElement, MdxFlowExpression, MdxjsEsm } from 'mdast-util-mdx';
import type {
MdxJsxAttribute,
MdxJsxAttributeValueExpression,
@@ -101,12 +101,22 @@ export const getChildren = (jsx: MdxJsxFlowElement | MdxJsxTextElement): any
* TODO: Make this more extensible to all types of nodes. isElement(node, 'type' or ['type1', 'type2']), say
*
* @param {Node} node
- * @returns {(node is MdxJsxFlowElement | MdxJsxTextElement)}
+ * @returns {(node is MdxJsxFlowElement | MdxJsxTextElement | MdxjsEsm)}
*/
export const isMDXElement = (node: Node): node is MdxJsxFlowElement | MdxJsxTextElement => {
return ['mdxJsxFlowElement', 'mdxJsxTextElement'].includes(node.type);
};
+/**
+ * Tests if a node is an MDX ESM element (i.e. import or export).
+ *
+ * @param {Node} node
+ * @returns {boolean}
+ */
+export const isMDXEsm = (node: Node): node is MdxjsEsm => {
+ return node.type === 'mdxjsEsm';
+}
+
/**
* Takes an HTML string and formats it for display in the editor. Removes leading/trailing newlines
* and unindents the HTML.