Pierwsza natywna wtyczka Markdown o wysokiej wydajności dla JavaScript
Ostatnia aktualizacja:
Wtyczka edytora tekstu Markdown, która przekształca natywny obszar tekstowy w pełny zestaw do edycji — nie wymaga synchronizacji. WYSIWYG i zwykłe tryby Markdown, podgląd na żywo, znajdź i zamień, obsługa RTL, tryb ciemny. Współpracuje z Django, Laravel, Rails, Node.js, PHP i dowolnym stosem.
Filozofia: „Najpierw rodzimy”
Większość redaktorów łamie standardowy przepływ pracy w sieci. MarkdownEditor to uwzględnia.
Ponieważ znajduje się on bezpośrednio nad <textarea>, nie musisz uczyć się nowego sposobu obsługi danych.
- Nie jest potrzebne wiązanie danych: od razu po wyjęciu z pudełka współpracuje z
<form method="POST"> - Dostęp standardowy: użyj
document.getElementById('editor').valuetak jak normalnego wejścia. - Niezależny od backendu: działa z dowolnym backendem (Python, Node.js, PHP itp.), tak jak normalne pole formularza
MarkdownEditor kontra EasyMDE / SimpleMDE
Większość edytorów przecen JavaScript — EasyMDE, SimpleMDE, edytory oparte na CodeMirror — Zastąp <textarea> elementem niestandardowym. Oznacza to przerwy w przesyłaniu formularza, .value nic nie zwraca i musisz napisać dodatkowy kod, aby ponownie odczytać zawartość. MarkdownEditor jest inny — ulepsza istniejący obszar tekstowy i nigdy go nie zastępuje.
| Feature | Edytor Markdown | EasyMDE / SimpleMDE |
|---|---|---|
| Zachowany natywny obszar tekstowy | ✅ | ❌ Wymieniony |
| Przesyłanie formularza działa bez zmian | ✅ | ❌ Wymaga dodatkowego JS |
Pobierz/ustaw wartość poprzez .value |
✅ | ❌ Potrzebny niestandardowy interfejs API |
| Tryb hybrydowy WYSIWYG | ✅ | ❌ |
| Wbudowane narzędzie Znajdź i zamień | ✅ | ❌ |
| RTL support | ✅ | ❌ |
| Kompatybilny z CSP (bez wbudowanego JS) | ✅ | ❌ |
| Zero konfliktów CSS | ✅ | ❌ |
| Tryb ciemny / motyw | ✅ | Limited |
| Rozmiar pakietu | ~116 KB | ~300KB+ |
Integracja frameworków
Ponieważ MarkdownEditor zachowuje natywny <textarea>, integruje się z każdym frameworkiem zaplecza bez dodatkowego kodu. Twój serwer otrzymuje treść przeceny dokładnie tak samo, jak z dowolnego standardowego pola formularza.
Django
Dodaj class do widżetu obszaru tekstowego i zainicjuj edytor — request.POST['content'] działa bez dodatkowych kroków.
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
Użyj f.text_area z klasą — $request->input('content') odbiera bezpośrednio przecenę.
1 2 | <textarea name="content" class="markdown-editor">{{ old('content') }}</textarea> <script>new MarkdownEditor('.markdown-editor');</script> |
Rubin na szynach
Współpracuje z form_with od razu po wyjęciu z pudełka — params[:content] zawiera przecenę. W przypadku Turbo Drive użyj turbo:load zamiast 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 otrzymuje przecenę po przesłaniu formularza — bez etapu synchronizacji, bez niestandardowej ekstrakcji.
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'] działa dokładnie tak samo jak każdy standardowy obszar tekstowy — wystarczy go dodać, a obsługa istniejącego formularza nie będzie wymagała żadnych zmian.
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> |
Kluczowe funkcje
🖼️ Zaawansowane przesyłanie obrazów (zoptymalizowane pod kątem SEO)
Nie przeciążaj swojej bazy danych ciężkimi ciągami Base64. Skonfiguruj nasze API, aby przesyłać obrazy bezpośrednio na serwer lub do segmentu S3. Edytor otrzymuje adres URL, dzięki czemu pliki Markdown są lekkie, a ranking SEO Twojej witryny wysoki.
🔀 Tryby hybrydowe i zwykłe
Daj swoim użytkownikom to, co najlepsze z obu światów. Przełączaj między trybem hybrydowym wizualnym (WYSIWYG), który ułatwia formatowanie, a trybem zwykłego znacznika, który pozwala na niezakłóconą, surową edycję składni.
🌍 Gotowy na cały świat z obsługą RTL
Pełna natywna obsługa języków pisanych od prawej do lewej (RTL). Idealny do projektów wymagających obsługi arabskiego, urdu lub farsi z automatycznym wyrównywaniem kierunku tekstu.
⚡ Wydajność na dużą skalę
- Lekki: niewielki rozmiar ~116 KB, który nie spowalnia ładowania strony
- Obsługa dużych dokumentów: zoptymalizowana pod kątem obsługi tysięcy linii tekstu bez opóźnień wprowadzania danych i zawieszania się przeglądarki
- Smart Rendering: Poprawione aktualizacje podglądu, obliczenia stylu w pamięci podręcznej i bezkonfliktowa obsługa klawiatury pomiędzy kontynuacją listy a wcięciami — więc Tab i Enter zawsze wykonują dokładnie jedną czynność
♿ Dostępne domyślnie
Pełna obsługa ARIA jest wbudowana i nie wymaga dodatkowej konfiguracji. Pasek narzędzi jest właściwym punktem orientacyjnym role="toolbar", panel podglądu ma etykietę role="region", wszystkie ikony SVG są ukryte przed czytnikami ekranu, przełącznik podglądu pokazuje jego stan włączenia/wyłączenia poprzez aria-pressed, a wyłączone przyciski paska narzędzi używają zarówno disabled, jak i aria-disabled, więc technologia wspomagająca nigdy nie jest wprowadzana w błąd. Modale po zamknięciu przywracają ostrość do przycisku wyzwalającego.
🛡️ Zero konfliktów CSS
Wszystkie style edytora są w pełni ograniczone do elementu .markdown-editor-wrapper. Globalna inspekcja wstępna Tailwinda (resetowanie elementów dla h1 – h6, a, button itp.) jest wykluczona, więc edytor może działać obok Bootstrap, Tailwind lub dowolnego innego frameworku CSS na tej samej stronie bez przerywania jednego stylu.
🔒 Podgląd bezpiecznego XSS
Wyrenderowany podgląd jest oczyszczany za pomocą DOMPurify przed zapisaniem w DOM. Tagi skryptów, wbudowane procedury obsługi zdarzeń i złośliwe adresy URL w spreparowanych danych wejściowych Markdown są usuwane automatycznie — nie jest wymagana żadna konfiguracja.
Wersja demonstracyjna edytora Markdown
Szybka realizacja
1. Instalacja
NPM (bundlery: Vite, webpack, Rollup itp.)
npm install markdown-text-editor |
1 2 | import MarkdownEditor from 'markdown-text-editor'; new MarkdownEditor('#markdown-editor'); |
CDN: moduł ES
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: globalny znacznik skryptu (IIFE)
Nie ma potrzeby importowania — MarkdownEditor jest automatycznie dostępny jako zmienna globalna.
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. Konfiguracja i inicjalizacja
Przekaż obiekt opcji, aby dostosować edytor. Wszystkie opcje są opcjonalne — pomiń którąkolwiek, aby użyć wartości domyślnej.
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'], }); |
Podoba Ci się Edytor Markdown?
Zajmuje to 2 sekundy i pomaga w rozwoju projektu. Jest częścią Frutjam, bezpłatnej biblioteki komponentów CSS Tailwind — gwiazdka też pomaga.
4. Konfiguracja i dostosowywanie
Możesz w pełni dostosować zachowanie i interfejs edytora, przekazując obiekt options. Jeśli pominiesz opcję, zostanie użyta wartość domyślna.
| Nieruchomość | Typ | Domyślny | Zamiar |
|---|---|---|---|
mode |
string |
'plain' |
Ustawia widok początkowy. Użyj hybrydy, aby uzyskać doświadczenie WYSIWYG lub zwykłej, aby uzyskać surową składnię. |
placeholder |
string |
'Write...' |
Tekst wyświetlany, gdy edytor jest pusty. |
toolbar |
array |
[...] |
Określa, które narzędzia pojawiają się i w jakiej kolejności. |
footer |
false | object |
wszystko widoczne | Steruje paskiem stanu widocznym pod edytorem. Ustaw wartość false, aby całkowicie ją ukryć, lub przekaż obiekt, aby przełączać poszczególne statystyki. |
theme |
string |
dziedziczny | Jawnie ustawia motyw edytora (jasny, ciemny, śnieżna, ciemna jagoda). Jeśli zostanie pominięty, edytor dziedziczy data-theme od najbliższego elementu nadrzędnego lub samego <textarea>. |
minHeight |
number |
200 |
Minimalna wysokość w pikselach, do której edytor się zmniejszy, gdy treść będzie krótka. W połączeniu z maxHeight ustawia zakres automatycznego wzrostu. |
maxHeight |
number |
500 |
Maksymalna wysokość w pikselach, do jakiej może urosnąć edytor w trybie innym niż pełnoekranowy. Gdy treść przekroczy tę wysokość, w edytorze pojawi się pasek przewijania. Edytor posiada również uchwyt przeciągania, dzięki czemu użytkownicy mogą ręcznie zmieniać jego rozmiar powyżej tego limitu. |
onChange |
function |
undefined |
Wywołanie zwrotne uruchamiane przy każdej zmianie treści — pisaniu, akcjach na pasku narzędzi, cofaniu/ponawianiu i kontynuacji listy. Odbiera bieżący ciąg przeceny jako jedyny argument. |
🛠 Dostosowywanie paska narzędzi
Pasek narzędzi jest modułowy. Modyfikując tablicę, możesz stworzyć minimalne środowisko lub w pełni funkcjonalny pakiet mocy.
Dostępne narzędzia
| Kategoria | Klucze narzędziowe |
|---|---|
| Typografia | heading, bold, italic, strikethrough, blockquote |
| Listy | ul (kula), ol (numerowane), checklist |
| Kod | code (wbudowane), codeblock (ogrodzony blok) |
| Wkładki | hr (reguła pozioma), table (szablon tabeli) |
| Głoska bezdźwięczna | link, image |
| Redagowanie | undo, redo, indent, outdent |
| Pogląd | preview |
💡 Wskazówki dotyczące wdrożenia:
- Zmiana kolejności: przyciski pojawiają się dokładnie w takiej kolejności, w jakiej zostały wymienione w tablicy
- Usuwanie: po prostu pomiń dowolny klucz (np.
image) z tablicy, aby całkowicie wyłączyć tę funkcję dla użytkownika - Natywna rezerwa: jeśli nie podasz
placeholderaw JS, wtyczka automatycznie użyje atrybutuplaceholderz Twojego<textarea>kodu HTML
📊 Stopka (pasek stanu)
Stopka znajduje się pod edytorem i pokazuje linię, kolumnę kursora, liczbę znaków dokumentu i opcjonalnie liczbę słów – wszystko aktualizowane w czasie rzeczywistym. Jest ona domyślnie widoczna i każdą statystykę można przełączać niezależnie.
| Klawisz | Typ | Domyślny | Opis |
|---|---|---|---|
line |
boolean |
true |
Pokaż bieżący numer linii. |
col |
boolean |
true |
Pokaż bieżący numer kolumny. |
chars |
boolean |
true |
Pokaż całkowitą liczbę znaków. |
words |
boolean |
false |
Pokaż całkowitą liczbę słów. Domyślnie wyłączone — ustaw na true, aby włączyć. |
Przykłady użycia
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. Pobieranie, ustawianie i przesyłanie treści
Jedną z głównych zalet MarkdownEditor jest to, że zapewnia doskonałą synchronizację podstawowego <textarea>. Niezależnie od tego, czy używasz nowoczesnego frameworku JavaScript, czy tradycyjnego backendu, takiego jak Django, PHP czy Laravel, przepływ pracy pozostaje prosty i natywny.
1. Sposób rodzimy (zalecany)
Ponieważ edytor rozszerza standardowy obszar tekstowy, możesz używać znanych metod DOM. To najszybszy sposób na interakcję z danymi bez konieczności poznawania nowego 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. Używanie odniesienia do zmiennej
Jeśli masz odwołanie do elementu Textarea, możesz go użyć bezpośrednio — nie jest potrzebny żaden interfejs API specyficzny dla biblioteki.
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. Ustawianie i odczytywanie treści
Zalecanym sposobem ustawienia treści początkowej jest bezpośrednio w kodzie HTML <textarea> — działa to naturalnie z każdym frameworkiem backendowym (Django, Laravel, Rails, PHP itp.), a edytor renderuje ją automatycznie podczas init.
1 2 | <!-- Recommended: set content server-side --> <textarea id="markdown-editor"># Hello World</textarea> |
Aby przeczytać lub zaktualizować treść w czasie wykonywania, użyj natywnej wartości textarea. Po aktualizacji wywołaj editor.render(), aby odświeżyć podgląd i warstwę hybrydową.
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. Zburzenie edytora — destroy()
Wywołaj funkcję editor.destroy(), aby usunąć opakowanie DOM edytora i przywrócić oryginalny <textarea> do jego pozycji w dokumencie. Przydatne w aplikacjach jednostronicowych podczas odmontowywania widoku.
1 2 3 4 | const editor = new MarkdownEditor('#markdown-editor'); // Remove the editor and restore the plain textarea editor.destroy(); |
Reagowanie na zmiany za pomocą onChange
Przekaż wywołanie zwrotne onChange, aby otrzymywać powiadomienia o każdej zmianie treści. Odbiera bieżący ciąg przeceny.
1 2 3 4 5 | const editor = new MarkdownEditor('#markdown-editor', { onChange(value) { console.log('Content changed:', value.length, 'characters'); } }); |
Wersja robocza jest automatycznie zapisywana w localStorage
Użyj onChange, aby zapisać wersję roboczą przy każdym naciśnięciu klawisza. Przywróć go, wypełniając obszar tekstowy przed inicjalizacją edytora.
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. Łatwe i automatyczne przesyłanie formularzy
Ponieważ MarkdownEditor jest zbudowany bezpośrednio na natywnym <textarea>, jest kompatybilny z każdym frameworkiem backendowym (Django, Laravel, PHP, Ruby on Rails itp.) od razu po wyjęciu z pudełka.
Tutaj błyszczy filozofia „Native-First”. Nie musisz ręcznie synchronizować danych przed przesłaniem formularza. Przeglądarka traktuje edytor dokładnie tak, jak standardowe pole wejściowe.
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> |
Uwaga: inicjalizacja wtyczki MarkdownEditor jest obowiązkowa
Po prostu użyj standardowego <formularz> HTML. Atrybut name w obszarze tekstowym jest tym, czego Twój serwer użyje do identyfikacji treści.
🚀 Dlaczego to zmienia zasady gry dla backendów
Ponieważ edytor zachowuje natywne zachowanie <textarea>, serwer obsługuje dane jako standardowy ciąg znaków. Nie jest wymagana żadna dodatkowa logika — nie ma preventDefault() ani ręcznej konstrukcji FormData.
💡 Dlaczego jest to „funkcja zabójcza”:
Większość edytorów (np. Quill, Editor.js, simpleMDE, easyMDE) zapisuje dane w złożonych strukturach JSON. Jeśli programista z nich korzysta, musi przepisać schemat bazy danych i logikę renderowania.
Dzięki MarkdownEditor programista może wykorzystać starą witrynę i zastąpić zwykły <textarea> Twoim edytorem, a backend nawet nie zauważy, że się to zmieniło. Po prostu otrzymuje ten sam surowy tekst, co zawsze, ale użytkownik otrzymuje 10 razy lepsze wrażenia.
| Ramy / język | Jak uzyskać dostęp do treści Markdown |
|---|---|
| PHP | $_POST['content'] |
| Django | request.POST.get('content') |
| Node.js (Express) | req.body.content |
| Laravel | $request->input('content') |
| Ruby on Rails | params[:content] |
Opcje konfiguracji
🖼️ Zaawansowane przesyłanie obrazów
Natywna obsługa przesyłania obrazów — zamiast polegania na wolnych, obciążających pamięć ciągach Base64 — to znacząca korzyść zarówno pod względem wydajności, jak i SEO.
Opcje konfiguracji
Narzędzie do tworzenia obrazów obsługuje konfigurację fileInput do obsługi bezpośredniego przesyłania na serwer.
accept: zdefiniuj tablicę dozwolonych formatów obrazów (np. „webp”, „avif”)uploadUrl: Określ punkt końcowy zaplecza, do którego obiektFilezostanie wysłany za pośrednictwemPOSTparams: opcjonalny obiekt do wysyłania dodatkowych danych (takich jak tokeny CSRF, identyfikatory użytkowników lub nazwy folderów) wraz z plikiem obrazu
Przykład użycia (pełna konfiguracja)
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); |
📡 Szczegóły integracji serwera
1. Prośba
Edytor wysyła żądanie POST jako multipart/form-data. Domyślnie zawiera:
image_file: Rzeczywisty obiekt plikuimage_alt: tekst alternatywny wprowadzony przez użytkownika- ...plus wszelkie niestandardowe dane zdefiniowane w obiekcie
params
2. Wymagana odpowiedź
Aby potwierdzić pomyślne przesłanie i wstawić obraz do edytora, Twój serwer musi zwrócić następującą strukturę JSON:
1 2 3 4 | { "success": true, "image_path": "https://cdn.yourdomain.com/uploads/image.webp" } |
Uwaga: upewnij się, że używasz klucza image_path jako adresu URL przesłanego obrazu.
Walidacja tekstu alternatywnego obrazu (altInput)
Aby mieć pewność, że Twoje treści pozostaną dostępne i przyjazne dla SEO, MarkdownEditor domyślnie wymusza sprawdzanie poprawności tekstu alternatywnego. Możesz skonfigurować to zachowanie, używając skrótu logicznego lub szczegółowego obiektu.
- Zachowanie domyślne: jeśli nie zdefiniowano
altInput, domyślnie jest to{ wymagane: true - Wymuś dostępność: użytkownicy nie będą mogli wstawić obrazu, dopóki nie zostanie podany opis alternatywny
Przykłady konfiguracji:
1. Domyślne (nie wymaga konfiguracji)
1 2 3 4 | // Alt text is REQUIRED by default image: { fileInput: { uploadUrl: '/api/upload' } } |
2. Skrót (wyłącz weryfikację)
Jeśli chcesz zezwolić na obrazy bez opisów, po prostu ustaw wartość logiczną na false.
1 2 3 | image: { altInput: false // Users can now skip the alt text field } |
3. Oparte na obiektach (jawne)
1 2 3 4 5 | image: { altInput: { required: false // Disables alt text validation — users can skip the alt field } } |
Standardowe użycie obrazu (brak fileInput):
Jeśli fileInput nie jest skonfigurowane, edytor domyślnie korzysta z prostego modalu opartego na adresie URL. Jest to idealne rozwiązanie, jeśli Twoi użytkownicy głównie łączą się z zewnętrznymi hostami obrazów.
1 2 3 4 5 6 7 8 | const options = { toolbar: [ 'link', 'image', 'preview' ], } const editor = new MarkdownEditor('#markdown-editor', options); |
💡 Po co używać parametrów?
W frameworkach takich jak Laravel czy Django nie można przesyłać plików bez tokena CSRF. Dodając _token do obiektu params, Twoje żądanie bezproblemowo przejdzie przez oprogramowanie pośredniczące bezpieczeństwa zaplecza, zachowując filozofię „Zero Logic” dla kontrolerów po stronie serwera.
🔀 Tryby edycji
MarkdownEditor oferuje dwa różne sposoby pisania i formatowania treści. Możesz przełączać się między tradycyjnym widokiem skupionym na składni lub nowoczesnym, opartym na wizualizacjach.
Konfiguracja
Tryb początkowy można zdefiniować za pomocą właściwości mode podczas inicjalizacji.
plain(Domyślne): czyste, wydajne środowisko Markdown, w którym widoczna jest składnia (taka jak**bold**lub# nagłówek). Idealny dla programistów i purystów Markdownhybrid: środowisko inspirowane WYSIWYG, które renderuje formatowanie (pogrubienie, kursywa, nagłówki) w czasie rzeczywistym podczas pisania, zachowując jednocześnie podstawową strukturę Markdown.
Realizacja:
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' }); |
Podgląd trybu hybrydowego i zwykłego:
Tryb hybrydowy
Formatowanie wizualne jest renderowane w czasie rzeczywistym podczas pisania.
Tryb zwykły (domyślny)
Koncentruje się na surowej składni Markdown, aby zapewnić lekkość.
| Konfig | Właściwość / narzędzie | Opis |
|---|---|---|
| Obiekt opcji | placeholder |
Ustawia tekst zastępczy dla obszaru tekstowego (opcjonalnie, ponieważ można również użyć standardowego atrybutu pola tekstowego HTML) |
mode: 'hybrid' |
Włącza funkcję inspirowaną WYSIWYG, która renderuje formatowanie (pogrubienie, kursywa, nagłówki) w czasie rzeczywistym podczas pisania | |
toolbar: Określa, które narzędziapojawiają się na pasku narzędzi i ich kolejność. |
heading |
Otwiera menu rozwijane umożliwiające wybranie poziomu nagłówka H1–H6 |
bold |
Włącza pogrubione formatowanie tekstu. | |
italic |
Umożliwia formatowanie tekstu kursywą. | |
strikethrough |
Umożliwia przekreślenie tekstu. | |
ol |
(Lista uporządkowana): Konwertuje tekst na format listy numerowanej. | |
ul |
(Lista nieuporządkowana): Konwertuje tekst na listę punktowaną. | |
checklist |
Dodaje pola wyboru do tekstu, dzięki czemu doskonale nadaje się do zadań, list rzeczy do zrobienia lub śledzenia stanu ukończenia. | |
blockquote |
Zaznacz cytowany lub podkreślony tekst. | |
code |
Zawija zaznaczony tekst pojedynczymi znacznikami dla kodu wbudowanego. Ponowne kliknięcie usuwa tylne znaczniki. | |
codeblock |
Zawija zaznaczony tekst w ogrodzonym bloku kodu z potrójnym znacznikiem. Ponowne kliknięcie usuwa ogrodzenia. | |
hr |
Wstawia linijkę poziomą --- w miejscu kursora, w osobnej linii. |
|
table |
Wstawia startowy szablon tabeli przecen 2x3 w pozycji kursora. | |
image |
Umożliwia wstawianie obrazów za pomocą składni przecen. | |
link |
Umożliwia dodawanie hiperłączy do tekstu. | |
undo |
Aby cofnąć ostatnie zmiany. | |
redo |
Aby ponownie zastosować ostatnio cofnięte zmiany. | |
indent |
Aby zwiększyć poziom wcięcia. | |
outdent |
Aby zmniejszyć poziom wcięcia. | |
preview |
Przełącza pełnoekranowy podgląd obok siebie. Pola wyboru w panelu podglądu można kliknąć i natychmiast zaktualizować źródło przeceny. Naciśnij Escape, aby wyjść z trybu pełnoekranowego. | |
| Zaawansowana funkcja przesyłania obrazów: Umożliwia konfigurowanie przesyłania obrazów na własny serwer i ustawianie ścieżki obrazu za pośrednictwem interfejsu API. Poprawia to wydajność i SEO. |
fileInput |
accept: tablica dozwolonych typów plików graficznych (np. 'webp', 'avif').uploadUrl: punkt końcowy zaplecza, do którego plik jest wysyłany za pośrednictwem POST.params: Opcjonalny obiekt dla dodatkowych danych (tokeny CSRF, identyfikatory użytkowników, nazwy folderów)
|
altInput |
required: false: Wyłącza sprawdzanie poprawności wprowadzania tekstu alternatywnego (wartość domyślna to true) |
⌨️ Skróty klawiaturowe
Typowe czynności formatowania można uruchomić bezpośrednio z klawiatury, bez dotykania paska narzędzi. Każdy skrót jest także pokazany w podpowiedzi odpowiedniego przycisku na pasku narzędzi.
| Skrót | Działanie |
|---|---|
Ctrl + B / ⌘ B |
Przełącz opcję Pogrubienie |
Ctrl + I / ⌘ I |
Przełącz opcję Kursywa |
Ctrl + K / ⌘ K |
Wstaw łącze |
Ctrl + ` / ⌘ ` |
Przełącz wbudowany Kod |
Ctrl + Shift + S / ⌘ ⇧ S |
Przełącz opcję |
Ctrl + Z / ⌘ Z |
Anulować |
Ctrl + Shift + Z / ⌘ ⇧ Z |
Przerobić |
Tab |
Wcięcie wybranych linii |
Shift + Tab |
Zmniejsz wybrane linie |
Ctrl + F / ⌘ F |
Otwórz panel Znajdź |
Ctrl + H / ⌘ H |
Otwórz panel Znajdź i zamień |
Escape |
Zamknij panel Znajdź / Wyjdź z podglądu pełnoekranowego |
🔍 Znajdź i amp; Zastępować
W edytorze dostępny jest wbudowany panel wyszukiwania i zamiany — nie jest potrzebne żadne rozszerzenie przeglądarki ani osobne narzędzie.
- Naciśnij
Ctrl + F(lub⌘ F), aby otworzyć panel Znajdź - Naciśnij
Ctrl + H(lub⌘ H), aby otworzyć Find & Wymień panel - Wyszukiwanie nie uwzględnia wielkości liter i wyświetla licznik meczów na żywo (np. 3 z 12)
- Nawiguj po dopasowaniach za pomocą przycisków ▲ / ▼ lub
Enter/Shift + Enter - Opcja Zamień zastępuje aktualnie podświetlone dopasowanie; Opcja Zamień wszystko zastępuje wszystkie wystąpienia na raz
- Naciśnij
Escape, aby zamknąć panel i powrócić do edytora
Panel unosi się w prawym górnym rogu obszaru zawartości edytora i nie zakłóca pisania.
🌙 Tematyka
MarkdownEditor automatycznie dziedziczy motyw z otaczającej strony — nie jest wymagana żadna konfiguracja. Edytor odczytuje data-theme od najbliższego przodka podczas inicjalizacji, dzięki czemu pozostaje zsynchronizowany z motywem Twojej witryny od razu po wyjęciu z pudełka.
Sposób rozwiązania tematu (kolejność priorytetów)
themeopcja — jawne nadpisanie przekazane w obiekcie opcjidata-themena<textarea>— ustawiane bezpośrednio na elemenciedata-themena dowolnym przodku — np.<html>,<body>lub opakowanie<div>
Dostępne motywy
'jasny' (domyślnie), 'ciemny', 'jasny', 'ciemny'
Opcja 1 — dziedzicz z <html> lub dowolnego przodka (konfiguracja zerowa)
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> |
Opcja 2 — ustaw data-theme bezpośrednio na <textarea>
1 2 3 4 | <textarea id="markdown-editor" data-theme="dark"></textarea> <script> new MarkdownEditor('#markdown-editor'); </script> |
Opcja 3 — jawna opcja theme (zastępuje wszystko)
1 2 3 | new MarkdownEditor('#markdown-editor', { theme: 'dark' }); |
🎨 Motyw niestandardowy za pomocą zmiennych CSS
Możesz w pełni dostosować wygląd edytora, zastępując jego zmienne CSS w elemencie .markdown-editor-wrapper lub dowolnym selektorze [data-theme]. Wszystkie kolory wykorzystują przestrzeń kolorów OKLCH, aby uzyskać spójne percepcyjnie rezultaty.
| Zmienny | Zamiar | Światło domyślne | Ciemny domyślny |
|---|---|---|---|
--color-base |
Tło redaktora | oklch(100% 0 0) |
oklch(10.9% 0 0) |
--color-on-base |
Podstawowy kolor tekstu | oklch(22% 0 0) |
oklch(98% 0 0) |
--color-primary |
Akcent podstawowy (aktywny pasek narzędzi, linki) | oklch(51.1% .262 277) |
oklch(66.4% .184 286) |
--color-on-primary |
Tekst na powierzchniach w kolorze podstawowym | oklch(96.2% .018 272) |
oklch(10% .01 270) |
--color-secondary |
Akcent wtórny | oklch(59.1% .293 323) |
oklch(65% .18 220) |
--color-accent |
Podświetl akcent (kod wbudowany, kursywa) | oklch(54.1% .281 293) |
oklch(75% .18 50) |
--color-neutral |
Powierzchnie neutralne (granice, przegrody) | oklch(15% 0 0) |
oklch(85% 0 0) |
--color-error |
Kolor stanu błędu | oklch(57.7% .245 27) |
oklch(60% .22 30) |
--border-radius |
Zaokrąglenie narożników ramki edytora | 0.25rem |
|
Przykład niestandardowego motywu
Zastąp dowolną zmienną w .markdown-editor-wrapper po zainicjowaniu edytora lub zdefiniuj niestandardowy blok [data-theme] w swoim arkuszu stylów:
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' }); |
- Podgląd w czasie rzeczywistym: zobacz, jak przeceny są renderowane natychmiast podczas pisania.
- Podświetlanie składni: zwiększona czytelność dzięki przejrzystemu kodowi i formatowaniu przecen.
- Łatwa integracja: bezproblemowo integruj się z dowolnym projektem internetowym przy minimalnej konfiguracji.
- Dostosowywany pasek narzędzi: dynamicznie konfiguruj i zmieniaj kolejność opcji paska narzędzi, takich jak pogrubienie, kursywa i inne.
Cechy
🔌 Integracja formularzy natywnych
Działa dokładnie tak jak standardowy <textarea>. Żadnych skomplikowanych interfejsów API — po prostu użyj atrybutu value lub name. To „po prostu działa” ze standardowymi formularzami HTML w PHP, Django lub Node.js.
🖼️ Zaawansowane przesyłanie obrazu
Skonfiguruj przesyłanie natywnego serwera za pośrednictwem interfejsu API. Unikaj ciężkich ciągów Base64, aby zapewnić szybsze ładowanie strony i lepsze SEO, hostując obrazy we własnej sieci CDN.
🔀 Tryby hybrydowe i zwykłe
Przełączaj się między trybem Hybrid (WYSIWYG) do edycji wizualnej lub trybem Plain Markdown, aby uzyskać tradycyjne wrażenia z kodowania.
🚀 Wysoka wydajność
Mały pakiet ~116 KB zoptymalizowany pod kątem „Ciężkich treści”. Obsługuje ogromne dokumenty i duże pliki bez opóźnień wejściowych i spadków wydajności.
🌍 Wbudowana obsługa RTL
Natywna obsługa języków pisanych od prawej do lewej, takich jak arabski, urdu i perski. Idealny do tworzenia aplikacji dostępnych na całym świecie.
🌙 Motywy adaptacyjne
Zawiera automatyczną obsługę trybu ciemnego. Synchronizuje się z ustawieniami systemu lub biblioteką Frutjam UI, zapewniając płynne wrażenia wizualne.
📝 Inteligentna edycja
Automatyczna kontynuacja listy w stylu GitHuba dla list uporządkowanych, list nieuporządkowanych i list kontrolnych — naciśnij Enter, a edytor będzie kontynuował wzorzec. Pola wyboru w okienku podglądu można kliknąć i natychmiast synchronizować ze źródłem przecen.
📱 W pełni responsywny
Płynny, dostosowany do urządzeń mobilnych interfejs użytkownika, który idealnie dopasowuje się do komputerów stacjonarnych, tabletów i smartfonów, umożliwiając edycję w dowolnym miejscu.
📦 Uniwersalne wsparcie
Kompatybilny z ESM, UMD, CommonJS i IIFE. Działa od razu po uruchomieniu za pośrednictwem CDN (<script src>), npm lub dowolnego programu pakującego (Vite, webpack, Rollup) — nie jest wymagana dodatkowa konfiguracja.
♿ Dostępne domyślnie
Wbudowana pełna obsługa ARIA — punkt orientacyjny paska narzędzi, oznaczony obszar podglądu, przyciski przyjazne dla czytnika ekranu, wciśnięty aria na przełączniku podglądu, wyłączony i aria-wyłączony na nieaktywnych narzędziach oraz prawidłowe przywracanie ostrości po zamknięciu modów.
🛡️ Zero konfliktów CSS
Style edytora są w pełni ograniczone do .markdown-editor-wrapper. Globalna inspekcja wstępna Tailwinda jest wykluczona, więc edytor może bezpiecznie współpracować z Bootstrapem, Tailwindem lub jakimkolwiek innym frameworkiem, nie naruszając ich stylu.
⌨️ Skróty klawiaturowe
Ctrl+B, Ctrl+I, Ctrl+K, Ctrl+`, Ctrl+Shift+S — typowe akcje formatowania bez dotykania myszy. Każdy skrót jest pokazany w etykiecie przycisku paska narzędzi.
🔍 Znajdź i amp; Zastępować
Naciśnij Ctrl+F, aby znaleźć lub Ctrl+H, aby otworzyć, znajdź & i zamień. Wyszukiwanie bez rozróżniania wielkości liter z licznikiem dopasowań na żywo, nawigacją następny/poprzedni, pojedynczym zastępowaniem i zastępowaniem wszystkich — bez opuszczania edytora.
Przykład pełnej konfiguracji
Użyj tego obszernego przykładu, aby zainicjować MarkdownEditor ze wszystkimi podstawowymi funkcjami, w tym niestandardową kolejnością pasków narzędzi i zaawansowaną obsługą przesyłania obrazów.
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(); |