Oznaczanie języka przy prezentacji kodu na stronie

Prezentując na stronie różne fragmenty kodu, czy to w formie pokolorowanej czy surowej, często nie podaje się oznaczenia języka. W końcu z kontekstu i składni wynika co to jest, choć nie zawsze łatwo jest to wydedukować. W związku z tym wpadłem na pomysł, aby “label” z identyfikatorem języka pojawił się obok wyświetlanego kodu.

Na początku myślałem, że uda mi się zmusić jakoś Hugo/Chroma do dodawania takiej informacji do generowanej strony. Ale gdy takowej możliwości nie znalazłem słuszne wydawało się zastosowanie do tego celu JS-a. Nie będę przecież dodawał jakiś specjalnych shortcodes sobie do kontentu. W końcu to tylko “upiększacz” to niech po stronie klienta sobie to przeglądarka “renderuje”. A skoro to tylko ozdobnik do prezentacji to dodatkowe tagi w kodzie lub elementy w DOM strony też nie bedą dobrym pomysłem - semantyka, clean-content. Trzeba to zrobić inaczej, czyli w CSS-sie ;)

Wypluwany przez (koloro-)generatory (tutaj chroma) kod jest zazwyczaj odpowiednio otagowany:

<div class="highlight">
	<pre class="chroma">
		<code class="language-js" data-lang="js">
			[...]
		</code>
	</pre>
</div>

Mając w atrybutach informacje o języku zawartego w elemencie kodu, bez problemu za pomocą selektorów atrybutu i pseudoelementów CSS można stworzyć takie “labele” wyświetlające nazwę (identyfikator) języka dołączonego kodu.

pre code[class=language-js]::before {
	content: "js";
	/* stylowanie i pozycjonowanie */
}

Dodanie takowych styli do każdej używanej na stronie składni kodu może być trochę upierdliwe. Na szczęście, gdy jest dostępny atrybut z “czystą” zawartością nadającą się bezpośrednio do prezentacji można skorzystać z bardziej generycznego sposobu z użyciem attr():

pre code[data-lang]::before {
	content: attr(data-lang);
	/* stylowanie i pozycjonowanie */
}

Niekiedy jednak może się zdarzyć, że chcielibyśmy inaczej oznaczyć kod - innym identyfikatorem, pełną nazwą lub zunifikować używane w różnych miejscach identyfikatory lub skróty danego języka. Wtedy jednak trzeba dodać te poszczególne elementy “nadpisując” kaskadowo domyślną wartość otrzymywaną z attr().

pre code[data-lang]::before {
	content: attr(data-lang);
}

pre code[data-lang=js]::before,
pre code[data-lang=javascript]::before
{
	content: "JS";
}

pre code[data-lang=cpp]::before,
pre code[data-lang=c++]::before,
pre code[data-lang=cplusplus]::before
{
	content: "C++";
}

Mi to nie powinno grozić bo będę trzymał się jednego identyfikatora, a pomagać mi w tym będą jakieś skrypty weryfikujące spójność stylu i użytych elementów w moich Markdown-owych plikach z treściami. Sam nie wiem, czy lepsze będą proste i ogólne znane identyfikatory, czy może skrócone lub pełne nazwy, bądź mieszanka… ale na pewno, co ważne, będą one spójne we wszystkich miejscach!

Co do stylowania i pozycjonowania miejsca usytuowania etykiety, to rozważam dwie opcje - w środku elementu z kodem lub bezpośrednio nad nim (akurat trafi w marginesie) po prawej stronie. Podgląd obu wariantów na poniższym obrazku.

Podgląd obu wariantów usytuowania etykiety

Obie wersje bardzo łatwo otrzymać z pomocą szczypty CSS-a pozycjonując i ewentualnie według upodobania stylizując etykietę. Oczywiście w jakimś mniej rzucającym się kolorze, aby nie odciągać od głównej zawartości strony (kodu).

pre {
	--padding-x: 1em;
	--padding-y: .8em;
	padding: var(--padding-y) var(--padding-x);
	position: relative;
}

pre code::before {
	content: attr(data-lang);
	position: absolute;
	color: #ccc;

	/* inside pre/code element */
	top: var(--padding-y);
	right: var(--padding-x);

	/* above pre/code element */
	/* top: -1lh; line-height unit not supported yet */
	line-height: 1.3;
	top: calc(1.3 * -1em);
	right: 0.25em;
}

Tym sposobem, za pomocą kilku linijek prostego CSS-a, udało się nieco wzbogacić prezentacje kodu na stronie. Może to wydawać się banalne, ale idealnie pokazuje to, jak małym wysiłkiem można poprawić użyteczność strony. Oczywiście przedstawiony sposób jest minimalistyczny i może być dobrym punktem wyjścia do dalszej rozbudowy. Takim ulepszeniem może być chociażby rozwijanie skrótu/identyfikatora w etykiecie do pełnej nazwy języka po najechaniu myszką na kod… lub co tam sobie ktoś wymyśli ;)


Mimo, że powyższe fragmenty dotyczą stricte kodu generowanego przez Hugo, w końcu na niego przesiadam się z tym blogiem, to idea jest tak prosta, że można ją zaadoptować do każdej innej strony/generatora.

Obecnie na tej stronie (w czasie pisania tego wpisu) na WordPress-ie używany jest jakiś stary plugin - WP-CodeBox, bazujący na silniku GeSHi. Wynikowy kod HTML-a z pokolorowaną składnią przedstawia się następująco:

<div class="wp_codebox">
	<table>
	[...]
		<pre class="cpp" style="font-family:monospace;">
			[...]
		</pre>
	[...]
	</table>
</div>

Trochę “napaćkane” dodatkowymi elementami, ale docelowy <pre/> zawiera klasę z nazwą wyświetlanego języka. Zatem wszystko jest podobne, a różni się jedynie selektorami i nazwami elementów/atrybutów.

Dodanie do aktualnych styli na stronie poniższego fragmentu robi swoja robotę!

.wp_codebox pre {
	position: relative;
}

.wp_codebox pre::before {
	content: attr(class);
	position: absolute;
	top: 0;
	right: 0;
	color: #aaa;
}

I w takim stanie też pozostanie do końca swojego żywota - przejścia na Hugo ;)

/2020-07-08 22:40:22 +02:00/

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *