Galerie w Hugo

Prosty spos├│b na wy┼Ťwietlenie obraz├│w w postaci ┼éadnych galerii bez niszczenia markdown na stronie opartej o Hugo.
Zawarto┼Ť─ç

Podczas migracji z WordPress do Hugo stan─ů┼éem przed nie lada wyzwaniem, je┼╝eli chodzi o galeri─Ö zdj─Ö─ç.

Ot├│┼╝ Hugo przetwarza pliki zapisane w markdown na statyczne strony HTML. W podstawowej konfiguracji ka┼╝de jedno zdj─Öcie wstawiane jest jako pe┼éno-wymiarowy obraz, kt├│ry nast─Öpnie mo┼╝e by─ç ogarni─Öty poprzez odpowiednie style CSS, aby wy┼Ťwietli─ç go tak jak b─Ödziemy chcieli.

A co jeżeli chcemy wstawić zdjęcia w postaci galerii? Na przykład jedno koło drugiego lub 3 na górze 2 na dole?


W internecie mo┼╝esz znale┼║─ç spor─ů liczb─Ö wpis├│w na temat jak u┼╝y─ç shortcodes w Hugo w celu osi─ůgni─Öcia zamierzonego efektu.

Wi─Ökszo┼Ť─ç z nich niestety opiera si─Ö na wprowadzeniu cz─Ö┼Ťci tych kod├│w do markdown, psuj─ůc je w ich domy┼Ťlnej formie.

I tak zamiast typowego markdown:

![Tekst alternatywny](images/obrazek.jpg)

Zach─Öcaj─ů oni do u┼╝ywania niniejszego odpowiednika:

{{< img src="images/obrazek.jpg" >}}

W moim przypadku totalnie sobie nie wyobra┼╝am przechodzenia raz jeszcze przez wszystkie wpisy na mojej stronie i zmienianie odno┼Ťnika ![]() na co┼Ť w stylu {{< img src="" >}}. Wystarczy, ┼╝e musia┼éem poprawi─ç wszystkie odno┼Ťniki raz, jak przenosi┼éem je z WordPressa podczas migracji do Hugo.

Zastosowanie rozwi─ůzania proponowanego przez praktycznie wszystkich powoduje utrat─Ö podstawowej uniwersalno┼Ťci u┼╝ywania markdown.

A co, gdy zamiast Hugo b─Ödziemy chcieli u┼╝ywa─ç w przysz┼éo┼Ťci co┼Ť innego? Po raz kolejny b─Ödziemy musieli przej┼Ť─ç przez wszystkie wpisy, zmieniaj─ůc wszystkie odno┼Ťniki do zdj─Ö─ç? Po to przechodzili┼Ťmy na markdown ab tego nie robi─ç. Nie dzi─Ökuj─Ö!

Postanowi┼éem przyjrze─ç si─Ö innemu zastosowaniu shortcodes kt├│ry nie psuje domy┼Ťlnego markdown w jego podstawowej formie, pozwalaj─ůcy jednocze┼Ťnie podejrze─ç go w formie preformatowanej (preview) w dowolnym edytorze obs┼éuguj─ůcym tego typu spos├│b formatowania tekstu (w moim przypadku iA Writer).


Shortcode z markdown #

Otóż Hugo obsługuje shortcodes wraz z markdown.

