跳转到主内容

适用于 JavaScript 的原生优先、高性能 Markdown 插件

最后更新:

Markdown 文本编辑器插件,可将本机文本区域转换为完整的编辑套件 - 无需同步。所见即所得和纯 Markdown 模式、实时预览、查找和替换、RTL 支持、深色模式。适用于 Django、Laravel、Rails、Node.js、PHP 和任何堆栈。

理念:“本土第一”

大多数编辑器都打破了标准的网络工作流程。 MarkdownEditor 拥抱它。 由于它直接位于 <textarea> 之上,因此您无需学习处理数据的新方法。

  • 无需数据绑定:开箱即用 <form method="POST">
  • 标准访问:像普通输入一样使用document.getElementById('editor').value
  • 与后端无关:可与任何后端(Python、Node.js、PHP 等)配合使用,就像普通表单字段一样

MarkdownEditor 与 EasyMDE / SimpleMDE

大多数 JavaScript Markdown 编辑器(EasyMDE、SimpleMDE、基于 CodeMirror 的编辑器)<textarea> 替换为自定义元素。这意味着表单提交中断,.value 不返回任何内容,并且您必须编写额外的代码才能读回内容。 MarkdownEditor 与 不同 — 它增强了您现有的文本区域,并且从不取代它。

特征 Markdown编辑器 EasyMDE / SimpleMDE
保留本机文本区域 ❌ 更换
表单提交按原样工作 ❌需要额外的JS
通过 .value 获取/设置值 ❌ 需要自定义API
所见即所得混合模式
内置查找和替换
RTL 支持
兼容 CSP(无内联 JS)
零 CSS 冲突
深色模式/主题 有限的
Bundle size 〜116KB ~300KB+

框架整合

Because MarkdownEditor preserves the native <textarea>, it integrates with every backend framework without any extra code.您的服务器接收 Markdown 内容,就像从任何标准表单字段接收一样。

Django

class 添加到您的文本区域小部件并初始化编辑器 - request.POST['content'] 无需额外步骤即可工作。

python
1
2
3
4
5
6
7
8
# forms.py
class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['content']
        widgets = {
            'content': forms.Textarea(attrs={'class': 'markdown-editor'}),
        }
javascript
1
2
new MarkdownEditor('.markdown-editor');
// request.POST['content'] contains the markdown on submit

Laravel

f.text_area 与类一起使用 — $request->input('content') 直接接收降价。

html
1
2
<textarea name="content" class="markdown-editor">{{ old('content') }}</textarea>
<script>new MarkdownEditor('.markdown-editor');</script>

红宝石 on Rails

开箱即用,可与 form_with 配合使用 — params[:content] 包含降价。对于 Turbo Drive,请使用 turbo:load 而不是 DOMContentLoaded

javascript
1
2
3
4
5
6
document.addEventListener('turbo:load', () => {
    document.querySelectorAll('.markdown-editor:not([data-mde-init])').forEach(el => {
        el.setAttribute('data-mde-init', 'true');
        new MarkdownEditor(el);
    });
});

Node.js / Express

req.body.content 接收表单提交时的降价 — 无同步步骤,无自定义提取。

html
1
2
3
<textarea name="content" class="markdown-editor"></textarea>
<script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script>
<script>new MarkdownEditor('.markdown-editor');</script>

PHP

$_POST['content'] 的工作方式与任何标准文本区域完全相同 - 将其放入,您现有的表单处理需要零更改。

html
1
2
3
4
5
6
<form method="POST" action="save.php">
  <textarea name="content" class="markdown-editor"></textarea>
  <button type="submit">Save</button>
</form>
<script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script>
<script>new MarkdownEditor('.markdown-editor');</script>

主要特点

🖼️ 高级图像上传(SEO 优化)

不要使用大量的 Base64 字符串来使数据库膨胀。配置我们的 API 以将图像直接上传到您的服务器或 S3 存储桶。编辑器接收 URL,使您的 Markdown 文件保持简洁,并保持网站的 SEO 排名较高。

