赞
踩
附cherry-markdown官网及api使用示例
官网:https://github.com/Tencent/cherry-markdown/blob/main/README.CN.md
考虑到复用性,我在插件的基础上做了二次封装,步骤如下:
1.下载 (一定要指定版本0.8.22,否则会报错: [vitel Internal server error: Failed to parse soERRORrce for import analysis because the content contains invalid Js syntax. If you are using JSX, make sure to name the file with the...)
npm i cherry-markdown@0.8.22
如果需要开启 mermaid
画图、表格自动转图表功能,需要同时添加mermaid
与echarts
包。
目前Cherry推荐的插件版本为echarts@5.3.3
、mermaid@9.4.3
# 安装mermaid依赖开启mermaid画图功能
npm i mermaid@9.4.3
# 安装echarts依赖开启表格自动转图表功能
npm i echarts@5.3.3
基础应用代码示例
- <template>
- <div @click.prevent.stop>
- <div id="markdown-container"></div>
- </div>
- </template>
-
- <script>
- import 'cherry-markdown/dist/cherry-markdown.css';
- import Cherry from 'cherry-markdown';
- const cherryInstance = new Cherry({
- id: 'markdown-container',
- value: '# welcome to cherry editor!',
- });
- </script>
核心构建包不包含 mermaid 依赖,需要手动引入相关插件。
- import 'cherry-markdown/dist/cherry-markdown.css';
- import Cherry from 'cherry-markdown/dist/cherry-markdown.core';
- import CherryMermaidPlugin from 'cherry-markdown/dist/addons/cherry-code-block-mermaid-plugin';
- import mermaid from 'mermaid';
-
- // 插件注册必须在Cherry实例化之前完成
- Cherry.usePlugin(CherryMermaidPlugin, {
- mermaid, // 传入mermaid引用
- // mermaidAPI: mermaid.mermaidAPI, // 也可以传入mermaid API
- // 同时可以在这里配置mermaid的行为,可参考mermaid官方文档
- // theme: 'neutral',
- // sequence: { useMaxWidth: false, showSequenceNumbers: true }
- });
-
- const cherryInstance = new Cherry({
- id: 'markdown-container',
- value: '# welcome to cherry editor!',
- });
2.附上组件代码
- <template>
- <div @click.prevent.stop style="position: relative; width: 100%; height: 100%; z-index: 9999999999;text-align: left;">
-
- <!-- ------- markdown组件容器 --------- -->
- <div ref="markdownContainerRef" :id="mdId" class="cherry_container scroll"
- :style="{ 'left': toc_Visiable ? '262px' : '0px' }" @scroll="onScroll">
- </div>
-
- <!-- ------- 显示目录 --------- -->
- <!-- <div class="toc_container" v-show="toc_Visiable">
- <div class="toc_header">目录</div>
- <div class="toc_list">
- <div v-for="(link, index) in toc_List" :key="link.id" class="toc_list_container"
- :style="{ 'padding-left': link.level * 20 + 'px' }" @click="jump(index)">{{ link.text }}
- </div>
- </div>
- </div>
- <div class="top-contrl">
- <div v-if="!toc_Visiable" @click="showToc(true)">显示目录</div>
- <div v-else @click="showToc(false)">隐藏目录</div>
- </div> -->
- </div>
- </template>
-
- <script setup>
- import { ref, onMounted, onBeforeMount, watch, onBeforeUnmount, toRefs, reactive, nextTick } from 'vue';
- import Axios from 'axios';
- import 'cherry-markdown/dist/cherry-markdown.css';
- import Cherry from 'cherry-markdown'
- // import Cherry from 'cherry-markdown/dist/cherry-markdown.core';
- import * as echarts from "echarts";
- import pinyin from '../assets/pinyinHelper.js'; // 引入pinyin函数
- import CherryMermaidPlugin from 'cherry-markdown/dist/addons/cherry-code-block-mermaid-plugin';
- import mermaid from 'mermaid';
- // 组件传值
- const props = defineProps({
- // markdown文本
- markDownConent: {
- type: String,
- default: '',
- },
- // markdown组件容器ID
- mdId: {
- type: String,
- default: 'markdownContainer',
- },
- // 编辑器的显示模式 view|edit
- displayModal: {
- type: String,
- default: 'view',
- },
- // 用来控制目录显示或隐藏
- tocVisiable: {
- type: Boolean,
- default: true,
- },
-
- });
- const emit = defineEmits(['input', 'md-change']);
- const { mdId, displayModal, tocVisiable, markDownConent } = toRefs(props);
-
-
- // 组件内部变量
- const content = ref('');
- const markdownContainerRef = ref(null); //dom 元素
- const markDown_Conent = ref('');
- const toc_Visiable = ref(tocVisiable.value); //目录 显隐
- const cherrInstance = ref(null); //Cherry MarkDown实例
-
- const initCherryMD = async (value) => {
- markDown_Conent.value = value || markDownConent.value;
- cherrInstance.value = new Cherry({
- id: mdId.value,
- value: markDown_Conent.value,
- externals: {
- echarts: echarts,
- },
- fileUpload,
- callback: {
- changeString2Pinyin: pinyin,
- // afterChange,
- afterInit,
- beforeImageMounted,
- onClickPreview: function (e) {
- const { target } = e;
- if (target.tagName === 'IMG') {
- console.log('click img', target);
- const tmp = new Viewer(target, {
- button: false,
- navbar: false,
- title: [1, (image, imageData) => `${image.alt.replace(/#.+$/, '')} (${imageData.naturalWidth} × ${imageData.naturalHeight})`],
- hidden() {
- tmp.destroy()
- },
- });
- tmp.show();
- }
- }
- },
- toolbars: {
- showToolbar:displayModal.value=="previewOnly"?false:true,
- toolbar: ['bold', 'italic', 'strikethrough', '|', 'color', 'header', 'ruby', '|', 'list', 'panel', 'detail'],
- // 定义侧边栏,默认为空
- sidebar: [],
- // 定义顶部右侧工具栏,默认为空
- toolbarRight: [],
- // 定义选中文字时弹出的“悬浮工具栏”,默认为 ['bold', 'italic', 'underline', 'strikethrough', 'sub', 'sup', 'quote', '|', 'size', 'color']
- bubble: false,
- // 定义光标出现在行首位置时出现的“提示工具栏”,默认为 ['h1', 'h2', 'h3', '|', 'checklist', 'quote', 'table', 'code']
- float: false,
- // 定义顶部工具栏
- toolbar: [
- 'bold',
- 'italic',
- {
- strikethrough: ['strikethrough', 'underline', 'sub', 'sup', 'ruby', 'boldAndItalicName'],
- },
- 'size',
- '|',
- 'color',
- 'header',
- '|',
- 'ol',
- 'ul',
- 'checklist',
- 'panel',
- 'justify',
- 'detail',
- '|',
- 'formula',
- {
- insert: ['image', 'audio', 'video', 'link', 'hr', 'br', 'code', 'formula', 'toc', 'table', 'pdf', 'word', 'ruby'],
- },
- 'graph',
- 'togglePreview',
- 'settings',
- 'codeTheme',
- 'export',
- // {
- // customMenuBName: ['ruby', 'audio', 'video', 'boldAndItalicName'],
- // },
- // 'customMenuCName',
- 'theme',
- ],
- // 定义侧边栏,默认为空
- sidebar: ['mobilePreview', 'copy', 'theme'],
- // 定义顶部右侧工具栏,默认为空
- toolbarRight: ['fullScreen', '|'],
-
- // 定义选中文字时弹出的“悬浮工具栏”,默认为 ['bold', 'italic', 'underline', 'strikethrough', 'sub', 'sup', 'quote', '|', 'size', 'color']
- bubble: ['bold', 'italic', 'underline', 'strikethrough', 'sub', 'sup', 'quote', 'ruby', '|', 'size', 'color'], // array or false
- showToolbar: true,
- // 定义光标出现在行首位置时出现的“提示工具栏”,默认为 ['h1', 'h2', 'h3', '|', 'checklist', 'quote', 'table', 'code']
- // float: false,
- toc: {
- updateLocationHash: false, // 要不要更新URL的hash
- defaultModel: 'full', // pure: 精简模式/缩略模式,只有一排小点; full: 完整模式,会展示所有标题
- },
- customMenu: {
- boldAndItalicName: boldAndItalic,
- customMenuBName: customMenuB,
- customMenuCName: customMenuC,
- },
- },
-
- editor: {
- id: `${mdId.value}editor`,
- name: 'cherry-text',
- autoSave2Textarea: true,
- defaultModel: displayModal.value,
- },
- previewer: {
- // 自定义markdown预览区域class
- // className: 'markdown'
- },
- // 预览页面不需要绑定事件
- isPreviewOnly: false,
- // 预览区域跟随编辑器光标自动滚动
- autoScrollByCursor: true,
- // 外层容器不存在时,是否强制输出到body上
- forceAppend: true,
- // The locale Cherry is going to use. Locales live in /src/locales/
- locale: 'zh_CN',
- keydown: [],
-
- // cherry初始化后是否检查 location.hash 尝试滚动到对应位置
- autoScrollByHashAfterInit: false,
- });
- };
-
-
-
-
-
- /**
- * 自定义一个自定义菜单
- * 点第一次时,把选中的文字变成同时加粗和斜体
- * 保持光标选区不变,点第二次时,把加粗斜体的文字变成普通文本
- */
- const boldAndItalic = Cherry.createMenuHook('加粗斜体', {
- iconName: 'font',
- onClick: function (selection) {
- // 获取用户选中的文字,调用getSelection方法后,如果用户没有选中任何文字,会尝试获取光标所在位置的单词或句子
- let $selection = this.getSelection(selection) || '同时加粗斜体';
- // 如果是单选,并且选中内容的开始结束内没有加粗语法,则扩大选中范围
- if (!this.isSelections && !/^\s*(\*\*\*)[\s\S]+(\1)/.test($selection)) {
- this.getMoreSelection('***', '***', () => {
- const newSelection = this.editor.editor.getSelection();
- const isBoldItalic = /^\s*(\*\*\*)[\s\S]+(\1)/.test(newSelection);
- if (isBoldItalic) {
- $selection = newSelection;
- }
- return isBoldItalic;
- });
- }
- // 如果选中的文本中已经有加粗语法了,则去掉加粗语法
- if (/^\s*(\*\*\*)[\s\S]+(\1)/.test($selection)) {
- return $selection.replace(/(^)(\s*)(\*\*\*)([^\n]+)(\3)(\s*)($)/gm, '$1$4$7');
- }
- /**
- * 注册缩小选区的规则
- * 注册后,插入“***TEXT***”,选中状态会变成“***【TEXT】***”
- * 如果不注册,插入后效果为:“【***TEXT***】”
- */
- this.registerAfterClickCb(() => {
- this.setLessSelection('***', '***');
- });
- return $selection.replace(/(^)([^\n]+)($)/gm, '$1***$2***$3');
- }
- });
- /**
- * 定义一个空壳,用于自行规划cherry已有工具栏的层级结构
- */
- const customMenuB = Cherry.createMenuHook('实验室', {
- iconName: '',
- });
- /**
- * 定义一个自带二级菜单的工具栏
- */
- const customMenuC = Cherry.createMenuHook('帮助中心', {
- iconName: 'question',
- onClick: (selection, type) => {
- switch (type) {
- case 'shortKey':
- console.log("声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/580649推荐阅读
相关标签
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。