Minditor是一款注重终端用户编辑体验和开发者体验的块级富文本编辑器。它具有以下特点:
我们的官方网站首页就是使用Minditor制作和渲染的。你可以在首页上体验几乎所有的功能。快来看看吧。
<div> <img src="https://yellow-cdn.veclightyear.com/835a84d5/04f17fcd-9f12-416a-bd68-f2f7227fd65b.png" alt="Minditor截图"/> </div>默认支持右键菜单和键盘快捷键进行复制、粘贴、剪切、撤销和重做操作。
Minditor提供以下命令以便快速编辑:
+[任意字符]+插入行内代码。鼠标悬停在选中的文本上会显示一个浮动工具栏,可以更改字体样式或创建链接。
<div> <img src="https://yellow-cdn.veclightyear.com/835a84d5/8f5cb61c-4a64-4641-ab64-9c71e9bda63f.png" alt="范围工具插件" width="1764"/> </div>输入"/"会触发一个下拉菜单,提供可插入的组件。如果在空行开头输入"/",可插入的Block和InlineBlock会同时出现。
<div> <img src="https://yellow-cdn.veclightyear.com/835a84d5/fe825465-ed7d-4481-bfd7-5c2b04a26730.png" alt="建议插件" width="1702"/> </div>鼠标移到任何Block上会在左侧显示一个浮动工具栏,提供默认的删除、复制、粘贴和插入Block的工具。
Minditor支持在文档外显示由标题组成的大纲,如官网首页左侧所示。
Minditor的图片组件允许用户将图片上传到指定接口或AWS S3存储桶,或者使用URL.createObjectURL将图片直接编码保存到文档中。Minditor已经包含了一个默认组件InlineImageBlock,用于将图片编码并保存到文档中。
<div> <img src="https://yellow-cdn.veclightyear.com/835a84d5/43f34d1d-db2a-40be-8396-98c6c55e9d4a.gif" alt="建议插件" width="978"/> </div> 你也可以使用`createImageBlock`并提供适当的参数来创建一个将图片上传到指定地址的组件:import {createImageBlock} from 'minditor' // @params // - type: 'xhr'|'aws' // - config: Uppy.XHRConfig|Uppy.AWS3Config const ImageBlock = createImageBlock( 'xhr', {endpoint: 'https://your-domain.com/upload'} )
图片块使用Uppy作为上传工具。更多配置选项请参考https://uppy.io/docs/xhr-upload/。
网格块中的单元格支持所有文档功能,相当于一个嵌入的小型文档。你可以在空段落使用左侧的块工具插入网格。也可以通过在段落开头输入"/"使用插入建议插件获取。网格支持的功能包括:
<div> <img src="https://yellow-cdn.veclightyear.com/835a84d5/70e1d6b8-d325-468c-aca7-dd9fc38b323d.png" alt="建议插件" width="752"/> </div>我们目前正在开发一个更强大的电子表格工具,包括增强的布局和数据处理能力。这个工具未来也会作为一个组件集成到Minditor中,所以目前的网格没有大规模的增强计划。
Minditor使用CodeMirror 6作为其代码组件。默认支持以下语言:
• javascript (别名 js/jsx) • typescript (别名 ts/tsx) • python • php • cpp • java • sql • json • rust • css • html • sass • less • xml • yaml
你可以在段落开头输入 ``` + [语言名称]来插入特定语言的代码块。也可以使用块工具或建议工具插入。
npm i minditor
Minditor本身可以在任何DOM节点中渲染,不需要任何外部布局或样式要求。 如果你只是用它来渲染最简单的文本,可以直接使用以下方法渲染:
import { Code, Grid, Heading, InlineImageBlock, InlineCode, Link, OLItem, Paragraph, Text, ULItem, InlineImageBlock } from "minditor";
const rootElement = document.getElementById('root')! const types = { Paragraph, Text, Heading, OLItem, ULItem, InlineCode, Code, Link, Grid, Image: InlineImageBlock } const data = { name: 'MyDoc', children: [{ type: 'Paragraph', content: [{type:'Text', value: '这是我的第一个文档。'}] }] }
const doc = new Document(rootElement, data, types) doc.render()
对于需要完整插件且视图高度自动适应外部容器的场景,我们建议使用`scaffold`创建视图:
```typescript
import {
Code,
createBlockTool,
createRangeTool,
createSuggestionTool,
defaultBlockWidgets,
defaultFormatWidgets,
defaultMarkdownPlugins,
defaultSuggestionWidgets,
Grid,
Heading,
InlineImageBlock,
InlineCode,
Link,
OLItem,
Paragraph,
scaffold,
Text,
ULItem,
createTOCTool
} from "minditor";
const root= document.getElementById('root')!
const types = {
Paragraph,
Text,
Heading,
OLItem,
ULItem,
InlineCode,
Code,
Link,
Grid,
Image: InlineImageBlock
}
const plugins = [
...defaultMarkdownPlugins,
createBlockTool(defaultBlockWidgets),
createRangeTool( defaultFormatWidgets ),
createSuggestionTool(defaultSuggestionWidgets),
createTOCTool()
]
const result = scaffold(root, {data: jsonData, types, plugins}, { debug: true })
result.render()
InlineBlock可以内联嵌入,开发InlineBlock非常简单。让我们以InlineCode为例:
export class InlineCode extends InlineComponent { static displayName = 'InlineCode' constructor(public data: InlineCodeData) { super(); } render() { return <span style={{display:'inline-block', background:'#eee', padding:'4px 8px'}}>{this.data.value}</span> } toText() { return this.data.value } }
有了InlineBlock后,需要提供用户使用的方法。有三种方式:
/时,会出现一个下拉菜单,显示这个Block,用户可以点击使用。