🔀 混合模式和普通模式

为您的用户提供两全其美的服务。在用于轻松格式化的视觉 (WYSIWYG) 混合模式和用于无干扰的原始语法编辑的纯 Markdown 模式之间切换。

🌍 全球就绪,支持 RTL

对从右到左 (RTL) 语言的完全本机支持。非常适合需要阿拉伯语、乌尔都语或波斯语支持并具有自动文本方向对齐功能的项目。

⚡ 大规模性能

  • 轻量级:占用空间约 116KB,不会减慢页面加载速度
  • 大文档支持:经过优化,可以处理数千行文本,而不会出现输入延迟或浏览器冻结的情况
  • 智能渲染:去抖预览更新、缓存样式计算以及列表延续和缩进之间的无冲突键盘处理 - 因此 Tab 和 Enter 始终只做一件事

♿ 默认可访问

内置完整的 ARIA 支持,无需额外配置。工具栏是一个正确的 role="toolbar" 地标,预览窗格是一个带标签的 role="region",所有 SVG 图标都对屏幕阅读器隐藏,预览切换通过 aria-pressed 显示其开/关状态,禁用的工具栏按钮同时使用 disabledaria-disabled,因此辅助技术永远不会被误导。模态框关闭时将焦点返回到触发按钮。

🛡️ 零 CSS 冲突

所有编辑器样式都完全限定在 .markdown-editor-wrapper 元素范围内。 Tailwind 的全局预检(h1h6abutton 等的元素重置)被排除在外,因此编辑器可以与 Bootstrap、Tailwind 或同一页面上的任何其他 CSS 框架一起使用,而不会破坏单个样式。

🔒 XSS 安全预览

渲染的预览在写入 DOM 之前通过 DOMPurify 进行清理。精心设计的 Markdown 输入中的脚本标签、内联事件处理程序和恶意 URL 都会被自动删除——无需配置。

Markdown 编辑器演示

快速实施

1. 安装

NPM(捆绑器:Vite、webpack、Rollup 等)

bash
npm install markdown-text-editor
javascript
1
2
import MarkdownEditor from 'markdown-text-editor';
new MarkdownEditor('#markdown-editor');

CDN:ES模块

html
1
2
3
4
<script type="module">
  import MarkdownEditor from 'https://cdn.jsdelivr.net/npm/markdown-text-editor/dist/markdown-text-editor.es.js';
  new MarkdownEditor('#markdown-editor');
</script>

CDN:全局脚本标签(IIFE)

无需导入 - MarkdownEditor 可自动作为全局变量使用。

html
1
2
3
4
5
6
7
8
9
<form action="/api/save" method="POST">
  <textarea id="markdown-editor" name="content"># Hello World</textarea>
  <button type="submit">Save Content</button>
</form>

<script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script>
<script>
  new MarkdownEditor('#markdown-editor');
</script>

2. 配置与初始化

传递一个选项对象来自定义编辑器。所有选项都是可选的 - 省略任何选项即可使用默认值。

javascript
1
2
3
4
const editor = new MarkdownEditor('#markdown-editor', {
  placeholder: 'Write your markdown...',
  toolbar: ['heading', 'bold', 'italic', 'strikethrough', 'ul', 'ol', 'checklist', 'blockquote', 'link', 'preview'],
});

喜欢 Markdown 编辑器吗?

It takes 2 seconds and helps the project grow. It's part of Frutjam, a free Tailwind CSS component library — a star there helps too.

在 GitHub 上加星标

4. 配置与定制

您可以通过传递 options 对象来完全自定义编辑器的行为和界面。如果省略选项,则使用默认值。

