Przejdź do głównej treści

The Native-First, High-Performance Markdown Plugin for JavaScript

Markdown text editor plugin that transforms a native textarea into a full editing suite. WYSIWYG and plain Markdown modes, live preview, RTL support, dark mode. Works with Django, HTMX, Laravel, React, and any stack.

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').value tak jak normalnego wejścia.
  • Niezależny od backendu: działa z dowolnym backendem (Python, Node.js, PHP itp.), tak jak normalne pole formularza

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
  • Inteligentne renderowanie: pozbawione błędów aktualizacje podglądu, obliczenia stylu w pamięci podręcznej i bezkonfliktowa obsługa klawiatury między kontynuacją listy a wcięciem — dzięki czemu 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 h1h6, a, button itp.) jest wykluczona, więc edytor może działać obok Bootstrap, Tailwind lub dowolnego innego frameworka 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

Możesz go zainstalować za pomocą NPM, bezpośrednio zaimportować plik JavaScript lub użyć CDN do szybkiego wdrożenia.

Zainstaluj przez NPM

bash
npm install markdown-text-editor
LUB

Korzystanie z CDN

Alternatywnie możesz dołączyć następujące linki CDN do swojego kodu HTML

html
<script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script>

2. Struktura HTML

Po prostu umieść <textarea> w standardowym formularzu. Nie są wymagane żadne specjalne opakowania.

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

3. Zaimportuj JS i CSS oraz zainicjuj wtyczkę w swoim elemencie tekstowym

javascript
1
2
3
4
5
6
import MarkdownEditor from "markdown-text-editor";

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

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 'hybrid', aby uzyskać obsługę WYSIWYG lub 'plain', 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', 'snowberry', 'ciemny'). 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 placeholdera w JS, wtyczka automatycznie użyje atrybutu placeholder z 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
javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// Default — line, col, and chars visible
new MarkdownEditor('#editor');

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

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

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

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

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

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

5. 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.

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

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

2. 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.

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

// Retrieve content
const markdown = textarea.value;

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

3. Ustawianie i odczytywanie treści

Zalecany sposób ustawiania treści początkowej odbywa się bezpośrednio w kodzie <textarea> HTML — działa to naturalnie z każdym frameworkiem zaplecza (Django, Laravel, Rails, PHP itp.), a edytor renderuje ją automatycznie podczas init.

html
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ą.

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

// Read
const markdown = textarea.value;

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

4. 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.

javascript
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.

javascript
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.

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

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

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

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

4. Ł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.

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

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

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

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 obiekt File zostanie wysłany za pośrednictwem POST
  • params: 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)

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

📡 Szczegóły integracji serwera

1. Prośba

Edytor wysyła żądanie POST jako multipart/form-data. Domyślnie zawiera:

  • image_file: Rzeczywisty obiekt pliku
  • image_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:

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)
javascript
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.

javascript
1
2
3
image: {
  altInput: false // Users can now skip the alt text field
}
3. Oparte na obiektach (jawne)
javascript
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.

javascript
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 Markdown
  • hybrid: środowisko inspirowane WYSIWYG, które renderuje formatowanie (pogrubienie, kursywa, nagłówki) w czasie rzeczywistym podczas pisania, zachowując jednocześnie podstawową strukturę Markdown.
Realizacja:
javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Default initialization (Plain Mode)
new MarkdownEditor('#markdown-editor');

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

// Hybrid (Visual) Mode
new MarkdownEditor('#markdown-editor', {
    mode: 'hybrid'
});
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ędzia
pojawiają 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ę Przekreślenie
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)

  1. Opcja theme — jawne zastąpienie przekazane w obiekcie opcji
  2. data-theme w <textarea> — ustawiany bezpośrednio na elemencie
  3. motyw danych dowolnego przodka — 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)
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>
Opcja 2 — ustaw data-theme bezpośrednio w <textarea>
html
1
2
3
4
<textarea id="markdown-editor" data-theme="dark"></textarea>
<script>
  new MarkdownEditor('#markdown-editor');
</script>
Opcja 3 — wyraźna opcja theme (zastępuje wszystko)
javascript
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:

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

/* Or define a full custom theme */
[data-theme="brand"] .markdown-editor-wrapper,
.markdown-editor-wrapper[data-theme="brand"] {
    --color-base:       oklch(15% 0.01 250);
    --color-on-base:    oklch(95% 0 0);
    --color-primary:    oklch(65% 0.22 145);   /* green */
    --color-on-primary: oklch(10% 0 0);
    --color-accent:     oklch(75% 0.18 60);
    --color-neutral:    oklch(80% 0 0);
    --border-radius:    0.75rem;
}
javascript
new MarkdownEditor('#markdown-editor', { theme: 'brand' });
  • 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 — wystarczy użyć 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 panelu 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 na pasku narzędzi, oznaczony obszar podglądu, przyciski przyjazne dla czytnika ekranu, wciśnięte aria na przełączniku podglądu, wyłączone i aria-wyłączone w nieaktywnych narzędziach oraz prawidłowe przywracanie fokusu 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 operacje 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ć funkcję find & zastępować. 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.

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

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

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

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