Pojęcia

Czym jest Markdown i dlaczego to ma znaczenie?

Markdown to lekki język znaczników do formatowania zwykłego tekstu w taki sposób, by pozostawał czytelny sam w sobie i jednocześnie dawał się bezproblemowo przekonwertować na czysty HTML. Plik napisany w tym formacie wygląda jak zwykły tekst, w którym kilka znaków interpunkcyjnych wykonuje pracę, jaką w edytorze tekstu wykonują pogrubienie, kursywa czy nagłówki — bez tagów, bez paska narzędzi, bez zamkniętego formatu pliku — i właśnie dlatego trafił pod pliki README, generatory stron statycznych, komunikatory, dokumentację techniczną i aplikacje do notatek jednocześnie.

Czym jest Markdown, mówiąc wprost?

Sposobem zapisu sformatowanego tekstu przy użyciu wyłącznie znaków dostępnych na klawiaturze, dzięki czemu surowy plik pozostaje przyjemny w czytaniu jeszcze zanim cokolwiek przekonwertuje go na cokolwiek innego.

Stworzył go w 2004 roku John Gruber, który nad samą składnią pracował razem z Aaronem Swartzem, i wydał go jako skrypt w Perlu o nazwie Markdown.pl, zamieniający plik .text na HTML. Deklarowanym celem Grubera było, by dokument sformatowany w Markdown dało się "opublikować w takiej postaci, w jakiej jest, jako zwykły tekst, bez wrażenia, że został oznaczony tagami czy instrukcjami formatowania" — zdanie, które dwie dekady później wciąż opisuje całą filozofię projektową tego formatu.

Sama nazwa to drobny żart językowy: to przeciwieństwo "znaczenia" tekstu tagami w nawiasach kątowych (ang. markup), choć na wyjściu i tak produkuje się markup.

Jak wygląda właściwa składnia?

Niewielka, celowo krótka lista konwencji, z których większość odpowiada temu, co ludzie i tak robili w zwykłych e-mailach: linia zaczynająca się od # to nagłówek (więcej znaków # oznacza głębszy poziom, aż do ###### dla nagłówka szóstego stopnia), gwiazdki lub podkreślniki wokół słowa dodają wyróżnienie (**pogrubienie**, _kursywa_), linia zaczynająca się od -, * lub liczby z kropką staje się elementem listy, a > na początku linii tworzy cytat blokowy.

Linki zapisuje się jako [tekst](adres), obrazy to ta sama składnia z poprzedzającym !, a kod inline umieszcza się między pojedynczymi znakami cudzysłowu odwrotnego (backtick), przy czym trzy takie znaki otwierają i zamykają blok kodu wieloliniowego, opcjonalnie oznaczony nazwą języka do kolorowania składni.

Linia pozioma to trzy lub więcej myślników, gwiazdek lub podkreślników samych w linii. Dwie spacje na końcu linii wymuszają złamanie linii wewnątrz akapitu, co jest jedną z niewielu naprawdę nieintuicyjnych reguł tego formatu i częstym źródłem zdziwienia u osób czytających surową specyfikację po raz pierwszy.

Dlaczego akurat ten format stał się tak popularny?

Ponieważ plik, który piszesz, jest już niemal tym dokumentem, którego chciałeś, co eliminuje całą kategorię tarcia, której cięższe formaty nigdy nie rozwiązały.

Plik .doc czy .docx wymaga Worda albo czegoś, co przekonująco go udaje, żeby był użyteczny; surowy plik HTML jest czytelny, ale żmudny do ręcznego pisania i łatwo go popsuć. Plik Markdown to zwykły plik tekstowy .md, który otwiera się w dowolnym edytorze na dowolnym systemie operacyjnym, czyta się go wyraźnie bez renderowania, daje się czysto porównywać w systemie kontroli wersji, bo jest tekstem zorientowanym liniowo, i degraduje się łagodnie — dokument bez dostępnego renderera wciąż jest w pełni czytelny, tylko z widocznymi gwiazdkami i krzyżykami.

Ta kombinacja cech — czytelny dla człowieka, konwertowalny maszynowo, niezależny od konkretnego narzędzia — sprawiła, że stał się domyślnym wyborem wszędzie tam, gdzie dokument musi przetrwać bycie czytanym przez człowieka, parsowanym przez oprogramowanie i przechowywanym w repozytorium Git, czasem wszystkie trzy naraz.

Czy jest jeden Markdown, czy wiele różnych?

Wiele, a różnice mają większe znaczenie, niż wydaje się większości przypadkowych użytkowników.