财产 类型 默认 目的
mode string 'plain' 设置初始视图。使用混合以获得所见即所得的体验,或使用普通的原始语法。
placeholder string 'Write...' 编辑器为空时显示的文本。
toolbar array [...] 定义显示哪些工具以及显示顺序。
footer false | object 全部可见 控制编辑器下方显示的状态栏。设置为 false 以完全隐藏它,或传递一个对象来切换单个统计信息。
theme string 遗传 显式设置编辑器主题(浅色、深色、雪莓、黑莓)。如果省略,编辑器将从最近的祖先元素或 <textarea> 本身继承 data-theme
minHeight number 200 当内容较短时,编辑器将缩小到的最小高度(以像素为单位)。与 maxHeight 配对以设置自动增长范围。
maxHeight number 500 编辑器在非全屏模式下可以增长到的最大高度(以像素为单位)。一旦内容超过此高度,编辑器内就会出现滚动条。该编辑器还有一个拖动手柄,因此用户可以手动将其大小调整到超出此限制。
onChange function undefined 每次内容更改时都会触发回调 - 键入、工具栏操作、撤消/重做和列表延续。接收当前的 markdown 字符串作为其唯一的参数。

🛠 工具栏自定义

工具栏是模块化的。您可以通过修改阵列来创建最低限度的体验或功能齐全的电源套件。

可用工具
类别 Tool Keys
版式 heading, bold, italic, strikethrough, blockquote
列表 ul (子弹), ol (编号的), checklist
代码 code (排队), codeblock (围栏块)
刀片 hr (水平线), table (表格模板)
媒体 link, image
编辑 undo, redo, indent, outdent
看法 preview
💡实施技巧:
  • 重新排序:按钮按照您在数组中列出的确切顺序显示
  • 删除:只需从数组中省略任何键(例如image)即可为用户完全禁用该功能
  • 原生后备:如果您未在 JS 中提供 placeholder,插件将自动使用 HTML <textarea> 中的 placeholder 属性

📊 页脚(状态栏)

页脚位于编辑器下方,显示光标的 linecolumn、文档的 字符计数 以及可选的 字计数 — 所有这些均实时更新。默认情况下它是可见的,并且每个统计数据都可以独立切换。

钥匙 类型 默认 描述
line boolean true 显示当前行号。
col boolean true 显示当前的列号。
chars boolean true 显示总字符数。
words boolean false 显示总字数。默认关闭 — 设置为 true 以启用。
使用示例
javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// Default — line, col, and chars visible
new MarkdownEditor('#editor');

// Disable the footer entirely
new MarkdownEditor('#editor', { footer: false });

// Hide only character count
new MarkdownEditor('#editor', { footer: { chars: false } });

// Hide line and column, keep character count
new MarkdownEditor('#editor', { footer: { line: false, col: false } });

// Show only line number
new MarkdownEditor('#editor', { footer: { col: false, chars: false } });

// Enable word count alongside the defaults
new MarkdownEditor('#editor', { footer: { words: true } });

// Show word count only
new MarkdownEditor('#editor', { footer: { line: false, col: false, chars: false, words: true } });

5. 获取、设置和提交内容

MarkdownEditor 的核心优势之一是它保持底层 <textarea> 完美同步。无论您使用现代 JavaScript 框架还是传统后端(例如 Django、PHP 或 Laravel),工作流程都保持简单且原生。

1. The Native Way(推荐)

由于编辑器增强了标准文本区域,因此您可以使用熟悉的 DOM 方法。这是无需学习新 API 即可与数据交互的最快方式。

javascript
1
2
3
4
5
// Retrieve content via ID
const markdown = document.getElementById('markdown-editor').value;

// Set content via ID (The editor UI updates automatically)
document.getElementById('markdown-editor').value = "# New Heading Content";

2. 使用变量引用

如果您有对 textarea 元素的引用,则可以直接使用它 - 不需要特定于库的 API。

javascript
1
2
3
4
5
6
7
const textarea = document.getElementById('markdown-editor');

// Retrieve content
const markdown = textarea.value;

// Set content (the editor UI reflects this immediately)
textarea.value = "## Updated via JS";

3. 设置和读取内容

设置初始内容的推荐方法是直接在 <textarea> HTML 中 - 这自然适用于每个后端框架(Django、Laravel、Rails、PHP 等),并且编辑器会在 init 时自动呈现它。

html
1
2
<!-- Recommended: set content server-side -->
<textarea id="markdown-editor"># Hello World</textarea>

要在运行时读取或更新内容,请使用本机 textarea 值。更新后调用 editor.render() 以刷新预览层和混合层。

javascript
1
2
3
4
5
6
7
8
const textarea = document.getElementById('markdown-editor');

// Read
const markdown = textarea.value;

// Update at runtime
textarea.value = '# New content';
editor.render();

4. 拆除编辑器 — destroy()

调用 editor.destroy() 删除编辑器 DOM 包装器并将原始 <textarea> 恢复到其在文档中的位置。在单页应用程序中卸载视图时很有用。

javascript
1
2
3
4
const editor = new MarkdownEditor('#markdown-editor');

// Remove the editor and restore the plain textarea
editor.destroy();
使用 onChange 响应更改

传递 onChange 回调以在每次内容更改时收到通知。接收当前的 Markdown 字符串。

javascript
1
2
3
4
5
const editor = new MarkdownEditor('#markdown-editor', {
    onChange(value) {
        console.log('Content changed:', value.length, 'characters');
    }
});
使用 localStorage 自动保存草稿

使用 onChange 在每次击键时保存草稿。在初始化编辑器之前通过预填充文本区域来恢复它。

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
const DRAFT_KEY = 'my-page-draft';

// Restore saved draft before init (only if textarea starts empty)
const textarea = document.getElementById('markdown-editor');
const saved = localStorage.getItem(DRAFT_KEY);
if (saved && !textarea.value) textarea.value = saved;

// Save on every change
const editor = new MarkdownEditor('#markdown-editor', {
    onChange(value) {
        localStorage.setItem(DRAFT_KEY, value);
    }
});

// Clear draft after successful form submission
document.querySelector('form').addEventListener('submit', () => {
    localStorage.removeItem(DRAFT_KEY);
});

4. 轻松自动提交表单

由于 MarkdownEditor 直接构建在原生 <textarea> 上,因此它开箱即用,与每个后端框架(Django、Laravel、PHP、Ruby on Rails 等)兼容。

这就是“本地优先”理念的闪光点。您无需在提交表单之前手动同步数据。浏览器将编辑器视为标准输入字段。

html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<form method="POST" action="/api/submit">
  <textarea id="markdown-editor" name="content" class="h-48" rows="5">
    # Initial Content
  </textarea>

  <button type="submit">Submit to Server</button>
</form>

<script>
  // Just initialize it. That's it.
  new MarkdownEditor('#markdown-editor');
</script>

注意: MarkdownEditor 插件必须初始化

只需使用标准 HTML <form>。文本区域上的 name 属性是您的服务器将用来识别内容的属性。

🚀 为什么它会改变后端的游戏规则

由于编辑器保留本机 <textarea> 行为,因此您的服务器将数据作为标准字符串处理。所需的额外逻辑为零,无需 preventDefault() 也无需手动构造 FormData

💡 为什么这是一个“杀手级功能”:

大多数编辑器(如 Quill、Editor.js、simpleMDE、easyMDE)以复杂的 JSON 结构保存数据。如果开发人员使用这些,他们必须重写他们的数据库模式和渲染逻辑。

借助 MarkdownEditor,开发人员可以使用旧网站,用编辑器替换普通的 <textarea>,并且后端甚至不知道它发生了变化。它只是收到与往常相同的原始文本,但用户获得了 10 倍更好的体验。

框架/语言 如何访问 Markdown 内容
PHP $_POST['content']
Django request.POST.get('content')
Node.js (Express) req.body.content
Laravel $request->input('content')
Ruby on Rails params[:content]

配置选项

🖼️高级图片上传

本地处理图像上传(而不是依赖于缓慢且占用大量内存的 Base64 字符串)对于性能和 SEO 来说都是一个重大胜利。

配置选项

图像工具支持 fileInput 配置来处理直接服务器上传。

  • accept:定义允许的图像格式数组(例如“webp”、“avif”)
  • uploadUrl:指定将通过 POST 发送 File 对象的后端端点
  • params:可选对象,用于与图像文件一起发送附加数据(例如 CSRF 令牌、用户 ID 或文件夹名称)

使用示例(完整配置)

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
const options = {
  placeholder: 'Start writing...',
  toolbar: [
    'link',
    {
      image: {
        fileInput: {
            accept: ['webp', 'avif'], // restrict the image upload format
            uploadUrl: '/api/upload', // Your upload endpoint
            params: {
                _token: 'your_csrf_token_here', // Essential for Laravel/Django
                folder: 'blog_posts'
            }
        },
        // Supports boolean: true/false OR object: { required: true }
        altInput: { required: true }
      }
    },
    'preview'
  ],
}
const editor = new MarkdownEditor('#markdown-editor', options);

📡 服务器集成详细信息

1. 请求

编辑器以 multipart/form-data 形式发送 POST 请求。默认情况下,它包括:

  • image_file:实际的文件对象
  • image_alt:用户输入的替代文本
  • ...加上 params 对象中定义的任何自定义数据
2. 所需的回应

要确认上传成功并将图像插入编辑器,您的服务器必须返回以下 JSON 结构:

json
1
2
3
4
{
  "success": true,
  "image_path": "https://cdn.yourdomain.com/uploads/image.webp"
}

注意:确保使用 image_path 键作为上传图像的 URL。

图像替代文本验证 (altInput)

为了确保您的内容保持可访问性和 SEO 友好性,MarkdownEditor 默认强制执行替代文本验证。您可以使用布尔简写或详细对象来配置此行为。

  • 默认行为:如果未定义altInput,则默认为{ required: true }
  • 强制辅助功能:在提供替代说明之前,用户将无法插入图像
配置示例:
1.默认(无需配置)
javascript
1
2
3
4
// Alt text is REQUIRED by default
image: {
  fileInput: { uploadUrl: '/api/upload' }
}
2. 速记(禁用验证)

如果您想允许没有描述的图像,只需将布尔值设置为 false 即可。

javascript
1
2
3
image: {
  altInput: false // Users can now skip the alt text field
}
3. 基于对象(显式)
javascript
1
2
3
4
5
image: {
    altInput: {
        required: false // Disables alt text validation — users can skip the alt field
    }
}

标准图像使用(无fileInput):

如果未配置 fileInput,则编辑器默认为简单的基于 URL 的模式。如果您的用户主要链接到外部图像主机,那么这是理想的选择。

javascript
1
2
3
4
5
6
7
8
const options = {
  toolbar: [
    'link',
    'image',
    'preview'
  ],
}
const editor = new MarkdownEditor('#markdown-editor', options);
💡 为什么使用参数?

在 Laravel 或 Django 等框架中,如果没有 CSRF 令牌,则无法上传文件。通过将 _token 添加到 params 对象,您的请求将无缝地通过后端的安全中间件,从而维护服务器端控制器的“零逻辑”理念。

🔀 编辑模式

MarkdownEditor 提供两种不同的方式来编写和格式化内容。您可以在传统的以语法为中心的视图或现代的视觉优先体验之间切换。

配置

