Markdown Decoder Plugins
PowerEditor includes built-in Markdown import and export support:
- Use
editor.insertMarkdown(markdown)to import Markdown into the editor - Use
editor.saveMarkdown()to export the current editor content as Markdown - Use
mdDecNodeFuncsPluginsandmdFlagsto customize how specific nodes and marks are rendered during export
Try It Online
Markdown Import And Export
Import Markdown
Use the exposed insertMarkdown(markdown) method to parse a Markdown string and write it into the editor.
<script setup>
import { ref } from "vue";
const editor = ref(null);
const importMarkdown = () => {
const markdown = `# Hello PowerEditor
- item 1
- item 2
`;
editor.value?.insertMarkdown(markdown);
};
</script>
<template>
<fv-button @click="importMarkdown">Import Markdown</fv-button>
<power-editor ref="editor" />
</template>When importing from a file, the usual flow is to read the file text first and then call:
const markdown = await file.text();
editor.value?.insertMarkdown(markdown);Export Markdown
Use saveMarkdown() to convert the current editor content into a Markdown string.
<script setup>
import { ref } from "vue";
const editor = ref(null);
const exportMarkdown = () => {
const markdown = editor.value?.saveMarkdown?.() ?? "";
console.log(markdown);
};
</script>
<template>
<fv-button @click="exportMarkdown">Export Markdown</fv-button>
<power-editor ref="editor" />
</template>If you want to download the result directly as a file:
const markdown = editor.value?.saveMarkdown?.() ?? "";
const blob = new Blob([markdown], { type: "text/markdown;charset=utf-8" });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "power-editor.md";
link.click();
URL.revokeObjectURL(url);Related Instance Methods
| Method | Description |
|---|---|
editor.insertMarkdown(markdown) | Parses Markdown and writes it into the editor. |
editor.saveMarkdown() | Exports the current editor content as a Markdown string. |
editor.computeMarkdown(markdown) | Only parses Markdown and returns editor-friendly content data without writing it into the editor. |
How To Customize Export Output
During Markdown export, the decoder traverses the ProseMirror document recursively in depth-first order. Built-in nodes use default decoder functions. You only need custom plugin functions for custom nodes or output formats that need special handling.
Plugin function names must match node names or mark names. A function can return a string, or an object with prefix and suffix.
type DecoderResult = string | {
prefix: string;
suffix: string;
};Custom Nodes
The example below renders blockquote with the correct number of > prefixes based on nesting depth.
> Level one
>> Level two
>>> Level threeblockquote(node, flags) {
const { blockquote: level } = flags;
let prefix = "";
for (let i = 0; i < level; i++) {
prefix += ">";
}
return `\n${prefix} `;
}A blockquote in PowerEditor may contain child nodes such as paragraph and text. In most cases, those children do not need to be handled manually, because the decoder continues with its default recursive rules.
Use Flags For Nesting
flags records which parent nodes the current node is inside and how deeply it is nested. Default flags usually look like this:
const flags = {
inline: false,
inlineWrapper: false,
heading: false,
bulletList: false,
orderedList: false,
blockquote: false,
powerTaskItem: false,
powerTaskList: false,
tableHeader: false,
tableCell: false,
tableRow: false,
table: false
};When traversal enters a tracked node, its flag changes from false to 1. If traversal enters a nested node of the same type, the value increments to 2, 3, and so on.
Pass Plugins To PowerEditor
<power-editor
ref="editor"
:md-dec-node-funcs-plugins="mdDecNodeFuncsPlugins"
:md-flags="mdFlags"
/>export default {
data() {
return {
mdDecNodeFuncsPlugins: {
blockquote: (node, flags) => {
const { blockquote: level } = flags;
let prefix = "";
for (let i = 0; i < level; i++) {
prefix += ">";
}
return `\n${prefix} `;
}
},
mdFlags: {
blockquote: false
}
};
}
};Then export with:
const markdown = editor.value?.saveMarkdown?.() ?? "";The resulting Markdown will use your custom rules.
Custom Marks
Mark plugins follow the same naming rule: the function name must match the mark name. The example below outputs the color value from textStyle as an HTML font tag:
<font color="red">Red text</font>textStyle(text, mark) {
const { color } = mark.attrs;
return {
prefix: `<font color="${color}">`,
suffix: "</font>"
};
}When an object is returned, prefix is written before the text and suffix after it. This is useful for paired Markdown or HTML syntax.