开源软件名称(OpenSource Name):bytedance/bytemd开源软件地址(OpenSource Url):https://github.com/bytedance/bytemd开源编程语言(OpenSource Language):TypeScript 51.3%开源软件介绍(OpenSource Introduction):ByteMDByteMD is a Markdown editor component built with Svelte. It could also be used in other libraries/frameworks such as React, Vue and Angular. Playground here: https://bytemd.js.org/playground/ Features
Installation
Legacy browsers supportThe default entry of NPM package only supports modern browsers. To make legacy browsers (IE9+) work, You can compile it with ESNext -> ES5 transpilers, such as Babel or SWC.
Notice that polyfills are not included, and should be imported manually, see the legacy browser example. UsageThere are two components: Before using the component, remember to import CSS file to make styles correct: import 'bytemd/dist/index.css' Svelte<script>
import { Editor, Viewer } from 'bytemd'
import gfm from '@bytemd/plugin-gfm'
let value
const plugins = [
gfm(),
// Add more plugins here
]
function handleChange(e) {
value = e.detail.value
}
</script>
<template>
<Editor {value} {plugins} on:change={handleChange} />
</template> Reactimport { Editor, Viewer } from '@bytemd/react'
import gfm from '@bytemd/plugin-gfm'
const plugins = [
gfm(),
// Add more plugins here
]
const App = () => {
const [value, setValue] = useState('')
return (
<Editor
value={value}
plugins={plugins}
onChange={(v) => {
setValue(v)
}}
/>
)
} Vue<template>
<Editor :value="value" :plugins="plugins" @change="handleChange" />
</template>
<script>
import { Editor, Viewer } from '@bytemd/vue'
import gfm from '@bytemd/plugin-gfm'
const plugins = [
gfm(),
// Add more plugins here
]
export default {
components: { Editor },
data() {
return { value: '', plugins }
},
methods: {
handleChange(v) {
this.value = v
},
},
}
</script> Vanilla JSimport { Editor, Viewer } from 'bytemd'
import gfm from '@bytemd/plugin-gfm'
const plugins = [
gfm(),
// Add more plugins here
]
const editor = new Editor({
target: document.body, // DOM to render
props: {
value: '',
plugins,
},
})
editor.$on('change', (e) => {
editor.$set({ value: e.detail.value })
}) OptionsViewer
Editor
Style customizationEditorThe default height of ByteMD Editor is .bytemd {
height: calc(100vh - 200px);
} The other styles could also be overridden, see the default style. ViewerThere is no built-in styles for the Viewer. You could use third-party markdown themes, for example juejin-markdown-themes and github-markdown-css. Plugin SystemByteMD provides a powerful plugin system for customization. There are several official plugins to support features such as code syntax highlight, math equation and Mermaid flowcharts. If you have more customized needs, you could also write your own plugin to support them. Official Plugins
Technical OverviewByteMD uses remark and rehype ecosystem to process Markdown. The complete process is as follows:
It could also be described as a flowchart: The 2,5,7 steps are designed for user customization via ByteMD plugin API. Authoring a PluginWe'll take Math formula plugin as an example to walk you through the process. First of all, scaffold the project according to the import type { BytemdPlugin } from 'bytemd'
export default function mathPlugin(): BytemdPlugin {
return {
// to be implement
}
} Then we look into the requirement more closely: If we want to render syntax like
For the first thing, luckily, we don't need to implement it with our own because remark-math already did it. The only thing we need to do is to import and use it: import type { BytemdPlugin } from 'bytemd'
+import remarkMath from 'remark-math'
export default function mathPlugin(): BytemdPlugin {
return {
- // to be implement
+ remark: (processor) => processor.use(remarkMath),
}
} Then consider the second thing, it would be a little complicated because we have two choices, do it in step 5 or 7. The difference is that step 5 is more friendly with SSR, while step 7 hand over the rendering to the client-side. This is why we have two plugin: @bytemd/plugin-math and @bytemd/plugin-math-ssr. // if we choose step 5:
import type { BytemdPlugin } from 'bytemd'
import remarkMath from 'remark-math'
+import rehypeKatex from 'rehype-katex'
export default function mathPlugin(): BytemdPlugin {
return {
remark: (processor) => processor.use(remarkMath),
+ rehype: (processor) => processor.use(rehypeKatex),
}
}
// if we choose step 7:
import type { BytemdPlugin } from 'bytemd'
import remarkMath from 'remark-math'
+import rehypeKatex from 'rehype-katex'
export default function mathPlugin(): BytemdPlugin {
return {
remark: (processor) => processor.use(remarkMath),
+ viewerEffect({ markdownBody }) {
+ const renderMath = async (selector: string, displayMode: boolean) => {
+ const katex = await import('katex').then((m) => m.default)
+
+ const els = markdownBody.querySelectorAll<HTMLElement>(selector)
+ els.forEach((el) => {
+ katex.render(el.innerText, el, { displayMode })
+ })
+ }
+
+ renderMath('.math.math-inline', false)
+ renderMath('.math.math-display', true)
+ },
}
} The last thing is to add an icon to the toolbar. we use the export default function mathPlugin(): BytemdPlugin {
return {
actions: [
{
title: 'Insert an math formula',
icon: '', // 16x16 SVG icon
handler: {
type: 'action',
click(ctx) {
// to be implement:
// the `ctx` is an instance of `BytemdEditorContext`, which has
// several utility methods to help operate the CodeMirror editor state.
// remember to call `focus` to avoid lost of focus
editor.focus()
},
},
},
],
}
} Now we have completed a minimalist version of the plugin! For more details and references please check out the source code. ContributorsLicenseMIT |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论