您可以在初始化期间使用 mode 属性定义启动模式。

  • plain默认):干净、高性能的 Markdown 环境,其中语法(如 **bold**# header)可见。开发人员和 Markdown 纯粹主义者的理想选择
  • hybrid:一种所见即所得的体验,可在您键入时实时呈现格式(粗体、斜体、标题),同时仍保持底层 Markdown 结构。
执行:
javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Default initialization (Plain Mode)
new MarkdownEditor('#markdown-editor');

// Explicit Plain Mode
new MarkdownEditor('#markdown-editor', {
    mode: 'plain'
});

// Hybrid (Visual) Mode
new MarkdownEditor('#markdown-editor', {
    mode: 'hybrid'
});
混合和普通模式预览:
混合模式

当您键入时,视觉格式会实时呈现。

普通模式(默认)

专注于原始 Markdown 语法以提供轻量级体验。

配置 财产/工具 描述
选项对象 placeholder 设置文本区域的占位符文本(可选,因为您还可以使用标准 HTML 文本区域属性)
mode: 'hybrid' 实现所见即所得的体验,在您键入时实时呈现格式(粗体、斜体、标题)
工具栏:确定工具栏中显示的工具
及其顺序。
heading 打开下拉菜单以选择标题级别 H1–H6
bold 启用粗体文本格式。
italic 启用斜体文本格式。
strikethrough 允许文本删除线。
ol (有序列表):将文本转换为编号列表格式。
ul (无序列表):将文本转换为项目符号列表。
checklist 在文本中添加复选框,使其非常适合任务、待办事项列表或跟踪完成状态。
blockquote 突出显示引用或强调的文本。
code 将选定的文本包含在单个反引号中以实现内联代码。再次单击可删除反引号。
codeblock 将选定的文本包装在三重反引号围栏代码块中。再次单击可移除栅栏。
hr 在光标位置插入一条 --- 水平线。
table 在光标位置插入起始 2x3 Markdown 表格模板。
image 允许您通过 Markdown 语法插入图像。
link 允许您向文本添加超链接。
undo 撤销最后的更改。
redo 重新应用上次撤消的更改。
indent 增加缩进级别。
outdent 降低压痕级别。
preview 切换全屏并排预览。预览窗格中的复选框可单击并立即更新 Markdown 源。按 Esc 键退出全屏。
高级图像上传功能
允许配置图像上传到
您自己的服务器并通过 API 设置图像
路径。这可以提高性能和 SEO。
fileInput accept:允许的图像文件类型数组(例如'webp''avif')。
uploadUrl:通过 POST 发送文件的后端端点。
params:额外数据的可选对象(CSRF 令牌、用户 ID、文件夹名称)
altInput required: false:禁用替代文本输入验证(默认为 true)

⌨️ 键盘快捷键

常见的格式化操作可以直接从键盘触发,无需触摸工具栏。每个快捷方式也显示在相应的工具栏按钮的工具提示中。

捷径 行动
Ctrl + B  /  ⌘ B 切换粗体
Ctrl + I  /  ⌘ I 切换斜体
Ctrl + K  /  ⌘ K 插入链接
Ctrl + `  /  ⌘ ` 切换内联代码
Ctrl + Shift + S  /  ⌘ ⇧ S 切换删除线
Ctrl + Z  /  ⌘ Z 撤消
Ctrl + Shift + Z  /  ⌘ ⇧ Z 重做
Tab 缩进选定的行
Shift + Tab 减少缩进选定的行
Ctrl + F  /  ⌘ F 打开查找面板
Ctrl + H  /  ⌘ H 打开查找和替换面板
Escape 关闭查找面板/退出全屏预览

🔍 查找并找到代替

编辑器内提供内置查找和替换面板 - 无需浏览器扩展或单独的工具。

  • Ctrl + F(或 ⌘ F)打开查找面板
  • Ctrl + H(或⌘ H)打开查找和查找窗口。更换面板
  • 搜索不区分大小写并显示实时比赛计数器(例如3 / 12
  • 使用 ▲ / ▼ 按钮或 Enter / Shift + Enter 导航匹配项
  • 替换替换当前突出显示的匹配项; 全部替换一次性替换所有出现的内容
  • Escape 关闭面板并将焦点返回到编辑器

该面板浮动在编辑器内容区域的右上角,不会中断写入。

🌙 主题化

MarkdownEditor 自动从周围页面继承其主题 - 无需配置。编辑器在初始化时从最近的祖先读取data-theme,因此它与您网站的主题保持同步。

主题如何解决(优先顺序)

  1. theme option - 在选项对象中传递的显式覆盖
  2. <textarea> 上的 data-theme — 直接在元素上设置
  3. 任何祖先的数据主题 - 例如<html><body> 或包装 <div>

可用主题

'light'(默认)、'dark''snowberry''darkberry'

选项 1 — 从 <html> 或任何祖先继承(零配置)
html
1
2
3
4
5
6
<html data-theme="dark">
  ...
  <textarea id="markdown-editor"></textarea>
  <script>
    new MarkdownEditor('#markdown-editor'); // picks up dark automatically
  </script>
选项 2 — 直接在 <textarea> 上设置 data-theme
html
1
2
3
4
<textarea id="markdown-editor" data-theme="dark"></textarea>
<script>
  new MarkdownEditor('#markdown-editor');
</script>
选项 3 — 显式 theme 选项(覆盖所有内容)
javascript
1
2
3
new MarkdownEditor('#markdown-editor', {
    theme: 'dark'
});

🎨 通过 CSS 变量自定义主题

您可以通过覆盖 .markdown-editor-wrapper 元素或任何 [data-theme] 选择器上的 CSS 变量来完全自定义编辑器的外观。所有颜色均使用 OKLCH 色彩空间 以获得统一的感知结果。

多变的 目的 浅色默认 深色默认
--color-base 编辑背景 oklch(100% 0 0) oklch(10.9% 0 0)
--color-on-base 主要文本颜色 oklch(22% 0 0) oklch(98% 0 0)
--color-primary 主要重音(工具栏活动,链接) oklch(51.1% .262 277) oklch(66.4% .184 286)
--color-on-primary 原色表面上的文字 oklch(96.2% .018 272) oklch(10% .01 270)
--color-secondary 次要口音 oklch(59.1% .293 323) oklch(65% .18 220)
--color-accent 突出显示重音符号(内联代码,斜体) oklch(54.1% .281 293) oklch(75% .18 50)
--color-neutral 中性表面(边界、分隔线) oklch(15% 0 0) oklch(85% 0 0)
--color-error 错误状态颜色 oklch(57.7% .245 27) oklch(60% .22 30)
--border-radius 编辑器框架的圆角 0.25rem
自定义主题示例

编辑器初始化后覆盖 .markdown-editor-wrapper 上的任何变量,或在样式表中定义自定义 [data-theme] 块:

css
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/* Override individual variables */
.markdown-editor-wrapper {
    --color-primary: oklch(60% 0.2 30);   /* orange accent */
    --border-radius: 0.5rem;
}

/* Or define a full custom theme */
[data-theme="brand"] .markdown-editor-wrapper,
.markdown-editor-wrapper[data-theme="brand"] {
    --color-base:       oklch(15% 0.01 250);
    --color-on-base:    oklch(95% 0 0);
    --color-primary:    oklch(65% 0.22 145);   /* green */
    --color-on-primary: oklch(10% 0 0);
    --color-accent:     oklch(75% 0.18 60);
    --color-neutral:    oklch(80% 0 0);
    --border-radius:    0.75rem;
}
javascript
new MarkdownEditor('#markdown-editor', { theme: 'brand' });
  • 实时预览:在您键入时查看立即呈现的 Markdown。
  • 语法突出显示:通过清晰的代码和 Markdown 格式增强可读性。
  • 轻松集成:只需最少的设置即可无缝集成到任何 Web 项目中。
  • 可自定义工具栏:动态配置和重新排序工具栏选项,例如粗体、斜体等。

特征

🔌 原生表单集成

工作原理与标准 <textarea> 完全相同。没有复杂的 API — 只需使用 valuename 属性。它“只适用于”PHP、Django 或 Node.js 中的标准 HTML 表单提交。

🖼️ 高级图像上传

通过 API 配置本机服务器上传。通过在您自己的 CDN 上托管图像,避免使用繁重的 Base64 字符串,以确保更快的页面加载和卓越的 SEO。

🔀 混合模式和普通模式

在用于可视化编辑的混合 (WYSIWYG) 体验和用于传统编码感觉的纯 Markdown 模式之间切换。

🚀 高性能

一个针对“重内容”进行优化的小型 ~116KB 捆绑包。处理大量文档和大文件,不会出现任何输入延迟或性能下降。

🌍 内置 RTL 支持

对阿拉伯语、乌尔都语和波斯语等从右到左语言的本机支持。非常适合构建全球可访问的应用程序。

🌙 自适应主题

包括自动深色模式支持。它与您的系统设置或 Frutjam UI 库同步,以提供无缝的视觉体验。

📝 智能编辑

GitHub 风格的自动列表延续,适用于有序列表、无序列表和清单 - 按 Enter 键,编辑器将继续该模式。预览窗格中的复选框可单击并立即同步回 Markdown 源。

📱 完全响应

流畅、移动优先的用户界面,完美适应台式机、平板电脑和智能手机,以便随时随地进行编辑。

📦 普遍支持

ESM、UMD、CommonJS 和 IIFE 兼容。通过 CDN (<script src>)、npm 或任何捆绑器(Vite、webpack、Rollup)开箱即用 — 无需额外配置。

♿ 默认可访问

内置完整的 ARIA 支持 - 工具栏地标、带标签的预览区域、屏幕阅读器友好的按钮、预览切换上的 aria-pressed、非活动工具上的 disabledaria-disabled,以及模态关闭时正确的焦点恢复。

🛡️ 零 CSS 冲突

编辑器样式的范围完全限于 .markdown-editor-wrapper。 Tailwind 的全局预检被排除,因此编辑器可以安全地与 Bootstrap、Tailwind 或任何其他框架一起使用,而不会破坏它们的风格。

⌨️ 键盘快捷键

Ctrl+BCtrl+ICtrl+KCtrl+`Ctrl+Shift+S — 无需触摸鼠标的常见格式化操作。每个快捷方式都显示在工具栏按钮的工具提示中。

🔍 查找并找到代替

Ctrl+F 进行查找或按Ctrl+H 打开查找&代替。不区分大小写的搜索,具有实时匹配计数器、下一个/上一个导航、单个替换和全部替换 - 无需离开编辑器。

完整配置示例

使用这个综合示例来初始化 MarkdownEditor 的所有主要功能,包括自定义工具栏排序和高级图像上传处理。

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
const editor = new MarkdownEditor('#markdown-editor', {
    mode: 'hybrid',
    placeholder: 'Start writing...',
    footer: {
        line: true,
        col: true,
        chars: true,
        words: true,
    },
    onChange(value) {
        console.log('Content updated:', value.length, 'characters');
    },
    toolbar: [
        'heading', 'bold', 'italic', 'strikethrough', 'blockquote',
        'ul', 'ol', 'checklist',
        'code', 'codeblock', 'hr', 'table',
        {
            image: {
                fileInput: {
                    accept: ['webp', 'avif', 'png'],
                    uploadUrl: '/api/upload'
                }
            }
        },
        'link', 'undo', 'redo', 'indent', 'outdent', 'preview'
    ],
});

// Read content natively
const markdown = document.getElementById('markdown-editor').value;

// Update content programmatically (dispatch input to keep preview in sync)
// const ta = document.getElementById('markdown-editor');
// ta.value = '# New content';
// ta.dispatchEvent(new Event('input', { bubbles: true }));

// destroy() when the view unmounts (SPAs)
// editor.destroy();