Arbeiten mit benutzerdefinierten MDX-Elementen und Kurzcodes

Avatar of Agney Menon
Agney Menon am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

MDX ist ein Killer-Feature für Dinge wie Blogs, Diavorträge und Dokumentationen für Komponenten. Es ermöglicht Ihnen, Markdown zu schreiben, ohne sich Gedanken über HTML-Elemente, deren Formatierung und Platzierung machen zu müssen, und gleichzeitig die Magie von benutzerdefinierten React-Komponenten einzubringen, wenn nötig.

Nutzen wir diese Magie und schauen wir uns an, wie wir MDX anpassen können, indem wir Markdown-Elemente durch unsere eigenen MDX-Komponenten ersetzen. Dabei führen wir das Konzept der „Kurzcodes“ bei der Verwendung dieser Komponenten ein.

Zur Information: Die Codeausschnitte hier basieren auf GatsbyJS und React, aber MDX kann auch mit anderen Frameworks geschrieben werden. Wenn Sie eine Einführung in MDX benötigen, beginnen Sie hier zuerst. Dieser Artikel erweitert den vorherigen um fortgeschrittenere Konzepte.

Einrichtung eines Layouts

Wir möchten unsere MDX-basierten Seiten fast immer in einem gemeinsamen Layout rendern. Auf diese Weise können sie mit anderen Komponenten auf unserer Website arrangiert werden. Wir können eine Standard-Layout-Komponente mit dem von uns verwendeten MDX-Plugin angeben. Zum Beispiel können wir ein Layout mit dem gatsby-plugin-mdx-Plugin wie folgt definieren:

{
  resolve: `gatsby-plugin-mdx`,
  options: {
    defaultLayouts: {
      default: path.resolve('./src/templates/blog-post.js'),
    },
    // ...other options
  }
}

Dies würde erfordern, dass die Datei src/templates/blog-post.js eine Komponente enthält, die die übergebene children-Prop rendert.

import { MDXRenderer } from 'gatsby-plugin-mdx';


function BlogPost({ children }) {
  return (
    <div>{children}</div>
  );
}


export default BlogPost;

Wenn wir programmatisch Seiten erstellen, müssten wir eine Komponente namens MDXRenderer verwenden, um dasselbe zu erreichen, wie in den Gatsby-Dokumenten angegeben.

Benutzerdefinierte Markdown-Elemente

MDX ist zwar ein Format, das uns das Schreiben von benutzerdefinierten HTML- und React-Komponenten ermöglicht, aber seine Stärke liegt im Rendern von Markdown mit benutzerdefinierten Inhalten. Was aber, wenn wir anpassen möchten, wie diese Markdown-Elemente auf dem Bildschirm gerendert werden?

Wir könnten sicherlich ein Remark-Plugin dafür schreiben, aber MDX bietet uns eine bessere und einfachere Lösung. Standardmäßig sind dies einige der Elemente, die von Markdown gerendert werden:

NameHTML-ElementMDX-Syntax
Absatz<p>
Überschrift 1<h1>#
Überschrift 2<h2>##
Überschrift 3<h3>###
Überschrift 4<h4>####
Überschrift 5<h5>#####
Überschrift 6<h6>######
Ungeordnete Liste<ul>-
Geordnete Liste<ol />1.
Bild<img />![alt](https://image-url)
Eine vollständige Liste der Komponenten finden Sie in den MDX Docs.

Um diese Standardeinstellungen durch unsere benutzerdefinierten React-Komponenten zu ersetzen, wird MDX mit einer Provider-Komponente namens  MDXProvider geliefert. Sie nutzt die React Context API, um neue benutzerdefinierte Komponenten einzufügen und sie mit den von MDX bereitgestellten Standardwerten zu verschmelzen.

import React from 'react';
import { MDXProvider } from "@mdx-js/react";
import Image from './image-component';


function Layout({ children }) {
  return (
    <MDXProvider
      components={{
        h1: (props) => <h1 {...props} className="text-xl font-light" />
        img: Image,
      }} 
    >
      {children}
    </MDXProvider>
  );
}


export default Layout;

In diesem Beispiel wird jede H1-Überschrift (#) in der MDX-Datei durch die benutzerdefinierte Implementierung ersetzt, die in der Prop der Provider-Komponente angegeben ist, während alle anderen Elemente weiterhin die Standardwerte verwenden. Mit anderen Worten, MDXProvider kann unser benutzerdefiniertes Markup für ein H1-Element übernehmen, es mit MDX-Standardwerten verschmelzen und dann das benutzerdefinierte Markup anwenden, wenn wir eine Überschrift 1 (#) in einer MDX-Datei schreiben.

MDX und benutzerdefinierte Komponenten

Das Anpassen von MDX-Elementen ist großartig, aber was, wenn wir *unsere eigenen* Komponenten einführen möchten?

---
title: Importing Components
---
import Playground from './Playground';


Here is a look at the `Playground` component that I have been building:


<Playground />

Wir können eine Komponente in eine MDX-Datei importieren und sie genauso verwenden wie jede React-Komponente. Und ja, obwohl dies für etwas wie eine Komponentendemo in einem Blogbeitrag gut funktioniert, was ist, wenn wir Playground auf allen Blogbeiträgen verwenden möchten? Es wäre mühsam, sie auf alle Seiten zu importieren. Stattdessen bietet uns MDX die Möglichkeit, Kurzcodes zu verwenden. So beschreibt die MDX-Dokumentation Kurzcodes:

[Ein Kurzcode] ermöglicht es Ihnen, Komponenten für alle Dokumente in Ihrer App oder Website verfügbar zu machen. Dies ist eine nützliche Funktion für häufig verwendete Komponenten wie YouTube-Embeds, Twitter-Karten oder alles andere, was häufig in Ihren Dokumenten verwendet wird.

Um Kurzcodes in einer MDX-Anwendung einzubinden, müssen wir uns wieder auf die MDXProvider-Komponente verlassen.

import React from 'react';
import { MDXProvider } from "@mdx-js/react";
import Playground from './playground-wrapper';


function Layout({ children }) {
  return (
    <MDXProvider
      components={{
        h1: (props) => <h1 {...props} className="text-xl font-light" />
        Playground,
      }} 
    >
      {children}
    </MDXProvider>
  );
}


export default Layout;

Sobald wir benutzerdefinierte Komponenten in das components-Objekt aufgenommen haben, können wir sie in MDX-Dateien verwenden, ohne sie zu importieren.

---
title: Demoing concepts
---


Here's the demo for the new concept:


<Playground />


> Look ma! No imports

Direkte Manipulation von Kindkomponenten

In React erhalten wir Top-Level-APIs, um Kinder mit React.Children zu manipulieren. Wir können diese verwenden, um neuen Props an Kindkomponenten zu übergeben, die deren Reihenfolge ändern oder deren Sichtbarkeit bestimmen. MDX bietet uns eine spezielle Wrapper-Komponente, um auf die von MDX übergebenen Kindkomponenten zuzugreifen.

Um einen Wrapper hinzuzufügen, können wir wie zuvor die MDXProvider verwenden.

import React from "react";
import { MDXProvider } from "@mdx-js/react";
const components = {
  wrapper: ({ children, ...props }) => {
    const reversedChildren = React.Children.toArray(children).reverse();
    return <>{reversedChildren}</>;
  },
};
export default (props) => (
  <MDXProvider components={components}>
    <main {...props} />
  </MDXProvider>
);

Dieses Beispiel kehrt die Reihenfolge der Kinder um, sodass sie in umgekehrter Reihenfolge erscheinen, in der wir sie geschrieben haben.

Wir können sogar wild werden und alle MDX-Kinder animieren, wenn sie eintreffen.

import React from "react";
import { MDXProvider } from "@mdx-js/react";
import { useTrail, animated, config } from "react-spring";


const components = {
  wrapper: ({ children, ...props }) => {
    const childrenArray = React.Children.toArray(children);
    const trail = useTrail(childrenArray.length, {
      xy: [0, 0],
      opacity: 1,
      from: { xy: [30, 50], opacity: 0 },
      config: config.gentle,
      delay: 200,
    });
    return (
      <section>
        {trail.map(({ y, opacity }, index) => (
          <animated.div
            key={index}
            style={{
              opacity,
              transform: xy.interpolate((x, y) => `translate3d(${x}px,${y}px,0)`),
            }}
          >
            {childrenArray[index]}
          </animated.div>
        ))}
      </section>
    );
  },
};


export default (props) => (
  <MDXProvider components={components}>
    <main {...props} />
  </MDXProvider>
);

Zusammenfassung

MDX ist von Natur aus flexibel, aber die Erweiterung mit einem Plugin kann noch mehr ermöglichen. Hier ist, was wir dank gatsby-plugin-mdx in kurzer Zeit tun konnten:

  1. Erstellen Sie Standard-Layout-Komponenten, die die Formatierung der MDX-Ausgabe unterstützen.
  2. Ersetzen Sie standardmäßige HTML-Elemente, die aus Markdown gerendert werden, durch benutzerdefinierte Komponenten.
  3. Verwenden Sie Kurzcodes, um den Import von Komponenten in jeder Datei zu vermeiden.
  4. Manipulieren Sie Kinder direkt, um die MDX-Ausgabe zu ändern.

Auch dies ist nur ein Tropfen auf den heißen Stein, was MDX angeht, um das Schreiben von Inhalten für statische Websites zu erleichtern.

Mehr über MDX