Oryginalna specyfikacja Grubera z 2004 roku była celowo nieformalna — opis prozą plus implementacja referencyjna, z kilkoma naprawdę niejednoznacznymi przypadkami brzegowymi (zagnieżdżone wyróżnienia, leniwa kontynuacja list, co dokładnie liczy się jako blok kodu), które różne parsery rozstrzygały inaczej. Przez kolejną dekadę dziesiątki implementacji — Python-Markdown, Redcarpet, Marked, Showdown i wiele innych — wypełniały te luki nieco odmiennie, więc ten sam plik mógł wyrenderować się na trzy różne sposoby w zależności od tego, które narzędzie go otworzyło.

CommonMark, opublikowany w 2014 roku przez grupę obejmującą Jeffa Atwooda i Johna MacFarlane'a, to odpowiedź na tę fragmentację: formalna, jednoznaczna specyfikacja z towarzyszącym zestawem testów obejmującym ponad sześćset przypadków, zaprojektowana tak, by każdy zgodny parser produkował identyczny co do bajtu wynik dla tego samego wejścia. To dziś domyślna baza, na której buduje większość nowoczesnych narzędzi.

GitHub Flavored Markdown (GFM) to CommonMark plus własne rozszerzenia GitHuba — tabele, przekreślenie (~~tekst~~), automatyczne zamienianie gołych adresów URL w linki oraz listy zadań (- [ ] / - [x]) — i jest, biorąc pod uwagę samą objętość czytelnictwa w plikach README i opisach pull requestów, prawdopodobnie najczęściej czytanym wariantem Markdown na świecie. MultiMarkdown i Markdown Pandoca idą jeszcze dalej, dodając przypisy, cytowania, listy definicji i konwersję między formatami, celując w publikacje akademickie i techniczne.

Gdzie właściwie Markdown jest dziś używany?

Niemal wszędzie tam, gdzie ktoś pisze tekst o pewnej strukturze, który jednocześnie musi dać się czytać jako źródło: dokumentacja repozytoriów, generatory stron statycznych, oprogramowanie do notatek i zaskakująco duża liczba interfejsów czatu.

Każda większa platforma hostująca kod automatycznie renderuje plik README.md repozytorium, co samo w sobie uczyniło Markdown domyślnym językiem dokumentacji open source. Generatory stron statycznych — Jekyll, Hugo, Gatsby, Eleventy — biorą folder plików Markdown plus front matter w YAML i produkują z tego całą stronę internetową, a frameworki dokumentacyjne, takie jak MkDocs, Docusaurus czy GitBook, są zbudowane na tej samej idei do podręczników technicznych i referencji API.

Narzędzia do notatek i osobistego zarządzania wiedzą — Obsidian, format eksportu leżący pod Notion, Bear, Logseq i SumizAI — przechowują notatki jako zwykłe pliki .md właśnie po to, by cały zbiór notatek pozostawał czytelny i przenośny niezależnie od aplikacji, która go stworzyła. Slack, Discord i WhatsApp obsługują okrojony podzbiór do podstawowego formatowania wiadomości, a autorzy akademiccy używają Pandoca, by pisać w Markdown i kompilować to samo źródło do PDF-a, dokumentu Worda albo pliku LaTeX na potrzeby publikacji.

Jak plik Markdown właściwie staje się plikiem HTML?

Parser czyta zwykły tekst i buduje pośrednią strukturę drzewiastą — abstrakcyjne drzewo składniowe, AST — reprezentującą nagłówki, akapity, listy i formatowanie inline dokumentu jako zagnieżdżone węzły, a osobny renderer przechodzi po tym drzewie i na jego podstawie generuje HTML (albo inny format docelowy).

Ten dwuetapowy podział — najpierw parsowanie, potem renderowanie — sprawia, że ten sam, leżący u podstaw dokument może stać się stroną internetową przez jeden renderer, plikiem PDF przez Pandoca albo prezentacją slajdów przez zupełnie inne narzędzie, bez żadnej zmiany w samym pliku źródłowym. To także powód, dla którego parsery oparte na AST, takie jak remark (JavaScript), cmark (referencyjna implementacja CommonMark w C) czy Python-Markdown, obsługują wtyczki: rozszerzenie podłącza się do drzewa między parsowaniem a renderowaniem zamiast dopasowywać wzorce w surowym tekście, co jest znacznie mniej podatne na błędy.

Większość nowoczesnych parserów jest też celowo defensywna wobec niezaufanego wejścia — specyfikacja CommonMark zawiera na ten temat wyraźne wytyczne — bo "skonwertuj ten tekst na HTML i umieść go na stronie" to podręcznikowy wektor ataku typu cross-site scripting, jeśli surowe tagi <script> albo linki javascript: wewnątrz Markdown przechodzą dalej bez przetworzenia.

Jakie funkcje znają doświadczeni użytkownicy Markdown, a rzadko odkrywają początkujący?

