PowerEditor
PowerEditor is the core rich text editor component in PowerEditor3. It is built with Vue 3, Tiptap and VFluent3, and provides a ready-to-use toolbar, theme switching, image preview, Markdown conversion, read-only display and slot-based customization.
On
Basic Usage
<template>
<power-editor
v-model="content"
theme="light"
:showDragHandler="true"
placeholder="Write something..."
@change="handleChange"
@save-html="handleSaveHtml"
@save-json="handleSaveJson"
/>
</template>Extension Guides
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
modelValue | string | No | <p>I'm running PowerEditor with Vue.js.</p> | Editor content. Plain text and HTML are supported. |
editable | boolean | No | true | Whether the editor is editable. Set it to false for read-only mode. |
placeholder | string | No | Write something... | Placeholder text. |
disabledPlaceholder | boolean | No | false | Whether to disable the placeholder. |
contentMaxWidth | number | No | 900 | Maximum content width in pixels. |
editorBackground | string | No | - | Inner editor background color. |
editorOutSideBackground | string | No | - | Outer editor background color. |
mobileDisplayWidth | number | No | 768 | Width threshold for mobile layout. |
showToolBar | boolean | No | true | Whether to show the toolbar. |
toolbarHeight | number | No | 70 | Toolbar height. |
toolbarBackground | string | No | - | Toolbar background color. |
toolbarBorderRadius | number | No | 8 | Toolbar border radius. |
editablePaddingTop | number | No | - | Top padding in editable mode. Internal default is used when omitted. |
readOnlyPaddingTop | number | No | 5 | Top padding in read-only mode. |
editablePaddingBottom | number | No | 315 | Bottom padding in editable mode. |
readOnlyPaddingBottom | number | No | 55 | Bottom padding in read-only mode. |
imgInterceptor | function | No | - | Image interceptor for upload, replacement and status control. See ImgInterceptor. |
mentionItemAttr | object | No | - | MentionItem configuration. See MentionItem. |
starterKit | object | No | () => ({}) | Custom configuration for Tiptap StarterKit. |
showControlOnReadonly | boolean | No | true | Whether to show controls in read-only mode. |
mediaContainerButtons | object | No | { left: [], right: [] } | Custom media container control buttons. See below. |
mdDecNodeFuncsPlugins | object | No | - | Custom Markdown decoder functions. See Markdown Decoder Plugins. |
mdFlags | object | No | - | Custom Markdown decoder traversal flags. |
foreground | string | No | #958DF1 | Editor accent color. |
linkColor | string | No | #958DF1 | Link color. |
selectionBackground | string | No | rgba(144, 145, 234, 0.3) | Selection background color. |
selectionForeground | string | No | - | Selection foreground color. |
tableDragColor | string | No | rgba(144, 145, 234, 0.6) | Table drag handle color. |
codeColor | string | No | - | Inline code or code block color. |
imgPreview | boolean | No | true | Whether to enable image preview. |
imgLazyLoad | boolean | No | false | Whether to lazy-load images. |
useTab | boolean | No | false | Whether to let the Tab key insert a tab character. When enabled, it does not insert inside bullet or ordered lists. |
theme | 'light' | 'dark' | No | light | Editor theme. |
extensions | array | No | [] | Extra Tiptap extensions. |
showSave | boolean | No | true | Whether to show the save button. |
showDragHandler | boolean | No | false | Whether to show the block drag handle. |
ignoreDragNodeType | array | No | [] | List of node types where the drag handle should be hidden. |
dragHandlerNested | boolean | No | false | Whether the drag handle should work inside nested block nodes. |
diffInlineBlockTypes | string[] | No | [] | Additional block node types that should still be diffed like inline content. Use this for custom nodes that look block-level but should compare inner inline fragments. |
diffContainerBlockTypes | string[] | No | [] | Additional block node types that should be diffed as container nodes. Useful for wrappers, layout containers, and custom nested structures. |
diffInsertColor | string | No | "" | Primary highlight color for inserted changes. |
diffDeleteColor | string | No | "" | Primary highlight color for deleted changes. |
diffInsertColorSec | string | No | "" | Secondary accent color for inserted changes, usually used for borders or supporting decoration. |
diffDeleteColorSec | string | No | "" | Secondary accent color for deleted changes. |
diffInsertHoverColor | string | No | "" | Hover highlight color for inserted changes. |
diffDeleteHoverColor | string | No | "" | Hover highlight color for deleted changes. |
diffInsertHoverColorSec | string | No | "" | Secondary hover accent color for inserted changes. |
diffDeleteHoverColorSec | string | No | "" | Secondary hover accent color for deleted changes. |
Custom Media Container Buttons
Media containers such as images, equations, embeds and drawings can show custom buttons on the left or right side of the control bar. Configure them with the mediaContainerButtons prop:
Click Add in the initial drawing block to append another drawing block.
Each button supports icon (Fluent UI icon name without the ms-Icon-- prefix), background (background color), title (tooltip) and func (click callback). The callback receives { editor, node, pos }: the current Tiptap editor, the media node and its document position. If omitted, background uses the same theme-based color as built-in buttons; both lists default to empty. Custom buttons follow the media control bar visibility rules, including showControlOnReadonly.
Events
| Event | Args | Description |
|---|---|---|
on-mounted | editor | Emitted after the editor is initialized. Returns the current Tiptap editor instance. |
container-scroll | event | Emitted when the editor container scrolls. |
change | payload | Emitted when editor content changes. |
content-change | payload | Emitted when external content is synchronized into the editor. |
save-json | string | Emitted with JSON content after saving. |
save-html | string | Emitted with HTML content after saving. |
Methods
Use a template ref to call exposed editor methods.
<script setup>
import { ref } from "vue";
const editor = ref(null);
const mdFileInput = ref(null);
const openMarkdownFile = () => {
mdFileInput.value?.click();
};
const handleMarkdownImport = async (event) => {
const file = event.target.files?.[0];
if (!file) return;
const markdown = await file.text();
editor.value?.insertMarkdown(markdown);
event.target.value = "";
};
const exportMarkdown = async () => {
const markdown = editor.value?.saveMarkdown?.() ?? "";
console.log(markdown);
await navigator.clipboard.writeText(markdown);
};
</script>
<template>
<input
ref="mdFileInput"
type="file"
accept=".md,.markdown,.txt,text/markdown,text/plain"
style="display: none;"
@change="handleMarkdownImport"
/>
<power-editor ref="editor" :showDragHandler="true">
<template #custom-buttons="{ defaultClass }">
<fv-button
:class="[defaultClass, 'round-btn']"
border-color="transparent"
title="Import Markdown"
@click="openMarkdownFile"
>
<i class="ms-Icon ms-Icon--Upload"></i>
</fv-button>
<fv-button
:class="[defaultClass, 'round-btn']"
border-color="transparent"
title="Export Markdown"
@click="exportMarkdown"
>
<i class="ms-Icon ms-Icon--Download"></i>
</fv-button>
</template>
</power-editor>
</template>
<style scoped>
.round-btn {
border-radius: 999px;
}
</style>| Method | Description |
|---|---|
editor.save() | Saves the current content and emits save-json and save-html. |
editor.saveMarkdown() | Converts the current editor content to Markdown. |
editor.computeMarkdown(markdown) | Parses Markdown into editor content. |
editor.insertMarkdown(markdown) | Inserts Markdown at the current position. |
editor.compareDiff(sourceDoc, targetDoc) | Runs the built-in diff entry and returns the same result shape as computeDiff(). |
editor.editor() | Returns the current Tiptap editor instance so you can call low-level APIs such as getJSON() or editor commands directly. |
editor.focus() | Moves focus into the editor. |
Slots
custom-buttons
Adds custom buttons to the toolbar. You can also use custom-buttons-front or custom-buttons-[index] to control the position. index starts from 0 and goes up to 4. When no position is provided, the button is inserted at the right end of the toolbar.
Slot props:
| Prop | Description |
|---|---|
editor | Current Tiptap editor instance. |
defaultClass | Default toolbar button class. |
<power-editor>
<template #custom-buttons="{ defaultClass }">
<fv-button :class="[defaultClass]">Custom</fv-button>
</template>
</power-editor>bubble-custom-buttons
Adds custom buttons to the bubble toolbar shown when text is selected. Three insertion positions are available:
| Slot | Position |
|---|---|
bubble-custom-buttons-front | Before all built-in buttons. |
bubble-custom-buttons-1 | After the first separator, before the Format Painter button. |
bubble-custom-buttons | After all built-in buttons. |
All three slots expose these props:
| Prop | Description |
|---|---|
editor | Current Tiptap editor instance. |
defaultClass | Default bubble toolbar button class: power-editor-bubble-cmd-btn. |
<power-editor>
<template #bubble-custom-buttons="{ editor, defaultClass }">
<fv-button
:class="defaultClass"
@click="editor.chain().focus().toggleBold().run()"
>
Bold
</fv-button>
</template>
</power-editor>Replace the slot name in the example with bubble-custom-buttons-front or bubble-custom-buttons-1 to change the button position.
front-content
Adds custom content before the document body.
<power-editor>
<template #front-content>
<div class="front-content-block">Before editor content</div>
</template>
</power-editor>