Nie będę ukrywał – ten blog pełen jest dygresji. Na tyle ich tutaj dużo, iż choćby doczekały się swoich własnych stylów. Niemniej całe rozwiązanie było napisane na kolanie i mocno niedomagało. W końcu postanowiłem choć trochę je poprawić.
Stare dygresje
Przyjrzyjmy się najpierw, jak kiedyś wyglądały dygresje:
Od strony HTML-a był to jeden element, najczęściej p, z klasą .note:
<p class="note">Treść dygresji</p>
Mimo to dygresja zawsze wyświetlana była jako element w ramce, w którym nad treścią był nagłówek z napisem Dygresja. Tego nagłówka nie ma w kodzie, jest dodawany przy pomocy generowanej treści w CSS-ie:
I choć jest to interesująca sztuczka, to nastręcza zadziwiająco dużej liczby problemów:
Tego typu nagłówek może być pomijany przez czytniki ekranu. Można się spierać, iż pominięcie słowa Dygresja nie jest jakimś poważnym błędem. Ale z drugiej strony – nie ma za bardzo powodu, by je pomijać.
Taki nagłówek nie zostanie przetłumaczony przez usługi typu Google Translate:
Dzieje się tak dlatego, iż nie korzystają z tego samego formatu co osoby odwiedzające stronę ((HTML + CSS), a z Atoma. W nim z kolei nie ma stylów CSS, stąd informacja o dygresji jest tracona.
Zmiana nagłówka dla pojedynczej dygresji zaczyna być problematyczna. Musiałbym kombinować np. z funkcją attr(). Tylko jeżeli i tak musiałbym zmieniać swój HTML, dodając nowy atrybut, to równie dobrze mógłbym po prostu przenieść nagłówek do HTML-a.
No i… takiego nagłówka nie da się zaznaczyć myszą. Osobiście tego typu tekst mnie strasznie irytuje.
A oprócz nagłówka problemy sprawiały też same dygresje. Dokładniej: sposób, w jaki je wstawiałem do postów. Z racji tego, iż Markdown nie ma składni do dygresji (pomijając to GitHubowe dziwactwo), używałem bezpośrednio HTML-a. A to jest zadziwiająco złożony temat w Markdownie. Mówiąc prosto: Markdown wewnątrz HTML-a częściej nie działa niż działa. A ja chciałbym, żeby działał zawsze.
Teraz dygresje znajdują się w elemencie div.note (1), który dodatkowo ma rolę note. Dzięki temu czytniki ekranowe zostaną poinformowane o tym, iż ten element zawiera poboczną treść (wtrącenie). Z kolei atrybut [aria-labelledby] pozwala wskazać, iż dygresja jest opisana przez element z etykietą (2). Choć wizualnie etykieta ta przypomina nagłówek (jest większym fontem i na wyróżniającym się tle), to ostatecznie doszedłem do wniosku, iż HTML-owy nagłówek byłby tutaj wręcz szkodliwy. Wystarczy wyobrazić sobie artykuł, w którym jest sporo dygresji. Wówczas na stronie byłoby pełno nagłówków o treści Dygresja. Wprowadzałoby to jedynie chaos dla osób korzystających z czytników ekranu i nagłówków do nawigacji. Stąd zwykły akapit. Sama treść (3) dygresji z kolei jest wewnątrz elementu div.note__content (4). Dzięki temu mogę dodawać bez przeszkód style dla samej treści.
Wygląd w dużej mierze zostawiłem ten sam, pozbyłem się jedynie tego dziwnego wcięcia dygresji względem pozostałej treści. Teraz ma taką samą szerokość jak wszystko inne.
Lepszy… erm, backend?
Przy okazji postanowiłem też poprawić sposób wstawiania dygresji. Odszedłem od czystego HTML-a na rzecz tzw. shortcode (krótkiego kodu; krodu), a dokładniej jego parzystej odmiany. W moim przypadku nazwałem krod note:
{\% note %}Treść dygresji{\% endnote %}
Dygresja
W rzeczywistości znaki ucieczki (\) nie powinny się znajdować w krodzie. Niemniej to był jedyny sposób, by go pokazać w Eleventy (moim systemie blogowym).
Na początku importujemy funkcję htmlmin z biblioteki html-minifier-terser (1). Posłuży ona nam do przemielenia wygenerowanego kodu HTML do jednolinijkowej wersji. Dzięki temu sprawimy, iż parser Markdowna zostawi nasz kod HTML w spokoju i go przypadkiem nie zepsuje. Następnie tworzymy zmienną currentId (2). Będzie nam służyła do generowania unikatowych identyfikatorów dla etykiet dygresji. Następnie tworzymy funkcję createNoteShortCode() (3). Przyjmuje ona jako argument markdownIt, a więc parser Markdowna – ten sam, który jest używany do generowania postów na blogu. Dzięki temu będziemy mogli używać Markdowna w dygresjach. Z funkcji createNoteShortCode() zwracamy funkcję kroda (4). Jako argument, content, przyjmuje ona treść dygresji. Następnie tworzymy zawartość atrybutu [id] etykiety (5), po czym kod HTML dygresji (6). By poprawnie wyświetlić treść dygresji, używamy metody markdownIt.render(), która przetworzy treść z Markdowna do HTML-a. Na końcu minifikujemy wygenerowany HTML (7) i zwracamy go.
Teraz jeszcze trzeba dodać nasz krod do konfiguracji Eleventy w pliku eleventy.config.js: