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.
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
# Angular
|
||||
|
||||
We don't provide Angular support out of box, but you can use the vanilla version with it easily.
|
||||
|
||||
## Install the Dependencies
|
||||
|
||||
```bash
|
||||
# install with npm
|
||||
npm install @milkdown/kit
|
||||
npm install @milkdown/theme-nord
|
||||
```
|
||||
|
||||
## Create a Component
|
||||
|
||||
Create a component is pretty easy.
|
||||
|
||||
```html
|
||||
<!-- editor.component.html -->
|
||||
<div #editorRef></div>
|
||||
```
|
||||
|
||||
```typescript
|
||||
// editor.component.ts
|
||||
import { Component, ElementRef, ViewChild } from "@angular/core";
|
||||
import { defaultValueCtx, Editor, rootCtx } from "@milkdown/kit/core";
|
||||
import { commonmark } from "@milkdown/kit/preset/commonmark";
|
||||
import { nord } from "@milkdown/theme-nord";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./editor.component.html",
|
||||
})
|
||||
export class AppComponent {
|
||||
@ViewChild("editorRef") editorRef: ElementRef;
|
||||
|
||||
defaultValue = "# Milkdown x Angular";
|
||||
|
||||
ngAfterViewInit() {
|
||||
Editor.make()
|
||||
.config((ctx) => {
|
||||
ctx.set(rootCtx, this.editorRef.nativeElement);
|
||||
ctx.set(defaultValueCtx, this.defaultValue);
|
||||
})
|
||||
.config(nord)
|
||||
.use(commonmark)
|
||||
.create();
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,51 @@
|
||||
# Next.js
|
||||
|
||||
Since we provide [react](/docs/recipes/react) support out of box, we can use it directly in [Next.js](https://nextjs.org/).
|
||||
|
||||
## Install the Dependencies
|
||||
|
||||
Except the `@milkdown/kit` and theme. We need to install the `@milkdown/react`, which provide lots of abilities for react in milkdown.
|
||||
|
||||
```bash
|
||||
# install with npm
|
||||
npm install @milkdown/react
|
||||
npm install @milkdown/kit
|
||||
npm install @milkdown/theme-nord
|
||||
```
|
||||
|
||||
## Create a Component
|
||||
|
||||
Create a component is pretty easy.
|
||||
|
||||
```tsx
|
||||
import { Editor, rootCtx } from "@milkdown/kit/core";
|
||||
import { commonmark } from "@milkdown/kit/preset/commonmark";
|
||||
import { Milkdown, MilkdownProvider, useEditor } from "@milkdown/react";
|
||||
import { nord } from "@milkdown/theme-nord";
|
||||
import React from "react";
|
||||
|
||||
const MilkdownEditor: React.FC = () => {
|
||||
const { editor } = useEditor((root) =>
|
||||
Editor.make()
|
||||
.config(nord)
|
||||
.config((ctx) => {
|
||||
ctx.set(rootCtx, root);
|
||||
})
|
||||
.use(commonmark),
|
||||
);
|
||||
|
||||
return <Milkdown />;
|
||||
};
|
||||
|
||||
export const MilkdownEditorWrapper: React.FC = () => {
|
||||
return (
|
||||
<MilkdownProvider>
|
||||
<MilkdownEditor />
|
||||
</MilkdownProvider>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## Online Demo
|
||||
|
||||
::iframe{src="https://stackblitz.com/github/Milkdown/examples/tree/main/next-commonmark"}
|
||||
@@ -0,0 +1,82 @@
|
||||
# NuxtJS
|
||||
|
||||
Since we provide [vue](/docs/recipes/vue) support out of box, we can use it directly in [NuxtJS](https://v3.nuxtjs.org/).
|
||||
|
||||
> NuxtJS version should be 3.x.
|
||||
|
||||
## Install the Dependencies
|
||||
|
||||
Except the `@milkdown/kit` and theme. We need to install the `@milkdown/vue`, which provide lots of abilities for vue in milkdown.
|
||||
|
||||
```bash
|
||||
# install with npm
|
||||
npm install @milkdown/vue
|
||||
npm install @milkdown/kit
|
||||
npm install @milkdown/theme-nord
|
||||
```
|
||||
|
||||
## Create a Component
|
||||
|
||||
Create a component is pretty easy.
|
||||
|
||||
First, we need to create a `MilkdownEditor` component.
|
||||
|
||||
```html
|
||||
<!-- MilkdownEditor.vue -->
|
||||
<template>
|
||||
<Milkdown />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor, rootCtx, defaultValueCtx } from "@milkdown/kit/core";
|
||||
import { commonmark } from "@milkdown/kit/preset/commonmark";
|
||||
import { nord } from "@milkdown/theme-nord";
|
||||
import { Milkdown, useEditor } from "@milkdown/vue";
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "Milkdown",
|
||||
components: {
|
||||
Milkdown,
|
||||
},
|
||||
setup: () => {
|
||||
useEditor((root) =>
|
||||
Editor.make()
|
||||
.config((ctx) => {
|
||||
ctx.set(rootCtx, root);
|
||||
})
|
||||
.config(nord)
|
||||
.use(commonmark),
|
||||
);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
Then, we need to create a `MilkdownEditorWrapper` component.
|
||||
|
||||
```html
|
||||
<!-- MilkdownEditorWrapper.vue -->
|
||||
<template>
|
||||
<MilkdownProvider>
|
||||
<MilkdownEditor />
|
||||
</MilkdownProvider>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { MilkdownProvider } from "@milkdown/vue";
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "MilkdownEditorWrapper",
|
||||
components: {
|
||||
MilkdownProvider,
|
||||
},
|
||||
setup: () => {},
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
## Online Demo
|
||||
|
||||
::iframe{src="https://stackblitz.com/github/Milkdown/examples/tree/main/nuxt-commonmark"}
|
||||
@@ -0,0 +1,213 @@
|
||||
# React Integration
|
||||
|
||||
Milkdown provides first-class React support with dedicated packages and hooks for seamless integration. You can choose between Crepe, our feature-rich WYSIWYG editor, or the core Milkdown editor for more customization options.
|
||||
|
||||
## Using Crepe
|
||||
|
||||
---
|
||||
|
||||
Crepe is a powerful, feature-rich Markdown editor built on top of Milkdown that provides a more user-friendly editing experience.
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
npm install @milkdown/crepe @milkdown/react @milkdown/kit
|
||||
```
|
||||
|
||||
### Implementation
|
||||
|
||||
```tsx
|
||||
import { Crepe } from "@milkdown/crepe";
|
||||
import { Milkdown, MilkdownProvider, useEditor } from "@milkdown/react";
|
||||
|
||||
const CrepeEditor: React.FC = () => {
|
||||
const { get } = useEditor((root) => {
|
||||
return new Crepe({ root });
|
||||
});
|
||||
|
||||
return <Milkdown />;
|
||||
};
|
||||
|
||||
export const MilkdownEditorWrapper: React.FC = () => {
|
||||
return (
|
||||
<MilkdownProvider>
|
||||
<CrepeEditor />
|
||||
</MilkdownProvider>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Online Demo
|
||||
|
||||
::iframe{src="https://stackblitz.com/github/Milkdown/examples/tree/main/react-crepe"}
|
||||
|
||||
## Using Milkdown
|
||||
|
||||
---
|
||||
|
||||
For more advanced use cases or when you need full control over the editor's configuration, you can use the core Milkdown editor directly.
|
||||
|
||||
### Install Dependencies
|
||||
|
||||
```bash
|
||||
npm install @milkdown/react @milkdown/kit
|
||||
```
|
||||
|
||||
### Basic Usage
|
||||
|
||||
Here's a minimal example to get started:
|
||||
|
||||
```tsx
|
||||
import { Editor, rootCtx } from "@milkdown/kit/core";
|
||||
import { commonmark } from "@milkdown/kit/preset/commonmark";
|
||||
import { Milkdown, MilkdownProvider, useEditor } from "@milkdown/react";
|
||||
import { nord } from "@milkdown/theme-nord";
|
||||
|
||||
const MilkdownEditor: React.FC = () => {
|
||||
const { get } = useEditor((root) =>
|
||||
Editor.make()
|
||||
.config(nord)
|
||||
.config((ctx) => {
|
||||
ctx.set(rootCtx, root);
|
||||
})
|
||||
.use(commonmark),
|
||||
);
|
||||
|
||||
return <Milkdown />;
|
||||
};
|
||||
|
||||
export const MilkdownEditorWrapper: React.FC = () => {
|
||||
return (
|
||||
<MilkdownProvider>
|
||||
<MilkdownEditor />
|
||||
</MilkdownProvider>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
::iframe{src="https://stackblitz.com/github/Milkdown/examples/tree/main/react-commonmark"}
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
---
|
||||
|
||||
### Accessing Editor Instance
|
||||
|
||||
The `useInstance()` hook can only be used within components that are children of `MilkdownProvider`. It returns a tuple containing a loading state and a getter function to access the editor instance.
|
||||
|
||||
```tsx
|
||||
import { useInstance } from "@milkdown/react";
|
||||
import { getMarkdown } from "@milkdown/utils";
|
||||
|
||||
// ❌ This won't work - ParentComponent is outside MilkdownProvider
|
||||
const ParentComponent: React.FC = () => {
|
||||
const [isLoading, getInstance] = useInstance(); // This will be [true, () => undefined]
|
||||
return <MilkdownEditorWrapper />;
|
||||
};
|
||||
|
||||
// ✅ This is the correct way - EditorControls is inside MilkdownProvider
|
||||
const EditorControls: React.FC = () => {
|
||||
const [isLoading, getInstance] = useInstance();
|
||||
|
||||
const handleSave = () => {
|
||||
if (isLoading) return;
|
||||
|
||||
const editor = getInstance();
|
||||
if (!editor) return;
|
||||
|
||||
const content = editor.action(getMarkdown());
|
||||
// Do something with the content
|
||||
};
|
||||
|
||||
return (
|
||||
<button onClick={handleSave} disabled={isLoading}>
|
||||
Save
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
// ✅ Proper component structure
|
||||
const EditorWithControls: React.FC = () => {
|
||||
return (
|
||||
<MilkdownProvider>
|
||||
<MilkdownEditorWrapper />
|
||||
<EditorControls />
|
||||
</MilkdownProvider>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Best Practices
|
||||
|
||||
1. **Component Structure**
|
||||
- Keep the editor component separate from business logic
|
||||
- Wrap the editor with `MilkdownProvider` at the highest necessary level
|
||||
- Use TypeScript for better type safety
|
||||
|
||||
2. **Performance**
|
||||
- Memoize the editor configuration if it's complex
|
||||
- Use React.memo for the editor component if needed
|
||||
- Avoid unnecessary re-renders of the editor
|
||||
|
||||
### Common Use Cases
|
||||
|
||||
**Form Integration**
|
||||
|
||||
```tsx
|
||||
const FormWithEditor: React.FC = () => {
|
||||
const [isLoading, getInstance] = useInstance();
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (isLoading) return;
|
||||
|
||||
const editor = getInstance();
|
||||
if (!editor) return;
|
||||
|
||||
const content = editor.action(getMarkdown());
|
||||
// Submit form with content
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<MilkdownEditorWrapper />
|
||||
<button type="submit" disabled={isLoading}>
|
||||
Submit
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
**Auto-save**
|
||||
|
||||
```tsx
|
||||
import { Editor, rootCtx } from "@milkdown/kit/core";
|
||||
import { commonmark } from "@milkdown/kit/preset/commonmark";
|
||||
import { listener, listenerCtx } from "@milkdown/kit/plugin/listener";
|
||||
import { Milkdown, useEditor } from "@milkdown/react";
|
||||
|
||||
const AutoSaveEditor: React.FC = () => {
|
||||
const { get } = useEditor((root) =>
|
||||
Editor.make()
|
||||
.config((ctx) => {
|
||||
ctx.set(rootCtx, root);
|
||||
// Add markdown listener for auto-save
|
||||
ctx.get(listenerCtx).markdownUpdated((ctx, markdown) => {
|
||||
// Save content to your backend or storage
|
||||
saveToBackend(markdown);
|
||||
});
|
||||
})
|
||||
.use(commonmark)
|
||||
.use(listener),
|
||||
);
|
||||
|
||||
return <Milkdown />;
|
||||
};
|
||||
```
|
||||
|
||||
## More Examples
|
||||
|
||||
---
|
||||
|
||||
- [Examples Repository](https://github.com/Milkdown/examples)
|
||||
@@ -0,0 +1,46 @@
|
||||
# SolidJS
|
||||
|
||||
We don't provide SolidJS support out of box, but you can use the vanilla version with it easily.
|
||||
|
||||
## Install the Dependencies
|
||||
|
||||
```bash
|
||||
# install with npm
|
||||
npm install @milkdown/kit
|
||||
npm install @milkdown/theme-nord
|
||||
```
|
||||
|
||||
## Create a Component
|
||||
|
||||
Create a component is pretty easy.
|
||||
|
||||
```tsx
|
||||
import { defaultValueCtx, Editor, rootCtx } from "@milkdown/kit/core";
|
||||
import { commonmark } from "@milkdown/kit/preset/commonmark";
|
||||
import { nord } from "@milkdown/theme-nord";
|
||||
import { onCleanup, onMount } from "solid-js";
|
||||
|
||||
const Milkdown = () => {
|
||||
let ref;
|
||||
let editor;
|
||||
onMount(async () => {
|
||||
editor = await Editor.make()
|
||||
.config((ctx) => {
|
||||
ctx.set(rootCtx, ref);
|
||||
})
|
||||
.config(nord)
|
||||
.use(commonmark)
|
||||
.create();
|
||||
});
|
||||
|
||||
onCleanup(() => {
|
||||
editor.destroy();
|
||||
});
|
||||
|
||||
return <div ref={ref} />;
|
||||
};
|
||||
```
|
||||
|
||||
## Online Demo
|
||||
|
||||
::iframe{src="https://stackblitz.com/github/Milkdown/examples/tree/main/solid-commonmark"}
|
||||
@@ -0,0 +1,45 @@
|
||||
# Svelte
|
||||
|
||||
We don't provide Svelte support out of box, but you can use the vanilla version with it easily.
|
||||
|
||||
## Install the Dependencies
|
||||
|
||||
```bash
|
||||
# install with npm
|
||||
npm install @milkdown/kit
|
||||
npm install @milkdown/theme-nord
|
||||
```
|
||||
|
||||
## Creating a Component
|
||||
|
||||
Creating a component is pretty easy.
|
||||
|
||||
```html
|
||||
<script>
|
||||
import { Editor, rootCtx, defaultValueCtx } from "@milkdown/kit/core";
|
||||
import { commonmark } from "@milkdown/kit/preset/commonmark";
|
||||
import { nord } from "@milkdown/theme-nord";
|
||||
|
||||
function editor(dom) {
|
||||
// to obtain the editor instance we need to store a reference of the editor.
|
||||
const MakeEditor = Editor.make()
|
||||
.config((ctx) => {
|
||||
ctx.set(rootCtx, dom);
|
||||
})
|
||||
.config(nord)
|
||||
.use(commonmark)
|
||||
.create();
|
||||
MakeEditor.then((editor) => {
|
||||
// here you have access to the editor instance.
|
||||
// const exampleContent = "# Hello World!";
|
||||
// editor.action(replaceAll(exampleContent));
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<div use:editor />
|
||||
```
|
||||
|
||||
## Online Demo
|
||||
|
||||
::iframe{src="https://stackblitz.com/github/Milkdown/examples/tree/main/svelte-commonmark"}
|
||||
@@ -0,0 +1,294 @@
|
||||
# Vue Integration
|
||||
|
||||
Milkdown provides first-class Vue support with dedicated packages and hooks for seamless integration. You can choose between Crepe, our feature-rich WYSIWYG editor, or the core Milkdown editor for more customization options.
|
||||
|
||||
> Vue version should be 3.x
|
||||
|
||||
## Using Crepe
|
||||
|
||||
---
|
||||
|
||||
Crepe is a powerful, feature-rich Markdown editor built on top of Milkdown that provides a more user-friendly editing experience.
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
npm install @milkdown/crepe @milkdown/vue @milkdown/kit
|
||||
```
|
||||
|
||||
### Implementation
|
||||
|
||||
```vue
|
||||
<!-- MilkdownEditor.vue -->
|
||||
<template>
|
||||
<Milkdown />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Crepe } from "@milkdown/crepe";
|
||||
import { Milkdown, MilkdownProvider, useEditor } from "@milkdown/vue";
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "MilkdownEditor",
|
||||
components: {
|
||||
Milkdown,
|
||||
},
|
||||
setup: () => {
|
||||
const { get } = useEditor((root) => {
|
||||
return new Crepe({ root });
|
||||
});
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- MilkdownEditorWrapper.vue -->
|
||||
<template>
|
||||
<MilkdownProvider>
|
||||
<MilkdownEditor />
|
||||
</MilkdownProvider>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { MilkdownProvider } from "@milkdown/vue";
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "MilkdownEditorWrapper",
|
||||
components: {
|
||||
MilkdownProvider,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
### Online Demo
|
||||
|
||||
::iframe{src="https://stackblitz.com/github/Milkdown/examples/tree/main/vue-crepe"}
|
||||
|
||||
## Using Milkdown
|
||||
|
||||
---
|
||||
|
||||
For more advanced use cases or when you need full control over the editor's configuration, you can use the core Milkdown editor directly.
|
||||
|
||||
### Install Dependencies
|
||||
|
||||
```bash
|
||||
npm install @milkdown/vue @milkdown/kit @milkdown/theme-nord
|
||||
```
|
||||
|
||||
### Basic Usage
|
||||
|
||||
Here's a minimal example to get started:
|
||||
|
||||
```vue
|
||||
<!-- MilkdownEditor.vue -->
|
||||
<template>
|
||||
<Milkdown />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor, rootCtx } from "@milkdown/kit/core";
|
||||
import { commonmark } from "@milkdown/kit/preset/commonmark";
|
||||
import { nord } from "@milkdown/theme-nord";
|
||||
import { Milkdown, useEditor } from "@milkdown/vue";
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "MilkdownEditor",
|
||||
components: {
|
||||
Milkdown,
|
||||
},
|
||||
setup: () => {
|
||||
const { get } = useEditor((root) =>
|
||||
Editor.make()
|
||||
.config(nord)
|
||||
.config((ctx) => {
|
||||
ctx.set(rootCtx, root);
|
||||
})
|
||||
.use(commonmark),
|
||||
);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- MilkdownEditorWrapper.vue -->
|
||||
<template>
|
||||
<MilkdownProvider>
|
||||
<MilkdownEditor />
|
||||
</MilkdownProvider>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { MilkdownProvider } from "@milkdown/vue";
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "MilkdownEditorWrapper",
|
||||
components: {
|
||||
MilkdownProvider,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
::iframe{src="https://stackblitz.com/github/Milkdown/examples/tree/main/vue-commonmark"}
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
---
|
||||
|
||||
### Accessing Editor Instance
|
||||
|
||||
The `useInstance()` hook can only be used within components that are children of `MilkdownProvider`. It returns a tuple containing a loading state and a getter function to access the editor instance.
|
||||
|
||||
```vue
|
||||
<!-- EditorControls.vue -->
|
||||
<template>
|
||||
<button @click="handleSave" :disabled="isLoading">Save</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useInstance } from "@milkdown/vue";
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "EditorControls",
|
||||
setup: () => {
|
||||
const [isLoading, getInstance] = useInstance();
|
||||
|
||||
const handleSave = () => {
|
||||
if (isLoading.value) return;
|
||||
|
||||
const editor = getInstance();
|
||||
if (!editor) return;
|
||||
|
||||
const content = editor.getMarkdown();
|
||||
// Do something with the content
|
||||
};
|
||||
|
||||
return {
|
||||
isLoading,
|
||||
handleSave,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- EditorWithControls.vue -->
|
||||
<template>
|
||||
<MilkdownProvider>
|
||||
<MilkdownEditor />
|
||||
<EditorControls />
|
||||
</MilkdownProvider>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { MilkdownProvider } from "@milkdown/vue";
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "EditorWithControls",
|
||||
components: {
|
||||
MilkdownProvider,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
### Best Practices
|
||||
|
||||
1. **Component Structure**
|
||||
- Keep the editor component separate from business logic
|
||||
- Wrap the editor with `MilkdownProvider` at the highest necessary level
|
||||
- Use TypeScript for better type safety
|
||||
|
||||
2. **Performance**
|
||||
- Memoize the editor configuration if it's complex
|
||||
- Use Vue's `shallowRef` for editor instance if needed
|
||||
- Avoid unnecessary re-renders of the editor
|
||||
|
||||
### Common Use Cases
|
||||
|
||||
**Form Integration**
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<form @submit.prevent="handleSubmit">
|
||||
<MilkdownEditorWrapper />
|
||||
<button type="submit" :disabled="isLoading">Submit</button>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useInstance } from "@milkdown/vue";
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "FormWithEditor",
|
||||
setup: () => {
|
||||
const [isLoading, getInstance] = useInstance();
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (isLoading.value) return;
|
||||
|
||||
const editor = getInstance();
|
||||
if (!editor) return;
|
||||
|
||||
const content = editor.getMarkdown();
|
||||
// Submit form with content
|
||||
};
|
||||
|
||||
return {
|
||||
isLoading,
|
||||
handleSubmit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
**Auto-save**
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<Milkdown />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Editor, rootCtx } from "@milkdown/kit/core";
|
||||
import { commonmark } from "@milkdown/kit/preset/commonmark";
|
||||
import { listener, listenerCtx } from "@milkdown/kit/plugin/listener";
|
||||
import { Milkdown, useEditor } from "@milkdown/vue";
|
||||
import { defineComponent } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
name: "AutoSaveEditor",
|
||||
components: {
|
||||
Milkdown,
|
||||
},
|
||||
setup: () => {
|
||||
const { get } = useEditor((root) =>
|
||||
Editor.make()
|
||||
.config((ctx) => {
|
||||
ctx.set(rootCtx, root);
|
||||
// Add markdown listener for auto-save
|
||||
ctx.get(listenerCtx).markdownUpdated((ctx, markdown) => {
|
||||
// Save content to your backend or storage
|
||||
saveToBackend(markdown);
|
||||
});
|
||||
})
|
||||
.use(commonmark)
|
||||
.use(listener),
|
||||
);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
## More Examples
|
||||
|
||||
---
|
||||
|
||||
- [Examples Repository](https://github.com/Milkdown/examples)
|
||||
@@ -0,0 +1,44 @@
|
||||
# Vue2
|
||||
|
||||
We don't provide Vue2 support out of box, but you can use the vanilla version with it easily.
|
||||
|
||||
## Install the Dependencies
|
||||
|
||||
```bash
|
||||
# install with npm
|
||||
npm install @milkdown/kit
|
||||
npm install @milkdown/theme-nord
|
||||
```
|
||||
|
||||
## Create a Component
|
||||
|
||||
Create a component is pretty easy.
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div ref="editor"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defaultValueCtx, Editor, rootCtx } from "@milkdown/kit/core";
|
||||
import { commonmark } from "@milkdown/kit/preset/commonmark";
|
||||
import { nord } from "@milkdown/theme-nord";
|
||||
|
||||
export default {
|
||||
name: "Editor",
|
||||
props: {
|
||||
msg: String,
|
||||
},
|
||||
mounted() {
|
||||
Editor.make()
|
||||
.config((ctx) => {
|
||||
ctx.set(rootCtx, this.$refs.editor);
|
||||
ctx.set(defaultValueCtx, this.$props.msg);
|
||||
})
|
||||
.config(nord)
|
||||
.use(commonmark)
|
||||
.create();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
```
|
||||
Reference in New Issue
Block a user