typedoc-plugin-markdown icon indicating copy to clipboard operation
typedoc-plugin-markdown copied to clipboard

🙏 Make `typedoc-plugin-markdown` works with MDX2

Open dimaMachina opened this issue 3 years ago • 5 comments
trafficstars

Currently using typedoc-plugin-markdown with MDX2 can't be possible as starting from MDX2 it's necessary to escape { and < open brackets because MDX2 parses < as JSX tag and { as JS expression.

typedoc-plugin-markdown escapes only > closing bracket but it's unnecessary, also he adds double whitespace before } closing bracket that also redundant.

I fixed these issues in [email protected] in the following patch:

diff --git a/node_modules/typedoc-plugin-markdown/dist/resources/helpers/declaration-title.js b/node_modules/typedoc-plugin-markdown/dist/resources/helpers/declaration-title.js
index ecf2699..3953091 100644
--- a/node_modules/typedoc-plugin-markdown/dist/resources/helpers/declaration-title.js
+++ b/node_modules/typedoc-plugin-markdown/dist/resources/helpers/declaration-title.js
@@ -21,9 +21,9 @@ function default_1() {
         }
         md.push(`${this.flags.isRest ? '... ' : ''} **${(0, utils_1.escapeChars)(this.name)}**`);
         if (this instanceof typedoc_1.DeclarationReflection && this.typeParameters) {
-            md.push(`<${this.typeParameters
+            md.push(`\\<${this.typeParameters // Escape `<` because MDX2 parse him as JSX tags
                 .map((typeParameter) => `\`${typeParameter.name}\``)
-                .join(', ')}\\>`);
+                .join(', ')}>`);
         }
         if (!((_a = this.parent) === null || _a === void 0 ? void 0 : _a.kindOf(typedoc_1.ReflectionKind.Enum))) {
             md.push(getType(this));
diff --git a/node_modules/typedoc-plugin-markdown/dist/resources/helpers/reflection-title.js b/node_modules/typedoc-plugin-markdown/dist/resources/helpers/reflection-title.js
index 6363a66..52b1ae3 100644
--- a/node_modules/typedoc-plugin-markdown/dist/resources/helpers/reflection-title.js
+++ b/node_modules/typedoc-plugin-markdown/dist/resources/helpers/reflection-title.js
@@ -19,7 +19,7 @@ function default_1(theme) {
                 const typeParameters = this.model.typeParameters
                     .map((typeParameter) => typeParameter.name)
                     .join(', ');
-                title.push(`<${typeParameters}${shouldEscape ? '\\>' : '>'}`);
+                title.push(`\\<${typeParameters}>`); // Escape `<` because MDX2 parse him as JSX tag
             }
         }
         return title.join('');
diff --git a/node_modules/typedoc-plugin-markdown/dist/resources/helpers/signature-title.js b/node_modules/typedoc-plugin-markdown/dist/resources/helpers/signature-title.js
index 9046905..1d3fdb3 100644
--- a/node_modules/typedoc-plugin-markdown/dist/resources/helpers/signature-title.js
+++ b/node_modules/typedoc-plugin-markdown/dist/resources/helpers/signature-title.js
@@ -20,9 +20,9 @@ function default_1() {
             md.push(`**${this.name}**`);
         }
         if (this.typeParameters) {
-            md.push(`<${this.typeParameters
+            md.push(`\\<${this.typeParameters // Escape `<` because MDX2 parse him as JSX tag
                 .map((typeParameter) => `\`${typeParameter.name}\``)
-                .join(', ')}\\>`);
+                .join(', ')}>`);
         }
         md.push(`(${getParameters(this.parameters)})`);
         if (this.type && !((_b = this.parent) === null || _b === void 0 ? void 0 : _b.kindOf(typedoc_1.ReflectionKind.Constructor))) {
diff --git a/node_modules/typedoc-plugin-markdown/dist/resources/helpers/type.js b/node_modules/typedoc-plugin-markdown/dist/resources/helpers/type.js
index d2afa18..9becfd8 100644
--- a/node_modules/typedoc-plugin-markdown/dist/resources/helpers/type.js
+++ b/node_modules/typedoc-plugin-markdown/dist/resources/helpers/type.js
@@ -90,7 +90,8 @@ function getDeclarationType(model) {
                     ? `= ${(0, utils_1.escapeChars)(obj.defaultValue)}`
                     : ''}`;
             });
-        return `{ ${indexSignature ? indexSignature : ''}${types ? types.join('; ') : ''} }${model.defaultValue && model.defaultValue !== '...'
+        // Escape `{` because MDX2 parse him as JS expression
+        return `\\{ ${indexSignature ? indexSignature : ''}${types ? types.join('; ') : ''}}${model.defaultValue && model.defaultValue !== '...'
             ? `= ${(0, utils_1.escapeChars)(model.defaultValue)}`
             : ''}`;
     }
@@ -99,9 +100,9 @@ function getDeclarationType(model) {
 function getFunctionType(modelSignatures) {
     const functions = modelSignatures.map((fn) => {
         const typeParams = fn.typeParameters
-            ? `<${fn.typeParameters
+            ? `\\<${fn.typeParameters // Escape `<` because MDX2 parse him as JSX tag
                 .map((typeParameter) => typeParameter.name)
-                .join(', ')}\\>`
+                .join(', ')}>`
             : [];
         const params = fn.parameters
             ? fn.parameters.map((param) => {
@@ -128,9 +129,9 @@ function getReferenceType(model, emphasis) {
                 : `\`${model.name}\``);
         }
         if (model.typeArguments && model.typeArguments.length > 0) {
-            reflection.push(`<${model.typeArguments
+            reflection.push(`\\<${model.typeArguments // Escape `<` because MDX2 parse him as JSX tag
                 .map((typeArgument) => Handlebars.helpers.type.call(typeArgument))
-                .join(', ')}\\>`);
+                .join(', ')}>`);
         }
         return reflection.join('');
     }
diff --git a/node_modules/typedoc-plugin-markdown/dist/utils.js b/node_modules/typedoc-plugin-markdown/dist/utils.js
index dc6b9e1..991fe79 100644
--- a/node_modules/typedoc-plugin-markdown/dist/utils.js
+++ b/node_modules/typedoc-plugin-markdown/dist/utils.js
@@ -11,7 +11,8 @@ function formatContents(contents) {
 exports.formatContents = formatContents;
 function escapeChars(str) {
     return str
-        .replace(/>/g, '\\>')
+        .replace(/</g, '\\<') // Escape `<` because MDX2 parse him as JSX tag
+        .replace(/{/g, '\\{') // Escape `{` because MDX2 parse him as JS expression
         .replace(/_/g, '\\_')
         .replace(/`/g, '\\`')
         .replace(/\|/g, '\\|');

P.S. I hope one day I will be able to remove the unnecessary patch and the support of MDX2 in typedoc-plugin-markdown will be out-of-box.

dimaMachina avatar Apr 12 '22 21:04 dimaMachina

thanks - agreed this should be the default. Docusaurus doesn't (yet) support MDX2 which is why its done like this, but will take a look at a workaround for that.

tgreyuk avatar Apr 16 '22 21:04 tgreyuk

I was on a similar journey and decided to just tell Nextra to interpret the files as regular Markdown:

https://github.com/tgreyuk/typedoc-plugin-markdown/pull/386

I think it does not make sense(?) to use MDX as the content would look weird in IDEs like VSCode, but correct me if you disagree.

balazsorban44 avatar Jan 25 '23 11:01 balazsorban44

thanks - agreed this should be the default. Docusaurus doesn't (yet) support MDX2 which is why its done like this, but will take a look at a workaround for that.

@tgreyuk , awesome to see this land in the next version of the plugin! :)

birkskyum avatar Jul 06 '23 12:07 birkskyum

thanks - agreed this should be the default. Docusaurus doesn't (yet) support MDX2 which is why its done like this, but will take a look at a workaround for that.

This version is still compatible with MDX V1, is my assumption correct?

aamir1995 avatar Aug 04 '23 10:08 aamir1995

Is this closed by 3.17.0 ?

birkskyum avatar Nov 08 '23 00:11 birkskyum

Is mdx 2 or 3 (released Oct '23) going to be in the upcoming v4 release?

birkskyum avatar Apr 07 '24 22:04 birkskyum

Looking at the migration guide there is no output that will cause any breaking change. Additionally the output is parsed and checked with remark-mdx. So yes the intention is that both mdx2 and 3 is supported.

tgreyuk avatar Apr 08 '24 08:04 tgreyuk

Excellent, I think the key feature of mdx3 is the ability to use the await inside of it.

birkskyum avatar Apr 08 '24 08:04 birkskyum