@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 +2 -0
- package/README.zh-TW.md +3 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +100 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
[English](./README.md) | [中文](./README.zh-TW.md)
|
|
2
2
|
|
|
3
|
+
[](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
|
-
[
|
|
1
|
+
[中文](./README.zh-TW.md) | [English](./README.md)
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@barzhsieh/nuxt-content-mermaid)
|
|
2
4
|
|
|
3
5
|
# nuxt-content-mermaid
|
|
4
6
|
|
package/dist/module.json
CHANGED
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
|
|
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
|
-
|
|
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)
|
|
208
|
+
if (!code) {
|
|
209
|
+
output.push(...lines.slice(index, closingIndex + 1));
|
|
210
|
+
index = closingIndex;
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
121
213
|
const encoded = encodeURIComponent(code);
|
|
122
|
-
|
|
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.
|
|
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",
|