Files
llm-in-text/milkdown-docs/plugin/composable-plugins.md
ydy0615 d9ab341223 Add documentation for using Milkdown with various frameworks
- Created a new document for using components in Milkdown.
- Added a guide for using plugins in Milkdown, including toggling plugins programmatically and listing official plugins.
- Introduced a recipe for integrating Milkdown with Angular, including installation steps and component creation.
- Added a recipe for using Milkdown with Next.js, detailing installation and component setup.
- Created a guide for integrating Milkdown with NuxtJS, including installation and component creation.
- Added a comprehensive guide for using Milkdown with React, covering both Crepe and core Milkdown usage.
- Introduced a recipe for SolidJS integration with Milkdown, including installation and component creation.
- Added a guide for using Milkdown with Svelte, detailing installation and component setup.
- Created a comprehensive guide for integrating Milkdown with Vue, covering both Crepe and core Milkdown usage.
- Added a recipe for using Milkdown with Vue2, including installation and component creation.
2026-01-17 14:18:08 +08:00

3.1 KiB

Composable Plugins

In the previous section, we showed you how to create a plugin from scratch. Luckily, you don't need to do that in most cases. Milkdown provides a lot of helpers in @milkdown/utils to make it easier to create plugins. The composable here means that you can use the plugin in other plugins. For example, you can use a command plugin in a keymap plugin. This is a very common pattern in Milkdown.

I'll show you some examples of how to use composable plugins. But I won't go into detail about the options and the usage of each plugin. You can find the details in the API reference.

Schema

The schema plugin is the most important plugin in Milkdown. It defines the structure of the document. A schema plugin in milkdown is a super set of the node schema spec or mark schema spec in ProseMirror.

Let's create a simple blockquote node plugin as an example:

import { $node } from "@milkdown/kit/utils";

const blockquote = $node("blockquote", () => ({
  content: "block+",
  group: "block",
  defining: true,
  parseDOM: [{ tag: "blockquote" }],
  toDOM: (node) => ["blockquote", ctx.get(blockquoteAttr.key)(node), 0],
  parseMarkdown: {
    match: ({ type }) => type === "blockquote",
    runner: (state, node, type) => {
      state.openNode(type).next(node.children).closeNode();
    },
  },
  toMarkdown: {
    match: (node) => node.type.name === "blockquote",
    runner: (state, node) => {
      state.openNode("blockquote").next(node.content).closeNode();
    },
  },
}));

Input Rule

Since we have a blockquote node, we can create an input rule plugin to make it easier to create a blockquote node. We expect that when we type > at the beginning of a line, the blockquote node will be created.

import { wrappingInputRule } from "@milkdown/kit/prose/inputrules";
import { $inputRule } from "@milkdown/kit/utils";

export const wrapInBlockquoteInputRule = $inputRule(() =>
  wrappingInputRule(/^\s*>\s$/, blockquoteSchema.type()),
);

Command

We can also create a command plugin to create a blockquote node. The command is useful when we want to create a button to create a blockquote node.

import { wrapIn } from "@milkdown/kit/prose/commands";
import { $command } from "@milkdown/kit/utils";

export const wrapInBlockquoteCommand = $command(
  "WrapInBlockquote",
  () => () => wrapIn(blockquoteSchema.type()),
);

Shortcut

We can also create a shortcut plugin for blockquote. Here we use Ctrl + Shift + B as the shortcut. When we press this shortcut, the blockquote node will be created. And we can also use the command we created in the previous section.

import { commandsCtx } from "@milkdown/kit/core";
import { $useKeymap } from "@milkdown/kit/utils";

export const blockquoteKeymap = $useKeymap("blockquoteKeymap", {
  WrapInBlockquote: {
    shortcuts: "Mod-Shift-b",
    command: (ctx) => {
      const commands = ctx.get(commandsCtx);
      return () => commands.call(wrapInBlockquoteCommand.key);
    },
  },
});