This article covers the use of the editor and some of the development techniques that accompany it.
The editor supports the following functions: basic MD editing, MD syntax shortcut keys, record saving, dark theme, picture uploading/copying picture uploading/cropping picture uploading, formatting content, browser full screen/full screen, preview mode only and other functions, waiting to be used.
For detailed editor API reference: documentation.
- Image cropping preview
- Editor preview
1. Basic use
Here are three ways to write in two environments:
1.1 NPM Installation usage
This method supports both. Vue template writing and JSX syntax.
The installation
yarn add md-editor-v3
Copy the code
Vue template basic use
<template>
<md-editor v-model="text" />
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import MdEditor from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
export default defineComponent({
components: { MdEditor },
data() {
return { text: ' '}; }});</script>
Copy the code
JSX syntax basics to use
import { defineComponent, ref } from 'vue';
import MdEditor from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
export default defineComponent({
name: 'MdEditor'.setup() {
const text = ref(' ');
return () = > (
<MdEditor modelValue={text.value} onChange={(v: string) = > (text.value = v)} />); }});Copy the code
1.2 Introduction of script tags
The link is to search mD-editor-v3 at cdn.jsdelivr.net.
<! -- Add style -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/lib/style.css" rel="stylesheet" />
<! - introduce vue3 -- -- >
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.global.prod.min.js"></script>
<! -- Importing components -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/md-editor-v3.umd.js"></script>
Copy the code
Certified components
const App = {
data() {
return {
text: 'Hello Editor!! '}; }}; Vue.createApp(App).use(MdEditorV3).mount('#md-editor-v3');
Copy the code
Using the component
<div id="md-editor-v3">
<md-editor-v3 v-model="text" />
</div>
Copy the code
2. Render content
The editor uses marked to parse MD to HTML without extended syntax.
In general, edit content is stored in MD format and rendered in HTML by marked.
2.1 Default Rendering
Since version 1.3.0, the editor supports previewOnly, which allows you to preview articles directly using the editor without bars, edits, etc.
<template>
<md-editor
v-model="text"
previewOnly
/>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import MdEditor from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
export default defineComponent({
components: { MdEditor },
data() { return { text: '## I will only show preview content '}; }});</script>
Copy the code
2.2 Active parsing demo
This is used to save the MD and then parse the MD content yourself.
import marked from 'marked';
// Code highlights
import hljs from 'highlight.js';
// Code highlighting style of your choice
import 'highlight.js/scss/atom-one-dark.scss';
// Use to record the number of headings, according to the business
let count = 0;
// Record the title content
const headstemp = [];
/ / marked Settings
const rendererMD = new marked.Renderer();
// Adjust the title content
rendererMD.heading = (text, level) = > {
headstemp.push({ text, level });
count++;
return `<h${level} id="heading-${count}"><span class="h-text">${text}</span></h${level}> `;
};
// Set the image content to display a unified cache image for lazy loading ~
rendererMD.image = (href, _, text) = >
`<img data-src="${href}" src="/cos/2020/1211175603.png" alt="${text}" >`;
marked.setOptions({
highlight(code) {
return hljs.highlightAuto(code).value
},
renderer: rendererMD
});
// The HTML is the element text inserted into the page
const html = marked('## md content ');
Copy the code
2.3 Realization of title navigation
The above example, HeadStemp, records all the titles during parsing to build a title navigation with the UI library component Anchor.
Here is a demo version based on Ant-Design-Vue. If you are using a UI library with similar anchor components, the code will need only minor changes. Code using JSX syntax, VUE template syntax please separate code ~
Link components in Recursive. TSX navigation
import { Anchor } from 'ant-design-vue';
import { defineComponent, PropType } from 'vue';
const { Link } = Anchor;
export interface Head {
text: string;
level: number;
}
export interface TocItem extends Head {
anchor: string; children? :Array<TocItem>;
}
const Recursive = defineComponent({
props: {
tocItem: {
type: Object as PropType<TocItem>,
default: () = >[]}},setup({ tocItem }) {
return (
<Link href={` # ${tocItem.anchor} `}title={tocItem.text}>
{tocItem.children &&
tocItem.children.map((item) => <Recursive key={item.anchor} tocItem={item} />)}
</Link>); }});export default Recursive;
Copy the code
Topicfy.tsx is used to generate the entire navigation content
import { Anchor } from 'ant-design-vue';
import { computed, defineComponent, PropType, ref, watch } from 'vue';
import Recursive, { Head, TocItem } from './Recursive';
const Topicfy = defineComponent({
props: {
// A list of parsed titles
heads: {
type: Array as PropType<Array<Head>>
}
},
setup(props) {
const topics = computed(() = > {
const tocItems: TocItem[] = [];
// Title counter
let count = 0;
const add = (text: string, level: number) = > {
count++;
const item = { anchor: `heading-${count}`, level, text };
if (tocItems.length === 0) {
// The first item is pushed directly
tocItems.push(item);
} else {
let lastItem = tocItems[tocItems.length - 1]; // 最后一个 item
if (item.level > lastItem.level) {
// Item is lastItem's children
for (let i = lastItem.level + 1; i <= 6; i++) {
const { children } = lastItem;
if(! children) {// If children do not exist
lastItem.children = [item];
break;
}
// reset lastItem to the lastItem of children
lastItem = children[children.length - 1];
if (item.level <= lastItem.level) {
// If item level is less than or equal to lastItem level, it is considered to be at the same level as children
children.push(item);
break; }}}else {
// put it at the toptocItems.push(item); }}}; props.heads? .forEach((item) = > {
add(item.text, item.level);
});
return tocItems;
});
return () = > (
<Anchor affix={false} showInkInFixed={true}>
{topics.value.map((item) => (
<Recursive key={item.anchor} tocItem={item} />
))}
</Anchor>); }});export default Topicfy;
Copy the code
The react version is based on Topicfy
2.4 Obtaining THE HTML code
The editor is concerned that the backend may not store mD-formatted text but HTML content, so it provides the onHtmlChanged method, which is used to edit the content changes, marked compiles the callback to the content, and the input is the HTML content.
<template>
<md-editor
v-model="text"
@onHtmlChanged="saveHtml"
/>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import MdEditor from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
export default defineComponent({
components: { MdEditor },
data() { return { text: ' ' }; },
methods: { saveHtml(h: string) { console.log(h) }}
});
</script>
Copy the code
JSX has the same syntax.
3. Function demonstration of the editor
3.1 Extension library links
Editor extension content mostly uses CDN, considering no extranet situation, supports Intranet link extension, demonstration (assuming that external libraries are in the root directory) :
<template>
<md-editor
v-model="text"
highlightJs="/highlight.min.js"
highlightCss="/atom-one-dark.min.css"
prettierCDN="/standalone.js"
prettierMDCDN="/parser-markdown.js"
cropperJs="/cropper.min.js"
cropperCss="/cropper.min.css"
/>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import MdEditor from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
export default defineComponent({
components: { MdEditor },
data() { return { text: ' '}; }});</script>
Copy the code
V1.2.0 currently supports the above links, and the icon links will be added in the following patches.
3.2 Toolbar Customization
By default, all toolbars are available, and each feature is bound with shortcut keys. If you need to selectively display toolbars, there are two apis: Toolbars, which display all of the array, and toolbarsExclude, which has more weight, which blocks all of the array. Here’s a reference:
The example does not show the Github button
<template>
<md-editor
v-model="text"
:toolbars="toobars"
/>
<md-editor
v-model="text"
:toolbarsExclude="toolbarsExclude"
/>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import MdEditor from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
export default defineComponent({
components: { MdEditor },
data() {
return {
text: ' '.toobars: ['bold'.'underline'.'italic'.'strikeThrough'.'sub'.'sup'.'quote'.'unorderedList'.'orderedList'.'codeRow'.'code'.'link'.'image'.'table'.'revoke'.'next'.'save'.'pageFullscreen'.'fullscreen'.'preview'.'htmlPreview'].toolbarsExclude: ['github']}; }});</script>
Copy the code
3.3 Extended Languages
Both Chinese and English are built into the editor by default, and both can be overridden by the extended API, which is mainly used to set content hints, such as titles in popovers, etc.
To extend a language, we call it zh-NB
<template>
<md-editor
v-model="text"
:language="language"
:languageUserDefined="languageUserDefined"
/>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import MdEditor, { StaticTextDefaultValue } from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
const languageUserDefined: { 'zh-NB': StaticTextDefaultValue } = {
'zh-NB': {
toolbarTips: {
bold: 'bold'.underline: 'underline'.italic: 'italics'.strikeThrough: 'Delete line'.title: 'title'.sub: 'the subscript'.sup: 'superscript'.quote: 'reference'.unorderedList: 'Unordered list'.orderedList: 'Ordered list'.codeRow: 'In-line code'.code: 'Block level code'.link: 'link'.image: 'images'.table: 'form'.revoke: 'back'.next: 'forward'.save: 'save'.prettier: 'beautification'.pageFullscreen: 'Browser full screen'.fullscreen: 'Full screen'.preview: 'preview'.htmlPreview: 'HTML Code Preview'.github: 'Source address'
},
titleItem: {
h1: 'First level heading'.h2: 'Secondary heading'.h3: 'Level 3 heading'.h4: 'Level 4 Title'.h5: 'Level 5 heading'.h6: 'Six level headings'
},
linkModalTips: {
title: 'add'.descLable: 'Link Description:'.descLablePlaceHolder: 'Please enter a description... '.urlLable: 'Link address:'.UrlLablePlaceHolder: 'Please enter the link... '.buttonOK: 'sure'.buttonUpload: 'upload'
},
/ / v1.2.0 added
clipModalTips: {
title: 'Crop picture upload'.buttonUpload: 'upload'
},
/ / v1.1.4 added
copyCode: {
text: 'Copy code'.tips: 'Copied'}}};export default defineComponent({
components: { MdEditor },
data() {
return {
text: ' '.language: "zh-NB", languageUserDefined }; }});</script>
Copy the code
If key = ‘zh-cn’, Chinese overwrite can be implemented, and so on.
3.4 Theme Switch
This section is relatively simple, built-in dark theme and default theme, using themeAPI switch, the demo is as follows:
<template>
<md-editor
v-model="text"
:theme="theme"
/>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import MdEditor from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';
export default defineComponent({
components: { MdEditor },
data() {
return {
text: ' '.theme: 'dark'}; }});</script>
Copy the code
4. At the end
For more updates: MD-editor-v3