From b23c03a31d11db8913fdf3f5ffbf351abb8bbc98 Mon Sep 17 00:00:00 2001 From: Dmitrii Troitskii Date: Fri, 10 Apr 2026 02:41:08 +0000 Subject: [PATCH 1/2] fix(deps): remove mermaid as hard runtime dependency mermaid was in dependencies but is only used as an import type in the core package. All runtime usage lives in @streamdown/mermaid plugin. Replace import type { MermaidConfig } from 'mermaid' with a local structural type so no type-level coupling remains in the dist bundle. Fixes #501 --- .changeset/fix-mermaid-hard-dep.md | 18 ++++++++++++++++++ packages/streamdown/index.tsx | 7 +++++-- packages/streamdown/lib/mermaid/index.tsx | 2 +- packages/streamdown/lib/plugin-types.ts | 10 +++++++++- packages/streamdown/package.json | 1 - pnpm-lock.yaml | 3 --- 6 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 .changeset/fix-mermaid-hard-dep.md diff --git a/.changeset/fix-mermaid-hard-dep.md b/.changeset/fix-mermaid-hard-dep.md new file mode 100644 index 00000000..7e088322 --- /dev/null +++ b/.changeset/fix-mermaid-hard-dep.md @@ -0,0 +1,18 @@ +--- +"streamdown": patch +--- + +fix(deps): remove `mermaid` as a hard runtime dependency + +`mermaid` was listed in `dependencies` but the core `streamdown` package +only imports it as a type (`import type { MermaidConfig }`). The actual +mermaid runtime is exclusively used by the optional `@streamdown/mermaid` +plugin — pulling ~75 MB into every install unnecessarily. + +This patch replaces the type import with a local structural type for +`MermaidConfig` so no type-level coupling to the `mermaid` package remains +in the distributed typings. Users who want fully-typed mermaid config can +still `import type { MermaidConfig } from 'mermaid'` themselves; the +structural type is compatible. + +Fixes #501 diff --git a/packages/streamdown/index.tsx b/packages/streamdown/index.tsx index be32d9fd..daef602c 100644 --- a/packages/streamdown/index.tsx +++ b/packages/streamdown/index.tsx @@ -1,6 +1,5 @@ "use client"; -import type { MermaidConfig } from "mermaid"; import { type ComponentProps, type CSSProperties, @@ -33,7 +32,11 @@ import { hasIncompleteCodeFence, hasTable } from "./lib/incomplete-code-utils"; import { type ExtraProps, Markdown, type Options } from "./lib/markdown"; import { parseMarkdownIntoBlocks } from "./lib/parse-blocks"; import { PluginContext } from "./lib/plugin-context"; -import type { PluginConfig, ThemeInput } from "./lib/plugin-types"; +import type { + MermaidConfig, + PluginConfig, + ThemeInput, +} from "./lib/plugin-types"; import { PrefixContext } from "./lib/prefix-context"; import { preprocessCustomTags } from "./lib/preprocess-custom-tags"; import { preprocessLiteralTagContent } from "./lib/preprocess-literal-tag-content"; diff --git a/packages/streamdown/lib/mermaid/index.tsx b/packages/streamdown/lib/mermaid/index.tsx index 3f483863..4f4408cf 100644 --- a/packages/streamdown/lib/mermaid/index.tsx +++ b/packages/streamdown/lib/mermaid/index.tsx @@ -1,8 +1,8 @@ -import type { MermaidConfig } from "mermaid"; import { useContext, useEffect, useState } from "react"; import { useDeferredRender } from "../../hooks/use-deferred-render"; import { StreamdownContext } from "../../index"; import { useMermaidPlugin } from "../plugin-context"; +import type { MermaidConfig } from "../plugin-types"; import { useCn } from "../prefix-context"; import { PanZoom } from "./pan-zoom"; diff --git a/packages/streamdown/lib/plugin-types.ts b/packages/streamdown/lib/plugin-types.ts index 95130362..6af3d8d4 100644 --- a/packages/streamdown/lib/plugin-types.ts +++ b/packages/streamdown/lib/plugin-types.ts @@ -1,4 +1,12 @@ -import type { MermaidConfig } from "mermaid"; +/** + * Structural type for Mermaid configuration. + * Avoids a hard dependency on the "mermaid" package in the core bundle. + * Users who need full type safety can import MermaidConfig from "mermaid" + * directly — it is structurally compatible with this type. + */ +// biome-ignore lint/suspicious/noExplicitAny: structural pass-through for mermaid config +export type MermaidConfig = Record; + import type React from "react"; import type { BundledLanguage, diff --git a/packages/streamdown/package.json b/packages/streamdown/package.json index b44b3474..4697c62a 100644 --- a/packages/streamdown/package.json +++ b/packages/streamdown/package.json @@ -74,7 +74,6 @@ "remend": "workspace:*", "tailwind-merge": "^3.4.0", "unified": "^11.0.5", - "mermaid": "^11.12.2", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9c6043ae..fade1baf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -322,9 +322,6 @@ importers: marked: specifier: ^17.0.1 version: 17.0.1 - mermaid: - specifier: ^11.12.2 - version: 11.12.2 react: specifier: ^18.0.0 || ^19.0.0 version: 19.2.3 From 56e02a1b7defcaffecbdfb236c8c35623b14f1f3 Mon Sep 17 00:00:00 2001 From: Dmitrii Troitskii Date: Fri, 10 Apr 2026 05:10:53 +0000 Subject: [PATCH 2/2] fix(deps): replace remaining MermaidConfig imports from 'mermaid' package Fix download-button.tsx, fullscreen-button.tsx, and mermaid.test.tsx which still imported MermaidConfig directly from the 'mermaid' package. All three now use the local structural type from lib/plugin-types.ts. Addresses VADE review feedback on #502. --- packages/streamdown/__tests__/mermaid.test.tsx | 3 +-- packages/streamdown/lib/mermaid/download-button.tsx | 2 +- packages/streamdown/lib/mermaid/fullscreen-button.tsx | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/streamdown/__tests__/mermaid.test.tsx b/packages/streamdown/__tests__/mermaid.test.tsx index 7af696fd..0cfaff03 100644 --- a/packages/streamdown/__tests__/mermaid.test.tsx +++ b/packages/streamdown/__tests__/mermaid.test.tsx @@ -1,12 +1,11 @@ import { render, waitFor } from "@testing-library/react"; -import type { MermaidConfig } from "mermaid"; import { act } from "react"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { Mermaid } from "../lib/mermaid"; import { MermaidDownloadDropdown } from "../lib/mermaid/download-button"; import { MermaidFullscreenButton } from "../lib/mermaid/fullscreen-button"; import { PluginContext } from "../lib/plugin-context"; -import type { DiagramPlugin } from "../lib/plugin-types"; +import type { DiagramPlugin, MermaidConfig } from "../lib/plugin-types"; const { saveMock, mockInitialize, mockRender, mockMermaid } = vi.hoisted(() => { const mockInitialize = vi.fn(); diff --git a/packages/streamdown/lib/mermaid/download-button.tsx b/packages/streamdown/lib/mermaid/download-button.tsx index 7f287f2d..c46c94e5 100644 --- a/packages/streamdown/lib/mermaid/download-button.tsx +++ b/packages/streamdown/lib/mermaid/download-button.tsx @@ -1,8 +1,8 @@ -import type { MermaidConfig } from "mermaid"; import { useContext, useEffect, useRef, useState } from "react"; import { StreamdownContext } from "../../index"; import { useIcons } from "../icon-context"; import { useMermaidPlugin } from "../plugin-context"; +import type { MermaidConfig } from "../plugin-types"; import { useCn } from "../prefix-context"; import { useTranslations } from "../translations-context"; import { save } from "../utils"; diff --git a/packages/streamdown/lib/mermaid/fullscreen-button.tsx b/packages/streamdown/lib/mermaid/fullscreen-button.tsx index 316095da..8491fd67 100644 --- a/packages/streamdown/lib/mermaid/fullscreen-button.tsx +++ b/packages/streamdown/lib/mermaid/fullscreen-button.tsx @@ -1,8 +1,8 @@ -import type { MermaidConfig } from "mermaid"; import { type ComponentProps, useContext, useEffect, useState } from "react"; import { createPortal } from "react-dom"; import { StreamdownContext } from "../../index"; import { useIcons } from "../icon-context"; +import type { MermaidConfig } from "../plugin-types"; import { useCn } from "../prefix-context"; import { lockBodyScroll, unlockBodyScroll } from "../scroll-lock"; import { useTranslations } from "../translations-context";