Thanh công cụ, bản xem trước trực tiếp và WYSIWYG trên vùng văn bản bạn đã có
Cập nhật lần cuối:
Trình chỉnh sửa đánh dấu giúp nâng cao vùng văn bản của bạn thay vì thay thế nó, nhờ đó việc gửi biểu mẫu, xác thực và các trường bắt buộc sẽ tiếp tục hoạt động. WYSIWYG và các chế độ Markdown đơn giản, xem trước trực tiếp, tìm và thay thế, hỗ trợ RTL, chế độ tối. Hoạt động độc lập với Django, Laravel, Rails, Node.js, PHP và bất kỳ ngăn xếp nào.
Không cần Frutjam và không cần Tailwind. Các kiểu được đóng gói sẵn nên người chỉnh sửa có thể tùy ý thực hiện bất kỳ dự án nào.
Cài đặt
NPM (các gói: Vite, webpack, Rollup, v.v.)
npm install markdown-text-editor |
1 2 | import MarkdownEditor from 'markdown-text-editor'; new MarkdownEditor('#markdown-editor'); |
Các định nghĩa TypeScript đi kèm với gói, do đó các tùy chọn, mục thanh công cụ và hình dạng biến đổi được kiểm tra và tự động hoàn thành mà không cần cài đặt thêm.
CDN: mô-đun 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: thẻ tập lệnh toàn cầu (IIFE)
Không cần nhập: MarkdownEditor tự động có sẵn dưới dạng biến toàn cục.
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> |
Bản trình diễn trình chỉnh sửa Markdown
Bắt đầu nhanh
Truyền một đối tượng tùy chọn để tùy chỉnh trình chỉnh sửa. Tất cả các tùy chọn đều là tùy chọn: bỏ qua bất kỳ tùy chọn nào để sử dụng giá trị mặc định.
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'], }); |
Triết lý: "Bản địa đầu tiên"
Hầu hết các biên tập viên đều phá vỡ quy trình làm việc web tiêu chuẩn. MarkdownEditor đón nhận nó. Bởi vì nó nằm ngay trên đầu một <textarea>, bạn không cần phải học cách mới để xử lý dữ liệu.
- Không cần ràng buộc dữ liệu: Hoạt động với
<form method="POST">ra khỏi hộp - Quyền truy cập tiêu chuẩn: Sử dụng
document.getElementById('editor').valuegiống như một đầu vào bình thường. - Backend Agnostic: Hoạt động với mọi backend (Python, Node.js, PHP, v.v.) giống như trường biểu mẫu thông thường
MarkdownEditor so với EasyMDE/SimpleMDE
Hầu hết các trình soạn thảo đánh dấu JavaScript (EasyMDE, SimpleMDE, trình soạn thảo dựa trên CodeMirror) ẩn <textarea> và chỉnh sửa một bản sao, viết lại nội dung khi biểu mẫu được gửi. Điều đó hoạt động cho đến khi một cái gì đó khác cần giá trị: a required trường trình duyệt không thể tập trung chặn hoàn toàn việc gửi và .value hoặc FormData đọc trước khi gửi trả về một chuỗi trống, chuỗi này phá vỡ các bộ bảo vệ htmx, Turbo, tự động lưu và các thay đổi chưa được lưu. MarkdownEditor thì khác. Nó tạo kiểu cho vùng văn bản bạn đã có và giữ nguyên nó như trường bạn nhập vào, vì vậy giá trị luôn chính xác.
| Tính năng | Trình chỉnh sửa Markdown | EasyMDE / SimpleMDE |
|---|---|---|
| Vùng văn bản gốc được bảo tồn | ✅ | ❌ Ẩn, chỉnh sửa dưới dạng bản sao |
Hoạt động với required lĩnh vực | ✅ | ❌ Trình duyệt chặn gửi |
.value sửa trước khi gửi | ✅ | ❌ Trống cho đến khi biểu mẫu được gửi |
Nối tiếp với FormData, htmx, Turbo | ✅ | ❌ Cần API riêng của người biên tập |
| Chế độ kết hợp WYSIWYG | ✅ | ❌ |
| Tích hợp Tìm & Thay thế | ✅ | ❌ |
| Hỗ trợ RTL | ✅ Tích hợp sẵn | Thông qua CodeMirror direction lựa chọn |
| Trình xử lý sự kiện nội tuyến (CSP) | ✅ Không có | Một số |
| Chế độ tối / chủ đề | ✅ | Giới hạn |
| Kích thước gói, được nén | 53 KB | 107 KB (JS + CSS) |
Tích hợp khung
Bởi vì MarkdownEditor bảo tồn kiểu gốc <textarea>, nó tích hợp với mọi khung phụ trợ mà không cần bất kỳ mã bổ sung nào. Máy chủ của bạn nhận được nội dung đánh dấu chính xác như từ bất kỳ trường biểu mẫu tiêu chuẩn nào. Đối với React và Vue, cần có vài dòng, được trình bày ở cuối phần này.
Django
Thêm một class vào tiện ích vùng văn bản của bạn và khởi tạo trình chỉnh sửa: request.POST['content'] hoạt động không có bước bổ sung.
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 |
Laravel
Sử dụng f.text_area với một lớp: $request->input('content') nhận được sự giảm giá trực tiếp.
1 2 | <textarea name="content" class="markdown-editor">{{ old('content') }}</textarea> <script>new MarkdownEditor('.markdown-editor');</script> |
Ruby trên đường ray
Hoạt động với form_with ra khỏi hộp: params[:content] chứa phần đánh dấu. Đối với Turbo Drive, hãy sử dụng turbo:load thay vì 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 nhận được mức giảm giá khi gửi biểu mẫu: không có bước đồng bộ hóa, không có trích xuất tùy chỉnh.
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'] hoạt động chính xác như với bất kỳ vùng văn bản tiêu chuẩn nào: thả nó vào và việc xử lý biểu mẫu hiện tại của bạn không cần thay đổi gì.
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> |
Phản ứng
Tạo trình chỉnh sửa trong một hiệu ứng và hủy nó khi ngắt kết nối. Sử dụng defaultValue còn hơn là value: trình soạn thảo ghi trực tiếp vào vùng văn bản, do đó, liên kết được kiểm soát sẽ ghi đè lên nội dung người dùng đang nhập.
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} />; } |
Trở về editor.destroy() từ hiệu ứng này cũng bao gồm StrictMode, chạy các hiệu ứng hai lần trong quá trình phát triển và nếu không thì sẽ để lại hai trình soạn thảo trên một vùng văn bản. Mảng phụ thuộc trống là có chủ ý: các tùy chọn được đọc một lần khi trình soạn thảo được tạo, do đó, việc chạy lại hiệu ứng sẽ phá bỏ nó và xây dựng lại nó sau mỗi thay đổi.
Vue
Cùng một ý tưởng. Đặt giá trị ban đầu một lần trong onMounted và không ràng buộc :valuehoặc mỗi lần nhấn phím được phát ra qua v-model sẽ ghi đè lên vùng văn bản.
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> |
Được sử dụng như <MarkdownField v-model="content" />. Ở dạng đơn giản, bạn có thể bỏ qua v-model hoàn toàn và đọc giá trị từ vùng văn bản khi gửi, như với bất kỳ khung công tác nào khác.
Cấu hình
Bạn hoàn toàn có thể tùy chỉnh hành vi và giao diện của trình soạn thảo bằng cách chuyển một options sự vật. Nếu bạn bỏ qua một tùy chọn, giá trị mặc định sẽ được sử dụng.
Các tùy chọn được đọc một lần khi trình soạn thảo được xây dựng. Thay đổi chúng sau đó không có tác dụng: gọi destroy() và thay vào đó hãy tạo một trình soạn thảo mới.
| Tài sản | Kiểu | Mặc định | Mục đích |
|---|---|---|---|
mode | string | 'plain' | Đặt chế độ xem ban đầu. Sử dụng kết hợp để có trải nghiệm WYSIWYG hoặc đơn giản cho cú pháp thô. |
placeholder | string | 'Write...' | Văn bản hiển thị khi trình chỉnh sửa trống. |
toolbar | array | [...] | Xác định những công cụ nào xuất hiện và theo thứ tự nào. |
footer | sai | đối tượng | tất cả có thể nhìn thấy | Điều khiển thanh trạng thái hiển thị bên dưới trình chỉnh sửa. Đặt thành false để ẩn nó hoàn toàn hoặc chuyển một đối tượng để chuyển đổi các số liệu thống kê riêng lẻ. |
theme | string | inherited | Đặt rõ ràng chủ đề của trình chỉnh sửa (sáng, tối, dâu tuyết, dâu đen). Nếu bị bỏ qua, trình soạn thảo sẽ kế thừa data-theme từ phần tử tổ tiên gần nhất hoặc <textarea> chính nó. |
minHeight | number | 200 | Chiều cao tối thiểu tính bằng pixel mà trình chỉnh sửa sẽ thu nhỏ lại khi nội dung ngắn. Cặp với maxHeight để thiết lập phạm vi tự động phát triển. |
maxHeight | number | 500 | Chiều cao tối đa tính bằng pixel mà trình chỉnh sửa có thể tăng lên ở chế độ không toàn màn hình. Khi nội dung vượt quá chiều cao này, thanh cuộn sẽ xuất hiện bên trong trình chỉnh sửa. Trình chỉnh sửa cũng có tay cầm kéo để người dùng có thể thay đổi kích thước thủ công vượt quá giới hạn này. |
renderer | function | marked | Thay thế trình phân tích cú pháp đánh dấu được sử dụng để xem trước. Nhận chuỗi đánh dấu và phải trả về chuỗi HTML. |
sanitizer | function | DOMPurify | Thay thế trình khử trùng HTML. Nhận HTML được hiển thị và phải trả về HTML an toàn để hiển thị. |
onChange | function | undefined | Lệnh gọi lại được thực hiện khi có mọi thay đổi về nội dung: gõ, thao tác trên thanh công cụ, hoàn tác/làm lại và tiếp tục danh sách. Nhận chuỗi đánh dấu hiện tại làm đối số duy nhất của nó. |
labels | object | undefined | Bản dịch cho giao diện riêng của người soạn thảo, được khóa bằng chuỗi tiếng Anh. Bất cứ điều gì bạn bỏ đi vẫn bằng tiếng Anh. |
🛠 Tùy chỉnh thanh công cụ
Thanh công cụ có tính mô-đun. Bạn có thể tạo trải nghiệm tối thiểu hoặc bộ năng lượng đầy đủ tính năng bằng cách sửa đổi mảng.
Công cụ có sẵn
| Loại | Phím công cụ |
|---|---|
| kiểu chữ | heading, bold, italic, strikethrough, blockquote |
| Danh sách | ul (bullet), ol (numbered), checklist |
| Mã số | code (nội tuyến), codeblock (khối có rào chắn) |
| Phụ trang | hr (quy tắc ngang), table (mẫu bảng) |
| Phương tiện truyền thông | link, image |
| Chỉnh sửa | undo, redo, indent, outdent |
| Xem | preview |
| Mẫu | { variables: [...] }, được định cấu hình nội tuyến |
Tham khảo công cụ
| Dụng cụ | Sự miêu tả |
|---|---|
heading | Mở menu thả xuống để chọn cấp tiêu đề H1–H6 |
bold | Cho phép định dạng văn bản in đậm. |
italic | Cho phép định dạng văn bản in nghiêng. |
strikethrough | Cho phép gạch ngang văn bản. |
ol | (Danh sách có thứ tự): Chuyển văn bản sang dạng danh sách đánh số. |
ul | (Danh sách không có thứ tự): Chuyển văn bản thành danh sách dấu đầu dòng. |
checklist | Thêm các hộp kiểm vào văn bản của bạn, giúp nó trở nên tuyệt vời cho các nhiệm vụ, danh sách việc cần làm hoặc theo dõi trạng thái hoàn thành. |
blockquote | Đánh dấu văn bản được trích dẫn hoặc nhấn mạnh. |
code | Bao bọc văn bản đã chọn bằng dấu backticks đơn cho mã nội tuyến. Nhấp lại sẽ loại bỏ dấu tích ngược. |
codeblock | Bao bọc văn bản đã chọn trong khối mã có hàng rào ba dấu ngược. Nhấp chuột một lần nữa sẽ loại bỏ hàng rào. |
hr | Chèn một --- quy tắc ngang tại vị trí con trỏ trên dòng riêng của nó. |
table | Chèn mẫu bảng đánh dấu 2x3 ban đầu vào vị trí con trỏ. |
image | Cho phép bạn chèn hình ảnh thông qua cú pháp đánh dấu. |
link | Cho phép bạn thêm siêu liên kết vào văn bản của mình. |
undo | Để đảo ngược những thay đổi cuối cùng. |
redo | Để áp dụng lại những thay đổi được hoàn tác gần đây nhất. |
indent | Để tăng mức độ thụt lề. |
outdent | Để giảm mức độ thụt lề. |
preview | Chuyển đổi chế độ xem trước toàn màn hình cạnh nhau. Các hộp kiểm trong khung xem trước có thể nhấp vào được và cập nhật nguồn đánh dấu ngay lập tức. Nhấn Escape để thoát toàn màn hình. Nếu tiêu đề cố định bao phủ trình chỉnh sửa ở chế độ toàn màn hình, hãy xem --mte-fullscreen-z-index. |
💡 Mẹo triển khai:
- Sắp xếp lại: Các nút xuất hiện theo đúng thứ tự bạn liệt kê trong mảng
- Xóa: Chỉ cần bỏ qua bất kỳ phím nào (như
image) khỏi mảng để tắt hoàn toàn tính năng đó cho người dùng - Dự phòng gốc: Nếu bạn không cung cấp
placeholdertrong JS, plugin sẽ tự động sử dụngplaceholderthuộc tính từ HTML của bạn<textarea>
📊 Chân trang (Thanh trạng thái)
Chân trang nằm bên dưới trình chỉnh sửa và hiển thị dòng, cột của con trỏ, số ký tự của tài liệu và số từ tùy chọn, tất cả đều được cập nhật theo thời gian thực. Nó hiển thị theo mặc định và mỗi chỉ số có thể được chuyển đổi độc lập.
| Chìa khóa | Kiểu | Mặc định | Sự miêu tả |
|---|---|---|---|
line | boolean | true | Hiển thị số dòng hiện tại. |
col | boolean | true | Hiển thị số cột hiện tại. |
chars | boolean | true | Hiển thị tổng số ký tự. |
words | boolean | false | Hiển thị tổng số từ. Tắt theo mặc định: đặt thành true để kích hoạt. |
Ví dụ sử dụng
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 } }); |
🔀 Chế độ chỉnh sửa
MarkdownEditor cung cấp hai cách riêng biệt để viết và định dạng nội dung của bạn. Bạn có thể chuyển đổi giữa chế độ xem tập trung vào cú pháp truyền thống hoặc trải nghiệm hiện đại, ưu tiên hình ảnh.
plain(Mặc định): Môi trường Markdown rõ ràng, hiệu suất cao trong đó cú pháp (như**bold**hoặc# heading) có thể nhìn thấy được. Lý tưởng cho các nhà phát triển và những người theo chủ nghĩa thuần túy Markdownhybrid: Trải nghiệm lấy cảm hứng từ WYSIWYG hiển thị định dạng (Đậm, Nghiêng, Tiêu đề) trong thời gian thực khi bạn nhập, trong khi vẫn duy trì cấu trúc Markdown cơ bản.
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' }); |
Xem trước chế độ kết hợp và đơn giản:
Chế độ kết hợp
Định dạng trực quan được hiển thị theo thời gian thực trong khi bạn nhập.
Chế độ đơn giản (Mặc định)
Tập trung vào cú pháp Markdown thô để có trải nghiệm nhẹ nhàng.
🌙 Chủ đề
MarkdownEditor tự động kế thừa chủ đề của nó từ trang xung quanh: không cần cấu hình. Biên tập viên đọc data-theme từ tổ tiên gần nhất khi khởi tạo, do đó, nó luôn đồng bộ với chủ đề trang web của bạn.
Cách giải quyết chủ đề (thứ tự ưu tiên)
themetùy chọn: ghi đè rõ ràng được truyền trong đối tượng tùy chọndata-themetrên<textarea>: đặt trực tiếp trên phần tử- **
data-themetrên bất kỳ tổ tiên nào **: ví dụ:<html>,<body>hoặc một trình bao bọc<div>
Chủ đề có sẵn
'light' (mặc định), 'dark', 'snowberry', 'darkberry'
Tùy chọn 1, kế thừa từ <html> hoặc bất kỳ tổ tiên nào (cấu hình không)
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> |
Tùy chọn 2: đặt data-theme trực tiếp trên <textarea>
1 2 3 4 | <textarea id="markdown-editor" data-theme="dark"></textarea> <script> new MarkdownEditor('#markdown-editor'); </script> |
Tùy chọn 3: rõ ràng theme tùy chọn (ghi đè mọi thứ)
1 2 3 | new MarkdownEditor('#markdown-editor', { theme: 'dark' }); |
🎨 Chủ đề tùy chỉnh thông qua các biến CSS
Bạn hoàn toàn có thể tùy chỉnh giao diện của trình soạn thảo bằng cách ghi đè các biến CSS của nó trên .markdown-editor-wrapper phần tử hoặc bất kỳ [data-theme] bộ chọn. Tất cả các màu đều sử dụng Không gian màu OKLCH cho kết quả thống nhất về mặt nhận thức.
| Biến | Mục đích | Ánh sáng mặc định | Mặc định tối |
|---|---|---|---|
--color-base | Nền soạn thảo | oklch(100% 0 0) | oklch(10.9% 0 0) |
--color-on-base | Màu văn bản chính | oklch(22% 0 0) | oklch(98% 0 0) |
--color-primary | Giọng chính (thanh công cụ đang hoạt động, liên kết) | oklch(51.1% .262 277) | oklch(66.4% .184 286) |
--color-on-primary | Văn bản trên bề mặt màu cơ bản | oklch(96.2% .018 272) | oklch(10% .01 270) |
--color-secondary | Giọng phụ | oklch(59.1% .293 323) | oklch(65% .18 220) |
--color-accent | Đánh dấu trọng âm (mã nội tuyến, in nghiêng) | oklch(54.1% .281 293) | oklch(75% .18 50) |
--color-neutral | Bề mặt trung tính (viền, vách ngăn) | oklch(15% 0 0) | oklch(85% 0 0) |
--color-error | Màu trạng thái lỗi | oklch(57.7% .245 27) | oklch(60% .22 30) |
--border-radius | Làm tròn góc của khung soạn thảo | 0.25rem |
Ví dụ về chủ đề tùy chỉnh
Ghi đè bất kỳ biến nào trên .markdown-editor-wrapper sau khi trình soạn thảo khởi tạo hoặc xác định một tùy chỉnh [data-theme] chặn trong biểu định kiểu của bạn:
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' }); |
🌐 Ngôn ngữ giao diện
Theo mặc định, văn bản, chú giải công cụ, mục menu, trường phương thức và nút của trình chỉnh sửa là tiếng Anh. Vượt qua một labels đối tượng dịch nó. Khóa là các chuỗi tiếng Anh, cách thức hoạt động của gettext, vì vậy bạn chỉ liệt kê những gì bạn muốn thay đổi và mọi thứ còn thiếu sẽ quay lại tiếng Anh.
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...', }, }); |
Điều này quan trọng nhất bên cạnh nội dung từ phải sang trái. Tiếng Ả Rập, tiếng Urdu và tiếng Farsi được sắp xếp chính xác nhưng thanh công cụ vẫn đọc chữ "Đậm" trên văn bản từ phải sang trái chỉ được dịch một nửa.
🏷 Biến
Thêm thanh công cụ thả xuống để chèn phần giữ chỗ. Hữu ích khi người viết tài liệu không phải là nhà phát triển đã xác định cú pháp giữ chỗ, như với các mẫu email, hóa đơn hoặc hợp đồng: họ chọn một tên dễ đọc và cú pháp chính xác được chèn cho chúng.
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' ] }); |
Công cụ này được cấu hình nội tuyến trong toolbar mảng, vì vậy vị trí của nó trong số các nút khác tùy thuộc vào bạn. Nút liệt kê các nhãn và việc nhấp vào một nhãn sẽ chèn nhãn đó value tại con trỏ, thay thế bất kỳ lựa chọn nào. Không có gì được hiển thị nếu danh sách trống.
Giá trị mẫu trong bản xem trước
Một mục được đưa ra một sample hiển thị mẫu đó trong bản xem trước, trong khi vùng văn bản giữ phần giữ chỗ thực. Các mục không có mục nào sẽ xuất hiện dưới dạng văn bản, vì vậy bạn có thể kết hợp cả hai.
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}} |
Nhóm
Đưa ra một mục items thay vì một value để hiển thị một phần có tiêu đề. Các mục được nhóm và phẳng có thể được trộn lẫn trong một danh sách.
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}}' } ]} ]} |
Những điều cần biết
- Trình chỉnh sửa không bao giờ giải quyết các biến. Nó chèn văn bản và ứng dụng của bạn sẽ thay thế các giá trị thực sau đó, thường là phía máy chủ.
samplechỉ ảnh hưởng đến những gì bản xem trước hiển thị. - Nhãn được hiển thị dưới dạng văn bản thuần túy, do đó, đánh dấu trong nhãn không bao giờ được hiển thị.
- Các mục không đúng định dạng sẽ bị bỏ qua thay vì ném và nút này hoàn toàn không được hiển thị khi không có cấu hình nào có thể sử dụng được.
🖋 Trình kết xuất tùy chỉnh
Bản xem trước được hiển thị với đánh dấu và khử trùng bằng DOMThanh lọc. Cả hai đều có thể được thay thế. Sử dụng tính năng này khi ứng dụng của bạn đã hiển thị đánh dấu với một thư viện khác và bạn muốn bản xem trước khớp chính xác với bản sản xuất.
Cả hai tùy chọn đều là các hàm đơn giản nhận một chuỗi và trả về một chuỗi, do đó, mọi trình phân tích cú pháp và bất kỳ trình khử trùng nào đều hoạt động.
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 vẫn chạy ở đầu ra, vì vậy bạn tiếp tục bảo vệ XSS mà không cần định cấu hình bất cứ thứ gì.
chất khử trùng tùy chỉnh
Chỉ cần thiết khi mặc định loại bỏ thứ gì đó mà trình kết xuất của bạn phát ra. DOMPurify loại bỏ <iframe> theo mặc định, vì vậy việc nhúng video cần được cho phép rõ ràng. DOMPurify phải được nhập bằng mã của riêng bạn vì bản sao đi kèm với trình chỉnh sửa là nội bộ.
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'] }) }); |
Sử dụng thẻ script thay vì bộ đóng gói, tải DOMPurify cùng với trình chỉnh sửa:
1 2 | <script src="https://cdn.jsdelivr.net/npm/dompurify"></script> <script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script> |
Những điều cần biết
- Chỉ xem trước. Định dạng trực tiếp của chế độ kết hợp sử dụng trình kết xuất bên trong riêng biệt và không bị ảnh hưởng.
- Danh sách nhiệm vụ cần hỗ trợ plugin. Tìm thấy các hộp kiểm có thể nhấp bằng cách tìm kiếm
input[type="checkbox"]ở đầu ra, vì vậy markdown-nó cầnmarkdown-it-task-lists. Trình chỉnh sửa sẽ ghi lại cảnh báo nếu phát hiện cú pháp danh sách nhiệm vụ và không có hộp kiểm. - Cả hai phải đồng bộ và trả về một chuỗi. MỘT
asyncchức năng viết[object Promise]vào bản xem trước. - Thay thế chất khử trùng sẽ thay thế sự bảo vệ của bạn. Việc lây truyền như
html => htmlvô hiệu hóa hoàn toàn quá trình khử trùng và chỉ an toàn cho nội dung hoàn toàn đáng tin cậy.
🎨 Tạo kiểu cho các yếu tố bên trong
Các biến CSS bao gồm hầu hết các chủ đề vì chúng kế thừa, do đó, hãy đặt một biến trên .markdown-editor-wrapper đến thanh công cụ, nút, xem trước và chân trang. Chỉ liên hệ với tên lớp khi không có biến nào hiển thị những gì bạn cần.
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); } |
Tham khảo lớp
Những tên lớp này ổn định và an toàn để tạo kiểu.
| Lớp học | Yếu tố |
|---|---|
.markdown-editor-wrapper | Vùng chứa bên ngoài bao bọc toàn bộ trình soạn thảo |
.toolbar | Dải thanh công cụ phía trên khu vực chỉnh sửa |
.markdown-btn | Nút thanh công cụ riêng lẻ |
.preview-btn | Nút chuyển đổi xem trước/toàn màn hình |
.editor-layout | Lưới giữ vùng chỉnh sửa và xem trước cạnh nhau |
.textarea-wrapper | Bao bọc xung quanh khu vực chỉnh sửa |
.editor-textarea | Phần tử vùng văn bản cơ bản |
.display-layer | Lớp định dạng được hiển thị, chỉ ở chế độ kết hợp |
.preview-wrapper | Cột xem trước |
.preview-content | Đánh dấu được hiển thị bên trong bản xem trước |
.editor-footer | Thanh trạng thái bên dưới trình chỉnh sửa |
.find-replace-panel | Bảng tìm kiếm và thay thế |
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); } |
Nhắm mục tiêu một biên tập viên
Với nhiều người chỉnh sửa trên một trang, hãy nhắm mục tiêu một trong số họ bằng data-editor. Trình bao bọc phản ánh id của nó <textarea>, Vì thế <textarea id="notes"> mang lại cho bạn [data-editor="notes"]. Bản thân id vẫn nằm trên vùng văn bản, vì vậy getElementById tiếp tục làm việc.
1 2 3 4 | /* one editor only */ [data-editor="notes"] { --border-radius: 0; } |
🪟 Toàn màn hình & Phân lớp (z-index)
Ở chế độ toàn màn hình, trình soạn thảo sử dụng z-index: 10000, thao tác này sẽ xóa các lớp mà hầu hết các khung giao diện người dùng dành riêng cho các tiêu đề và lớp phủ cố định. Nếu tiêu đề hoặc thanh bên cố định vẫn bao phủ trình chỉnh sửa, hãy tăng giá trị này.
Ghi đè nó bằng --mte-fullscreen-z-index. Giá trị chỉ áp dụng ở chế độ toàn màn hình và nó kế thừa, do đó, việc đặt nó trên bất kỳ tổ tiên nào sẽ bao gồm mọi trình soạn thảo bên dưới nó.
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 nội dung
Một trong những điểm mạnh cốt lõi của MarkdownEditor là nó giữ được các yếu tố cơ bản <textarea> được đồng bộ hóa hoàn hảo. Cho dù bạn đang sử dụng khung JavaScript hiện đại hay chương trình phụ trợ truyền thống như Django, PHP hay Laravel, quy trình làm việc vẫn đơn giản và nguyên bản.
Đọc và viết nội dung
1. Cách bản địa (Được khuyến nghị)
Vì trình chỉnh sửa nâng cao vùng văn bản tiêu chuẩn nên bạn có thể sử dụng các phương thức DOM quen thuộc. Đây là cách nhanh nhất để tương tác với dữ liệu của bạn mà không cần tìm hiểu API mới.
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. Sử dụng tham chiếu biến
Nếu bạn có tham chiếu đến phần tử vùng văn bản, bạn có thể sử dụng trực tiếp: không cần API dành riêng cho thư viện.
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. Đặt phía máy chủ nội dung ban đầu
Cách được đề xuất để đặt nội dung ban đầu là trực tiếp trong <textarea> HTML: tính năng này hoạt động tự nhiên với mọi khung công tác phụ trợ (Django, Laravel, Rails, PHP, v.v.) và trình soạn thảo sẽ tự động hiển thị nó trên init.
1 2 | <!-- Recommended: set content server-side --> <textarea id="markdown-editor"># Hello World</textarea> |
Để đọc hoặc cập nhật nội dung trong thời gian chạy, hãy sử dụng kiểu gốc textarea giá trị. Gọi editor.render() sau khi cập nhật để làm mới lớp xem trước và lớp kết hợp.
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. Xé trình soạn thảo: destroy()
Gọi editor.destroy() để xóa trình bao bọc DOM của trình soạn thảo và khôi phục bản gốc <textarea> vào vị trí của nó trong tài liệu. Hữu ích trong các ứng dụng một trang khi ngắt kết nối một chế độ xem.
1 2 3 4 | const editor = new MarkdownEditor('#markdown-editor'); // Remove the editor and restore the plain textarea editor.destroy(); |
Phản ứng với những thay đổi bằng onChange
Vượt qua một onChange gọi lại để được thông báo về mọi thay đổi nội dung. Nhận chuỗi đánh dấu hiện tại.
1 2 3 4 5 | const editor = new MarkdownEditor('#markdown-editor', { onChange(value) { console.log('Content changed:', value.length, 'characters'); } }); |
Tự động lưu bản nháp với localStorage
Sử dụng onChange để lưu bản nháp sau mỗi lần nhấn phím. Khôi phục nó bằng cách điền trước vùng văn bản trước khi khởi tạo trình chỉnh sửa.
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); }); |
Gửi biểu mẫu
Vì MarkdownEditor được xây dựng trực tiếp trên mã gốc <textarea>, nó tương thích với mọi khung công tác phụ trợ (Django, Laravel, PHP, Ruby on Rails, v.v.) ngay lập tức.
Đây là nơi triết lý "Bản địa là trên hết" tỏa sáng. Bạn không cần phải đồng bộ hóa dữ liệu theo cách thủ công trước khi gửi biểu mẫu. Trình duyệt xử lý trình chỉnh sửa chính xác như trường nhập tiêu chuẩn.
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> |
Ghi chú: Bắt buộc khởi tạo plugin MarkdownEditor
Chỉ cần sử dụng HTML tiêu chuẩn <form>. các name thuộc tính trên vùng văn bản là thuộc tính mà máy chủ của bạn sẽ sử dụng để xác định nội dung.
🚀 Tại sao nó là công cụ thay đổi cuộc chơi cho phần phụ trợ
Vì trình soạn thảo giữ nguyên bản gốc <textarea> hành vi, máy chủ của bạn xử lý dữ liệu dưới dạng chuỗi tiêu chuẩn. Không cần thêm logic nào: không preventDefault() và không có hướng dẫn sử dụng FormData sự thi công.
💡 Tại sao đây là "Tính năng sát thủ":
Hầu hết các trình soạn thảo (như Quill, Editor.js, simpleMDE, easyMDE) đều lưu dữ liệu ở dạng cấu trúc JSON phức tạp. Nếu nhà phát triển sử dụng những thứ đó, họ phải viết lại lược đồ cơ sở dữ liệu và logic kết xuất của họ.
Với MarkdownEditor, nhà phát triển có thể lấy một trang web cũ, thay thế một trang web đơn giản <textarea> bằng trình chỉnh sửa của bạn và phụ trợ thậm chí không biết nó đã thay đổi. Nó chỉ nhận được văn bản thô giống như mọi khi nhưng người dùng sẽ có được trải nghiệm tốt hơn gấp 10 lần.
| Khung/Ngôn ngữ | Cách truy cập nội dung Markdown |
|---|---|
| PHP | $_POST['content'] |
| Django | request.POST.get('content') |
| Node.js (Express) | req.body.content |
| Laravel | $request->input('content') |
| Ruby trên đường ray | params[:content] |
🖼️ Tải lên hình ảnh nâng cao
Xử lý nguyên bản tải lên hình ảnh: thay vì dựa vào các chuỗi Base64 chậm và tốn nhiều bộ nhớ, đây là một lợi thế đáng kể cho cả hiệu suất và SEO.
Dán và thả
Dán ảnh chụp màn hình hoặc kéo tệp hình ảnh vào trình chỉnh sửa và tải lên thông qua cùng điểm cuối với nút thanh công cụ. Một trình giữ chỗ xuất hiện ngay lập tức để trình chỉnh sửa không bao giờ bị đóng băng và được thay thế bằng đường dẫn thực sau khi quá trình tải lên hoàn tất. Nếu tải lên không thành công, trình giữ chỗ sẽ được thay thế bằng điểm đánh dấu hiển thị thay vì biến mất một cách im lặng.
Điều này cần uploadUrl được cấu hình bên dưới. Nếu không có nó, việc dán hình ảnh sẽ không có tác dụng gì và trình chỉnh sửa sẽ ghi lại cảnh báo giải thích nội dung cần thêm vì giải pháp thay thế sẽ là chuỗi Base64 trong cơ sở dữ liệu của bạn.
Một số tệp được tải lên cùng lúc, do đó hình ảnh sẽ xuất hiện theo thứ tự xuất hiện.
Tùy chọn cấu hình
Công cụ hình ảnh hỗ trợ fileInput cấu hình để xử lý tải lên máy chủ trực tiếp.
accept: Xác định một loạt các định dạng hình ảnh được phép (ví dụ: 'webp', 'avif')uploadUrl: Chỉ định điểm cuối phụ trợ nơiFileđối tượng sẽ được gửi quaPOSTparams: Đối tượng tùy chọn để gửi dữ liệu bổ sung (như mã thông báo CSRF, ID người dùng hoặc tên thư mục) cùng với tệp hình ảnh
Ví dụ sử dụng (Cấu hình đầy đủ)
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); |
📡 Tích hợp máy chủ
Yêu cầu
Biên tập viên gửi một POST yêu cầu như multipart/form-data. Theo mặc định, nó bao gồm:
image_file: Đối tượng tập tin thực tếimage_alt: Văn bản thay thế được người dùng nhập vào- ...cộng với mọi dữ liệu tùy chỉnh được xác định trong
paramssự vật
Phản hồi bắt buộc
Để xác nhận tải lên thành công và chèn hình ảnh vào trình chỉnh sửa, máy chủ của bạn phải trả về cấu trúc JSON sau:
1 2 3 4 | { "success": true, "image_path": "https://cdn.yourdomain.com/uploads/image.webp" } |
Lưu ý: Đảm bảo bạn sử dụng chìa khóa image_path cho URL của hình ảnh được tải lên.
Xác thực văn bản thay thế hình ảnh (altInput)
Để đảm bảo nội dung của bạn vẫn có thể truy cập được và thân thiện với SEO, MarkdownEditor thực thi xác thực văn bản thay thế theo mặc định.
- Hành vi mặc định: Nếu
altInputkhông được xác định, nó mặc định là{ required: true } - Thực thi khả năng truy cập: Người dùng sẽ bị ngăn chèn hình ảnh cho đến khi cung cấp mô tả thay thế
1. Mặc định (Không cần cấu hình)
1 2 3 4 | // Alt text is REQUIRED by default image: { fileInput: { uploadUrl: '/api/upload' } } |
2. Viết tắt (Tắt xác thực)
Nếu bạn muốn cho phép hình ảnh không có mô tả, chỉ cần đặt boolean thành false.
1 2 3 | image: { altInput: false // Users can now skip the alt text field } |
3. Dựa trên đối tượng (Rõ ràng)
1 2 3 4 5 | image: { altInput: { required: false // Disables alt text validation — users can skip the alt field } } |
Sử dụng hình ảnh tiêu chuẩn (Không fileInput)
Nếu như fileInput không được định cấu hình, trình soạn thảo sẽ mặc định sử dụng phương thức dựa trên URL đơn giản. Điều này lý tưởng nếu người dùng của bạn chủ yếu liên kết đến các máy chủ hình ảnh bên ngoài.
1 2 3 4 5 6 7 8 | const options = { toolbar: [ 'link', 'image', 'preview' ], } const editor = new MarkdownEditor('#markdown-editor', options); |
💡 Tại sao nên sử dụng thông số?
Trong các framework như Laravel hoặc Django, bạn không thể tải tệp lên mà không có mã thông báo CSRF. Bằng cách thêm _token đến params object, yêu cầu của bạn sẽ chuyển qua phần mềm trung gian bảo mật của chương trình phụ trợ một cách liền mạch, duy trì triết lý "Zero Logic" cho bộ điều khiển phía máy chủ của bạn.
⌨️ Phím tắt
Các hành động định dạng phổ biến có thể được kích hoạt trực tiếp từ bàn phím mà không cần chạm vào thanh công cụ. Mỗi phím tắt cũng được hiển thị trong chú giải công cụ của nút thanh công cụ tương ứng.
| Phím tắt | Hoạt động |
|---|---|
Ctrl + B / ⌘ B | Chuyển đổi Đậm |
Ctrl + I / ⌘ I | Chuyển đổi nghiêng |
Ctrl + K / ⌘ K | Chèn liên kết |
Ctrl + ` / ⌘ ` | Chuyển đổi nội tuyến Code |
Ctrl + Shift + S / ⌘ ⇧ S | Chuyển đổi |
Ctrl + 1 / ⌘ 1 | Tiêu đề 1 |
Ctrl + 2 / ⌘ 2 | Tiêu đề 2 |
Ctrl + 3 / ⌘ 3 | Tiêu đề 3 |
Ctrl + L / ⌘ L | Chuyển đổi danh sách dấu đầu dòng |
Ctrl + Z / ⌘ Z | Hoàn tác |
Ctrl + Shift + Z / ⌘ ⇧ Z | Làm lại |
Tab | Thụt lề các dòng đã chọn |
Shift + Tab | Nhô ra các dòng đã chọn |
Ctrl + F / ⌘ F | Mở bảng Tìm kiếm |
Ctrl + H / ⌘ H | Mở bảng Tìm & Thay thế |
Ctrl + Shift + F / ⌘ ⇧ F | Chuyển đổi xem trước toàn màn hình |
F11 | Chuyển đổi xem trước toàn màn hình |
Escape | Đóng Tìm bảng điều khiển/Thoát xem trước toàn màn hình |
🔍 Tìm & Thay thế
Bảng điều khiển tìm và thay thế tích hợp sẵn có sẵn bên trong trình chỉnh sửa: không cần tiện ích mở rộng trình duyệt hoặc công cụ riêng biệt.
- Nhấn
Ctrl + F(hoặc⌘ F) để mở bảng Tìm - Nhấn
Ctrl + H(hoặc⌘ H) để mở bảng Tìm & Thay thế - Tìm kiếm không phân biệt chữ hoa chữ thường và hiển thị bộ đếm trận đấu trực tiếp (ví dụ: 3 trên 12)
- Điều hướng các kết quả khớp bằng các nút ▲ / ▼ hoặc
Enter/Shift + Enter - Thay thế thay thế kết quả được đánh dấu hiện tại; Thay thế tất cả thay thế mọi lần xuất hiện cùng một lúc
- Nhấn
Escapeđể đóng bảng điều khiển và trả lại tiêu điểm cho trình chỉnh sửa
Bảng điều khiển nổi ở góc trên bên phải của khu vực nội dung trình soạn thảo và không làm gián đoạn quá trình viết.
🔗 Liên kết từ một URL được dán
Chọn một số văn bản, dán URL lên nó và bạn sẽ nhận được liên kết đánh dấu thay vì URL thay thế những gì bạn đã chọn.
1 2 | Read the docs <- select "the docs", paste https://example.com Read [the docs](https://example.com) <- what you get |
Quy tắc này được cố tình nghiêm ngặt: chỉ trần trụi http hoặc https URL không có khoảng trắng được xử lý theo cách này. Dán một câu có chứa URL hoặc dán mà không chọn gì sẽ hoạt động giống như dán thông thường.
Đặc trưng
🔌 Tích hợp biểu mẫu gốc
Hoạt động chính xác như một tiêu chuẩn <textarea>. Không có API phức tạp: chỉ cần sử dụng value hoặc name thuộc tính. Nó "chỉ hoạt động" với việc gửi biểu mẫu HTML tiêu chuẩn bằng PHP, Django hoặc Node.js.
🖼️ Tải lên hình ảnh nâng cao
Định cấu hình tải lên máy chủ gốc thông qua API. Tránh các chuỗi Base64 nặng để đảm bảo tải trang nhanh hơn và SEO vượt trội bằng cách lưu trữ hình ảnh trên CDN của riêng bạn.
🔀 Chế độ lai & trơn
Chuyển đổi giữa một Lai (WYSIWYG) kinh nghiệm chỉnh sửa hình ảnh hoặc Đánh dấu đơn giản chế độ cho cảm giác mã hóa truyền thống.
🚀 Hiệu suất cao
MỘT 53 KB được nén gói (được rút gọn 252 KB, bao gồm CSS) được tối ưu hóa cho "Nội dung nặng". Xử lý các tài liệu lớn và các tệp lớn mà không có bất kỳ độ trễ đầu vào hoặc giảm hiệu suất nào. Các bản cập nhật xem trước đã được gỡ bỏ, tính toán kiểu được lưu trong bộ nhớ đệm và xử lý bàn phím không xung đột: vì vậy Tab và Enter luôn thực hiện chính xác một việc.
🌍 Hỗ trợ RTL tích hợp
Hỗ trợ gốc cho các ngôn ngữ từ phải sang trái như tiếng Ả Rập, tiếng Urdu và tiếng Farsi. Hoàn hảo để xây dựng các ứng dụng có thể truy cập toàn cầu.
✨ Đánh dấu cú pháp
Nâng cao khả năng đọc với mã rõ ràng và định dạng đánh dấu.
🌙 Chủ đề thích ứng
Bao gồm hỗ trợ Chế độ tối tự động. Nó đồng bộ với cài đặt hệ thống của bạn hoặc Giao diện người dùng Frutjam thư viện để có trải nghiệm hình ảnh liền mạch.
📝 Chỉnh sửa thông minh
Tiếp tục danh sách tự động theo kiểu GitHub cho danh sách có thứ tự, danh sách không có thứ tự và danh sách kiểm tra: nhấn Enter và trình soạn thảo tiếp tục mô hình. Các hộp kiểm trong khung xem trước có thể nhấp vào được và đồng bộ hóa trở lại nguồn đánh dấu ngay lập tức.
📱 Hoàn toàn đáp ứng
Giao diện người dùng linh hoạt, ưu tiên thiết bị di động, thích ứng hoàn hảo với máy tính để bàn, máy tính bảng và điện thoại thông minh để chỉnh sửa khi đang di chuyển.
📦 Hỗ trợ toàn cầu
Tương thích với ESM, UMD, CommonJS và IIFE. Hoạt động tốt thông qua CDN (<script src>), npm hoặc bất kỳ gói nào (Vite, webpack, Rollup): không cần cấu hình bổ sung.
♿ Có thể truy cập theo mặc định
Hỗ trợ ARIA đầy đủ được tích hợp sẵn: mốc thanh công cụ, vùng xem trước được gắn nhãn, các nút thân thiện với trình đọc màn hình, aria-pressed trên nút chuyển đổi xem trước, disabled Và aria-disabled trên các công cụ không hoạt động và khôi phục tiêu điểm chính xác khi các chế độ đóng.
🛡️ Không có xung đột CSS
Các phong cách soạn thảo hoàn toàn nằm trong phạm vi .markdown-editor-wrapper. Tính năng kiểm tra trước toàn cầu của Tailwind bị loại trừ nên trình soạn thảo hoạt động an toàn cùng với Bootstrap, Tailwind hoặc bất kỳ khung nào khác mà không phá vỡ phong cách của chúng.
⌨️ Phím tắt
Ctrl+B, Ctrl+I, Ctrl+K, Ctrl+`, Ctrl+Shift+S: các thao tác định dạng phổ biến mà không cần chạm vào chuột. Mỗi phím tắt được hiển thị trong chú giải công cụ của nút thanh công cụ.
🔍 Tìm & Thay thế
Nhấn Ctrl+F để tìm hoặc Ctrl+H để mở tìm & thay thế. Tìm kiếm không phân biệt chữ hoa chữ thường với bộ đếm so khớp trực tiếp, điều hướng tiếp theo/trước, thay thế một lần và thay thế tất cả: mà không cần rời khỏi trình chỉnh sửa.
🔒 Xem trước an toàn XSS
Bản xem trước được hiển thị được làm sạch thông qua DOMThanh lọc trước khi được ghi vào DOM. Thẻ tập lệnh, trình xử lý sự kiện nội tuyến và URL độc hại trong đầu vào đánh dấu thủ công sẽ tự động bị loại bỏ: không cần cấu hình.
♥️ Xem trước theo thời gian thực
Xem phần đánh dấu của bạn được hiển thị ngay lập tức khi bạn nhập.
🔗 Tích hợp dễ dàng
Tích hợp liền mạch vào bất kỳ dự án web nào với thiết lập tối thiểu.
🛠️ Thanh công cụ có thể tùy chỉnh
Tự động định cấu hình và sắp xếp lại các tùy chọn thanh công cụ như in đậm, in nghiêng, v.v.
Ví dụ về cấu hình đầy đủ
Sử dụng ví dụ toàn diện này để khởi tạo MarkdownEditor với tất cả các tính năng chính, bao gồm thứ tự thanh công cụ tùy chỉnh và xử lý tải lên hình ảnh nâng cao.
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(); |
Tìm thấy điều này hữu ích?
Ngôi sao GitHub giúp các nhà phát triển khác khám phá trình soạn thảo. Nó là một phần của trái cây. Một ngôi sao ở đó cũng giúp ích.