hexo-renderer-mdx 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.js +70 -11
  2. package/package.json +1 -1
  3. package/test-mdx.js +47 -0
package/index.js CHANGED
@@ -1,8 +1,45 @@
1
1
  'use strict';
2
2
 
3
- const { compile } = require('@mdx-js/mdx');
4
3
  const { renderToString } = require('react-dom/server');
5
4
  const React = require('react');
5
+ const fs = require('fs');
6
+ const { createRequire } = require('module');
7
+
8
+ // Create a require for loading ESM modules
9
+ let compile;
10
+ let compileLoaded = false;
11
+
12
+ async function loadCompile() {
13
+ if (!compileLoaded) {
14
+ try {
15
+ // Try to load @mdx-js/mdx - it may be CJS or ESM depending on the environment
16
+ try {
17
+ // First try: dynamic import with proper error handling
18
+ const mdxModule = await (async () => {
19
+ try {
20
+ return await import('@mdx-js/mdx');
21
+ } catch (err) {
22
+ // If dynamic import fails, this might be a require context issue
23
+ // Return null to trigger fallback
24
+ return null;
25
+ }
26
+ })();
27
+
28
+ if (mdxModule) {
29
+ compile = mdxModule.compile;
30
+ } else {
31
+ throw new Error('Could not load @mdx-js/mdx via dynamic import');
32
+ }
33
+ } catch (err) {
34
+ // Fallback: try to require it directly (in case it's been transpiled)
35
+ compile = require('@mdx-js/mdx').compile;
36
+ }
37
+ compileLoaded = true;
38
+ } catch (err) {
39
+ throw new Error(`Failed to load @mdx-js/mdx: ${err.message}`);
40
+ }
41
+ }
42
+ }
6
43
 
7
44
  /**
8
45
  * MDX Renderer for Hexo
@@ -22,10 +59,19 @@ async function mdxRenderer(data) {
22
59
  const { text, path } = data;
23
60
 
24
61
  try {
62
+ // Ensure compile function is loaded
63
+ await loadCompile();
64
+
65
+ // Read the original file directly to bypass Hexo's template processing
66
+ let content;
67
+ try {
68
+ content = fs.readFileSync(path, 'utf8');
69
+ } catch (err) {
70
+ // If reading fails, fall back to the provided text
71
+ content = text;
72
+ }
73
+
25
74
  // Strip YAML front matter if present
26
- // Note: Hexo typically strips front matter before passing to renderers,
27
- // but we handle it here as a safety measure for edge cases
28
- let content = text;
29
75
  const frontMatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n/;
30
76
  const match = content.match(frontMatterRegex);
31
77
 
@@ -35,17 +81,21 @@ async function mdxRenderer(data) {
35
81
  }
36
82
 
37
83
  // Compile MDX to JavaScript with automatic JSX runtime
84
+ // Use outputFormat: 'function-body' and development: true to avoid jsxImportSource
38
85
  const compiled = await compile(content, {
39
86
  outputFormat: 'function-body',
40
- development: false,
41
- jsxImportSource: 'react'
87
+ development: true,
88
+ // remarkRehypeOptions for markdown processing
89
+ remarkRehypeOptions: {
90
+ allowDangerousHtml: true
91
+ }
42
92
  });
43
93
 
44
94
  // Create a function from the compiled code
45
95
  const code = String(compiled);
46
96
 
47
- // The compiled code expects arguments[0] to be the jsx-runtime
48
- const jsxRuntime = require('react/jsx-runtime');
97
+ // When development: true, the compiled code uses jsxDEV from react/jsx-dev-runtime
98
+ const jsxDevRuntime = require('react/jsx-dev-runtime');
49
99
 
50
100
  // Create and execute the MDX module function
51
101
  // Note: Using new Function() here is safe because:
@@ -53,7 +103,7 @@ async function mdxRenderer(data) {
53
103
  // 2. MDX compilation itself validates and sanitizes the content
54
104
  // 3. This is a build-time operation, not runtime user input
55
105
  const fn = new Function(code);
56
- const mdxModule = fn.call(null, jsxRuntime);
106
+ const mdxModule = fn.call(null, jsxDevRuntime);
57
107
 
58
108
  // The result has a default export which is the MDX component
59
109
  const MDXContent = mdxModule.default;
@@ -65,11 +115,20 @@ async function mdxRenderer(data) {
65
115
 
66
116
  return html;
67
117
  } catch (err) {
68
- throw new Error(`MDX compilation failed for ${path}: ${err.message}`);
118
+ // Provide more detailed error information
119
+ const errorMsg = `MDX compilation failed for ${path}: ${err.message}`;
120
+ console.error(errorMsg);
121
+ if (err.position) {
122
+ console.error(`Error at line ${err.position.start.line}, column ${err.position.start.column}`);
123
+ }
124
+ throw new Error(errorMsg);
69
125
  }
70
126
  }
71
127
 
72
128
  /**
73
129
  * Register the MDX renderer with Hexo
130
+ * Note: Using disableNunjucks: true to prevent template processing of {{ }} syntax
74
131
  */
75
- hexo.extend.renderer.register('mdx', 'html', mdxRenderer, true);
132
+ hexo.extend.renderer.register('mdx', 'html', mdxRenderer, {
133
+ disableNunjucks: true
134
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hexo-renderer-mdx",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "MDX renderer plugin for Hexo with React component support",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/test-mdx.js ADDED
@@ -0,0 +1,47 @@
1
+ const { compile } = require('@mdx-js/mdx');
2
+
3
+ const testContent = `---
4
+ title: My First MDX Post
5
+ date: 2026-01-06
6
+ tags: [hexo, mdx]
7
+ ---
8
+
9
+ # Hello
10
+
11
+ <div style={{ padding: '20px', backgroundColor: '#e3f2fd' }}>
12
+ 🎉 Test
13
+ </div>
14
+ `;
15
+
16
+ async function test() {
17
+ try {
18
+ // Strip front matter like the renderer does
19
+ let content = testContent;
20
+ const frontMatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n/;
21
+ const match = content.match(frontMatterRegex);
22
+
23
+ if (match) {
24
+ content = content.slice(match[0].length);
25
+ }
26
+
27
+ console.log('Content to compile:');
28
+ console.log(content);
29
+ console.log('\n---\n');
30
+
31
+ const result = await compile(content, {
32
+ outputFormat: 'function-body',
33
+ development: false,
34
+ jsxImportSource: 'react',
35
+ format: 'mdx',
36
+ mdxExtensions: ['.mdx'],
37
+ remarkRehypeOptions: {
38
+ allowDangerousHtml: true
39
+ }
40
+ });
41
+ console.log('Success!');
42
+ } catch (err) {
43
+ console.error('Error:', err.message);
44
+ }
45
+ }
46
+
47
+ test();