From 9226671f49b507ce6f71e6e2c3621014f05f74e9 Mon Sep 17 00:00:00 2001
From: Armand Philippot <git@armandphilippot.com>
Date: Wed, 23 Mar 2022 22:05:30 +0100
Subject: refactor: load prism plugins without babel

---
 src/components/MDX/CodeBlock/CodeBlock.tsx | 81 ++++++++++++++++++++++--------
 1 file changed, 60 insertions(+), 21 deletions(-)

(limited to 'src/components/MDX/CodeBlock/CodeBlock.tsx')

diff --git a/src/components/MDX/CodeBlock/CodeBlock.tsx b/src/components/MDX/CodeBlock/CodeBlock.tsx
index 69f0124..c330063 100644
--- a/src/components/MDX/CodeBlock/CodeBlock.tsx
+++ b/src/components/MDX/CodeBlock/CodeBlock.tsx
@@ -1,28 +1,25 @@
+import {
+  PrismDefaultPlugins,
+  PrismLanguages,
+  PrismPlugins,
+} from '@ts/types/prism';
+import { usePrismTheme } from '@utils/providers/prism-theme';
 import { useRouter } from 'next/router';
 import Prism from 'prismjs';
-import { ReactChildren, useEffect } from 'react';
+import { useCallback, useEffect, useMemo } from 'react';
 import { useIntl } from 'react-intl';
-import '@utils/plugins/prism-color-scheme';
-import { usePrismTheme } from '@utils/providers/prism';
 
 const CodeBlock = ({
-  className,
-  children,
+  code,
+  language,
+  plugins,
 }: {
-  className: string;
-  children: ReactChildren;
+  code: string;
+  language: PrismLanguages;
+  plugins: PrismPlugins[];
 }) => {
-  const classNames = className.split('+');
-  const languageClass = classNames.find((name: string) =>
-    name.startsWith('language-')
-  );
   const intl = useIntl();
   const router = useRouter();
-
-  useEffect(() => {
-    Prism.highlightAll();
-  }, []);
-
   const { setCodeBlocks } = usePrismTheme();
 
   useEffect(() => {
@@ -32,6 +29,46 @@ const CodeBlock = ({
     setCodeBlocks(allPre);
   }, [setCodeBlocks, router.asPath]);
 
+  const defaultPlugins: PrismDefaultPlugins[] = useMemo(
+    () => [
+      'autoloader',
+      'toolbar',
+      'show-language',
+      'copy-to-clipboard',
+      'color-scheme',
+      'match-braces',
+      'normalize-whitespace',
+    ],
+    []
+  );
+
+  const loadPrismPlugins = useCallback(
+    async (prismPlugins: (PrismDefaultPlugins | PrismPlugins)[]) => {
+      for (const plugin of prismPlugins) {
+        try {
+          if (plugin === 'color-scheme') {
+            await import(`@utils/plugins/prism-${plugin}`);
+          } else {
+            await import(`prismjs/plugins/${plugin}/prism-${plugin}.min.js`);
+
+            if (plugin === 'autoloader')
+              Prism.plugins.autoloader.languages_path = '/prism/';
+          }
+        } catch (error) {
+          console.error('CodeBlock: an error occurred with Prism.');
+          console.error(error);
+        }
+      }
+    },
+    []
+  );
+
+  useEffect(() => {
+    loadPrismPlugins([...defaultPlugins, ...plugins]).then(() => {
+      Prism.highlightAll();
+    });
+  }, [loadPrismPlugins, defaultPlugins, plugins]);
+
   const copyText = intl.formatMessage({
     defaultMessage: 'Copy',
     description: 'Prism: copy button text (no clicked)',
@@ -58,18 +95,20 @@ const CodeBlock = ({
     id: 'Ua2g2p',
   });
 
+  const defaultPluginsClasses = 'match-braces';
+  const pluginsClasses = plugins.join(' ');
+
   return (
-    <div
+    <pre
+      className={`language-${language} ${defaultPluginsClasses} ${pluginsClasses}`}
       data-prismjs-copy={copyText}
       data-prismjs-copy-success={copiedText}
       data-prismjs-copy-error={errorText}
       data-prismjs-color-scheme-dark={darkTheme}
       data-prismjs-color-scheme-light={lightTheme}
     >
-      <pre className={classNames.join(' ')}>
-        <code className={languageClass}>{children}</code>
-      </pre>
-    </div>
+      <code className={`language-${language}`}>{code}</code>
+    </pre>
   );
 };
 
-- 
cgit v1.2.3