Front matter w YAML to ta największa: blok metadanych klucz: wartość otoczony liniami --- na samej górze pliku, który generatory stron statycznych i aplikacje do notatek odczytują jako dane strukturalne — tytuł, datę, tagi, autora — bez konieczności, by kiedykolwiek pojawiły się w wyrenderowanym dokumencie. Dzięki temu folder zwykłych plików tekstowych zyskuje metadane warte całej bazy danych, bez żadnej bazy danych w środku.

Linki w stylu referencyjnym ([tekst][id] z faktycznym adresem URL zdefiniowanym raz, gdzie indziej w dokumencie) utrzymują długie dokumenty czytelnymi, wynosząc powtarzające się adresy poza bieżący tekst. Przypisy (tekst[^1] z definicją [^1]: treść przypisu gdziekolwiek w pliku) i listy definicji istnieją w większości rozszerzonych wariantów, ale nie w samym CommonMark, co jest częstym źródłem zamieszania typu "to działa na GitHubie, ale nie w moim generatorze stron statycznych".

Znaki ucieczki mają większe znaczenie, niż się wydaje: dosłowna gwiazdka czy podkreślnik wymagają ukośnika wstecznego (\*) właśnie dlatego, że te znaki są w przeciwnym razie znaczącą składnią, a znajomość tego zwykle odróżnia kogoś, kto używał Markdown okazjonalnie, od kogoś, kto debugował, dlaczego jego ścieżka pliku z podkreślnikami wyrenderowała się w połowie kursywą.

MDX to przypadek graniczny, warty znajomości: Markdown rozszerzony o możliwość osadzania komponentów JSX, używany przez frameworki dokumentacyjne potrzebujące interaktywnych przykładów wewnątrz poza tym statycznej prozy — prawdziwa hybryda języka znaczników i składni komponentów, i sygnał tego, jak daleko rozciągnięto ten format poza pierwotny, czysto tekstowy cel Grubera.

Jakie są realne ograniczenia Markdown i kiedy jest złym wyborem?

To format dokumentów dla prozy z lekką strukturą, a nie system układu graficznego ani format wymiany danych, i oba te nadużycia zdarzają się często.

Nie ma natywnego sposobu na wyrażenie układu dwukolumnowego, precyzyjnej typografii czy pozycjonowania co do piksela — od tego są HTML i CSS, a większość rendererów rzeczywiście dopuszcza surowy HTML inline właśnie jako furtkę na te rzadkie przypadki, które tego potrzebują. Dla danych strukturalnych — konfiguracji, ładunków API, wszystkiego, co program musi wiarygodnie sparsować — właściwym wyborem są YAML, JSON lub TOML; tabele Markdown istnieją, ale są pomyślane jako czytelne dla człowieka podsumowania, a nie format serializacji.

Opisana wcześniej fragmentacja na warianty ma realny, praktyczny koszt: dokument używający tabel czy przypisów z GFM po cichu wyrenderuje się jako zepsuta lub brakująca składnia w renderrze obsługującym wyłącznie surowy CommonMark, więc twierdzenia o przenośności ("to tylko zwykły tekst, działa wszędzie") są prawdziwe tylko w takim stopniu, w jakim pozwala na to najsłabsze narzędzie w całym łańcuchu.

A ponieważ renderowanie oznacza konwersję niezaufanego tekstu na HTML, każde narzędzie, które przyjmuje Markdown od użytkowników z zewnątrz i renderuje go bez sanityzacji, wystawia się na wstrzyknięte skrypty i linki — to realna, a nie teoretyczna powierzchnia ataku, i dlatego każda poważna biblioteka do Markdown dostarcza krok sanityzacji albo jawne reguły ucieczki dla surowego HTML.

Jak Markdown wypada na tle HTML, reStructuredText i AsciiDoc?

Każdy z nich rozwiązuje ten sam podstawowy problem — pisanie ustrukturyzowanych dokumentów jako zwykłego tekstu — z innym kompromisem między prostotą a mocą, i to właśnie różnice sprawiają, że żaden z nich w pełni nie zastąpił pozostałych.

HTML to sufit: potrafi wyrazić wszystko, co przeglądarka jest w stanie wyrenderować, ale ręczne pisanie go jest rozwlekłe i mało wybaczające — jeden niezamknięty tag potrafi zepsuć całą stronę, i nikt nie pisze akapitu w tagach <p></p>, jeśli ma wybór. Markdown celowo pokrywa mały, wspólny podzbiór tego samego wyjścia i przełącza się na surowy HTML dla wszystkiego, do czego nie ma własnej składni, dlatego oba te formaty opisuje się zwykle jako uzupełniające się, a nie konkurujące.

