4/8/2022 ∙ 4 minuty czytania

banner

Podświetlanie składni 💡

Posty są zdecydowanie bardziej czytelne od kiedy został do nich dodany plugin do Tailwind'a odpowiadający za typografie.

Jednak kod, który jest w tych postach wyświetlany mógłby wyglądać zdecydowanie lepiej. Programista, który czyta kod w swoim edytorze, jest przyzwyczajony do możliwości podświetlania składni. W dzisiejszym poście ten problem zostanie rozwiązany.

Jak Remix renderuje pliki w formacie Markdown?

Remix ma wbudowane wsparcie dla plików w formacie .md oraz .mdx. Jeżeli umieścimy je w odpowiedniej hierarchii w katalogu app/routes to Remix rozpozna je i przetworzy w taki sposób, żeby zostały wyświetlone w postaci HTML'a.

Remix używa do tego paczek remark oraz rehype. Parserów, które zostały zbudowane w oparciu o interfejs unified.

Czym jest Unified?

Jest to przede wszystkim biblioteka, która jest interfejsem służącym do procesowania tekstu używając drzewa składniowego (ang. syntax tree). Jest to potężna paczka, za pomocą której możemy zamieniać jedna forme tekstu na inna. Przykładowo możemy zamienic Markdown na HTML, co dzieje sie właśnie za kulisami Remix'a.

Czym jest Remark?

Odpowiada za procesowanie formatu Markdown. Remark ma system wtyczek, dzięki którym możemy dorzucić do markdown'a ekstra funkcjonalności. Przykładowo, możemy dorzucić wsparcie dla GFM (GitHub Flavored Markdown), albo zrozumienie składni, która pozwoli stworzyć rozwijana sekcje w postach, albo skompiluje markdown na dokument w formacie .docx, albo przekształci Markdown na HTML.

Czym jest Rehype?

Odpowiada za procesowanie formatu HTML. Podobnie jak Remark, Rehype również posiada rozbudowany system wtyczek, dzięki którym możemy dorzucić do HTMLa ekstra funkcjonalności, których potrzebujemy. Np możemy dorzucać atrybuty do wybranych elementów HTML takie jak class czy id. Możemy zamienic HTML na inny format np Markdown, albo React. Możemy dokonać odkażania (ang. sanitize) elementu HTML albo dorzucić do niego obsługę podświetlania składni kodu.

Podświetlanie składni

https://rehype-pretty-code.netlify.app/

Co dzieje się za kulisami Remixa?

Remix korzysta z gotowej paczki, która kompiluje kod markdown'a na HTML. W tym celu używam wyżej wymienionych paczek Remark oraz Rehype. Możemy sobie ten proces wyobrazić w następujący sposób:

markdown |> remark |> remark-rehype |> rehype |> html
  1. na wejściu unified jest tekst w formacie markdown
  2. markdown jest wzbogacany za pomocą wtyczek remarka
  3. remark kompiluje markdowna na HTML za pomocą remark-rehype
  4. rehype dorzuca do HTMLa ekstra funkcjonalności za pomocą wtyczek
  5. na wyjściu unified jest tekst w formacie HTML

Remix udostępnia bardzo prosty interfejs, który pozwala na dorzucenie do systemu kompilacji naszego artykułu napisanego w markdown'ie na kod w formacie HTML.

remix.config.js

module.exports = {
  // ...
  mdx: {
    rehypePlugins: [
      // pluginy transformujące HTML
    ],
    remarkPlugins: [
      // pluginy transformujące Markdown
    ],
  },
}

Jak upiększyć kod?

Przede wszystkim musimy wybrać odpowiedni moment w całym procesie przetwarzania naszego kodu z postaci Markdown na HTML.

Najbardziej odpowiednim, będzie moment, w którym juz wykonała sie kompilacja markdown'a na HTML. Kod ten należy po prostu wzbogacić o css'y oraz skrypty, dzięki którym możliwe będzie podświetlanie składni, wiec na pewno będziemy szukać wtyczki do rehype. Do tego należy wybrać odpowiednie narzędzie do podświetlania składni. Na tej stronie skorzystam z Shiki.

W tym celu skorzystam z wtyczki rehype-pretty-code.

npm install rehype-pretty-code shiki

Importujemy i konfigurujemy plugin do rehype:

const rehypePrettyCode = require('rehype-pretty-code')

const options = {
  theme: 'one-dark-pro',
}

module.exports = {
  // ...
  mdx: {
    rehypePlugins: [[rehypePrettyCode, options]],
    remarkPlugins: [],
  },
}

Każdorazowa zamiana w pliku remix.config.js wymaga restartu serwera deweloperskiego strony.

Dark / light mode

Jeżeli chcemy, żeby nasz kod byl jeszcze bardziej czytelny w zależności od wybranego schematu, to możemy skorzystać z rozbicia opcji theme dla rehype-pretty-code na dwie opcje:

const options = {
  theme: {
    dark: 'github-dark',
    light: 'github-light',
  },
}

Nie jest to jedyna modyfikacja, która należy wykonać, bo od tej pory nasz kod będzie posiadał duplikowane elementy HTML zawierające fragment kodu. Musimy w związku z tym w CSS ukryć element, którego nie używamy. W tym celu w pliku app/styles/code.css dodamy następujący fragment:

@media (prefers-color-scheme: dark) {
  pre code[data-theme='light'] {
    display: none;
  }
}

@media (prefers-color-scheme: light), (prefers-color-scheme: no-preference) {
  pre code[data-theme='dark'] {
    display: none;
  }
}

a następnie załadujemy do naszego szablonu posta (app/routes/blog.tsx):

import { Outlet } from '@remix-run/react'
import codeStyles from '~/styles/code.css'

export function links() {
  return [{ rel: 'stylesheet', href: codeStyles }]
}

const Blog = () => {
  return (
    <article className="prose dark:prose-invert lg:prose-xl mx-4 my-16 sm:mx-auto">
      <Outlet />
    </article>
  )
}

export default Blog

Od tej pory nasz kod jest zdecydowanie bardziej czytelny. Więcej w tym temacie można przeczytać na oficjalnej dokumentacji Remix'a w sekcji poświęconej renderowaniu MDX.

exit

Poniżej znajdziesz więcej postów, które mogą Cię zainteresować.