@barzhsieh/nuxt-content-mermaid 2.0.1 → 2.1.0-alpha.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.
package/README.md CHANGED
@@ -95,7 +95,6 @@ export default defineNuxtConfig({
95
95
  lazy: true,
96
96
  },
97
97
  theme: {
98
- useColorModeTheme: true,
99
98
  light: "default",
100
99
  dark: "dark",
101
100
  },
@@ -126,11 +125,12 @@ export default defineNuxtConfig({
126
125
 
127
126
  **theme**
128
127
 
129
- | Option | Type | Default | Description |
130
- | :-------------------------- | :------ | :---------- | :-------------------------------------------------------------------------------------------------------- |
131
- | `theme.useColorModeTheme` | boolean | `true` | If `@nuxtjs/color-mode` is installed, automatically follow its current theme. |
132
- | `theme.light` | string | `'default'` | Mermaid theme to use when color mode is light (and as fallback when color-mode is off). |
133
- | `theme.dark` | string | `'dark'` | Mermaid theme to use when color mode is dark (and as fallback when color-mode is off). |
128
+ Color mode integration is automatic when `@nuxtjs/color-mode` is installed; manual themes set via `useMermaidTheme()` take precedence.
129
+
130
+ | Option | Type | Default | Description |
131
+ | :---------------- | :----- | :---------- | :------------------------------------------------------------------------------------------ |
132
+ | `theme.light` | string | `'default'` | Mermaid theme to use when color mode is light (and as fallback when color-mode is missing). |
133
+ | `theme.dark` | string | `'dark'` | Mermaid theme to use when color mode is dark (and as fallback when color-mode is missing). |
134
134
 
135
135
  **components**
136
136
 
@@ -157,16 +157,43 @@ export default defineNuxtConfig({
157
157
 
158
158
  The module determines the active Mermaid theme with the following priority:
159
159
 
160
- 1. If `theme.useColorModeTheme: true` _and_ `@nuxtjs/color-mode` is available:
161
- - `dark` → `theme.dark`
162
- - `light` → `theme.light`
163
- 2. Otherwise (color-mode missing or `theme.useColorModeTheme` is `false`):
164
- - Use `loader.init.theme` if provided.
165
- - Else fall back to `theme.light`, then `theme.dark`.
160
+ 1. Frontmatter `config.theme` (per-page override)
161
+ 2. Manual mode via `useMermaidTheme()` (if set)
162
+ 3. `@nuxtjs/color-mode` (auto-detected when installed):
163
+ - `dark` → `theme.dark`
164
+ - `light` → `theme.light`
165
+ 4. `loader.init.theme` (if provided)
166
+ 5. Fallback: `theme.light`, then Mermaid default `'default'`
167
+
168
+ For advanced manual control (e.g., forcing specific themes, custom toggle logic), please refer to the [Manual Theme Control Guide](./docs/en/MANUAL_THEME_CONTROL.md).
166
169
 
167
170
  ### Override Per-Page Settings with Frontmatter
168
171
 
169
172
  Each Markdown file can override module settings by adding a `config` field in the frontmatter.
173
+
174
+ > **⚠️ To use frontmatter `config` overrides, you MUST declare the `config` field in your collection schema in `content.config.ts`.**
175
+ > Without this, Nuxt Content will not parse the `config` field as a JSON object, and your overrides will not work.
176
+
177
+ Add this to your `content.config.ts`:
178
+
179
+ ```ts
180
+ import { defineContentConfig, defineCollection, z } from '@nuxt/content'
181
+
182
+ export default defineContentConfig({
183
+ collections: {
184
+ content: defineCollection({
185
+ type: 'page',
186
+ source: '**',
187
+ schema: z.object({
188
+ config: z.record(z.unknown()).optional(), // ← Declare config field
189
+ }).passthrough(),
190
+ }),
191
+ },
192
+ })
193
+ ```
194
+
195
+ Then use it in your Markdown frontmatter:
196
+
170
197
  ````markdown
171
198
  ---
172
199
  title: Example of Overriding Mermaid Settings Per Page
@@ -181,24 +208,6 @@ flowchart LR
181
208
  ```
182
209
  ````
183
210
 
184
- > **Important: If you want to control settings via frontmatter, declare it in the collection schema in `content.config.ts`, for example:**
185
- >
186
- > ```ts
187
- > import { defineContentConfig, defineCollection, z } from '@nuxt/content'
188
- >
189
- > export default defineContentConfig({
190
- > collections: {
191
- > content: defineCollection({
192
- > type: 'page',
193
- > source: '**',
194
- > schema: z.object({
195
- > config: z.record(z.unknown()).optional(), // Declare config field
196
- > }).passthrough(),
197
- > }),
198
- > },
199
- > })
200
- > ```
201
-
202
211
  ### Priority Order of `%%{init}%%` Syntax, Frontmatter, and Module Settings
203
212
 
204
213
  Mermaid itself also supports overriding settings within diagrams using the `%%{init: ...}%%` syntax, for example:
package/README.zh-TW.md CHANGED
@@ -95,7 +95,6 @@ export default defineNuxtConfig({
95
95
  lazy: true,
96
96
  },
97
97
  theme: {
98
- useColorModeTheme: true,
99
98
  light: "default",
100
99
  dark: "dark",
101
100
  },
@@ -126,11 +125,12 @@ export default defineNuxtConfig({
126
125
 
127
126
  **theme**
128
127
 
129
- | 參數 | 類型 | 預設值 | 說明 |
130
- | :-------------------------- | :------ | :---------- | :------------------------------------------------------------------------------------------------------ |
131
- | `theme.useColorModeTheme` | boolean | `true` | 若安裝了 `@nuxtjs/color-mode`,是否自動跟隨其主題。 |
132
- | `theme.light` | string | `'default'` | 當 `colorMode` 為 light 時的主題,也可作為 fallback。 |
133
- | `theme.dark` | string | `'dark'` | 當 `colorMode` 為 dark 時的主題,也可作為 fallback。 |
128
+ 若專案安裝了 `@nuxtjs/color-mode` 會自動偵測並跟隨;透過 `useMermaidTheme()` 設定的手動主題會優先。
129
+
130
+ | 參數 | 類型 | 預設值 | 說明 |
131
+ | :------------ | :----- | :---------- | :-------------------------------------------------------------------------------- |
132
+ | `theme.light` | string | `'default'` | 當 color-mode 為 light 時的主題,若 color-mode 不存在也會回退使用。 |
133
+ | `theme.dark` | string | `'dark'` | 當 color-mode 為 dark 時的主題,若 color-mode 不存在也會回退使用。 |
134
134
 
135
135
  **components**
136
136
 
@@ -153,21 +153,47 @@ export default defineNuxtConfig({
153
153
  - **Debug 關閉**:`mermaid.run` 使用 `suppressErrors: true`,避免單一圖表錯誤中斷其他圖表的渲染。
154
154
  - **主控台輸出**:模組會額外輸出渲染佇列的診斷資訊與執行時間統計。
155
155
 
156
- ### 主題與顏色模式 (Color Mode)
156
+ ### 主題與顏色模式 (Theme & Color Mode)
157
157
 
158
158
  模組會依據以下優先順序決定主題:
159
159
 
160
- 1. 若 `theme.useColorModeTheme: true`,且專案有安裝 `@nuxtjs/color-mode`:
161
- - 偵測為 `dark` → 使用 `theme.dark`
162
- - 偵測為 `light` → 使用 `theme.light`
163
- 2. 否則(color-mode 未安裝或 `theme.useColorModeTheme` 為 `false`):
164
- - 優先使用 `loader.init.theme`。
165
- - 若未提供,依序回退至 `theme.light`,若沒有設置則會回退至 `theme.dark`。
160
+ 1. Frontmatter `config.theme`(單篇覆寫)
161
+ 2. `useMermaidTheme()` 設定的手動模式(若有)
162
+ 3. `@nuxtjs/color-mode`(安裝時自動偵測):
163
+ - `dark` → 使用 `theme.dark`
164
+ - `light` → 使用 `theme.light`
165
+ 4. `loader.init.theme`(若有設定)
166
+ 5. 回退:`theme.light`,若無則 Mermaid 預設 `'default'`
167
+
168
+ 更多進階手動控制(如:強制指定特定主題、自訂切換邏輯),請參閱 [手動主題控制指南](./docs/ch/MANUAL_THEME_CONTROL.md)。
166
169
 
167
170
  ### 以 frontmatter 覆寫單頁設定
168
171
 
169
172
  每篇 Markdown 都可以透過於 frontmatter 中加入 `config` 欄位來覆寫模組設定。
170
173
 
174
+ > **⚠️ 若要使用 frontmatter `config` 覆寫,務必在 `content.config.ts` 的 collection schema 中宣告 `config` 欄位。**
175
+ > 若未宣告,Nuxt Content 不會將 `config` 解析為 JSON 物件,覆寫將無法生效。
176
+
177
+ 在 `content.config.ts` 加上:
178
+
179
+ ```ts
180
+ import { defineContentConfig, defineCollection, z } from '@nuxt/content'
181
+
182
+ export default defineContentConfig({
183
+ collections: {
184
+ content: defineCollection({
185
+ type: 'page',
186
+ source: '**',
187
+ schema: z.object({
188
+ config: z.record(z.unknown()).optional(), // 宣告 config 欄位
189
+ }).passthrough(),
190
+ }),
191
+ },
192
+ })
193
+ ```
194
+
195
+ 接著在 Markdown frontmatter 使用:
196
+
171
197
  ````markdown
172
198
  ---
173
199
  title: 單篇覆寫 Mermaid 設定範例
@@ -183,24 +209,6 @@ flowchart LR
183
209
  ```
184
210
  ````
185
211
 
186
- > **重要:如果要使用 frontmatter 控制設定,請在 `content.config.ts` 的 collection schema 中宣告它,例如:**
187
- >
188
- > ```ts
189
- > import { defineContentConfig, defineCollection, z } from '@nuxt/content'
190
- >
191
- > export default defineContentConfig({
192
- > collections: {
193
- > content: defineCollection({
194
- > type: 'page',
195
- > source: '**',
196
- > schema: z.object({
197
- > config: z.record(z.unknown()).optional(), // 宣告 config 欄位
198
- > }).passthrough(),
199
- > }),
200
- > },
201
- > })
202
- > ```
203
-
204
212
  ### `%%{init}%%` 語法、frontmatter 與模組設定的優先順序
205
213
 
206
214
  Mermaid 本身也支援在圖表內透過 `%%{init: ...}%%` 語法覆寫設定,例如:
package/dist/module.d.mts CHANGED
@@ -34,8 +34,8 @@ interface ModuleOptions {
34
34
  */
35
35
  theme?: {
36
36
  /**
37
- * Whether to sync Mermaid theme with @nuxtjs/color-mode
38
- * @default true
37
+ * @deprecated The module now automatically detects and syncs with @nuxtjs/color-mode.
38
+ * This option no longer has any effect and will be removed in a future version.
39
39
  */
40
40
  useColorModeTheme?: boolean;
41
41
  light?: MermaidConfig['theme'];
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.0.1",
7
+ "version": "2.1.0-alpha.1",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { defineNuxtModule, useLogger, createResolver, addVitePlugin, addPlugin, addComponent, addTypeTemplate } from '@nuxt/kit';
1
+ import { defineNuxtModule, useLogger, createResolver, addVitePlugin, addPlugin, addComponent, addImports, addTypeTemplate } from '@nuxt/kit';
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
 
@@ -11,7 +11,6 @@ const DEFAULTS = {
11
11
  lazy: true
12
12
  },
13
13
  theme: {
14
- useColorModeTheme: true,
15
14
  light: DEFAULT_LIGHT_THEME,
16
15
  dark: DEFAULT_DARK_THEME
17
16
  },
@@ -79,6 +78,13 @@ const module$1 = defineNuxtModule({
79
78
  name: baseMermaidComponentName,
80
79
  filePath: resolver.resolve(runtimeDir, "components/Mermaid.vue")
81
80
  });
81
+ addImports([
82
+ {
83
+ name: "useMermaidTheme",
84
+ as: "useMermaidTheme",
85
+ from: resolver.resolve(runtimeDir, "composables/useMermaidTheme")
86
+ }
87
+ ]);
82
88
  addTypeTemplate({
83
89
  filename: "types/mermaid-content.d.ts",
84
90
  getContents: () => `
@@ -12,6 +12,7 @@ import {
12
12
  } from "vue";
13
13
  import { mergeMermaidConfig, resolveMermaidTheme } from "../mermaid-config";
14
14
  import { enqueueRender } from "../utils";
15
+ import { useMermaidTheme } from "../composables/useMermaidTheme";
15
16
  import Spinner from "./Spinner.vue";
16
17
  const props = defineProps({
17
18
  config: { type: null, required: false },
@@ -29,11 +30,11 @@ const lazyOption = loaderOptions.lazy;
29
30
  const isLazy = lazyOption !== false;
30
31
  const lazyThreshold = typeof lazyOption === "object" && typeof lazyOption.threshold === "number" ? lazyOption.threshold : 0.1;
31
32
  const baseMermaidInit = loaderOptions.init || {};
32
- const useColorModeTheme = themeOptions.useColorModeTheme;
33
33
  const lightTheme = themeOptions.light;
34
34
  const darkTheme = themeOptions.dark;
35
35
  const colorMode = nuxtApp.$colorMode;
36
36
  const { $mermaid } = nuxtApp;
37
+ const { currentTheme: manualThemeMode } = useMermaidTheme();
37
38
  const mermaidContainer = useTemplateRef("mermaidContainer");
38
39
  const hasRenderedOnce = ref(false);
39
40
  const isLoading = ref(false);
@@ -47,9 +48,9 @@ const frontmatterConfig = computed(() => {
47
48
  if (!value)
48
49
  return void 0;
49
50
  if (typeof value !== "object") {
50
- if (import.meta.dev) {
51
+ if (import.meta.dev && value !== null && value !== void 0) {
51
52
  console.warn(
52
- "[nuxt-content-mermaid] Ignoring non-object `config` prop on <Mermaid> component. This usually means your `content.config.ts` collection schema did not declare `config` as a JSON field. See README section about per-page overrides via frontmatter.",
53
+ "[nuxt-content-mermaid] Received non-object `config` prop on <Mermaid> component. This usually means your `content.config.ts` collection schema did not declare `config` as a JSON field. See README section about per-page overrides via frontmatter.",
53
54
  value
54
55
  );
55
56
  }
@@ -59,8 +60,8 @@ const frontmatterConfig = computed(() => {
59
60
  });
60
61
  const mermaidTheme = computed(() => {
61
62
  return resolveMermaidTheme({
62
- useColorModeTheme,
63
63
  colorModeValue: colorMode?.value,
64
+ manualThemeMode: manualThemeMode.value,
64
65
  frontmatterTheme: frontmatterConfig.value?.theme,
65
66
  baseTheme: baseMermaidInit.theme,
66
67
  lightTheme,
@@ -0,0 +1,48 @@
1
+ import type { MermaidConfig } from 'mermaid';
2
+ /**
3
+ * 簡寫模式主題,用於快速切換配置的 light/dark 主題
4
+ * - 'light': 對應 contentMermaid.theme.light 設定
5
+ * - 'dark': 對應 contentMermaid.theme.dark 設定
6
+ * @see https://mermaid.js.org/ecosystem/integrations.html
7
+ */
8
+ export type SimpleMermaidTheme = 'light' | 'dark';
9
+ /**
10
+ * Mermaid 主題類型
11
+ * 可以是:
12
+ * - 簡寫模式: 'light', 'dark' (對應配置的 light/dark 主題)
13
+ * - 官方主題: 'default', 'forest', 'dark', 'neutral', 'base' 等
14
+ * - null: 重置為自動模式
15
+ */
16
+ export type MermaidThemeMode = MermaidConfig['theme'] | SimpleMermaidTheme | null;
17
+ /**
18
+ * Composable for managing Mermaid theme independently of @nuxtjs/color-mode
19
+ *
20
+ * @example
21
+ * ```vue
22
+ * <script setup>
23
+ * const { setMermaidTheme, currentTheme } = useMermaidTheme()
24
+ *
25
+ * function toggleTheme() {
26
+ * setMermaidTheme(currentTheme.value === 'dark' ? 'light' : 'dark')
27
+ * }
28
+ * </script>
29
+ * ```
30
+ */
31
+ export declare function useMermaidTheme(): {
32
+ /**
33
+ * The current manual theme mode (reactive ref)
34
+ */
35
+ currentTheme: import("vue").Ref<MermaidThemeMode, MermaidThemeMode>;
36
+ /**
37
+ * Set the Mermaid theme manually
38
+ */
39
+ setMermaidTheme: (mode: MermaidThemeMode) => void;
40
+ /**
41
+ * Get the current manual theme mode
42
+ */
43
+ getMermaidTheme: () => MermaidThemeMode;
44
+ /**
45
+ * Reset to automatic theme mode
46
+ */
47
+ resetMermaidTheme: () => void;
48
+ };
@@ -0,0 +1,31 @@
1
+ import { useState } from "#app";
2
+ export function useMermaidTheme() {
3
+ const manualThemeMode = useState("mermaid-theme-mode", () => null);
4
+ function setMermaidTheme(mode) {
5
+ manualThemeMode.value = mode;
6
+ }
7
+ function getMermaidTheme() {
8
+ return manualThemeMode.value;
9
+ }
10
+ function resetMermaidTheme() {
11
+ manualThemeMode.value = null;
12
+ }
13
+ return {
14
+ /**
15
+ * The current manual theme mode (reactive ref)
16
+ */
17
+ currentTheme: manualThemeMode,
18
+ /**
19
+ * Set the Mermaid theme manually
20
+ */
21
+ setMermaidTheme,
22
+ /**
23
+ * Get the current manual theme mode
24
+ */
25
+ getMermaidTheme,
26
+ /**
27
+ * Reset to automatic theme mode
28
+ */
29
+ resetMermaidTheme
30
+ };
31
+ }
@@ -1,13 +1,14 @@
1
1
  import type { MermaidConfig } from 'mermaid';
2
+ import type { MermaidThemeMode } from './composables/useMermaidTheme.js';
2
3
  interface ThemeOptions {
3
- useColorModeTheme?: boolean;
4
4
  colorModeValue?: string;
5
+ manualThemeMode?: MermaidThemeMode;
5
6
  baseTheme?: MermaidConfig['theme'];
6
7
  lightTheme?: MermaidConfig['theme'];
7
8
  darkTheme?: MermaidConfig['theme'];
8
9
  frontmatterTheme?: MermaidConfig['theme'];
9
10
  }
10
- export declare function resolveMermaidTheme(options: ThemeOptions): "default" | "base" | "dark" | "forest" | "neutral" | "null" | undefined;
11
+ export declare function resolveMermaidTheme(options: ThemeOptions): "default" | "base" | "dark" | "forest" | "neutral" | "null";
11
12
  interface MergeOptions extends MermaidConfig {
12
13
  baseConfig?: MermaidConfig;
13
14
  overrideConfig?: MermaidConfig;
@@ -1,19 +1,27 @@
1
1
  import { defu } from "defu";
2
2
  export function resolveMermaidTheme(options) {
3
3
  const {
4
- useColorModeTheme,
5
4
  colorModeValue,
5
+ manualThemeMode,
6
6
  frontmatterTheme,
7
7
  baseTheme,
8
8
  lightTheme,
9
9
  darkTheme
10
10
  } = options;
11
11
  if (frontmatterTheme) return frontmatterTheme;
12
- if (useColorModeTheme && colorModeValue) {
13
- if (colorModeValue === "dark" && darkTheme) return darkTheme;
14
- if (colorModeValue !== "dark" && lightTheme) return lightTheme;
12
+ if (manualThemeMode) {
13
+ if (manualThemeMode === "dark") return darkTheme ?? "dark";
14
+ if (manualThemeMode === "light") return lightTheme ?? "default";
15
+ return manualThemeMode;
15
16
  }
16
- return baseTheme ?? lightTheme ?? darkTheme;
17
+ if (colorModeValue) {
18
+ if (colorModeValue === "dark") {
19
+ return darkTheme ?? "dark";
20
+ } else {
21
+ return lightTheme ?? "default";
22
+ }
23
+ }
24
+ return baseTheme ?? lightTheme ?? "default";
17
25
  }
18
26
  export function mergeMermaidConfig(options) {
19
27
  const {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barzhsieh/nuxt-content-mermaid",
3
- "version": "2.0.1",
3
+ "version": "2.1.0-alpha.1",
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",
@@ -72,6 +72,12 @@
72
72
  "release:patch": "pnpm run release:base && changelogen --release --patch --push && pnpm publish",
73
73
  "release:minor": "pnpm run release:base && changelogen --release --minor --push && pnpm publish",
74
74
  "release:major": "pnpm run release:base && changelogen --release --major --push && pnpm publish",
75
+ "release:minor:alpha": "pnpm run release:base && changelogen --release --preminor alpha --push && pnpm publish --tag alpha",
76
+ "release:minor:beta": "pnpm run release:base && changelogen --release --preminor beta --push && pnpm publish --tag beta",
77
+ "release:minor:rc": "pnpm run release:base && changelogen --release --preminor rc --push && pnpm publish --tag rc",
78
+ "release:alpha": "pnpm run release:base && changelogen --release --prerelease alpha --push && pnpm publish --tag alpha",
79
+ "release:beta": "pnpm run release:base && changelogen --release --prerelease beta --push && pnpm publish --tag beta",
80
+ "release:rc": "pnpm run release:base && changelogen --release --prerelease rc --push && pnpm publish --tag rc",
75
81
  "release": "pnpm run release:patch",
76
82
  "lint": "eslint .",
77
83
  "test": "vitest run",