reStructuredText, powstały w społeczności dokumentacji Pythona, jest ściślejszy i znacznie bardziej rozbudowany od razu po wyjęciu z pudełka — ma natywną składnię dla tabel, przypisów, odniesień krzyżowych i dyrektyw dla dowolnych rozszerzeń — kosztem znacznie stromszej krzywej uczenia i dużo mniej wybaczającego parsera; niewyrównane wcięcie listy powoduje błąd budowania, a nie lekko dziwnie wyglądającą listę. AsciiDoc idzie o krok dalej w tym samym kierunku: ma pierwszorzędne wsparcie dla wieloczęściowych książek, adnotacji, warunkowych włączeń treści i odniesień międzydokumentowych, a narzędzia takie jak Asciidoctor używają go do pełnych książek technicznych i dokumentacji API, gdzie sam Markdown wymagałby ciężkiego, niestandardowego tooling'u, by sobie poradzić.

Praktyczna zasada, jaką kierują się profesjonaliści: sięgaj po Markdown, gdy odbiorcy równie często czytają surowe źródło, co wyrenderowany wynik; sięgaj po reStructuredText albo AsciiDoc, gdy dokument jest długi, głęboko ustrukturyzowany, a inwestycja w narzędzia się zwraca; sięgaj po surowy HTML tylko dla konkretnego fragmentu, który naprawdę tego potrzebuje.

Jak wygląda w praktyce poważny warsztat pracy z Markdown?

Edytor zwykłego tekstu z podglądem na żywo, linter i system kontroli wersji — dokładnie ten sam zestaw narzędzi co przy pisaniu kodu, co nie jest przypadkiem, biorąc pod uwagę, skąd wzięli się najintensywniejsi użytkownicy tego formatu.

Wbudowany podgląd Markdown w VS Code, edytor Typory z renderowaniem na żywo i tryb edycji Obsidiana to najczęstsze wybory; wszystkie trzy renderują formatowanie w trakcie pisania, nie ukrywając leżącego pod spodem zwykłego tekstu, co ma znaczenie, bo całym sensem tego formatu jest to, że źródło pozostaje czytelne. markdownlint i podobne narzędzia wyłapują błędy łatwe do popełnienia i trudne do zauważenia gołym okiem — niespójne poziomy nagłówków, końcowe białe znaki o niezamierzonym znaczeniu, zduplikowane definicje odnośników do linków — tę samą kategorię błędu, jaką linter kodu wyłapuje w języku programowania.

Ponieważ plik Markdown to zwykły tekst zorientowany liniowo, naturalnie współgra z Gitem: jednoliniowa edycja daje jednoliniowy diff, konflikty scalania są czytelne zamiast być nieprzejrzystym starciem binarnym, a git blame mówi dokładnie, kto zmienił które zdanie i kiedy. Duże zbiory dokumentacji idą jeszcze dalej i dodają krok w ciągłej integracji, który renderuje każdy plik Markdown przy każdym commicie właśnie po to, by wyłapać złamane linki wewnętrzne i wadliwą składnię, zanim trafią na żywą stronę — tę samą dyscyplinę stosowaną wobec prozy, jaka normalnie jest zarezerwowana dla kodu.

Jak SumizAI wykorzystuje Markdown dla notatek, które generuje?

Jako format przechowywania każdej pojedynczej notatki, z założenia i bez wyjątków: gdy odpowiedź AI jest warta zachowania, SumizAI zamienia ją w notatki ai — tytuł, podsumowanie, rozwinięcie i pełną oryginalną wymianę pytania i odpowiedzi — zapisane jako zwykły plik .md wewnątrz vaultu, który jest po prostu folderem na Twoim własnym dysku.

Ten wybór to bezpośrednia, praktyczna korzyść z wszystkiego, co opisano powyżej: notatki ai, które pisze SumizAI, otwierają się w Obsidianie, VS Code, generatorze stron statycznych czy dowolnym edytorze zwykłego tekstu bez żadnego kroku importu i bez zamkniętego formatu, z którego trzeba by uciekać, linki między notatkami to zwykłe linki Markdown [tekst](plik.md) do plików, które faktycznie istnieją, a spis treści vaultu sam jest wygenerowanym plikiem base.md, a nie rekordem w bazie danych ukrytym za aplikacją.

Baza danych, którą SumizAI utrzymuje, jest wyłącznie indeksem wyszukiwania; to notatki ai są źródłem prawdy, i gdyby aplikacja zniknęła jutro, to, co by zostało, to folder zwykłych plików Markdown — czytelnych, przenośnych i dokładnie tak użytecznych, jak zaprojektowano ten format w 2004 roku.

Siedem dni, bez karty, potem dolar miesięcznie

Wskaż SumizAI katalog, podłącz dostawcę AI, za którego już płacisz, i zacznij rozmowę. Pierwsza notatka odłoży się sama.