@barzhsieh/nuxt-content-mermaid 2.1.2 → 2.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.
- package/README.md +162 -1
- package/README.zh-TW.md +166 -2
- package/dist/module.d.mts +83 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +126 -9
- package/dist/runtime/components/Mermaid.d.vue.ts +6 -4
- package/dist/runtime/components/Mermaid.vue +492 -36
- package/dist/runtime/components/Mermaid.vue.d.ts +6 -4
- package/dist/runtime/components/MermaidExpandOverlay.d.vue.ts +25 -0
- package/dist/runtime/components/MermaidExpandOverlay.vue +140 -0
- package/dist/runtime/components/MermaidExpandOverlay.vue.d.ts +25 -0
- package/dist/runtime/components/MermaidZoomToolbar.d.vue.ts +23 -0
- package/dist/runtime/components/MermaidZoomToolbar.vue +66 -0
- package/dist/runtime/components/MermaidZoomToolbar.vue.d.ts +23 -0
- package/dist/runtime/components/icons/IconClipboard.d.vue.ts +8 -0
- package/dist/runtime/components/icons/IconClipboard.vue +32 -0
- package/dist/runtime/components/icons/IconClipboard.vue.d.ts +8 -0
- package/dist/runtime/components/icons/IconClipboardHover.d.vue.ts +8 -0
- package/dist/runtime/components/icons/IconClipboardHover.vue +33 -0
- package/dist/runtime/components/icons/IconClipboardHover.vue.d.ts +8 -0
- package/dist/runtime/components/icons/IconClipboardSuccess.d.vue.ts +8 -0
- package/dist/runtime/components/icons/IconClipboardSuccess.vue +33 -0
- package/dist/runtime/components/icons/IconClipboardSuccess.vue.d.ts +8 -0
- package/dist/runtime/components/icons/IconCollapse.d.vue.ts +8 -0
- package/dist/runtime/components/icons/IconCollapse.vue +34 -0
- package/dist/runtime/components/icons/IconCollapse.vue.d.ts +8 -0
- package/dist/runtime/components/icons/IconExpand.d.vue.ts +8 -0
- package/dist/runtime/components/icons/IconExpand.vue +34 -0
- package/dist/runtime/components/icons/IconExpand.vue.d.ts +8 -0
- package/dist/runtime/components/icons/IconMinus.d.vue.ts +8 -0
- package/dist/runtime/components/icons/IconMinus.vue +46 -0
- package/dist/runtime/components/icons/IconMinus.vue.d.ts +8 -0
- package/dist/runtime/components/icons/IconPlus.d.vue.ts +8 -0
- package/dist/runtime/components/icons/IconPlus.vue +57 -0
- package/dist/runtime/components/icons/IconPlus.vue.d.ts +8 -0
- package/dist/runtime/components/icons/iconFullScreen.d.vue.ts +8 -0
- package/dist/runtime/components/icons/iconFullScreen.vue +26 -0
- package/dist/runtime/components/icons/iconFullScreen.vue.d.ts +8 -0
- package/dist/runtime/components/icons/iconFullScreenExit.d.vue.ts +8 -0
- package/dist/runtime/components/icons/iconFullScreenExit.vue +26 -0
- package/dist/runtime/components/icons/iconFullScreenExit.vue.d.ts +8 -0
- package/dist/runtime/composables/_configurable.d.ts +27 -0
- package/dist/runtime/composables/_configurable.js +5 -0
- package/dist/runtime/composables/shared/index.d.ts +5 -0
- package/dist/runtime/composables/shared/index.js +5 -0
- package/dist/runtime/composables/shared/tryOnMounted.d.ts +10 -0
- package/dist/runtime/composables/shared/tryOnMounted.js +11 -0
- package/dist/runtime/composables/shared/tryOnScopeDispose.d.ts +7 -0
- package/dist/runtime/composables/shared/tryOnScopeDispose.js +8 -0
- package/dist/runtime/composables/shared/watchImmediate.d.ts +5 -0
- package/dist/runtime/composables/shared/watchImmediate.js +11 -0
- package/dist/runtime/composables/unrefElement.d.ts +12 -0
- package/dist/runtime/composables/unrefElement.js +5 -0
- package/dist/runtime/composables/useEventListener.d.ts +73 -0
- package/dist/runtime/composables/useEventListener.js +40 -0
- package/dist/runtime/composables/useFullscreen.d.ts +25 -0
- package/dist/runtime/composables/useFullscreen.js +122 -0
- package/dist/runtime/composables/useMermaidCursors.d.ts +12 -0
- package/dist/runtime/composables/useMermaidCursors.js +41 -0
- package/dist/runtime/composables/useMermaidExpand.d.ts +45 -0
- package/dist/runtime/composables/useMermaidExpand.js +480 -0
- package/dist/runtime/composables/useMermaidZoom.d.ts +37 -0
- package/dist/runtime/composables/useMermaidZoom.js +261 -0
- package/dist/runtime/composables/useMounted.d.ts +8 -0
- package/dist/runtime/composables/useMounted.js +16 -0
- package/dist/runtime/composables/useSupported.d.ts +2 -0
- package/dist/runtime/composables/useSupported.js +10 -0
- package/dist/runtime/constants.d.ts +4 -0
- package/dist/runtime/constants.js +24 -0
- package/dist/runtime/mermaid-config.d.ts +1 -1
- package/dist/runtime/plugins/mermaid.client.d.ts +2 -2
- package/dist/runtime/styles.css +1 -0
- package/dist/runtime/types/expand.d.ts +48 -0
- package/dist/runtime/types/expand.js +0 -0
- package/dist/runtime/types/utils.d.ts +115 -0
- package/dist/runtime/types/utils.js +0 -0
- package/dist/runtime/utils/index.d.ts +52 -0
- package/dist/runtime/utils/index.js +113 -0
- package/dist/runtime/utils/is.d.ts +15 -0
- package/dist/runtime/utils/is.js +31 -0
- package/dist/runtime/utils/mermaid-transform.d.ts +18 -0
- package/dist/runtime/utils/mermaid-transform.js +345 -0
- package/dist/runtime/utils/vue.d.ts +2 -0
- package/dist/runtime/utils/vue.js +4 -0
- package/package.json +4 -2
- package/dist/runtime/utils.d.ts +0 -1
- package/dist/runtime/utils.js +0 -30
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
let renderQueue = Promise.resolve();
|
|
2
|
+
let queueSize = 0;
|
|
3
|
+
export function enqueueRender(task, debug = false) {
|
|
4
|
+
queueSize++;
|
|
5
|
+
if (debug) {
|
|
6
|
+
console.log(`[nuxt-content-mermaid] \u{1F535} Enqueueing task. Queue size: ${queueSize}`);
|
|
7
|
+
}
|
|
8
|
+
const wrappedTask = async () => {
|
|
9
|
+
if (debug) {
|
|
10
|
+
console.log(`[nuxt-content-mermaid] \u{1F7E2} Starting render task. Pending: ${queueSize - 1}`);
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
await task();
|
|
14
|
+
} catch (e) {
|
|
15
|
+
console.error("[nuxt-content-mermaid] Render error:", e);
|
|
16
|
+
throw e;
|
|
17
|
+
} finally {
|
|
18
|
+
queueSize--;
|
|
19
|
+
if (debug) {
|
|
20
|
+
console.log(`[nuxt-content-mermaid] \u2705 Task finished. Remaining: ${queueSize}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
renderQueue = renderQueue.then(wrappedTask).catch((e) => {
|
|
25
|
+
if (debug) {
|
|
26
|
+
console.error("[nuxt-content-mermaid] \u274C Queue chain caught error:", e);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
return renderQueue;
|
|
30
|
+
}
|
|
31
|
+
export function parseSizeToPx(value, defaultSize = 14) {
|
|
32
|
+
if (value === void 0 || value === null) return defaultSize;
|
|
33
|
+
if (typeof value === "number") return value;
|
|
34
|
+
const match = value.match(/^([\d.]+)(px|rem|em)?$/);
|
|
35
|
+
if (!match) return defaultSize;
|
|
36
|
+
const num = Number.parseFloat(match[1] || "0");
|
|
37
|
+
const unit = match[2] || "px";
|
|
38
|
+
if (unit === "rem" || unit === "em") {
|
|
39
|
+
return num * 16;
|
|
40
|
+
}
|
|
41
|
+
return num;
|
|
42
|
+
}
|
|
43
|
+
export function promiseTimeout(ms, throwOnTimeout = false, reason = "Timeout") {
|
|
44
|
+
return new Promise((resolve, reject) => {
|
|
45
|
+
if (throwOnTimeout)
|
|
46
|
+
setTimeout(() => reject(reason), ms);
|
|
47
|
+
else
|
|
48
|
+
setTimeout(resolve, ms);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
export function identity(arg) {
|
|
52
|
+
return arg;
|
|
53
|
+
}
|
|
54
|
+
export function createSingletonPromise(fn) {
|
|
55
|
+
let _promise;
|
|
56
|
+
function wrapper() {
|
|
57
|
+
if (!_promise)
|
|
58
|
+
_promise = fn();
|
|
59
|
+
return _promise;
|
|
60
|
+
}
|
|
61
|
+
wrapper.reset = async () => {
|
|
62
|
+
const _prev = _promise;
|
|
63
|
+
_promise = void 0;
|
|
64
|
+
if (_prev)
|
|
65
|
+
await _prev;
|
|
66
|
+
};
|
|
67
|
+
return wrapper;
|
|
68
|
+
}
|
|
69
|
+
export function invoke(fn) {
|
|
70
|
+
return fn();
|
|
71
|
+
}
|
|
72
|
+
export function containsProp(obj, ...props) {
|
|
73
|
+
return props.some((k) => k in obj);
|
|
74
|
+
}
|
|
75
|
+
export function increaseWithUnit(target, delta) {
|
|
76
|
+
if (typeof target === "number")
|
|
77
|
+
return target + delta;
|
|
78
|
+
const value = target.match(/^-?\d+\.?\d*/)?.[0] || "";
|
|
79
|
+
const unit = target.slice(value.length);
|
|
80
|
+
const result = Number.parseFloat(value) + delta;
|
|
81
|
+
if (Number.isNaN(result))
|
|
82
|
+
return target;
|
|
83
|
+
return result + unit;
|
|
84
|
+
}
|
|
85
|
+
export function objectPick(obj, keys, omitUndefined = false) {
|
|
86
|
+
return keys.reduce((n, k) => {
|
|
87
|
+
if (k in obj) {
|
|
88
|
+
if (!omitUndefined || obj[k] !== void 0)
|
|
89
|
+
n[k] = obj[k];
|
|
90
|
+
}
|
|
91
|
+
return n;
|
|
92
|
+
}, {});
|
|
93
|
+
}
|
|
94
|
+
export function objectOmit(obj, keys, omitUndefined = false) {
|
|
95
|
+
return Object.fromEntries(Object.entries(obj).filter(([key, value]) => {
|
|
96
|
+
return (!omitUndefined || value !== void 0) && !keys.includes(key);
|
|
97
|
+
}));
|
|
98
|
+
}
|
|
99
|
+
export function objectEntries(obj) {
|
|
100
|
+
return Object.entries(obj);
|
|
101
|
+
}
|
|
102
|
+
export function toArray(value) {
|
|
103
|
+
return Array.isArray(value) ? value : [value];
|
|
104
|
+
}
|
|
105
|
+
export function escapeHtmlAttribute(value) {
|
|
106
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/'/g, "'");
|
|
107
|
+
}
|
|
108
|
+
export function stringifyInlineValue(value) {
|
|
109
|
+
return escapeHtmlAttribute(JSON.stringify(value));
|
|
110
|
+
}
|
|
111
|
+
export * from "./is.js";
|
|
112
|
+
export * from "./vue.js";
|
|
113
|
+
export * from "./mermaid-transform.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const isClient: boolean;
|
|
2
|
+
export declare const isWorker: boolean;
|
|
3
|
+
export declare const isDef: <T = unknown>(val?: T) => val is T;
|
|
4
|
+
export declare const notNullish: <T = unknown>(val?: T | null | undefined) => val is T;
|
|
5
|
+
export declare const assert: (condition: boolean, ...infos: unknown[]) => void;
|
|
6
|
+
export declare const isObject: (val: unknown) => val is object;
|
|
7
|
+
export declare const now: () => number;
|
|
8
|
+
export declare const timestamp: () => number;
|
|
9
|
+
export declare const clamp: (n: number, min: number, max: number) => number;
|
|
10
|
+
export declare const noop: () => void;
|
|
11
|
+
export declare const rand: (min: number, max: number) => number;
|
|
12
|
+
export declare const hasOwn: <T extends object, K extends keyof T>(val: T, key: K) => key is K;
|
|
13
|
+
export declare const isIOS: boolean;
|
|
14
|
+
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
15
|
+
export declare function isNonEmptyRecord(value: Record<string, unknown>): boolean;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export const isClient = typeof window !== "undefined" && typeof document !== "undefined";
|
|
2
|
+
export const isWorker = typeof WorkerGlobalScope !== "undefined" && globalThis instanceof WorkerGlobalScope;
|
|
3
|
+
export const isDef = (val) => typeof val !== "undefined";
|
|
4
|
+
export const notNullish = (val) => val != null;
|
|
5
|
+
export const assert = (condition, ...infos) => {
|
|
6
|
+
if (!condition)
|
|
7
|
+
console.warn(...infos);
|
|
8
|
+
};
|
|
9
|
+
const toString = Object.prototype.toString;
|
|
10
|
+
export const isObject = (val) => toString.call(val) === "[object Object]";
|
|
11
|
+
export const now = () => Date.now();
|
|
12
|
+
export const timestamp = () => +Date.now();
|
|
13
|
+
export const clamp = (n, min, max) => Math.min(max, Math.max(min, n));
|
|
14
|
+
export const noop = () => {
|
|
15
|
+
};
|
|
16
|
+
export const rand = (min, max) => {
|
|
17
|
+
min = Math.ceil(min);
|
|
18
|
+
max = Math.floor(max);
|
|
19
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
20
|
+
};
|
|
21
|
+
export const hasOwn = (val, key) => Object.prototype.hasOwnProperty.call(val, key);
|
|
22
|
+
export const isIOS = /* @__PURE__ */ getIsIOS();
|
|
23
|
+
function getIsIOS() {
|
|
24
|
+
return isClient && !!window?.navigator?.userAgent && (/iP(?:ad|hone|od)/.test(window.navigator.userAgent) || window?.navigator?.maxTouchPoints > 2 && /iPad|Macintosh/.test(window?.navigator.userAgent));
|
|
25
|
+
}
|
|
26
|
+
export function isRecord(value) {
|
|
27
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
28
|
+
}
|
|
29
|
+
export function isNonEmptyRecord(value) {
|
|
30
|
+
return Object.keys(value).length > 0;
|
|
31
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type MermaidFrontmatterInfo = {
|
|
2
|
+
data: Record<string, unknown>;
|
|
3
|
+
startIndex: number;
|
|
4
|
+
endIndex: number;
|
|
5
|
+
indent: string;
|
|
6
|
+
};
|
|
7
|
+
export type MermaidInlineOverrides = {
|
|
8
|
+
title?: string;
|
|
9
|
+
displayMode?: string;
|
|
10
|
+
config?: Record<string, unknown>;
|
|
11
|
+
toolbar?: Record<string, unknown>;
|
|
12
|
+
};
|
|
13
|
+
export declare function parseMermaidFrontmatter(rawCode: string, newline: string): MermaidFrontmatterInfo | null;
|
|
14
|
+
export declare function parseInlineAttrs(info: string): Record<string, unknown> | null;
|
|
15
|
+
export declare function extractToolbarProps(source: Record<string, unknown> | null | undefined): Record<string, unknown> | undefined;
|
|
16
|
+
export declare function extractMermaidInlineOverrides(source: Record<string, unknown> | null): MermaidInlineOverrides | null;
|
|
17
|
+
export declare function applyMermaidFrontmatterOverrides(rawCode: string, newline: string, frontmatterInfo: MermaidFrontmatterInfo | null, overrides: MermaidInlineOverrides, fallbackIndent: string): string;
|
|
18
|
+
export declare function mergeToolbarProps(yamlToolbar: Record<string, unknown> | undefined, inlineToolbar: Record<string, unknown> | undefined): {} | undefined;
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import { defu } from "defu";
|
|
2
|
+
import destr from "destr";
|
|
3
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
4
|
+
import { isNonEmptyRecord, isRecord } from "./is.js";
|
|
5
|
+
const UNSAFE_INLINE_KEYS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
|
|
6
|
+
export function parseMermaidFrontmatter(rawCode, newline) {
|
|
7
|
+
const lines = rawCode.split(newline);
|
|
8
|
+
let startIndex = 0;
|
|
9
|
+
while (startIndex < lines.length) {
|
|
10
|
+
const line = lines[startIndex];
|
|
11
|
+
const trimmed = line.trim();
|
|
12
|
+
if (!trimmed) {
|
|
13
|
+
startIndex += 1;
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
if (isMermaidDirectiveStart(line)) {
|
|
17
|
+
startIndex = skipMermaidDirective(lines, startIndex);
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (isMermaidCommentLine(line)) {
|
|
21
|
+
startIndex += 1;
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
if (startIndex >= lines.length)
|
|
27
|
+
return null;
|
|
28
|
+
const startLine = lines[startIndex];
|
|
29
|
+
if (startLine.trim() !== "---")
|
|
30
|
+
return null;
|
|
31
|
+
const indentMatch = startLine.match(/^\s*/);
|
|
32
|
+
const indent = indentMatch ? indentMatch[0] : "";
|
|
33
|
+
let endIndex = -1;
|
|
34
|
+
for (let i = startIndex + 1; i < lines.length; i++) {
|
|
35
|
+
if (lines[i].trim() === "---") {
|
|
36
|
+
endIndex = i;
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (endIndex === -1)
|
|
41
|
+
return null;
|
|
42
|
+
const yamlLines = lines.slice(startIndex + 1, endIndex).map((line) => line.startsWith(indent) ? line.slice(indent.length) : line);
|
|
43
|
+
const yamlRaw = yamlLines.join("\n").trim();
|
|
44
|
+
try {
|
|
45
|
+
const data = yamlRaw ? parseYaml(yamlRaw) : {};
|
|
46
|
+
if (!isRecord(data))
|
|
47
|
+
return null;
|
|
48
|
+
return {
|
|
49
|
+
data,
|
|
50
|
+
startIndex,
|
|
51
|
+
endIndex,
|
|
52
|
+
indent
|
|
53
|
+
};
|
|
54
|
+
} catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function isMermaidDirectiveStart(line) {
|
|
59
|
+
return line.trim().startsWith("%%{");
|
|
60
|
+
}
|
|
61
|
+
function isMermaidCommentLine(line) {
|
|
62
|
+
const trimmed = line.trim();
|
|
63
|
+
return trimmed.startsWith("%%") && !trimmed.startsWith("%%{");
|
|
64
|
+
}
|
|
65
|
+
function skipMermaidDirective(lines, startIndex) {
|
|
66
|
+
let index = startIndex;
|
|
67
|
+
while (index < lines.length) {
|
|
68
|
+
if (lines[index].includes("}%%"))
|
|
69
|
+
return index + 1;
|
|
70
|
+
index += 1;
|
|
71
|
+
}
|
|
72
|
+
return lines.length;
|
|
73
|
+
}
|
|
74
|
+
export function parseInlineAttrs(info) {
|
|
75
|
+
const attrsBlock = extractInlineAttrsBlock(info);
|
|
76
|
+
if (!attrsBlock)
|
|
77
|
+
return null;
|
|
78
|
+
return parseInlineAttrsBlock(attrsBlock);
|
|
79
|
+
}
|
|
80
|
+
function extractInlineAttrsBlock(info) {
|
|
81
|
+
const startIndex = info.indexOf("{");
|
|
82
|
+
if (startIndex === -1)
|
|
83
|
+
return null;
|
|
84
|
+
let depth = 0;
|
|
85
|
+
let quote = null;
|
|
86
|
+
for (let i = startIndex; i < info.length; i++) {
|
|
87
|
+
const char = info[i];
|
|
88
|
+
if (quote) {
|
|
89
|
+
if (char === quote && info[i - 1] !== "\\")
|
|
90
|
+
quote = null;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (char === '"' || char === "'") {
|
|
94
|
+
quote = char;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (char === "{") {
|
|
98
|
+
depth += 1;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (char === "}") {
|
|
102
|
+
depth -= 1;
|
|
103
|
+
if (depth === 0)
|
|
104
|
+
return info.slice(startIndex + 1, i);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
function parseInlineAttrsBlock(raw) {
|
|
110
|
+
const result = {};
|
|
111
|
+
let index = 0;
|
|
112
|
+
while (index < raw.length) {
|
|
113
|
+
index = skipSeparators(raw, index);
|
|
114
|
+
if (index >= raw.length)
|
|
115
|
+
break;
|
|
116
|
+
const keyStart = index;
|
|
117
|
+
while (index < raw.length && isAttrKeyChar(raw[index]))
|
|
118
|
+
index += 1;
|
|
119
|
+
const key = raw.slice(keyStart, index).trim();
|
|
120
|
+
if (!key)
|
|
121
|
+
break;
|
|
122
|
+
index = skipWhitespace(raw, index);
|
|
123
|
+
let value = true;
|
|
124
|
+
if (index < raw.length && (raw[index] === "=" || raw[index] === ":")) {
|
|
125
|
+
index += 1;
|
|
126
|
+
index = skipWhitespace(raw, index);
|
|
127
|
+
const { value: rawValue, nextIndex, quoted } = readAttributeValue(raw, index);
|
|
128
|
+
index = nextIndex;
|
|
129
|
+
value = parseAttributeValue(rawValue, quoted);
|
|
130
|
+
}
|
|
131
|
+
setNestedValue(result, key, value);
|
|
132
|
+
}
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
function skipWhitespace(input, index) {
|
|
136
|
+
let cursor = index;
|
|
137
|
+
while (cursor < input.length) {
|
|
138
|
+
const char = input[cursor];
|
|
139
|
+
if (char !== " " && char !== " " && char !== "\n" && char !== "\r")
|
|
140
|
+
break;
|
|
141
|
+
cursor += 1;
|
|
142
|
+
}
|
|
143
|
+
return cursor;
|
|
144
|
+
}
|
|
145
|
+
function skipSeparators(input, index) {
|
|
146
|
+
let cursor = index;
|
|
147
|
+
while (cursor < input.length) {
|
|
148
|
+
const char = input[cursor];
|
|
149
|
+
if (char !== " " && char !== " " && char !== "\n" && char !== "\r" && char !== ";")
|
|
150
|
+
break;
|
|
151
|
+
cursor += 1;
|
|
152
|
+
}
|
|
153
|
+
return cursor;
|
|
154
|
+
}
|
|
155
|
+
function isAttrKeyChar(char) {
|
|
156
|
+
return /[\w.-]/.test(char);
|
|
157
|
+
}
|
|
158
|
+
function readAttributeValue(input, start) {
|
|
159
|
+
const char = input[start];
|
|
160
|
+
if (char === '"' || char === "'")
|
|
161
|
+
return readQuotedValue(input, start);
|
|
162
|
+
if (char === "{" || char === "[")
|
|
163
|
+
return readBalancedValue(input, start);
|
|
164
|
+
let end = start;
|
|
165
|
+
while (end < input.length) {
|
|
166
|
+
const current = input[end];
|
|
167
|
+
if (current === ";" || current === " " || current === " " || current === "\n" || current === "\r")
|
|
168
|
+
break;
|
|
169
|
+
end += 1;
|
|
170
|
+
}
|
|
171
|
+
return { value: input.slice(start, end), nextIndex: end, quoted: false };
|
|
172
|
+
}
|
|
173
|
+
function readQuotedValue(input, start) {
|
|
174
|
+
const quote = input[start];
|
|
175
|
+
let cursor = start + 1;
|
|
176
|
+
let result = "";
|
|
177
|
+
while (cursor < input.length) {
|
|
178
|
+
const char = input[cursor];
|
|
179
|
+
if (char === "\\" && cursor + 1 < input.length) {
|
|
180
|
+
result += input[cursor + 1];
|
|
181
|
+
cursor += 2;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (char === quote) {
|
|
185
|
+
return { value: result, nextIndex: cursor + 1, quoted: true };
|
|
186
|
+
}
|
|
187
|
+
result += char;
|
|
188
|
+
cursor += 1;
|
|
189
|
+
}
|
|
190
|
+
return { value: result, nextIndex: cursor, quoted: true };
|
|
191
|
+
}
|
|
192
|
+
function readBalancedValue(input, start) {
|
|
193
|
+
const open = input[start];
|
|
194
|
+
const close = open === "{" ? "}" : "]";
|
|
195
|
+
let depth = 0;
|
|
196
|
+
let quote = null;
|
|
197
|
+
for (let i = start; i < input.length; i++) {
|
|
198
|
+
const char = input[i];
|
|
199
|
+
if (quote) {
|
|
200
|
+
if (char === quote && input[i - 1] !== "\\")
|
|
201
|
+
quote = null;
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
if (char === '"' || char === "'") {
|
|
205
|
+
quote = char;
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
if (char === open) {
|
|
209
|
+
depth += 1;
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
if (char === close) {
|
|
213
|
+
depth -= 1;
|
|
214
|
+
if (depth === 0) {
|
|
215
|
+
return { value: input.slice(start, i + 1), nextIndex: i + 1, quoted: false };
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return { value: input.slice(start), nextIndex: input.length, quoted: false };
|
|
220
|
+
}
|
|
221
|
+
function parseAttributeValue(raw, quoted) {
|
|
222
|
+
const value = raw.trim();
|
|
223
|
+
if (!value)
|
|
224
|
+
return "";
|
|
225
|
+
const isStructured = value.startsWith("{") || value.startsWith("[");
|
|
226
|
+
if (quoted) {
|
|
227
|
+
if (!isStructured)
|
|
228
|
+
return value;
|
|
229
|
+
return parseStructuredValue(value);
|
|
230
|
+
}
|
|
231
|
+
if (isStructured)
|
|
232
|
+
return parseStructuredValue(value);
|
|
233
|
+
return destr(value);
|
|
234
|
+
}
|
|
235
|
+
function parseStructuredValue(value) {
|
|
236
|
+
const parsed = destr(value);
|
|
237
|
+
if (parsed !== value)
|
|
238
|
+
return parsed;
|
|
239
|
+
try {
|
|
240
|
+
const yamlParsed = parseYaml(value);
|
|
241
|
+
if (isRecord(yamlParsed) || Array.isArray(yamlParsed))
|
|
242
|
+
return yamlParsed;
|
|
243
|
+
} catch {
|
|
244
|
+
}
|
|
245
|
+
return value;
|
|
246
|
+
}
|
|
247
|
+
function setNestedValue(target, path, value) {
|
|
248
|
+
const keys = path.split(".").filter(Boolean);
|
|
249
|
+
if (!keys.length)
|
|
250
|
+
return;
|
|
251
|
+
let current = target;
|
|
252
|
+
for (let i = 0; i < keys.length; i++) {
|
|
253
|
+
const key = keys[i];
|
|
254
|
+
if (UNSAFE_INLINE_KEYS.has(key))
|
|
255
|
+
return;
|
|
256
|
+
if (i === keys.length - 1) {
|
|
257
|
+
current[key] = value;
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
const existing = current[key];
|
|
261
|
+
if (!isRecord(existing)) {
|
|
262
|
+
current[key] = {};
|
|
263
|
+
}
|
|
264
|
+
current = current[key];
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
export function extractToolbarProps(source) {
|
|
268
|
+
if (!source)
|
|
269
|
+
return void 0;
|
|
270
|
+
return isRecord(source.toolbar) ? source.toolbar : void 0;
|
|
271
|
+
}
|
|
272
|
+
export function extractMermaidInlineOverrides(source) {
|
|
273
|
+
if (!source)
|
|
274
|
+
return null;
|
|
275
|
+
const overrides = {};
|
|
276
|
+
let hasOverrides = false;
|
|
277
|
+
if (source.title !== void 0) {
|
|
278
|
+
overrides.title = String(source.title);
|
|
279
|
+
hasOverrides = true;
|
|
280
|
+
}
|
|
281
|
+
if (source.displayMode !== void 0) {
|
|
282
|
+
overrides.displayMode = String(source.displayMode);
|
|
283
|
+
hasOverrides = true;
|
|
284
|
+
}
|
|
285
|
+
if (isRecord(source.config)) {
|
|
286
|
+
overrides.config = source.config;
|
|
287
|
+
hasOverrides = true;
|
|
288
|
+
}
|
|
289
|
+
if (isRecord(source.toolbar)) {
|
|
290
|
+
overrides.toolbar = source.toolbar;
|
|
291
|
+
hasOverrides = true;
|
|
292
|
+
}
|
|
293
|
+
return hasOverrides ? overrides : null;
|
|
294
|
+
}
|
|
295
|
+
export function applyMermaidFrontmatterOverrides(rawCode, newline, frontmatterInfo, overrides, fallbackIndent) {
|
|
296
|
+
const mergedFrontmatter = mergeMermaidFrontmatter(frontmatterInfo?.data, overrides);
|
|
297
|
+
const frontmatterLines = serializeMermaidFrontmatter(
|
|
298
|
+
mergedFrontmatter,
|
|
299
|
+
frontmatterInfo?.indent ?? fallbackIndent
|
|
300
|
+
);
|
|
301
|
+
const lines = rawCode.split(newline);
|
|
302
|
+
if (frontmatterInfo) {
|
|
303
|
+
const before = lines.slice(0, frontmatterInfo.startIndex);
|
|
304
|
+
const after = lines.slice(frontmatterInfo.endIndex + 1);
|
|
305
|
+
return [...frontmatterLines, ...before, ...after].join(newline);
|
|
306
|
+
}
|
|
307
|
+
return [
|
|
308
|
+
...frontmatterLines,
|
|
309
|
+
...lines
|
|
310
|
+
].join(newline);
|
|
311
|
+
}
|
|
312
|
+
function mergeMermaidFrontmatter(existing, overrides) {
|
|
313
|
+
const merged = existing ? { ...existing } : {};
|
|
314
|
+
if (overrides.title !== void 0)
|
|
315
|
+
merged.title = overrides.title;
|
|
316
|
+
if (overrides.displayMode !== void 0)
|
|
317
|
+
merged.displayMode = overrides.displayMode;
|
|
318
|
+
if (overrides.config && isRecord(overrides.config)) {
|
|
319
|
+
const baseConfig = isRecord(merged.config) ? merged.config : void 0;
|
|
320
|
+
merged.config = defu({}, overrides.config, baseConfig || {});
|
|
321
|
+
}
|
|
322
|
+
if (overrides.toolbar && isRecord(overrides.toolbar)) {
|
|
323
|
+
const baseToolbar = isRecord(merged.toolbar) ? merged.toolbar : void 0;
|
|
324
|
+
merged.toolbar = defu({}, overrides.toolbar, baseToolbar || {});
|
|
325
|
+
}
|
|
326
|
+
return merged;
|
|
327
|
+
}
|
|
328
|
+
export function mergeToolbarProps(yamlToolbar, inlineToolbar) {
|
|
329
|
+
const merged = defu(
|
|
330
|
+
{},
|
|
331
|
+
inlineToolbar || {},
|
|
332
|
+
yamlToolbar || {}
|
|
333
|
+
);
|
|
334
|
+
return isNonEmptyRecord(merged) ? merged : void 0;
|
|
335
|
+
}
|
|
336
|
+
function serializeMermaidFrontmatter(frontmatter, indent) {
|
|
337
|
+
const yaml = stringifyYaml(frontmatter).trim();
|
|
338
|
+
const yamlLines = yaml ? yaml.split("\n").map((line) => `${indent}${line}`) : [];
|
|
339
|
+
const delimiter = `${indent}---`;
|
|
340
|
+
return [
|
|
341
|
+
delimiter,
|
|
342
|
+
...yamlLines,
|
|
343
|
+
delimiter
|
|
344
|
+
];
|
|
345
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barzhsieh/nuxt-content-mermaid",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
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",
|
|
@@ -38,7 +38,9 @@
|
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@nuxt/kit": "4.2.1",
|
|
40
40
|
"defu": "^6.1.4",
|
|
41
|
-
"
|
|
41
|
+
"destr": "^2.0.5",
|
|
42
|
+
"mermaid": "^11.12.2",
|
|
43
|
+
"yaml": "^2.8.2"
|
|
42
44
|
},
|
|
43
45
|
"peerDependencies": {
|
|
44
46
|
"@nuxt/content": ">=3.5.0",
|
package/dist/runtime/utils.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function enqueueRender(task: () => Promise<void>, debug?: boolean): Promise<void>;
|
package/dist/runtime/utils.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
let renderQueue = Promise.resolve();
|
|
2
|
-
let queueSize = 0;
|
|
3
|
-
export function enqueueRender(task, debug = false) {
|
|
4
|
-
queueSize++;
|
|
5
|
-
if (debug) {
|
|
6
|
-
console.log(`[nuxt-content-mermaid] \u{1F535} Enqueueing task. Queue size: ${queueSize}`);
|
|
7
|
-
}
|
|
8
|
-
const wrappedTask = async () => {
|
|
9
|
-
if (debug) {
|
|
10
|
-
console.log(`[nuxt-content-mermaid] \u{1F7E2} Starting render task. Pending: ${queueSize - 1}`);
|
|
11
|
-
}
|
|
12
|
-
try {
|
|
13
|
-
await task();
|
|
14
|
-
} catch (e) {
|
|
15
|
-
console.error("[nuxt-content-mermaid] Render error:", e);
|
|
16
|
-
throw e;
|
|
17
|
-
} finally {
|
|
18
|
-
queueSize--;
|
|
19
|
-
if (debug) {
|
|
20
|
-
console.log(`[nuxt-content-mermaid] \u2705 Task finished. Remaining: ${queueSize}`);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
renderQueue = renderQueue.then(wrappedTask).catch((e) => {
|
|
25
|
-
if (debug) {
|
|
26
|
-
console.error("[nuxt-content-mermaid] \u274C Queue chain caught error:", e);
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
return renderQueue;
|
|
30
|
-
}
|