一個 Markdown 編輯器,可以增強您的文字區域而不是替換它,因此表單提交、驗證和必填欄位可以繼續工作。所見即所得和純 Markdown 模式、即時預覽、尋找和替換、RTL 支援、深色模式。可與 Django、Laravel、Rails、Node.js、PHP 和任何堆疊獨立工作。
**不需要 Frutjam 和 Tailwind。 ** 樣式是捆綁的,因此編輯器可以放入任何項目中。
安裝
NPM(捆綁器:Vite、webpack、Rollup 等)
npm install markdown-text-editor |
1 2 | import MarkdownEditor from 'markdown-text-editor'; new MarkdownEditor('#markdown-editor'); |
TypeScript 定義隨套件一起提供,因此選項、工具列條目和變數形狀都會被檢查並自動完成,無需額外安裝。
CDN:ES模組
1 2 3 4 | <script type="module"> import MarkdownEditor from 'https://cdn.jsdelivr.net/npm/markdown-text-editor/+esm'; new MarkdownEditor('#markdown-editor'); </script> |
CDN:全域腳本標籤(IIFE)
無需導入:MarkdownEditor 可自動作為全域變數使用。
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> |
Markdown 編輯器演示
快速入門
傳遞一個選項物件來自訂編輯器。所有選項都是可選的:省略任何選項即可使用預設值。
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'], }); |
理念:“本土第一”
大多數編輯器都打破了標準的網路工作流程。 MarkdownEditor 擁抱它。因為它直接位於 <textarea>,您不需要學習處理資料的新方法。
- 無需資料綁定: 適用於
<form method="POST">開箱即用 - 標準訪問: 使用
document.getElementById('editor').value就像普通輸入一樣。 - 與後端無關: 可與任何後端(Python、Node.js、PHP 等)一起使用,就像普通表單欄位一樣
MarkdownEditor 與 EasyMDE / SimpleMDE
大多數 JavaScript Markdown 編輯器(EasyMDE、SimpleMDE、基於 CodeMirror 的編輯器)隱藏您的 <textarea> 並編輯副本,提交表單時寫回內容。這一直有效,直到其他東西需要該值: required 瀏覽器無法聚焦的欄位會完全阻止提交,並且 .value 或者 FormData 在提交之前讀取會傳回一個空字串,這會破壞 htmx、Turbo、自動儲存和未儲存變更防護。 **MarkdownEditor 是不同的。 ** 它對您已有的文字區域進行樣式設置,並將其保留為您輸入的字段,因此該值在任何時候都是正確的。
| 特徵 | Markdown編輯器 | EasyMDE / SimpleMDE |
|---|---|---|
| 保留本機文字區域 | ✅ | ❌ 隱藏,編輯為副本 |
與 required 領域 | ✅ | ❌ 瀏覽器阻止提交 |
.value 提交前更正 | ✅ | ❌ 表單提交之前為空 |
連載於 FormData, htmx, 渦輪增壓 | ✅ | ❌ 需要編輯器自己的API |
| 所見即所得混合模式 | ✅ | ❌ |
| 內建尋找和替換 | ✅ | ❌ |
| RTL 支持 | ✅ 內置 | 透過 CodeMirror 的 direction 選項 |
| 內嵌事件處理程序 (CSP) | ✅ 無 | 一些 |
| 深色模式/主題 | ✅ | 有限的 |
| 捆綁包大小,gzip 壓縮 | 53 KB | 107 KB(JS + CSS) |
框架整合
因為 MarkdownEditor 保留了原生 <textarea>,它與每個後端框架集成,無需任何額外程式碼。您的伺服器接收 Markdown 內容,就像從任何標準表單欄位接收一樣。對於 React 和 Vue,它需要幾行,在本節末尾介紹。
薑戈
添加一個 class 到您的文字區域小部件並初始化編輯器: request.POST['content'] 無需額外步驟即可工作。
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'}), } |
1 2 | new MarkdownEditor('.markdown-editor'); // request.POST['content'] contains the markdown on submit |
拉維爾
使用 f.text_area 有一個類別: $request->input('content') 直接接收markdown。
1 2 | <textarea name="content" class="markdown-editor">{{ old('content') }}</textarea> <script>new MarkdownEditor('.markdown-editor');</script> |
紅寶石 on Rails
與 form_with 開箱即用: params[:content] 包含降價。對於渦輪驅動器,請使用 turbo:load 而不是 DOMContentLoaded.
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 接收表單提交時的降價:沒有同步步驟,沒有自訂提取。
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'] 與任何標準文字區域完全相同:將其放入,您現有的表單處理需要零更改。
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> |
反應
在效果中建立編輯器並在卸載時銷毀它。使用 defaultValue 而不是 value:編輯器直接寫入文字區域,因此受控綁定將覆蓋使用者輸入的內容。
1 2 3 4 5 6 7 8 9 10 11 12 13 | import { useEffect, useRef } from 'react'; import MarkdownEditor from 'markdown-text-editor'; function MarkdownField({ name, defaultValue = '', onChange }) { const ref = useRef(null); useEffect(() => { const editor = new MarkdownEditor(ref.current, { onChange }); return () => editor.destroy(); }, []); return <textarea ref={ref} name={name} defaultValue={defaultValue} />; } |
返回 editor.destroy() from theeffect 還涵蓋了 StrictMode,它在開發過程中運行兩次效果,否則會在一個文字區域上留下兩個編輯器。空依賴數組是故意的:創建編輯器時會讀取一次選項,因此重新運行效果會拆除它並在每次更改時重建它。
維埃
同樣的想法。設定一次初始值 onMounted 並且不綁定 :value,或透過發送回的每個擊鍵 v-model 會覆蓋文字區域。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <script setup> import { ref, onMounted, onBeforeUnmount } from 'vue'; import MarkdownEditor from 'markdown-text-editor'; const el = ref(null); const props = defineProps({ modelValue: { type: String, default: '' } }); const emit = defineEmits(['update:modelValue']); let editor = null; onMounted(() => { el.value.value = props.modelValue; editor = new MarkdownEditor(el.value, { onChange: value => emit('update:modelValue', value) }); }); onBeforeUnmount(() => editor?.destroy()); </script> <template><textarea ref="el"></textarea></template> |
用作 <MarkdownField v-model="content" />。在簡單的形式中,您可以跳過 v-model 與任何其他框架一樣,完全並在提交時從文字區域讀取值。
配置
您可以透過傳遞一個來完全自訂編輯器的行為和介面 options 目的。如果省略選項,則使用 預設 值。
建置編輯器時,選項將被讀取一次。之後更改它們沒有任何效果:調用 destroy() 並建立一個新的編輯器。
| 財產 | 類型 | 預設 | 目的 |
|---|---|---|---|
mode | string | 'plain' | 設定初始視圖。使用混合以獲得所見即所得的體驗,或使用普通的原始語法。 |
placeholder | string | 'Write...' | 編輯器為空時顯示的文字。 |
toolbar | array | [...] | 定義顯示哪些工具以及顯示順序。 |
footer | 假| 對象 | 全部可見 | 控制編輯器下方顯示的狀態列。設定為 false 完全隱藏它,或傳遞一個物件來切換單一統計資料。 |
theme | string | inherited | 明確設定編輯器主題(淺色、深色、雪莓、黑莓)。如果省略,編輯器繼承 data-theme 從最近的祖先元素或 <textarea> 本身。 |
minHeight | number | 200 | 當內容較短時,編輯器將縮小到的最小高度(以像素為單位)。配對 maxHeight 設定自動增長範圍。 |
maxHeight | number | 500 | 編輯器在非全螢幕模式下可以增長到的最大高度(以像素為單位)。一旦內容超過此高度,編輯器內就會出現捲軸。該編輯器還有一個拖曳手柄,因此使用者可以手動將其大小調整到超出此限制。 |
renderer | function | marked | 替換用於預覽的 Markdown 解析器。接收 markdown 字串並且必須傳回 HTML 字串。 |
sanitizer | function | DOMPurify | 取代 HTML 清理程式。接收渲染的 HTML,必須傳回安全的 HTML 來顯示。 |
onChange | function | undefined | 每次內容變更時都會觸發回調:鍵入、工具列操作、撤銷/重做和清單延續。接收目前的 markdown 字串作為其唯一的參數。 |
labels | object | undefined | 編輯器本身介面的翻譯,由英文字串鍵入。您遺漏的任何內容都將保留為英文。 |
🛠 工具列定制
工具列是模組化的。您可以透過修改陣列來創建最低限度的體驗或功能齊全的電源套件。
可用工具
| 類別 | 工具鍵 |
|---|---|
| 版式 | heading, bold, italic, strikethrough, blockquote |
| 清單 | ul (bullet), ol (numbered), checklist |
| 程式碼 | code (排隊), codeblock (圍欄塊) |
| 刀片 | hr (水平規則), table (表格範本) |
| 媒體 | link, image |
| 編輯 | undo, redo, indent, outdent |
| 看法 | preview |
| 範本 | { variables: [...] }, 內聯配置 |
工具參考
| 工具 | 描述 |
|---|---|
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 鍵退出全螢幕。如果固定標題覆蓋全螢幕編輯器,請參閱 --mte-fullscreen-z-index. |
💡實施技巧:
- 重新排序:按鈕會依照您在陣列中列出的確切順序顯示
- 刪除:只需省略任何鍵(例如
image) 從陣列中完全為使用者停用該功能 - 本機後備:如果您不提供
placeholder在 JS 中,插件會自動使用placeholder來自 HTML 的屬性<textarea>
📊 頁腳(狀態列)
頁腳位於編輯器下方,顯示遊標的行、列、文檔的字元數以及可選的字數,所有這些都是即時更新的。預設情況下它是可見的,並且每個統計資料都可以獨立切換。
| 鑰匙 | 類型 | 預設 | 描述 |
|---|---|---|---|
line | boolean | true | 顯示目前行號。 |
col | boolean | true | 顯示目前的列號。 |
chars | boolean | true | 顯示總字元數。 |
words | boolean | false | 顯示總字數。預設關閉:設定為 true 啟用。 |
使用範例
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 } }); |
🔀 編輯模式
MarkdownEditor 提供兩種不同的方式來撰寫和格式化內容。您可以在傳統的以語法為中心的視圖或現代的視覺優先體驗之間切換。
plain(預設):一個乾淨、高效能的 Markdown 環境,其中語法(例如**bold**或者# heading) 可見。開發人員和 Markdown 純粹主義者的理想選擇hybrid:所見即所得的體驗,可在您鍵入時即時呈現格式(粗體、斜體、標題),同時仍保持底層 Markdown 結構。
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語法,以獲得輕量級體驗。
佈景主🌙題
-
- MarkdownEditor * *自動從周圍頁面繼承其主題:無需配置。編輯器讀取
data-theme在初始化時與最近的祖先保持同步,因此它與您網站的開箱即用主題保持同步。
- MarkdownEditor * *自動從周圍頁面繼承其主題:無需配置。編輯器讀取
如何解析主題(優先順序)
- *
theme選項 * :在選項物件中傳遞的明確覆寫 - *
data-theme於<textarea>* :直接在元素上設定 - *
data-theme任何祖先 * :例如<html>,<body>或包裹<div>
可使用的佈景主題
'light' (預設) 'dark', 'snowberry', 'darkberry'
選項1 ,繼承自 <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 :設定 data-theme 直接在 <textarea>
1 2 3 4 | <textarea id="markdown-editor" data-theme="dark"></textarea> <script> new MarkdownEditor('#markdown-editor'); </script> |
選項3 :明確 theme 選項(覆蓋一切)
1 2 3 | new MarkdownEditor('#markdown-editor', { theme: 'dark' }); |
透過CSS變數🎨自訂佈景主題
您可以通過覆蓋編輯器的CSS變量來完全自定義編輯器的外觀 .markdown-editor-wrapper 元素或任何 [data-theme] 選擇器。所有顏色都使用 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] 樣式表中的區塊:
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; } |
new MarkdownEditor('#markdown-editor', { theme: 'brand' }); |
介面語言
編輯器自己的文字、工具提示、選單項目、對話框欄位和按鈕預設為英文。傳遞 labels 以翻譯它。key是英文字符串, gettext的工作方式,因此您只列出要更改的內容,任何缺失的內容都會返回到英文。
1 2 3 4 5 6 7 8 9 10 11 12 13 | new MarkdownEditor('#markdown-editor', { labels: { 'Bold': 'Gras', 'Italic': 'Italique', 'Heading': 'Titre', 'Link': 'Lien', 'Image link': 'Lien de l\'image', 'URL': 'URL', 'Alt text': 'Texte alternatif', 'Apply': 'Appliquer', 'Uploading...': 'Téléversement...', }, }); |
這與從右到左的內容最為重要。阿拉伯文、烏爾都文和波斯文可自行正確排列,但右至左文字上仍顯示「粗體」的工具列只翻譯了一半。
變數
新增工具列下拉式選單以插入佔位符。當撰寫文件的人不是定義佔位符語法的開發人員時很有用,例如電子郵件、發票或合約範本:他們選擇可讀的名稱,並為他們插入正確的語法。
1 2 3 4 5 6 7 8 9 | new MarkdownEditor('#markdown-editor', { toolbar: ['bold', 'italic', 'link', { variables: [ { label: 'Customer Name', value: '{{customer.name}}' }, { label: 'Invoice No', value: '{{invoice.number}}' } ]}, 'preview' ] }); |
工具在中內聯配置 toolbar 陣列,因此它在其他按鈕中的位置由您決定。按鈕會列出標籤,按一下即可插入 value 在遊標上,替換任何選擇。如果清單為空,則不會渲染任何內容。
預覽中的範例值
給定一個條目 sample 在預覽中顯示該樣本,而textarea保留真實的佔位符。沒有條目的條目會顯示為寫入狀態,因此您可以將兩者混合。
1 2 3 4 5 6 7 | { variables: [ { label: 'Customer Name', value: '{{customer.name}}', sample: 'Hannes' }, { label: 'Invoice No', value: '{{invoice.number}}' } ]} // textarea : Hi {{customer.name}}, invoice {{invoice.number}} // preview : Hi Hannes, invoice {{invoice.number}} |
群組
輸入條目 items 而不是 value 以呈現標題區段。分組和平面條目可以混合在一個列表中。
1 2 3 4 5 6 7 8 9 10 | { variables: [ { label: 'Today', value: '{{today}}', sample: '10 September 2026' }, { label: 'Customer', items: [ { label: 'Name', value: '{{customer.name}}', sample: 'Hannes' }, { label: 'Email', value: '{{customer.email}}', sample: 'hannes@example.com' } ]}, { label: 'Invoice', items: [ { label: 'Number', value: '{{invoice.number}}' } ]} ]} |
注意事項
-
- 編輯器永遠不會解析變數。 *它會插入文字,您的應用程式稍後會取代實際值,通常是伺服器端。
sample只會影響預覽顯示的內容。
- 編輯器永遠不會解析變數。 *它會插入文字,您的應用程式稍後會取代實際值,通常是伺服器端。
-
- 標籤以純文字顯示 * ,因此標籤中的標記永遠不會呈現。
-
- 跳過格式不正確的條目 *而不是拋出,並且在未配置任何可用項目時根本不會渲染按鈕。
🖋 自定義渲染器
預覽呈現方式 已標記 並使用以下方式消毒 DOMPurify。兩者都可以更換。當您的應用程式已經與另一個程式庫渲染markdown ,並且您希望預覽與生產完全匹配時,請使用此功能。
這兩個選項都是普通函數,它們會接收字串並傳回字串,因此任何剖析器和任何消毒劑都可以運作。
1 2 3 4 5 6 7 8 9 | import MarkdownIt from 'markdown-it'; import taskLists from 'markdown-it-task-lists'; import MarkdownEditor from 'markdown-text-editor'; const md = new MarkdownIt({ linkify: true, breaks: true }).use(taskLists); new MarkdownEditor('#markdown-editor', { renderer: markdown => md.render(markdown) }); |
DOMPurify仍在輸出上運行,因此您可以在不配置任何內容的情況下保持XSS保護。
自訂消毒劑
僅在默認條帶渲染器發射的東西時才需要。DOMPurify刪除 <iframe> 默認情況下,因此視頻嵌入需要明確允許。DOMPurify必須在您自己的代碼中匯入,因為與編輯器捆綁在一起的副本是內部的。
1 2 3 4 5 6 7 8 9 | import DOMPurify from 'dompurify'; new MarkdownEditor('#markdown-editor', { renderer: markdown => md.render(markdown), sanitizer: html => DOMPurify.sanitize(html, { ADD_TAGS: ['iframe'], ADD_ATTR: ['allow', 'allowfullscreen', 'frameborder'] }) }); |
使用script標籤而不是bundler ,在編輯器旁邊載入DOMPurify :
1 2 | <script src="https://cdn.jsdelivr.net/npm/dompurify"></script> <script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script> |
注意事項
-
- 僅限預覽。 *混合模式的即時格式使用單獨的內部渲染器,不受影響。
-
- 任務清單需要外掛程式支援。 *可透過尋找找到可點擊的核取方塊
input[type="checkbox"]在輸出中,所以markdown-它需要markdown-it-task-lists。如果偵測到工作清單語法且沒有核取方塊,編輯器會記錄警告。
- 任務清單需要外掛程式支援。 *可透過尋找找到可點擊的核取方塊
-
- 兩者必須是同步的 *並傳回字串。
async函數寫入[object Promise]進入預覽。
- 兩者必須是同步的 *並傳回字串。
-
- 更換消毒劑會取代防護裝置。 *傳遞,例如
html => html完全禁用消毒,並且僅對完全受信任的內容是安全的。
- 更換消毒劑會取代防護裝置。 *傳遞,例如
🎨 樣式內部元素
CSS變數涵蓋大多數主題,因為它們會繼承,因此設置一個 .markdown-editor-wrapper 到達工具列、按鈕、預覽和頁尾。僅當沒有變數公開您需要的內容時,才會觸及類別名稱。
1 2 3 4 5 | /* Variables set on the wrapper inherit down to every child */ .markdown-editor-wrapper { --border-radius: 12px; /* rounds the editor and its toolbar buttons */ --color-primary: oklch(60% 0.2 30); } |
類別參考
這些類別名稱是穩定且安全的樣式。
| 類別 | 元件 |
|---|---|
.markdown-editor-wrapper | 包裝整個編輯器的外部容器 |
.toolbar | 編輯區域上方的工具列 |
.markdown-btn | 個別工具列按鈕 |
.preview-btn | 預覽/全螢幕切換按鈕 |
.editor-layout | 保持編輯區域和預覽並排的網格 |
.textarea-wrapper | 編輯區域周圍的包裝 |
.editor-textarea | 底層textarea元素 |
.display-layer | 渲染格式圖層,僅限混合模式 |
.preview-wrapper | 預覽欄 |
.preview-content | 在預覽內渲染扣分 |
.editor-footer | 編輯器下方的狀態列 |
.find-replace-panel | 尋找並更換面板 |
1 2 3 4 5 6 7 8 9 10 | /* Some variables are set by the component on itself, which beats an inherited value. Target the element directly for those. */ .markdown-editor-wrapper .markdown-btn { --btn--font-size: 0.875rem; } /* And use classes for anything no variable exposes */ .markdown-editor-wrapper .toolbar { border-bottom: 2px solid oklch(60% 0.2 30); } |
鎖定一個編輯器
在一個頁面上有幾個編輯器,針對其中一個編輯器 data-editor。包裝鏡像其ID <textarea>因此 <textarea id="notes"> 爲您提供 [data-editor="notes"]。ID本身停留在textarea上,因此 getElementById 繼續運作。
1 2 3 4 | /* one editor only */ [data-editor="notes"] { --border-radius: 0; } |
🪟 全螢幕與圖層(z-index)
在全螢幕中,編輯器使用 z-index: 10000,這將清除大多數UI框架為固定標題和疊加層保留的圖層。如果固定的標題或側邊欄仍覆蓋編輯器,請提高此值。
覆蓋它 --mte-fullscreen-z-index。該值僅適用於全螢幕,並且會繼承,因此在任何祖先上設置它會覆蓋其下方的每個編輯器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /* every editor on the page */ .markdown-editor-wrapper { --mte-fullscreen-z-index: 20000; } /* one section only - the value inherits down */ #admin-panel { --mte-fullscreen-z-index: 20000; } /* a single editor, by its textarea id */ [data-editor="notes"] { --mte-fullscreen-z-index: 20000; } |
內容API
-
- MarkdownEditor * 的核心優勢之一是它保留了
<textarea>完全同步。無論您是使用現代JavaScript框架還是 * Django、PHP或Laravel * *等傳統後端,工作流程都保持簡單和原生。
- MarkdownEditor * 的核心優勢之一是它保留了
閱讀和撰寫內容
1.原生方式(推薦)
由於編輯器增強了標準文字區域,因此您可以使用熟悉的DOM方法。這是無需學習新API即可與數據進行交互的最快方式。
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。
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時自動渲染它。
1 2 | <!-- Recommended: set content server-side --> <textarea id="markdown-editor"># Hello World</textarea> |
若要在執行階段讀取或更新內容,請使用原生 textarea value. Call editor.render() 更新以刷新預覽和混合圖層之後。
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> 至其在文件中的位置。在單頁應用程式中卸載檢視時很有用。
1 2 3 4 | const editor = new MarkdownEditor('#markdown-editor'); // Remove the editor and restore the plain textarea editor.destroy(); |
通過以下方式對更改作出反應 onChange
通過 onChange 每次內容變更時都會收到通知。接收當前的markdown字符串。
1 2 3 4 5 | const editor = new MarkdownEditor('#markdown-editor', { onChange(value) { console.log('Content changed:', value.length, 'characters'); } }); |
草稿自動儲存方式 localStorage
使用 onChange 在每次按鍵時儲存草稿在初始化編輯器之前,透過預先填充文字區域來還原它。
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); }); |
表單提交
因爲* * MarkdownEditor * *直接構建於原生 <textarea>,它與開箱即用的所有後端框架( Django、Laravel、PHP、Ruby on Rails等)兼容。
這就是「原住民優先」理念的閃耀之處。在提交表單之前,您無需手動同步數據。瀏覽器將編輯器視為標準輸入欄位。
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上的屬性是伺服器用來識別內容的內容。
🚀 為什麼它是後端改變遊戲規則的關鍵
由於編輯器保留原生 <textarea> 行為,伺服器會將資料作為標準字串處理。無需額外邏輯:否 preventDefault() 也沒有手冊 FormData 建造
💡 為什麼這是「殺手級功能」:
大多數編輯器(如Quill、Editor.js、simpleMDE、easyMDE )以複雜的JSON結構儲存資料。如果開發人員使用這些,他們必須重寫其資料庫架構和渲染邏輯。
使用* * MarkdownEditor * * ,開發人員可以使用舊網站,取代普通網站 <textarea> 您的編輯器,而* 後端甚至不知道它已變更 *。它只會收到相同的原始文字,但用戶的體驗要好10倍。
| 架構/語言 | 如何存取Markdown內容 |
|---|---|
| PHP | $_POST['content'] |
| 薑戈 | request.POST.get('content') |
| Node.js ( Express ) | req.body.content |
| 拉維爾 | $request->input('content') |
| 紅寶石 on Rails | params[:content] |
🖼️ 進階圖片上傳
以原生方式處理圖片上傳:與其依賴緩慢且耗費大量記憶體的Base64字串,對於效能和SEO來說都是一大勝利。
貼上並放下
貼上螢幕擷取畫面或將影像檔案拖曳到編輯器中,並透過與工具列按鈕相同的端點上傳。佔位符會立即出現,因此編輯器永遠不會凍結,一旦上傳到達,它將被替換為真實路徑。如果上傳失敗,佔位符將替換為可見的標記,而不是無聲地消失。
這需要 uploadUrl 下面配置。如果沒有它,貼上圖像無效,編輯器會記錄一個警告,解釋要添加的內容,因為替代方案是資料庫中的Base64字串。
系統會一次上傳一個或多個檔案,因此影像會按照送達的順序放置。
設定選項
圖片工具支援 fileInput 設定以處理直接伺服器上傳。
accept:定義允許的圖像格式陣列(例如, 'webp' , 'avif' )uploadUrl:指定後端端點,其中File物件將透過傳送POSTparams:在影像檔案旁邊傳送額外資料(如CSRF權杖、使用者ID或資料夾名稱)的可選物件
使用示例(完整配置)
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); |
📡 伺服器整合
送出詢價單
編輯器傳送 POST 請求為 multipart/form-data。預設情況下,它包括:
image_file:實際的檔案物件image_alt:使用者輸入的替代文字 -...加上在中定義的任何自定義數據params物件
所需的回應
若要確認上傳成功並將圖片插入編輯器,伺服器* 必須 *傳回以下JSON結構:
1 2 3 4 | { "success": true, "image_path": "https://cdn.yourdomain.com/uploads/image.webp" } |
- 注意 * :請務必使用密鑰
image_path上傳圖片的網址。
圖片替代文字驗證(altInput)
為確保內容可存取且適合SEO , * * MarkdownEditor * *預設會強制執行替代文字驗證。
-
- 預設行為 * :如果
altInput未定義,預設為{ required: true }
- 預設行為 * :如果
-
- 強制執行無障礙功能 * :在提供替代說明之前,用戶將無法插入圖片
1.預設(不需要設定)
1 2 3 4 | // Alt text is REQUIRED by default image: { fileInput: { uploadUrl: '/api/upload' } } |
2.速記(停用驗證)
如果您想允許沒有描述的圖像,只需將布林值設置為 false.
1 2 3 | image: { altInput: false // Users can now skip the alt text field } |
3.以物件為基礎(明確)
1 2 3 4 5 | image: { altInput: { required: false // Disables alt text validation — users can skip the alt field } } |
標準影像使用(否 fileInput)
如果 fileInput 未設定,編輯器預設為簡單的基於URL的對話框。如果您的用戶主要是連結到外部圖片主機,這是理想的選擇。
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 對象,您的請求將無縫地通過後端的安全中間件,為您的服務器端控制器保持“零邏輯”理念。
鍵盤快速鍵
無需觸摸工具列,即可直接從鍵盤觸發常見的格式化操作。每個捷徑也會顯示在對應工具列按鈕的工具提示中。
| 快捷词 | 操作 |
|---|---|
Ctrl + B / ⌘ B | 切換粗體 |
Ctrl + I / ⌘ I | 切換斜體 |
Ctrl + K / ⌘ K | 插入連結 |
Ctrl + ` / ⌘ ` | 切換檢視行內 Code |
Ctrl + Shift + S / ⌘ ⇧ S | 切換~ |
Ctrl + 1 / ⌘ 1 | H1 |
Ctrl + 2 / ⌘ 2 | H2 |
Ctrl + 3 / ⌘ 3 | H3 |
Ctrl + L / ⌘ L | 切換項目符號清單 |
Ctrl + Z / ⌘ Z | 還原 |
Ctrl + Shift + Z / ⌘ ⇧ Z | 重做 |
Tab | 縮排所選行 |
Shift + Tab | 縮排所選行 |
Ctrl + F / ⌘ F | 打開“查找”面板 |
Ctrl + H / ⌘ H | 開啟「尋找與取代」面板 |
Ctrl + Shift + F / ⌘ ⇧ F | 切換全螢幕預覽 |
F11 | 切換全螢幕預覽 |
Escape | 關閉尋找面板/退出全螢幕預覽 |
尋找 & 取代
編輯器內建內建的尋找與取代面板:無需瀏覽器擴充功能或獨立工具。
按 Ctrl + F (或 ⌘ F)打開* 查找 面板
按 Ctrl + H (或 ⌘ H)以開啟 尋找與取代 面板
-搜尋為 不區分大小寫 * ,並顯示即時比對計數器(例如* 3/12 )
-使用 ▲/ ▼*按鈕或 Enter / Shift + Enter
-
- 取代 *取代當前高亮顯示的匹配項; * 全部取代 *一次取代每個匹配項
按
Escape關閉面板並將焦點返回到編輯器
- 取代 *取代當前高亮顯示的匹配項; * 全部取代 *一次取代每個匹配項
按
面板浮動在編輯器內容區域的右上角,不會中斷寫入。
來自貼上網址的🔗連結
選取文字並貼上網址,系統就會顯示扣分連結,而非取代所選網址的網址。
1 2 | Read the docs <- select "the docs", paste https://example.com Read [the docs](https://example.com) <- what you get |
這項規定是刻意嚴格的:只有一點點 http 或者 https 沒有空白的網址會以這種方式處理。貼上碰巧包含網址的句子,或未選擇任何內容的貼上,其行為與普通貼上相似。
特色Features
🔌 原生表單集成
運作方式與標準一模一樣 <textarea>。沒有複雜的API :只需使用 value 或者 name 屬性。它僅適用於PHP、Django或Node.js中的標準HTML表單提交。
🖼️ 進階圖片上傳
透過API設定本機伺服器上傳。避免繁重的Base64字串,透過在您自己的CDN上託管圖像,確保更快的頁面載入和優越的SEO。
🔀 混合和普通模式
在之間切換 混合(所見即所得) 視覺編輯體驗或 普通扣分 模式,帶來傳統的編碼感。
高效率
可 53 KB gzipped 捆綁包( 252 KB縮小,包括CSS )針對「重度內容」進行了優化。"處理大量文件和大型檔案,沒有任何輸入延遲或性能下降。發佈預覽更新、快取樣式計算和無衝突鍵盤處理:因此Tab和Enter總是只做一件事。
🌍 內置RTL支持
原生支援從右到左的語言,如阿拉伯語、烏爾都語和波斯語。非常適合構建全球可訪問的應用程序。
語法醒目提示
透過清晰的程式碼和markdown格式加強可讀性。
🌙 自適應主題
包括自動深色模式支援。它會與您的系統設定或 Frutjam UI 提供無縫視覺體驗的圖書館。
📝 智慧編輯
有序清單、無序清單和檢查清單的GitHub風格自動清單連續:按 Enter 然後編輯器繼續圖案預覽窗格中的核取方塊可點擊並立即同步回Markdown來源。
📱 全方位回應
流暢的行動優先使用者介面,可完美適應桌上型電腦、平板電腦和智慧型手機,隨時隨地進行編輯。
📦 通用支持
兼容 ESM、UMD、CommonJS和LIFE。通過CDN開箱即用(<script src>)、npm或任何bundler ( Vite、webpack、Rollup ) :無需額外配置。
預♿ 設為可存取
內建完整的ARIA支援:工具列地標、標籤預覽區域、螢幕閱讀器友好按鈕、 aria-pressed 在預覽切換上, disabled 以及 aria-disabled 在非活動工具上,並在模態關閉時正確恢復焦點。
🛡️ 零 CSS 衝突
編輯器樣式完全適用於 .markdown-editor-wrapper。 Tailwind 的全域預檢被排除,因此編輯器可以安全地與 Bootstrap、Tailwind 或任何其他框架一起使用,而不會破壞它們的風格。
鍵盤快速鍵
Ctrl+B, Ctrl+I, Ctrl+K, Ctrl+`, Ctrl+Shift+S:無需觸碰滑鼠的常見格式化操作。每個快捷方式都顯示在工具列按鈕的工具提示中。
🔍 尋找和替換
按 Ctrl+F 尋找或 Ctrl+H 打開尋找和取代。不區分大小寫的搜索,具有即時匹配計數器、下一個/上一個導航、單一替換和全部替換:無需離開編輯器。
🔒 XSS 安全預覽
渲染的預覽透過以下方式進行清理 DOMPurify 在寫入 DOM 之前。精心設計的 Markdown 輸入中的腳本標籤、內聯事件處理程序和惡意 URL 都會自動刪除:無需配置。
▶️即時預覽
在您鍵入時查看立即呈現的 Markdown。
🔗 輕鬆集成
只需最少的設定即可無縫整合到任何 Web 專案中。
🛠️ 可自訂的工具列
動態配置和重新排序工具列選項,例如粗體、斜體等。
完整配置範例
使用這個綜合範例來初始化 MarkdownEditor 的所有主要功能,包括自訂工具列排序和進階影像上傳處理。
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'); }, labels: { 'Bold': 'Gras', 'Italic': 'Italique', 'Uploading...': 'Téléversement...', }, 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; // destroy() when the view unmounts (SPAs) // editor.destroy(); |
覺得有用嗎?
GitHub 之星可以幫助其他開發人員發現該編輯器。它是的一部分 弗魯賈姆。那裡的明星也有幫助。