astro-mermaid 1.1.0 → 1.2.0

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.
@@ -1,5 +1,20 @@
1
1
  import { resolve } from 'import-meta-resolve';
2
2
 
3
+ /**
4
+ * Helper function to HTML-escape text content
5
+ * This ensures HTML tags in mermaid diagrams are preserved as text
6
+ */
7
+ function escapeHtml(text) {
8
+ const htmlEntities = {
9
+ '&': '&',
10
+ '<': '&lt;',
11
+ '>': '&gt;',
12
+ '"': '&quot;',
13
+ "'": '&#39;'
14
+ };
15
+ return text.replace(/[&<>"']/g, char => htmlEntities[char]);
16
+ }
17
+
3
18
  /**
4
19
  * Remark plugin to transform mermaid code blocks at the markdown level
5
20
  */
@@ -13,10 +28,10 @@ function remarkMermaidPlugin(options = {}) {
13
28
  if (node.lang === 'mermaid') {
14
29
  mermaidCount++;
15
30
 
16
- // Transform to html node with pre.mermaid
31
+ // Transform to html node with pre.mermaid, escaping HTML content
17
32
  const htmlNode = {
18
33
  type: 'html',
19
- value: `<pre class="mermaid">${node.value}</pre>`
34
+ value: `<pre class="mermaid">${escapeHtml(node.value)}</pre>`
20
35
  };
21
36
 
22
37
  // Replace the code node with html node
@@ -36,6 +51,49 @@ function remarkMermaidPlugin(options = {}) {
36
51
  };
37
52
  }
38
53
 
54
+ /**
55
+ * Helper function to serialize HAST nodes back to HTML text
56
+ * This preserves HTML tags within the mermaid content
57
+ */
58
+ function serializeHastChildren(children) {
59
+ let result = '';
60
+
61
+ for (const child of children) {
62
+ if (child.type === 'text') {
63
+ result += child.value;
64
+ } else if (child.type === 'element') {
65
+ // Reconstruct the HTML tag
66
+ const tagName = child.tagName;
67
+ const selfClosing = ['br', 'hr', 'img', 'input', 'meta', 'link'].includes(tagName);
68
+
69
+ result += `<${tagName}`;
70
+
71
+ // Add attributes if any
72
+ if (child.properties) {
73
+ for (const [key, value] of Object.entries(child.properties)) {
74
+ if (key !== 'className') {
75
+ result += ` ${key}="${value}"`;
76
+ } else if (Array.isArray(value)) {
77
+ result += ` class="${value.join(' ')}"`;
78
+ }
79
+ }
80
+ }
81
+
82
+ if (selfClosing) {
83
+ result += '/>';
84
+ } else {
85
+ result += '>';
86
+ if (child.children && child.children.length > 0) {
87
+ result += serializeHastChildren(child.children);
88
+ }
89
+ result += `</${tagName}>`;
90
+ }
91
+ }
92
+ }
93
+
94
+ return result;
95
+ }
96
+
39
97
  /**
40
98
  * Rehype plugin to transform mermaid code blocks
41
99
  * Converts ```mermaid code blocks to <pre class="mermaid">
@@ -43,7 +101,6 @@ function remarkMermaidPlugin(options = {}) {
43
101
  function rehypeMermaidPlugin(options = {}) {
44
102
  return async function transformer(tree, file) {
45
103
  const { visit } = await import('unist-util-visit');
46
- const { toString } = await import('mdast-util-to-string');
47
104
 
48
105
  let mermaidCount = 0;
49
106
 
@@ -59,8 +116,8 @@ function rehypeMermaidPlugin(options = {}) {
59
116
 
60
117
  if (Array.isArray(className) && className.includes('language-mermaid')) {
61
118
  mermaidCount++;
62
- // Get the mermaid diagram content
63
- const diagramContent = toString(codeNode);
119
+ // Get the mermaid diagram content, preserving HTML tags
120
+ const diagramContent = serializeHastChildren(codeNode.children || []);
64
121
 
65
122
  // Transform to <pre class="mermaid">
66
123
  node.properties = {
@@ -68,9 +125,10 @@ function rehypeMermaidPlugin(options = {}) {
68
125
  className: ['mermaid']
69
126
  };
70
127
 
128
+ // Escape HTML to preserve it as text content
71
129
  node.children = [{
72
130
  type: 'text',
73
- value: diagramContent
131
+ value: escapeHtml(diagramContent)
74
132
  }];
75
133
 
76
134
  if (options.logger) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro-mermaid",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "An Astro integration for rendering Mermaid diagrams with automatic theme switching and client-side rendering",
5
5
  "type": "module",
6
6
  "main": "./astro-mermaid-integration.js",
@@ -39,15 +39,30 @@
39
39
  }
40
40
  },
41
41
  "dependencies": {
42
+ "@anthropic-ai/claude-code": "^1.0.128",
42
43
  "import-meta-resolve": "^4.2.0",
43
44
  "mdast-util-to-string": "^4.0.0",
44
45
  "unist-util-visit": "^5.0.0"
45
46
  },
47
+ "scripts": {
48
+ "claude": "claude",
49
+ "test": "vitest",
50
+ "test:ui": "vitest --ui",
51
+ "test:coverage": "vitest --coverage"
52
+ },
46
53
  "devDependencies": {
47
54
  "@types/hast": "^3.0.4",
55
+ "@vitest/ui": "^3.2.4",
48
56
  "astro": "^5.0.0",
57
+ "hast-util-from-html": "^2.0.3",
49
58
  "mermaid": "^11.0.0",
50
- "typescript": "^5.0.0"
59
+ "rehype-parse": "^9.0.1",
60
+ "rehype-stringify": "^10.0.1",
61
+ "remark-mermaid": "^0.2.0",
62
+ "remark-parse": "^11.0.0",
63
+ "typescript": "^5.0.0",
64
+ "unified": "^11.0.5",
65
+ "vitest": "^3.2.4"
51
66
  },
52
67
  "repository": {
53
68
  "type": "git",
@@ -57,4 +72,4 @@
57
72
  "bugs": {
58
73
  "url": "https://github.com/joesaby/astro-mermaid/issues"
59
74
  }
60
- }
75
+ }