Shortcodes z markdown w mo┼╝na rozpozna─ç po tym, ┼╝e zaczyna si─Ö one od {{% a nie {{< .

W skr├│cie, zdj─Öcia, kt├│re chcemy umie┼Ťci─ç w postaci galerii, wystarczy otoczy─ç shortcodem z markdown, kt├│ry zrobi reszt─Ö za nas.

Shortcode o kt├│rym mowa w moim przypadku wygl─ůda nast─Öpuj─ůco (w pliku u┼╝ywaj─ůcym markdown - wpis.md).

{{% gallery 2x2 %}}

![Tekst alternatywny Obrazek 1](images/obrazek1.jpg)
![Tekst alternatywny Obrazek 2](images/obrazek2.jpg)

{{% /gallery %}}

M├│j shortcode sk┼éada si─Ö z nazwy (gallery) oraz parametru ÔÇô zmiennej (2x2), kt├│re wyt┼éumacz─Ö dalej.

Nazewnictwo jest dowolne.

Ca┼éo┼Ť─ç, aby dzia┼éa┼éa, zapisana jest w pliku gallery.html (r├│wnie┼╝ dowolne) w folderze layouts/shortcodes/ w motywie strony.

Plik gallery.html zawiera nast─Öpuj─ůcy kod:

<div class="gallery_{{ .Get 0 }}">
  {{ .Inner }}
</div>

Jak zapewne si─Ö domy┼Ťlacie, element {{% gallery 2x2 %}} w trakcie generowania strony zast─ůpiony jest przez <div class="gallery_{{ .Get 0 }}"> a ostatni {{% /gallery %} przez zamykaj─ůcy </div>.

Cz─Ö┼Ť─ç pomi─Ödzy {{ .Inner }} odpowiada za pobranie zawarto┼Ťci, kt├│ra wstawiona jest pomi─Ödzy oba elementy. Jako ┼╝e ten shortcode wykorzystuje markdown, elementy ![]() zostan─ů wygenerowane w postaci <img src="" alt=""> zgodnie z podstawow─ů zasad─ů.

Ca┼éo┼Ť─ç b─Ödzie wygl─ůda─ç mniej wi─Öcej tak:

<div class="gallery_{{ .Get 0 }}">
	<p><img src="images/obrazek1.jpg" alt="Tekst alternatywny Obrazek 1"></p>
	<p><img src="images/obrazek2.jpg" alt="Tekst alternatywny Obrazek 2"></p>
</div>

Nie wspomniałem jeszcze, czym jest {{ .Get 0 }} w tym kodzie.

Ot├│┼╝ {{ .Get 0 }} odpowiada za parametr w naszym shortcode, czyli w {{% gallery 2x2 %}} jest nim 2x2.

I tak ostatecznie b─Ödzie wygl─ůda┼éo to tak:

<div class="gallery_2x2">
	<p><img src="images/obrazek1.jpg" alt="Tekst alternatywny Obrazek 1"></p>
	<p><img src="images/obrazek2.jpg" alt="Tekst alternatywny Obrazek 2"></p>
</div>

My┼Ťl─Ö, ┼╝e ju┼╝ wiesz, do czego zmierzam.

Je┼╝eli nasze obrazy otoczone s─ů przez klas─Ö CSS gallery_2x2 wystarczy zdefiniowa─ç, co ta klasa b─Ödzie robi┼éa.

W moim (uproszczonym) przypadku wygl─ůda to nast─Öpuj─ůco:

div.gallery_2x2 p img {
  float: left;
  max-width: 50%;
}

Dzi─Öki czemu oba obrazki zostan─ů wy┼Ťwietlone w szeroko┼Ťci nie wi─Ökszej ni┼╝ 50% do zawarto┼Ťci okna, ka┼╝de obok siebie.

W domy┼Ťlnej formie, oba obrazy wy┼Ťwietlane b─Öd─ů, bazuj─ůc na pe┼énowymiarowym pliku, co nie jest dobre ze wzgl─Ödu na SEO oraz pr─Ödko┼Ťci ┼éadowania si─Ö strony, szczeg├│lnie na wolnych ┼é─ůczach. W tym calu nale┼╝y zastosowa─ç generowane dynamicznie obrazy o r├│┼╝nych rozdzielczo┼Ťciach z wykorzystaniem wbudowanej w Hugo opcji .Resize oraz standardowego loading="lazy" obs┼éugiwanego przez wszystkie obecne przegl─ůdarki. O tym, jak to osi─ůgn─ů─ç innym razem.

I takim sposobem mamy galeri─Ö w formacie 2x2.

A co w przypadku 3x3?

Moja galeria 3x3 wygl─ůda (prawie) nast─Öpuj─ůco:

div.gallery_3x3 p img {
  float: left;
  max-width: 33%;
}

Na swojej stronie czasami wrzucam zdj─Öcia, kt├│re s─ů zrzutami ekranu, zrobionymi w pozycji pionowej a ni┼╝eli poziomej ÔÇô horyzontalnej, w├│wczas u┼╝ywam nieco innych parametr├│w 2v2 i odpowiedniego stylu div.gallery_2v2 p img.

Całe nazewnictwo (jak już wspomniałem) jest dowolne, nie ma tutaj żadnego narzutu.

Nadal tam, gdzie b─Öd─Ö chcia┼é, aby poszczeg├│lne obrazy wy┼Ťwietla┼éy si─Ö w postaci galerii, b─Öd─Ö musia┼é wyedytowa─ç plik markdown dodaj─ůc {{% gallery 2x2 %}} i {{% /gallery %}} jednak┼╝e jest to znacznie rozs─ůdniejsze zastosowanie a ni┼╝eli niszczenie markdown i zast─Öpowanie go czym┼Ť mniej kompatybilnym ({{< img src="" >}}) z innymi statycznymi generatorami, kt├│re s─ů lub mog─Ö pojawi─ç si─Ö w przysz┼éo┼Ťci.


Kod nie działa! #

Niestety, powy┼╝sze rozwi─ůzanie nie dzia┼éa od tak.

Wstawianie kodu HTML podczas generowania strony z pliku markdown uwa┼╝ane jest za niebezpieczne, gdy┼╝ kto┼Ť mo┼╝e umie┼Ťci─ç w nim z┼éo┼Ťliwy kod, kt├│ry b─Ödzie wykonywany na danej stronie.

W zwi─ůzku z tym nasz <div class="gallery_2x2"> zostanie domy┼Ťlnie zmieniony na <!-- raw HTML omitted -->.

W pe┼éni ┼Ťwiadomi ryzyka dodajemy nast─Öpuj─ůc─ů opcj─Ö do naszego pliku konfiguracyjnego Hugo config.toml aby temu zapobiec.

[markup]
  [markup.goldmark]
    [markup.goldmark.renderer]
      unsafe = "true"

Efekt mo┼╝ecie oceni─ç w moim wpisie Recenzja podr├│bki opaski Pride 2020 do Apple Watch.

Powy┼╝sze rozwi─ůzanie nie wygeneruje nam inteligentnych galerii mozaikowych, do kt├│rych przyzwyczai┼é nas JetPack w Wordpress, ale od czego┼Ť trzeba zacz─ů─ç.

A bez u┼╝ycia float? #

Aktualizacja 03/04/2021

U┼╝ywanie float w CSS ma swoje plusy, ale r├│wnie┼╝ mo┼╝e powodowa─ç szereg niepo┼╝─ůdanych skutk├│w ubocznych. W zwi─ůzku z tym postanowi┼éem sprawdzi─ç, czy ten sam efekt otrzymam z u┼╝yciem opcji flex popularnej w tak zwanym flexbox.

Ot├│┼╝, m├│j CSS wygl─ůda┼é nast─Öpuj─ůco:

div.gallery_2x2 p img {
  float: left;
  max-width: 48%;
  padding: 0 1% 2% 1%;
}

div.gallery_2v2 p img {
  float: left;
  max-width: 48%;
  padding: 0 1% 2% 1%;
}

div.gallery_3x3 p img {
  float: left;
  max-width: 31%;
  padding: 0 1% 2% 1%;
}

Z wykorzystaniem flex przedstawi┼é si─Ö nast─Öpuj─ůco:

div.gallery_2x2,
div.gallery_2v2,
div.gallery_3x3 {
 display: flex;
 flex-wrap: wrap;
}

div.gallery_2x2 p {
  width: 48%;
}

div.gallery_2v2 p {
  width: 48%;
}

div.gallery_3x3 p {
  width: 31%;
}

Efekt ko┼äcowy praktycznie niezauwa┼╝alny bez u┼╝ycia float a jednocze┼Ťnie bardziej przejrzysty.

Aby jednak flexbox działał jak należy, pomiędzy zdjęciami w markdown musi być odstęp.

Dla przykładu poniższe nie działa

{{% gallery 2x2 %}}

![Tekst alternatywny Obrazek 1](images/obrazek1.jpg)
![Tekst alternatywny Obrazek 2](images/obrazek2.jpg)

{{% /gallery %}}

Natomiast to działa

{{% gallery 2x2 %}}

![Tekst alternatywny Obrazek 1](images/obrazek1.jpg)

![Tekst alternatywny Obrazek 2](images/obrazek2.jpg)

{{% /gallery %}}

Pozdrawiam.

Komentarze