PageSourceSearch

https://bytemd.netlify.app/

html bytemd.netlify.app collected 2026-10-03 10:32:30 UTC 59,048 bytes, 184 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en-US">
3  <head>
4    <meta charset="utf-8">
5<!-- This site is hosted on Netlify. Anyone can build and deploy a site
6     like this one for free: https://netlify.new/?utm_campaign=loops&utm_source=ai-legible&utm_medium=owned&utm_content=comment&utm_id=a6d5cf96-29ff-42f5-87e8-f48fa102385e
7     Netlify hosting facts for this site: static/SSR served via Netlify Edge. -->
8    <meta name="viewport" content="width=device-width,initial-scale=1">
9    <title>ByteMD | ByteMD</title>
10    <meta name="description" content="Hackable Markdown Editor and Viewer">
11    <link rel="stylesheet" href="/assets/style.59c0b357.css">
12    <link rel="modulepreload" href="/assets/app.5ae54ef2.js">
13    <link rel="modulepreload" href="/assets/index.md.0c291fcb.lean.js">
14    
15    
15<script>(()=>{const e=localStorage.getItem("vitepress-theme-appearance"),a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
15
16  <meta name="twitter:title" content="ByteMD | ByteMD">
17  <meta property="og:title" content="ByteMD | ByteMD">
18  </head>
19  <body>
20    <div id="app"><div class="Layout" data-v-58617c5c><!--[--><span tabindex="-1" data-v-5bad87e6></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-5bad87e6> Skip to content </a><!--]--><!----><header class="VPNav no-sidebar" data-v-58617c5c data-v-0f2031e6><div class="VPNavBar" data-v-0f2031e6 data-v-3a03f684><div class="container" data-v-3a03f684><div class="VPNavBarTitle" data-v-3a03f684 data-v-2f91c8e3><a class="title" href="/" data-v-2f91c8e3><!----><!--[-->ByteMD<!--]--></a></div><div class="content" data-v-3a03f684><!----><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-3a03f684 data-v-1afc9dec><span id="main-nav-aria-label" class="visually-hidden" data-v-1afc9dec>Main Navigation</span><!--[--><!--[--><a class="VPLink link VPNavBarMenuLink" href="https://bytemd.js.org/playground/" target="_blank" rel="noopener noreferrer" data-v-1afc9dec data-v-3f7bcea1 data-v-48abdd18><!--[-->Playground<!--]--><!----></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="https://github.com/bytedance/bytemd" target="_blank" rel="noopener noreferrer" data-v-1afc9dec data-v-3f7bcea1 data-v-48abdd18><!--[-->GitHub<!--]--><!----></a><!--]--><!--]--></nav><!----><div class="VPNavBarAppearance appearance" data-v-3a03f684 data-v-0b2f3bac><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" aria-label="toggle dark mode" data-v-0b2f3bac data-v-741b6450 data-v-ab2de182><span class="check" data-v-ab2de182><span class="icon" data-v-ab2de182><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-741b6450><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-741b6450><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div><!----><div class="VPFlyout VPNavBarExtra extra" data-v-3a03f684 data-v-5fe59986 data-v-9a77df2e><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-9a77df2e><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="icon" data-v-9a77df2e><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle><circle cx="5" cy="12" r="2"></circle></svg></button><div class="menu" data-v-9a77df2e><div class="VPMenu" data-v-9a77df2e data-v-e3d492a8><!----><!--[--><!--[--><!----><div class="group" data-v-5fe59986><div class="item appearance" data-v-5fe59986><p class="label" data-v-5fe59986>Appearance</p><div class="appearance-action" data-v-5fe59986><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" aria-label="toggle dark mode" data-v-5fe59986 data-v-741b6450 data-v-ab2de182><span class="check" data-v-ab2de182><span class="icon" data-v-ab2de182><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-741b6450><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-741b6450><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div></div></div><!----><!--]--><!--]--></div></div></div><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-3a03f684 data-v-0a484f1e><span class="container" data-v-0a484f1e><span class="top" data-v-0a484f1e></span><span class="middle" data-v-0a484f1e></span><span class="bottom" data-v-0a484f1e></span></span></button></div></div></div><!----></header><!----><!----><div class="VPContent" id="VPContent" data-v-58617c5c data-v-01cd33ac><div class="VPDoc" data-v-01cd33ac data-v-4119e94e><div class="container" data-v-4119e94e><div class="aside" data-v-4119e94e><div class="aside-curtain" data-v-4119e94e></div><div class="aside-container" data-v-4119e94e><div class="aside-content" data-v-4119e94e><div class="VPDocAside" data-v-4119e94e data-v-ab3cfea0><!--[--><!--]--><!--[--><!--]--><div class="VPDocAsideOutline has-outline" data-v-ab3cfea0 data-v-381d3fd7><div class="content" data-v-381d3fd7><div class="outline-marker" data-v-381d3fd7></div><div class="outline-title" data-v-381d3fd7>On this page</div><nav aria-labelledby="doc-outline-aria-label" data-v-381d3fd7><span class="visually-hidden" id="doc-outline-aria-label" data-v-381d3fd7> Table of Contents for current page </span><ul class="root" data-v-381d3fd7><!--[--><li style="" data-v-381d3fd7><a class="outline-link" href="#features" data-v-381d3fd7>Features</a><!----></li><li style="" data-v-381d3fd7><a class="outline-link" href="#installation" data-v-381d3fd7>Installation</a><!----></li><li style="" data-v-381d3fd7><a class="outline-link" href="#usage" data-v-381d3fd7>Usage</a><!----></li><li style="" data-v-381d3fd7><a class="outline-link" href="#options" data-v-381d3fd7>Options</a><!----></li><li style="" data-v-381d3fd7><a class="outline-link" href="#plugin-system" data-v-381d3fd7>Plugin System</a><!----></li><li style="" data-v-381d3fd7><a class="outline-link" href="#contributors" data-v-381d3fd7>Contributors</a><!----></li><li style="" data-v-381d3fd7><a class="outline-link" href="#license" data-v-381d3fd7>License</a><!----></li>
20<!--]--></ul></nav></div></div><!--[--><!--]--><div class="spacer" data-v-ab3cfea0></div><!--[--><!--]--><!----><!--[--><!--]--><!--[--><!--]--></div></div></div></div><div class="content" data-v-4119e94e><div class="content-container" data-v-4119e94e><main class="main" data-v-4119e94e><div style="position:relative;" class="vp-doc .." data-v-4119e94e><div><h1 id="bytemd" tabindex="-1">ByteMD <a class="header-anchor" href="#bytemd" aria-hidden="true">#</a></h1><p><img src="https://github.com/bytedance/bytemd/workflows/test/badge.svg" alt="test"> <a href="https://app.fossa.com/projects/git%2Bgithub.com%2Fbytedance%2Fbytemd?ref=badge_shield" target="_blank" rel="noopener noreferrer"><img src="https://app.fossa.com/api/projects/git%2Bgithub.com%2Fbytedance%2Fbytemd.svg?type=shield" alt="FOSSA Status"></a></p><p>ByteMD is a Markdown editor component built with Svelte. It could also be used in other libraries/frameworks such as React, Vue and Angular.</p><p>Playground here: <a href="https://bytemd.js.org/playground/" target="_blank" rel="noopener noreferrer">https://bytemd.js.org/playground/</a></p><h2 id="features" tabindex="-1">Features <a class="header-anchor" href="#features" aria-hidden="true">#</a></h2><ol><li><strong>Lightweight and framework agnostic</strong>: ByteMD is built with <a href="https://svelte.dev/" target="_blank" rel="noopener noreferrer">Svelte</a>. It compiles to vanilla JS DOM manipulation without importing any UI Framework runtime bundle, which makes it lightweight, and easily adapted to other libraries/frameworks.</li><li><strong>Easy to extend</strong>: ByteMD has a plugin system to extend the basic Markdown syntax, which makes it easy to add additional features such as code syntax highlight, math equation and <a href="https://mermaid-js.github.io/mermaid/" target="_blank" rel="noopener noreferrer">Mermaid</a> flowcharts. You can also <a href="#write-a-plugin">write your own plugin</a> if these ones don&#39;t meet your needs.</li><li><strong>Secure by default</strong>: <a href="https://en.wikipedia.org/wiki/Cross-site_scripting" target="_blank" rel="noopener noreferrer">Cross-site scripting(XSS)</a> attack such as <code>&lt;script&gt;</code> and <code>&lt;img onerror&gt;</code> have been correctly handled by ByteMD. No need to introduce extra DOM sanitize steps.</li><li><strong>SSR compatible</strong>: ByteMD could be used in the <a href="https://ssr.vuejs.org/" target="_blank" rel="noopener noreferrer">Server-side rendering(SSR)</a> environment without extra config. SSR is widely used in some cases due to its better SEO and fast time-to-content in slow network connection.</li></ol><h2 id="installation" tabindex="-1">Installation <a class="header-anchor" href="#installation" aria-hidden="true">#</a></h2><table><thead><tr><th>Package</th><th>Status</th><th>Description</th></tr></thead><tbody><tr><td><a href="https://github.com/bytedance/bytemd/tree/main/packages/bytemd" target="_blank" rel="noopener noreferrer">bytemd</a></td><td><a href="https://npm.im/bytemd" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/npm/v/bytemd?label=" alt="npm"></a></td><td>Svelte/Vanilla JS component</td></tr><tr><td><a href="https://github.com/bytedance/bytemd/tree/main/packages/react" target="_blank" rel="noopener noreferrer">@bytemd/react</a></td><td><a href="https://npm.im/@bytemd/react" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/npm/v/@bytemd/react.svg?label=" alt="npm"></a></td><td>React component</td></tr><tr><td><a href="https://github.com/bytedance/bytemd/tree/main/packages/vue" target="_blank" rel="noopener noreferrer">@bytemd/vue</a></td><td><a href="https://npm.im/@bytemd/vue" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/npm/v/@bytemd/vue.svg?label=" alt="npm"></a></td><td>Vue 2 component</td></tr><tr><td><a href="https://github.com/bytedance/bytemd/tree/main/packages/vue-next" target="_blank" rel="noopener noreferrer">@bytemd/vue-next</a></td><td><a href="https://npm.im/@bytemd/vue-next" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/npm/v/@bytemd/vue-next.svg?label=" alt="npm"></a></td><td>Vue 3 component</td></tr></tbody></table><h3 id="legacy-browsers-support" tabindex="-1">Legacy browsers support <a class="header-anchor" href="#legacy-browsers-support" aria-hidden="true">
20#</a></h3><p>The default entry of NPM package only supports modern browsers. To make legacy browsers (<strong>IE9+</strong>) work, You can compile it with ESNext -&gt; ES5 transpilers, such as <a href="https://babeljs.io/" target="_blank" rel="noopener noreferrer">Babel</a> or <a href="https://swc.rs/" target="_blank" rel="noopener noreferrer">SWC</a>.</p><blockquote><p>The ES5 bundle will no longer be available after version 1.11.0. If you need it, you can use <a href="https://unpkg.com/[email protected]/dist/index.es5.min.js" target="_blank" rel="noopener noreferrer">version 1.11.0</a> or earlier versions</p></blockquote><p>Notice that polyfills are not included, and should be imported manually, see the <a href="https://github.com/bytedance/bytemd/blob/main/examples/legacy-browser/index.html" target="_blank" rel="noopener noreferrer">legacy browser example</a>.</p><h2 id="usage" tabindex="-1">Usage <a class="header-anchor" href="#usage" aria-hidden="true">#</a></h2><p>There are two components: <code>Editor</code> and <code>Viewer</code>. <code>Editor</code> is the Markdown editor, as the name suggests; <code>Viewer</code> is commonly used to display rendered Markdown results without editing.</p><p>Before using the component, remember to import CSS file to make styles correct:</p><div class="language-js"><span class="copy"></span><pre><code><span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">bytemd/dist/index.css</span><span style="color:#89DDFF;">&#39;</span></span>
21<span class="line"></span></code></pre></div><h3 id="svelte" tabindex="-1">Svelte <a class="header-anchor" href="#svelte" aria-hidden="true">#</a></h3><div class="language-svelte"><span class="copy"></span><pre><code><span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">script</span><span style="color:#89DDFF;">&gt;</span></span>
22<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">Editor</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">Viewer</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">bytemd</span><span style="color:#89DDFF;">&#39;</span></span>
23<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> gfm </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">@bytemd/plugin-gfm</span><span style="color:#89DDFF;">&#39;</span></span>
24<span class="line"></span>
25<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> value</span></span>
26<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> plugins </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> [</span></span>
27<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#82AAFF;">gfm</span><span style="color:#A6ACCD;">()</span><span style="color:#89DDFF;">,</span></span>
28<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// Add more plugins here</span></span>
29<span class="line"><span style="color:#A6ACCD;">  ]</span></span>
30<span class="line"></span>
31<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">handleChange</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">
31{</span></span>
32<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">value</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">detail</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">value</span></span>
33<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
34<span class="line"><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">script</span><span style="color:#89DDFF;">&gt;</span></span>
35<span class="line"></span>
36<span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">template</span><span style="color:#89DDFF;">&gt;</span></span>
37<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Editor</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">{</span><span style="color:#A6ACCD;">value</span><span style="color:#C792EA;">}</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">{</span><span style="color:#A6ACCD;">plugins</span><span style="color:#C792EA;">}</span><span style="color:#89DDFF;"> </span><span style="color:#89DDFF;font-style:italic;">on</span><span style="color:#89DDFF;">:</span><span style="color:#FFCB6B;">change</span><span style="color:#89DDFF;">={</span><span style="color:#A6ACCD;">handleChange</span><span style="color:#89DDFF;">} /&gt;</span></span>
38<span class="line"><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">template</span><span style="color:#89DDFF;">&gt;</span></span>
39<span class="line"></span></code></pre></div><h3 id="react" tabindex="-1">React <a class="header-anchor" href="#react" aria-hidden="true">#</a></h3><div class="language-js"><span class="copy"></span><pre><code><span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> gfm </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">@bytemd/plugin-gfm</span><span style="color:#89DDFF;">&#39;</span></span>
40<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">Editor</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">Viewer</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">@bytemd/react</span><span style="color:#89DDFF;">&#39;</span></span>
41<span class="line"></span>
42<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> plugins </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> [</span></span>
43<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#82AAFF;">gfm</span><span style="color:#A6ACCD;">()</span><span style="color:#89DDFF;">,</span></span>
44<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// Add more plugins here</span></span>
45<span class="line"><span style="color:#A6ACCD;">]</span></span>
46<span class="line"></span>
47<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> App </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
48<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">value</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">setValue</span><span style="color:#89DDFF;">]</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">useState</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&#39;&#39;</span><span style="color:#F07178;">)</span></span>
49<span class="line"></span>
50<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> (</span></span>
51<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Editor</span></span>
52<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#C792EA;">value</span><span style="color:#89DDFF;">={</span><span style="color:#A6ACCD;">value</span><span style="color:#89DDFF;">}</span></span>
53<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#C792EA;">plugins</span><span style="color:#89DDFF;">={</span><span style="color:#A6ACCD;">plugins</span><span style="color:#89DDFF;">}</span></span>
54<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#C792EA;">onChange</span><span style="color:#89DDFF;">={(</span><span style="color:#A6ACCD;">v</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">
54{</span></span>
55<span class="line"><span style="color:#F07178;">        </span><span style="color:#82AAFF;">setValue</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">v</span><span style="color:#F07178;">)</span></span>
56<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">}}</span></span>
57<span class="line"><span style="color:#89DDFF;">    /&gt;</span></span>
58<span class="line"><span style="color:#F07178;">  )</span></span>
59<span class="line"><span style="color:#89DDFF;">}</span></span>
60<span class="line"></span></code></pre></div><h3 id="vue" tabindex="-1">Vue <a class="header-anchor" href="#vue" aria-hidden="true">#</a></h3><div class="language-vue"><span class="copy"></span><pre><code><span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">template</span><span style="color:#89DDFF;">&gt;</span></span>
61<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Editor</span><span style="color:#89DDFF;"> :</span><span style="color:#C792EA;">value</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">value</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;"> :</span><span style="color:#C792EA;">plugins</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">plugins</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;"> @</span><span style="color:#C792EA;">change</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">handleChange</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;"> /&gt;</span></span>
62<span class="line"><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">template</span><span style="color:#89DDFF;">&gt;</span></span>
63<span class="line"></span>
64<span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">script</span><span style="color:#89DDFF;">&gt;</span></span>
65<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> gfm </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">@bytemd/plugin-gfm</span><span style="color:#89DDFF;">&#39;</span></span>
66<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">Editor</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">Viewer</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">@bytemd/vue</span><span style="color:#89DDFF;">&#39;</span></span>
67<span class="line"></span>
68<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> plugins </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> [</span></span>
69<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#82AAFF;">gfm</span><span style="color:#A6ACCD;">()</span><span style="color:#89DDFF;">,</span></span>
70<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// Add more plugins here</span></span>
71<span class="line"><span style="color:#A6ACCD;">]</span></span>
72<span class="line"></span>
73<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
74<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">components</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">
74{</span><span style="color:#A6ACCD;"> Editor </span><span style="color:#89DDFF;">},</span></span>
75<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">data</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
76<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> value</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&#39;&#39;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">plugins</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
77<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">},</span></span>
78<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">methods</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
79<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F07178;">handleChange</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">v</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
80<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">value</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">v</span></span>
81<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">},</span></span>
82<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">},</span></span>
83<span class="line"><span style="color:#89DDFF;">}</span></span>
84<span class="line"><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">script</span><span style="color:#89DDFF;">&gt;</span></span>
85<span class="line"></span></code></pre></div><h3 id="vanilla-js" tabindex="-1">Vanilla JS <a class="header-anchor" href="#vanilla-js" aria-hidden="true">#</a></h3><div class="language-js"><span class="copy"></span><pre><code><span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> gfm </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">@bytemd/plugin-gfm</span><span style="color:#89DDFF;">&#39;</span></span>
86<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">Editor</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">Viewer</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">bytemd</span><span style="color:#89DDFF;">&#39;</span></span>
87<span class="line"></span>
88<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> plugins </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> [</span></span>
89<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#82AAFF;">gfm</span><span style="color:#A6ACCD;">()</span><span style="color:#89DDFF;">,</span></span>
90<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// Add more plugins here</span></span>
91<span class="line"><span style="color:#A6ACCD;">]</span></span>
92<span class="line"></span>
93<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> editor </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">new</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Editor</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">
93{</span></span>
94<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">target</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">body</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// DOM to render</span></span>
95<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">props</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
96<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F07178;">value</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;&#39;</span><span style="color:#89DDFF;">,</span></span>
97<span class="line"><span style="color:#A6ACCD;">    plugins</span><span style="color:#89DDFF;">,</span></span>
98<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">},</span></span>
99<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
100<span class="line"></span>
101<span class="line"><span style="color:#A6ACCD;">editor</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">$on</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">change</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
102<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">editor</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">$set</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> value</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">e</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">detail</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">value</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span></span>
103<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
104<span class="line"></span></code></pre></div><h2 id="options" tabindex="-1">Options <a class="header-anchor" href="#options" aria-hidden="true">#</a></h2><h3 id="viewer" tabindex="-1">Viewer <a class="header-anchor" href="#viewer" aria-hidden="true">#</a></h3><table><thead><tr><th>Key</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>value</code></td><td><code>string</code> (required)</td><td>Markdown text</td></tr><tr><td><code>plugins</code></td><td><code>BytemdPlugin[]</code></td><td>ByteMD plugin list</td></tr><tr><td><code>sanitize</code></td><td><code>(schema: Schema) =&gt; Schema</code></td><td>Sanitize strategy</td></tr><tr><td><code>remarkRehype</code></td><td><a href="https://github.com/remarkjs/remark-rehype#options" target="_blank" rel="noopener noreferrer">documentation</a></td><td>remark-rehype config options</td></tr></tbody></table><h3 id="editor" tabindex="-1">Editor <a class="header-anchor" href="#editor" aria-hidden="true">#</a></h3><p><code>Editor</code> component also accepts the options of <code>Viewer</code> for preview. Besides that, there are some other options:</p><table><thead><tr><th>Key</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td><code>mode</code></td><td><code>split</code>, <code>tab</code>, <code>auto</code></td><td>Editor display mode, default: <code>auto</code></td></tr><tr><td><code>previewDebounce</code></td><td><code>number</code></td><td>Debounce time (ms) for preview, default: <code>300</code></td></tr><tr><td><code>placeholder</code></td><td><code>string</code></td><td>Editor placeholder</td></tr><tr><td><code>editorConfig</code></td><td><a href="https://codemirror.net/doc/manual.html#config" target="_blank" rel="noopener noreferrer">documentation</a></td><td>CodeMirror editor config</td></tr><tr><td><code>locale</code></td><td></td><td>i18n locale. Available locales could be found at <code>bytemd/locales</code>, default: use <code>en.json</code></td></tr><tr><td><code>uploadImages</code></td><td><code>function</code></td><td>Specify how to upload images. If set, the image icon will appear on the toolbar</td></tr><tr><td><code>maxLength</code></td><td><code>number</code></td><td>Maximum length (number of characters) of value</td></tr></tbody></table><h3 id="style-customization" tabindex="-1">Style customization <a class="header-anchor" href="#style-customization" aria-hidden="true">
104#</a></h3><h4 id="editor-1" tabindex="-1">Editor <a class="header-anchor" href="#editor-1" aria-hidden="true">#</a></h4><p>The default height of ByteMD Editor is <code>300px</code>. It could be overridden by CSS:</p><div class="language-css"><span class="copy"></span><pre><code><span class="line"><span style="color:#89DDFF;">.</span><span style="color:#FFCB6B;">bytemd</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
105<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#B2CCD6;">height</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">calc</span><span style="color:#89DDFF;">(</span><span style="color:#F78C6C;">100vh</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">200px</span><span style="color:#89DDFF;">);</span></span>
106<span class="line"><span style="color:#89DDFF;">}</span></span>
107<span class="line"></span></code></pre></div><p>The other styles could also be overridden, see <a href="https://github.com/bytedance/bytemd/blob/main/packages/bytemd/src/index.scss" target="_blank" rel="noopener noreferrer">the default style</a>.</p><h4 id="viewer-1" tabindex="-1">Viewer <a class="header-anchor" href="#viewer-1" aria-hidden="true">#</a></h4><p>There is no built-in styles for the Viewer. You could use third-party markdown themes, for example <a href="https://github.com/xitu/juejin-markdown-themes" target="_blank" rel="noopener noreferrer">juejin-markdown-themes</a> and <a href="https://github.com/sindresorhus/github-markdown-css" target="_blank" rel="noopener noreferrer">github-markdown-css</a>.</p><h2 id="plugin-system" tabindex="-1">Plugin System <a class="header-anchor" href="#plugin-system" aria-hidden="true">#</a></h2><p>ByteMD 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.</p><p>If you have more customized needs, you could also write your own plugin to support them.</p><h3 id="official-plugins" tabindex="-1">Official Plugins <a class="header-anchor" href="#official-plugins" aria-hidden="true">#</a></h3><table><thead><tr><th>Package</th><th>Status</th><th>Description</th></tr></thead><tbody><tr><td><a href="https://github.com/bytedance/bytemd/tree/main/packages/plugin-breaks" target="_blank" rel="noopener noreferrer">@bytemd/plugin-breaks</a></td><td><a href="https://npm.im/@bytemd/plugin-breaks" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/npm/v/@bytemd/plugin-breaks.svg?label=" alt="npm"></a></td><td>Support breaks</td></tr><tr><td><a href="https://github.com/bytedance/bytemd/tree/main/packages/plugin-frontmatter" target="_blank" rel="noopener noreferrer">@bytemd/plugin-frontmatter</a></td><td><a href="https://npm.im/@bytemd/plugin-frontmatter" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/npm/v/@bytemd/plugin-frontmatter.svg?label=" alt="npm"></a></td><td>Parse frontmatter</td></tr><tr><td><a href="https://github.com/bytedance/bytemd/tree/main/packages/plugin-gemoji" target="_blank" rel="noopener noreferrer">@bytemd/plugin-gemoji</a></td><td><a href="https://npm.im/@bytemd/plugin-gemoji" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/npm/v/@bytemd/plugin-gemoji.svg?label=" alt="npm"></a></td><td>Support Gemoji shortcodes</td></tr><tr><td><a href="https://github.com/bytedance/bytemd/tree/main/packages/plugin-gfm" target="_blank" rel="noopener noreferrer">@bytemd/plugin-gfm</a></td><td><a href="https://npm.im/@bytemd/plugin-gfm" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/npm/v/@bytemd/plugin-gfm.svg?label=" alt="npm"></a></td><td>Support GFM (autolink literals, strikethrough, tables, tasklists)</td></tr><tr><td><a href="https://github.com/bytedance/bytemd/tree/main/packages/plugin-highlight" target="_blank" rel="noopener noreferrer">@bytemd/plugin-highlight</a></td><td><a href="https://npm.im/@bytemd/plugin-highlight" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/npm/v/@bytemd/plugin-highlight.svg?label=" alt="npm"></a></td><td>Highlight code blocks</td></tr><tr><td><a href="https://github.com/bytedance/bytemd/tree/main/packages/plugin-highlight-ssr" target="_blank" rel="noopener noreferrer">@bytemd/plugin-highlight-ssr</a></td><td><a href="https://npm.im/@bytemd/plugin-highlight-ssr" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/npm/v/@bytemd/plugin-highlight-ssr.svg?label=" alt="npm"></a></td><td>Highlight code blocks (SSR compatible)</td></tr><tr><td><a href="https://github.com/bytedance/bytemd/tree/main/packages/plugin-math" target="_blank" rel="noopener noreferrer">@bytemd/plugin-math</a></td><td><a href="https://npm.im/@bytemd/plugin-math" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/npm/v/@bytemd/plugin-math.svg?label=" alt="npm"></a></td><td>Support math formula</td></tr><tr><td><a href="https://github.com/bytedance/bytemd/tree/main/packages/plugin-math-ssr" target="_blank" rel="noopener noreferrer">@bytemd/plugin-math-ssr</a></td><td><a href="https://npm.im/@bytemd/plugin-math-ssr" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/npm/v/@bytemd/plugin-math-ssr.svg?label=" alt="npm"></a></td><td>Support math formula (SSR compatible)</td></tr><tr><td><a href="https://github.com/bytedance/bytemd/tree/main/packages/plugin-medium-zoom" target="_blank" rel="noopener noreferrer">@bytemd/plugin-medium-zoom</a></td><td><a href="https://npm.im/@bytemd/plugin-medium-zoom" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/npm/v/@bytemd/plugin-medium-zoom.svg?label=" alt="npm"></a></td><td>Zoom images like Medium</td></tr><tr><td><a href="https://github.com/bytedance/bytemd/tree/main/packages/plugin-mermaid" target="_blank" rel="noopener noreferrer">@bytemd/plugin-mermaid</a></td><td><a href="https://npm.im/@bytemd/plugin-mermaid" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/npm/v/@bytemd/plugin-mermaid.svg?label=" alt="npm"></a></td><td>Support Mermaid diagram</td></tr></tbody></table>
107<h3 id="technical-overview" tabindex="-1">Technical Overview <a class="header-anchor" href="#technical-overview" aria-hidden="true">#</a></h3><p>ByteMD uses <a href="https://github.com/remarkjs/remark" target="_blank" rel="noopener noreferrer">remark</a> and <a href="https://github.com/rehypejs/rehype" target="_blank" rel="noopener noreferrer">rehype</a> ecosystem to process Markdown. The complete process is as follows:</p><ol><li>The markdown text is parsed to an <a href="https://github.com/syntax-tree/mdast" target="_blank" rel="noopener noreferrer">AST</a></li><li>The Markdown AST could be manipulated by several <a href="https://github.com/remarkjs/remark/blob/main/doc/plugins.md" target="_blank" rel="noopener noreferrer">remark plugins</a></li><li>The Markdown AST is transformed to a HTML AST</li><li>The HTML AST is sanitized for security reason</li><li>The HTML AST could be manipulated by several <a href="https://github.com/rehypejs/rehype/blob/main/doc/plugins.md" target="_blank" rel="noopener noreferrer">rehype plugins</a></li><li>The HTML AST is stringified to HTML</li><li>Some extra DOM manipulation after the HTML being rendered</li></ol><p>It could also be described as a flowchart:</p><p><img src="https://raw.githubusercontent.com/bytedance/bytemd/main/assets/plugin.svg" alt="plugin system"></p><p>The 2,5,7 steps are designed for user customization via ByteMD plugin API.</p><h3 id="authoring-a-plugin" tabindex="-1">Authoring a Plugin <a class="header-anchor" href="#authoring-a-plugin" aria-hidden="true">#</a></h3><p>We&#39;ll take Math formula plugin as an example to walk you through the process.</p><p>First of all, scaffold the project according to the <code>BytemdPlugin</code> type signature:</p><div class="language-ts"><span class="copy"></span><pre><code><span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">type</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">BytemdPlugin</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">bytemd</span><span style="color:#89DDFF;">&#39;</span></span>
108<span class="line"></span>
109<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">mathPlugin</span><span style="color:#89DDFF;">():</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">BytemdPlugin</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
110<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
111<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// to be implement</span></span>
112<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
113<span class="line"><span style="color:#89DDFF;">}</span></span>
114<span class="line"></span></code></pre></div><p>Then we look into the requirement more closely: If we want to render syntax like <code>$a+b$</code> to Math formula, there are several things we need to do:</p><ul><li>Support <code>$a+b$</code> syntax as a Math formula in Markdown (step 2)</li><li>Render these nodes correctly in HTML (step 5 or 7)</li><li>Additionally, an extra icon in the toolbar would be great for user convenience</li></ul><p>For the first thing, luckily, we don&#39;t need to implement it with our own because <a href="https://github.com/remarkjs/remark-math" target="_blank" rel="noopener noreferrer">remark-math</a> already did it. The only thing we need to do is to import and use it:</p><div class="language-diff"><span class="copy"></span>
114<pre><code><span class="line"><span style="color:#A6ACCD;">import type { BytemdPlugin } from &#39;bytemd&#39;</span></span>
115<span class="line"><span style="color:#89DDFF;">+</span><span style="color:#C3E88D;">import remarkMath from &#39;remark-math&#39;</span></span>
116<span class="line"></span>
117<span class="line"><span style="color:#A6ACCD;">export default function mathPlugin(): BytemdPlugin {</span></span>
118<span class="line"><span style="color:#A6ACCD;">  return {</span></span>
119<span class="line"><span style="color:#89DDFF;">-</span><span style="color:#F07178;">    // to be implement</span></span>
120<span class="line"><span style="color:#89DDFF;">+</span><span style="color:#C3E88D;">    remark: (processor) =&gt; processor.use(remarkMath),</span></span>
121<span class="line"><span style="color:#A6ACCD;">  }</span></span>
122<span class="line"><span style="color:#A6ACCD;">}</span></span>
123<span class="line"></span></code></pre></div><p>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: <a href="https://github.com/bytedance/bytemd/tree/main/packages/plugin-math" target="_blank" rel="noopener noreferrer">@bytemd/plugin-math</a> and <a href="https://github.com/bytedance/bytemd/tree/main/packages/plugin-math-ssr" target="_blank" rel="noopener noreferrer">@bytemd/plugin-math-ssr</a>.</p><div class="language-diff"><span class="copy"></span><pre><code><span class="line"><span style="color:#A6ACCD;">// if we choose step 5:</span></span>
124<span class="line"><span style="color:#A6ACCD;">import type { BytemdPlugin } from &#39;bytemd&#39;</span></span>
125<span class="line"><span style="color:#A6ACCD;">import remarkMath from &#39;remark-math&#39;</span></span>
126<span class="line"><span style="color:#89DDFF;">+</span><span style="color:#C3E88D;">import rehypeKatex from &#39;rehype-katex&#39;</span></span>
127<span class="line"></span>
128<span class="line"><span style="color:#A6ACCD;">export default function mathPlugin(): BytemdPlugin {</span></span>
129<span class="line"><span style="color:#A6ACCD;">  return {</span></span>
130<span class="line"><span style="color:#A6ACCD;">    remark: (processor) =&gt; processor.use(remarkMath),</span></span>
131<span class="line"><span style="color:#89DDFF;">+</span><span style="color:#C3E88D;">   rehype: (processor) =&gt; processor.use(rehypeKatex),</span></span>
132<span class="line"><span style="color:#A6ACCD;">  }</span></span>
133<span class="line"><span style="color:#A6ACCD;">}</span></span>
134<span class="line"></span>
135<span class="line"><span style="color:#A6ACCD;">// if we choose step 7:</span></span>
136<span class="line"><span style="color:#A6ACCD;">import type { BytemdPlugin } from &#39;bytemd&#39;</span></span>
137<span class="line"><span style="color:#A6ACCD;">import remarkMath from &#39;remark-math&#39;</span></span>
138<span class="line"><span style="color:#89DDFF;">+</span><span style="color:#C3E88D;">import rehypeKatex from &#39;rehype-katex&#39;</span></span>
139<span class="line"></span>
140<span class="line"><span style="color:#A6ACCD;">export default function mathPlugin(): BytemdPlugin {</span></span>
141<span class="line"><span style="color:#A6ACCD;">  return {</span></span>
142<span class="line"><span style="color:#A6ACCD;">    remark: (processor) =&gt; processor.use(remarkMath),</span></span>
143<span class="line"><span style="color:#89DDFF;">+</span><span style="color:#C3E88D;">   viewerEffect({ markdownBody }) {</span></span>
144<span class="line"><span style="color:#89DDFF;">+</span><span style="color:#C3E88D;">     const renderMath = async (selector: string, displayMode: boolean) =&gt; {</span></span>
145<span class="line"><span style="color:#89DDFF;">+</span><span style="color:#C3E88D;">       const katex = await import(&#39;katex&#39;).then((m) =&gt; m.default)</span></span>
146<span class="line"><span style="color:#89DDFF;">+</span></span>
147<span class="line"><span style="color:#89DDFF;">+</span><span style="color:#C3E88D;">       const els = markdownBody.querySelectorAll&lt;HTMLElement&gt;(selector)</span></span>
148<span class="line"><span style="color:#89DDFF;">+</span><span style="color:#C3E88D;">
148       els.forEach((el) =&gt; {</span></span>
149<span class="line"><span style="color:#89DDFF;">+</span><span style="color:#C3E88D;">         katex.render(el.innerText, el, { displayMode })</span></span>
150<span class="line"><span style="color:#89DDFF;">+</span><span style="color:#C3E88D;">       })</span></span>
151<span class="line"><span style="color:#89DDFF;">+</span><span style="color:#C3E88D;">     }</span></span>
152<span class="line"><span style="color:#89DDFF;">+</span></span>
153<span class="line"><span style="color:#89DDFF;">+</span><span style="color:#C3E88D;">     renderMath(&#39;.math.math-inline&#39;, false)</span></span>
154<span class="line"><span style="color:#89DDFF;">+</span><span style="color:#C3E88D;">     renderMath(&#39;.math.math-display&#39;, true)</span></span>
155<span class="line"><span style="color:#89DDFF;">+</span><span style="color:#C3E88D;">   },</span></span>
156<span class="line"><span style="color:#A6ACCD;">  }</span></span>
157<span class="line"><span style="color:#A6ACCD;">}</span></span>
158<span class="line"></span></code></pre></div><p>The last thing is to add an icon to the toolbar. we use the <code>actions</code> prop to implement it:</p><div class="language-ts"><span class="copy"></span><pre><code><span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">mathPlugin</span><span style="color:#89DDFF;">():</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">BytemdPlugin</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
159<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
160<span class="line"><span style="color:#F07178;">    actions</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> [</span></span>
161<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">{</span></span>
162<span class="line"><span style="color:#F07178;">        title</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">Insert an math formula</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,</span></span>
163<span class="line"><span style="color:#F07178;">        icon</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&#39;&#39;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 16x16 SVG icon</span></span>
164<span class="line"><span style="color:#F07178;">        handler</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
165<span class="line"><span style="color:#F07178;">          type</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">action</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,</span></span>
166<span class="line"><span style="color:#F07178;">          click</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">ctx</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
167<span class="line"><span style="color:#89DDFF;">            </span><span style="color:#676E95;font-style:italic;">// to be implement:</span></span>
168<span class="line"><span style="color:#89DDFF;">            </span><span style="color:#676E95;font-style:italic;">// the `ctx` is an instance of `BytemdEditorContext`, which has</span></span>
169<span class="line"><span style="color:#89DDFF;">            </span><span style="color:#676E95;font-style:italic;">// several utility methods to help operate the CodeMirror editor state.</span></span>
170<span class="line"></span>
171<span class="line"><span style="color:#89DDFF;">            </span><span style="color:#676E95;font-style:italic;">// remember to call `focus` to avoid lost of focus</span></span>
172<span class="line"><span style="color:#F07178;">            </span><span style="color:#A6ACCD;">editor</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">focus</span><span style="color:#F07178;">()</span></span>
173<span class="line"><span style="color:#F07178;">          </span><span style="color:#89DDFF;">},</span></span>
174<span class="line"><span style="color:#F07178;">        </span><span style="color:#89DDFF;">},</span></span>
175<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">},</span></span>
176<span class="line"><span style="color:#F07178;">    ]</span><span style="color:#89DDFF;">,</span></span>
177<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
178<span class="line"><span style="color:#89DDFF;">}</span></span>
179<span class="line"></span></code></pre></div><p>Now we have completed a minimalist version of the plugin! For more details and references please check out the source code.</p><h2 id="contributors" tabindex="-1">Contributors <a class="header-anchor" href="#contributors" aria-hidden="true">
179#</a></h2><p><a href="https://github.com/bytedance/bytemd/graphs/contributors" target="_blank" rel="noopener noreferrer"><img src="https://contrib.rocks/image?repo=bytedance/bytemd" alt=""></a></p><h2 id="license" tabindex="-1">License <a class="header-anchor" href="#license" aria-hidden="true">#</a></h2><p>MIT</p><p><a href="https://app.fossa.com/projects/git%2Bgithub.com%2Fbytedance%2Fbytemd?ref=badge_large" target="_blank" rel="noopener noreferrer"><img src="https://app.fossa.com/api/projects/git%2Bgithub.com%2Fbytedance%2Fbytemd.svg?type=large" alt="FOSSA Status"></a></p></div></div></main><!----></div></div></div></div></div><!----></div></div>
180    
180<script>__VP_HASH_MAP__ = JSON.parse("{\"index.md\":\"0c291fcb\"}")</script>
180
181    
181<script type="module" async src="/assets/app.5ae54ef2.js"></script>
181
182    
183  </body>
184</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.