掘金同款Markdown编辑器
再
2021年03月10日 17:01
的时候稀土君发表了掘友们的创作利器-新版掘金编辑器上线啦!Markdown
掘金bytemd
编辑器开源了。
使用掘金编辑器体验与其他编辑器的区别
个人觉得最大的就是支持复制
html
->markdown
语法了。 比如我再MDN
复制一段api
说明介绍, 不用我自己再转成Markdown
语法了,会自动转换。
**bytemd
编辑器并没有支持html
-> markdown
**的转换,想要体验的下bytemd
能力的可以去 演武场 自己去试试。
bytemd
插件
bytemd
编辑器的功能做成插件的形式了,像其他编辑器的话也有一些是配置式,就是那个功能我不需要我搞个配置就好了。插件形式话也是算是配置式,需要那个安装那个,好处是可以自己按照bytemd
的插件要求去扩展更多的功能。插件如下:
- @bytemd/plugin-breaks (Support breaks)
- @bytemd/plugin-frontmatter (Parse frontmatter)
- @bytemd/plugin-gemoji (Support Gemoji shortcodes)
- @bytemd/plugin-gfm (Support GFM (autolink literals, strikethrough, tables, tasklists))
- @bytemd/plugin-highlight (Highlight code blocks)
- @bytemd/plugin-highlight-ssr (Highlight code blocks (SSR compatible))
- @bytemd/plugin-math (Support math formula)
- @bytemd/plugin-math-ssr (Support math formula (SSR compatible))
- @bytemd/plugin-medium-zoom (Zoom images like Medium)
- @bytemd/plugin-mermaid (Support Mermaid diagram)
插件大致能力就是支持图片可点击放大、支持表格、支持表情包、支持Mermaid语法图表、支持math公式等。全都安装给bytemd
去使用就好了。
bytemd
实现复制HTML 转成 Markdown 实现方案
1、有直接监听复制事件,完事直接使用turndown
转的使用如下:(vue配置bytemd(掘金同款MarkDown插件)文章链接)
核心代码如下:
document.addEventListener('paste', function (event) {
that.SetHtml(event);
});
//转markdown语法
async SetHtml(e) {
e.preventDefault();
const list = e.clipboardData.items;
for (let i = 0; i < list.length; i++) {
if (list[i].kind === 'string' && list[i].type.match('^text/html')) {
const h = await new Promise(t => list[i].getAsString(e => t(e)));
const ts = new TurndownService()
this.value = ts.turndown(h)
}
}
}
功能实现了,不好的点是:比如我粘贴到的位置不是你的编辑器里面呢!你也都解析了。未加是否再编辑器中的判断!!
2、 开发一款@bytemd/plugin-html2md
插件,下面细说!
bytemd
插件开发@bytemd/plugin-html2md 初始化(一)
开发一款
@bytemd/plugin-html2md
插件,他的能力呢就是把复制来的html
转成md
。插件生命周期如下图:
interface BytemdPlugin {
/**
* Customize Markdown parse by remark plugins:
*
* https://github.com/remarkjs/remark/blob/main/doc/plugins.md
*/
remark?: (p: Processor) => Processor
/**
* Customize HTML parse by rehype plugins:
*
* https://github.com/rehypejs/rehype/blob/main/doc/plugins.md
*/
rehype?: (p: Processor) => Processor
/**
* 在工具栏,备忘单和快捷方式中注册操作
*/
actions?: BytemdAction[]
/**
* 编辑器的副作用,当插件更改时触发
*/
editorEffect?(ctx: BytemdEditorContext): void | (() => void)
/**
* 对查看器的副作用,当查看器道具改变时触发
*/
viewerEffect?(ctx: BytemdViewerContext): void | (() => void)
}
export default function html2mdPlugin(): BytemdPlugin {
return {
// to be implement
}
}
咱们要更改的是编辑视图用到的是editorEffect
了,代码结构如下:
export default function html2mdPlugin(): BytemdPlugin {
return {
editorEffect(ctx) {
},
}
}
bytemd
插件开发@bytemd/plugin-html2md 使用turndown解析HTML(二)
用
editorEffect
去监听编辑时候发生更改做相关处理。使用turndown
把HTML
转成Markdown
语法,。
turndown
使用如下:
import TurndownService from 'turndown';
const turndownService = new TurndownService({ option: 'value' });
const markdown = turndownService.turndown('<h1>Hello world!</h1>');
Option | Valid values | Default |
---|---|---|
headingStyle | setext or atx | setext |
hr | Any Thematic break | * * * |
bulletListMarker | - , + , or * | * |
codeBlockStyle | indented or fenced | indented |
fence | ``` or ~~~ | ``` |
emDelimiter | _ or * | _ |
strongDelimiter | ** or __ | ** |
linkStyle | inlined or referenced | inlined |
linkReferenceStyle | full , collapsed , or shortcut | full |
preformattedCode | false or true | false |
bytemd
插件开发@bytemd/plugin-html2md (三)
完整开发如下:
import type { Editor, EditorConfiguration } from 'codemirror'
export interface BytemdEditorContext extends EditorUtils {
codemirror: typeof CodeMirror
/**
* CodeMirror editor instance
*/
editor: Editor
/**
* The root element
*/
root: HTMLElement
}
export default function html2mdPlugin(): BytemdPlugin {
return {
editorEffect({ editor }) {
// editor 详细用法请参考 https://codemirror.net/docs/guide/
editor.on('parse', ($editor, event) => {
let itemList: any[] = [];
if (event instanceof ClipboardEvent) {
itemList = Array.from(event?.clipboardData?.items) || [];
} else {
itemList = Array.from(event?.dataTransfer?.items) || [];
}
const HTMLItem = itemList.find((v) => v.type.includes('text/html'))
if (!HTMLItem) {
return;
}
let HTMLStr;
switch (HTMLItem.kind) {
case 'string':
HTMLStr = await new Promise((res) =>
HTMLItem.getAsString((e) => {
res(e);
}));
break;
case 'file':
HTMLStr = await HTMLItem.getAsFile().text();
break;
default:
throw new Error('粘贴的item.kind有未知的类型,需要手动处理!');
}
const markdown = turndownService.turndown(HTMLStr);
$editor.replaceSelection(markdown);
});
},
}
}
使用
具体使用如下:
<template>
<Editor :value="value" :plugins="plugins" @change="handleChange" />
</template>
<script>
import { Editor, Viewer } from '@bytemd/vue'
import gfm from '@bytemd/plugin-gfm'
import highlight from '@bytemd/plugin-highlight-ssr';
import mediumZoom from "@bytemd/plugin-medium-zoom";
import gemoji from "@bytemd/plugin-gemoji";
import html2mdPlugin from './html2md-plugin.js'
// 引入中文包
import zhHans from "bytemd/lib/locales/zh_Hans.json";
// 引入基础css
import 'bytemd/dist/index.min.css';
// 引入高亮css
import "highlight.js/styles/vs.css";
const plugins = [
gfm(),
highlight(),
mediumZoom(),
gemoji(),
html2mdPlugin(),
// Add more plugins here
]
export default {
components: { Editor },
data() {
return { value: '', plugins }
},
methods: {
handleChange(v) {
this.value = v
},
},
}
</script>
总结
这个样就可以使
bytemd
复制HTML
到转成Markdown
了。