@barzhsieh/nuxt-content-mermaid 2.1.2 → 2.1.3

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.
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  [English](./README.md) | [中文](./README.zh-TW.md)
2
2
 
3
+ [![nuxt-content-social-card](https://raw.githubusercontent.com/andy820621/nuxt-content-mermaid/main/src/assets/nuxt-content-mermaid.webp)](https://www.npmjs.com/package/@barzhsieh/nuxt-content-mermaid)
4
+
3
5
  # nuxt-content-mermaid
4
6
 
5
7
  [![npm version][npm-version-src]][npm-version-href]
package/README.zh-TW.md CHANGED
@@ -1,4 +1,6 @@
1
- [English](./README.md) | [中文](./README.zh-TW.md)
1
+ [中文](./README.zh-TW.md) | [English](./README.md)
2
+
3
+ [![nuxt-content-social-card](https://raw.githubusercontent.com/andy820621/nuxt-content-mermaid/main/src/assets/nuxt-content-mermaid.webp)](https://www.npmjs.com/package/@barzhsieh/nuxt-content-mermaid)
2
4
 
3
5
  # nuxt-content-mermaid
4
6
 
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^3.20.1 || ^4.1.0"
6
6
  },
7
- "version": "2.1.2",
7
+ "version": "2.1.3",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -2,8 +2,8 @@ import { defineNuxtModule, useLogger, createResolver, addVitePlugin, addPlugin,
2
2
  import { defu } from 'defu';
3
3
  import { DEFAULT_MERMAID_CONFIG, DEFAULT_DARK_THEME, DEFAULT_LIGHT_THEME, DEFAULT_FRONTMATTER_CONFIG_KEY } from '../dist/runtime/constants.js';
4
4
 
5
- const MERMAID_BLOCK = /```mermaid([\s\S]*?)```/gi;
6
5
  const SANITIZE_URL_PACKAGE = "@braintree/sanitize-url";
6
+ const MERMAID_FENCE_RE = /^[ \t]*(?:`{3,}|~{3,})[ \t]*mermaid(?:$|[ \t{[])/im;
7
7
  const DEFAULTS = {
8
8
  enabled: true,
9
9
  loader: {
@@ -106,7 +106,7 @@ export {}
106
106
  nuxt.hook("content:file:beforeParse", (ctx) => {
107
107
  const { file } = ctx;
108
108
  if (!file.id?.endsWith(".md")) return;
109
- if (!file.body.toLowerCase().includes("```mermaid")) return;
109
+ if (!MERMAID_FENCE_RE.test(file.body)) return;
110
110
  file.body = transformMermaidCodeBlocks(
111
111
  file.body,
112
112
  baseMermaidComponentName
@@ -115,12 +115,106 @@ export {}
115
115
  }
116
116
  });
117
117
  function transformMermaidCodeBlocks(body, componentName, frontmatterConfigKey = DEFAULT_FRONTMATTER_CONFIG_KEY) {
118
- return body.replace(MERMAID_BLOCK, (_, rawCode = "") => {
118
+ const newline = body.includes("\r\n") ? "\r\n" : "\n";
119
+ const lines = body.split(newline);
120
+ const output = [];
121
+ let inFence = false;
122
+ let fenceChar = null;
123
+ let fenceLength = 0;
124
+ const isClosingFence = (line) => {
125
+ if (!fenceChar) return false;
126
+ const trimmed = line.trim();
127
+ if (trimmed.length < fenceLength) return false;
128
+ for (const char of trimmed) {
129
+ if (char !== fenceChar) return false;
130
+ }
131
+ return true;
132
+ };
133
+ const isFenceMarkerChar = (char) => char === "`" || char === "~";
134
+ const parseFence = (line) => {
135
+ let index = 0;
136
+ while (index < line.length && (line[index] === " " || line[index] === " "))
137
+ index++;
138
+ const indent = line.slice(0, index);
139
+ const markerChar = line[index];
140
+ if (!isFenceMarkerChar(markerChar))
141
+ return null;
142
+ let markerEnd = index;
143
+ while (markerEnd < line.length && line[markerEnd] === markerChar)
144
+ markerEnd++;
145
+ const markerLength = markerEnd - index;
146
+ if (markerLength < 3)
147
+ return null;
148
+ return {
149
+ indent,
150
+ markerChar,
151
+ markerLength,
152
+ info: line.slice(markerEnd).trim()
153
+ };
154
+ };
155
+ const isMermaidFence = (info) => {
156
+ if (!info) return false;
157
+ const lower = info.toLowerCase();
158
+ if (!lower.startsWith("mermaid")) return false;
159
+ const next = lower.slice("mermaid".length, "mermaid".length + 1);
160
+ return next === "" || /\s/.test(next) || next === "{" || next === "[";
161
+ };
162
+ const buildComponentTag = (encoded) => `<${componentName} :config="${frontmatterConfigKey}" code="${encoded}"></${componentName}>`;
163
+ for (let index = 0; index < lines.length; index++) {
164
+ const line = lines[index];
165
+ if (inFence) {
166
+ output.push(line);
167
+ if (isClosingFence(line)) {
168
+ inFence = false;
169
+ fenceChar = null;
170
+ fenceLength = 0;
171
+ }
172
+ continue;
173
+ }
174
+ const fence = parseFence(line);
175
+ if (!fence) {
176
+ output.push(line);
177
+ continue;
178
+ }
179
+ if (!isMermaidFence(fence.info)) {
180
+ inFence = true;
181
+ fenceChar = fence.markerChar;
182
+ fenceLength = fence.markerLength;
183
+ output.push(line);
184
+ continue;
185
+ }
186
+ let closingIndex = -1;
187
+ for (let j = index + 1; j < lines.length; j++) {
188
+ const trimmed = lines[j].trim();
189
+ if (trimmed.length < fence.markerLength) continue;
190
+ let isFence = true;
191
+ for (const char of trimmed) {
192
+ if (char !== fence.markerChar) {
193
+ isFence = false;
194
+ break;
195
+ }
196
+ }
197
+ if (isFence) {
198
+ closingIndex = j;
199
+ break;
200
+ }
201
+ }
202
+ if (closingIndex === -1) {
203
+ output.push(line);
204
+ continue;
205
+ }
206
+ const rawCode = lines.slice(index + 1, closingIndex).join(newline);
119
207
  const code = rawCode.trim();
120
- if (!code) return _;
208
+ if (!code) {
209
+ output.push(...lines.slice(index, closingIndex + 1));
210
+ index = closingIndex;
211
+ continue;
212
+ }
121
213
  const encoded = encodeURIComponent(code);
122
- return `<${componentName} :config="${frontmatterConfigKey}" code="${encoded}"></${componentName}>`;
123
- });
214
+ output.push(`${fence.indent}${buildComponentTag(encoded)}`);
215
+ index = closingIndex;
216
+ }
217
+ return output.join(newline);
124
218
  }
125
219
 
126
220
  export { module$1 as default, transformMermaidCodeBlocks };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barzhsieh/nuxt-content-mermaid",
3
- "version": "2.1.2",
3
+ "version": "2.1.3",
4
4
  "description": "A Nuxt module designed for integrating Mermaid with `@nuxt/content`. It automatically converts `mermaid` code blocks in Markdown into responsive chart components, and supports lazy loading and dark/light theme switching.",
5
5
  "keywords": [
6
6
  "nuxt",