diff options
| author | Armand Philippot <git@armandphilippot.com> | 2022-03-23 22:05:30 +0100 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2022-03-24 15:01:03 +0100 |
| commit | 9226671f49b507ce6f71e6e2c3621014f05f74e9 (patch) | |
| tree | 73a148d12ceebbf0d8a95b82353d3d84f6a7a76a | |
| parent | 4e7a96c5a831882463802cdd4f84fe1464969cb0 (diff) | |
refactor: load prism plugins without babel
| -rw-r--r-- | .babelrc | 52 | ||||
| -rw-r--r-- | src/components/MDX/CodeBlock/CodeBlock.tsx | 81 | ||||
| -rw-r--r-- | src/components/Settings/PrismThemeToggle/PrismThemeToggle.tsx | 2 | ||||
| m--------- | src/content | 0 | ||||
| -rw-r--r-- | src/pages/_app.tsx | 2 | ||||
| -rw-r--r-- | src/pages/article/[slug].tsx | 58 | ||||
| -rw-r--r-- | src/pages/projet/[slug].tsx | 1 | ||||
| -rw-r--r-- | src/styles/vendors/_prism.scss | 28 | ||||
| -rw-r--r-- | src/ts/types/prism.ts | 51 | ||||
| -rw-r--r-- | src/utils/helpers/prism.ts | 21 | ||||
| -rw-r--r-- | src/utils/providers/prism-theme.tsx (renamed from src/utils/providers/prism.tsx) | 8 |
11 files changed, 178 insertions, 126 deletions
diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 657e285..0000000 --- a/.babelrc +++ /dev/null @@ -1,52 +0,0 @@ -{ - "presets": ["next/babel"], - "plugins": [ - [ - "prismjs", - { - "languages": [ - "apacheconf", - "bash", - "css", - "diff", - "docker", - "editorconfig", - "ejs", - "git", - "html", - "ignore", - "ini", - "javascript", - "jsdoc", - "json", - "jsx", - "makefile", - "markup", - "php", - "phpdoc", - "regex", - "scss", - "shell-session", - "smarty", - "tcl", - "toml", - "tsx", - "twig", - "yaml" - ], - "plugins": [ - "command-line", - "copy-to-clipboard", - "diff-highlight", - "inline-color", - "line-highlight", - "line-numbers", - "match-braces", - "normalize-whitespace", - "show-language", - "toolbar" - ] - } - ] - ] -} 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> ); }; diff --git a/src/components/Settings/PrismThemeToggle/PrismThemeToggle.tsx b/src/components/Settings/PrismThemeToggle/PrismThemeToggle.tsx index 9707097..20ad267 100644 --- a/src/components/Settings/PrismThemeToggle/PrismThemeToggle.tsx +++ b/src/components/Settings/PrismThemeToggle/PrismThemeToggle.tsx @@ -1,7 +1,7 @@ import { Toggle } from '@components/FormElements'; import { MoonIcon, SunIcon } from '@components/Icons'; import Spinner from '@components/Spinner/Spinner'; -import { usePrismTheme } from '@utils/providers/prism'; +import { usePrismTheme } from '@utils/providers/prism-theme'; import { useEffect, useState } from 'react'; import { useIntl } from 'react-intl'; diff --git a/src/content b/src/content -Subproject b5aa522476547db4efa2d6c8e774ca0422ef654 +Subproject 52c97a48f39ef0de9a61d2cf120fae2c7079055 diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index e8c00de..84c2469 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,7 +1,7 @@ import { AppPropsWithLayout } from '@ts/types/app'; import { settings } from '@utils/config'; import { AckeeProvider } from '@utils/providers/ackee'; -import { PrismThemeProvider } from '@utils/providers/prism'; +import { PrismThemeProvider } from '@utils/providers/prism-theme'; import { ThemeProvider } from 'next-themes'; import { useRouter } from 'next/router'; import { IntlProvider } from 'react-intl'; diff --git a/src/pages/article/[slug].tsx b/src/pages/article/[slug].tsx index 41b84b6..27a6f7b 100644 --- a/src/pages/article/[slug].tsx +++ b/src/pages/article/[slug].tsx @@ -14,21 +14,20 @@ import { import styles from '@styles/pages/Page.module.scss'; import { NextPageWithLayout } from '@ts/types/app'; import { ArticleMeta, ArticleProps } from '@ts/types/articles'; +import { PrismDefaultPlugins, PrismPlugins } from '@ts/types/prism'; import { settings } from '@utils/config'; import { getFormattedPaths } from '@utils/helpers/format'; import { loadTranslation } from '@utils/helpers/i18n'; import { addPrismClasses } from '@utils/helpers/prism'; -import { usePrismTheme } from '@utils/providers/prism'; import { GetStaticPaths, GetStaticProps, GetStaticPropsContext } from 'next'; import Head from 'next/head'; import { useRouter } from 'next/router'; -import { highlightAll } from 'prismjs'; +import Script from 'next/script'; +import Prism from 'prismjs'; import { ParsedUrlQuery } from 'querystring'; -import { useEffect } from 'react'; +import { useCallback, useEffect, useMemo } from 'react'; import { useIntl } from 'react-intl'; import { Blog, BlogPosting, Graph, WebPage } from 'schema-dts'; -import '@utils/plugins/prism-color-scheme'; -import Script from 'next/script'; const SingleArticle: NextPageWithLayout<ArticleProps> = ({ comments, @@ -37,19 +36,48 @@ const SingleArticle: NextPageWithLayout<ArticleProps> = ({ const intl = useIntl(); const router = useRouter(); - useEffect(() => { - addPrismClasses(); - highlightAll(); - }); + 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`); - const { setCodeBlocks } = usePrismTheme(); + if (plugin === 'autoloader') + Prism.plugins.autoloader.languages_path = '/prism/'; + } + } catch (error) { + console.error('Article: an error occurred with Prism.'); + console.error(error); + } + } + }, + [] + ); + + const plugins: (PrismDefaultPlugins | PrismPlugins)[] = useMemo( + () => [ + 'autoloader', + 'toolbar', + 'show-language', + 'copy-to-clipboard', + 'color-scheme', + 'command-line', + 'line-numbers', + 'match-braces', + 'normalize-whitespace', + ], + [] + ); useEffect(() => { - const allPre: NodeListOf<HTMLPreElement> = document.querySelectorAll( - 'pre[data-prismjs-color-scheme-current]' - ); - setCodeBlocks(allPre); - }, [setCodeBlocks, router.asPath]); + loadPrismPlugins(plugins).then(() => { + addPrismClasses(); + Prism.highlightAll(); + }); + }, [plugins, loadPrismPlugins]); if (router.isFallback) return <Spinner />; diff --git a/src/pages/projet/[slug].tsx b/src/pages/projet/[slug].tsx index b9a8f39..1f09fed 100644 --- a/src/pages/projet/[slug].tsx +++ b/src/pages/projet/[slug].tsx @@ -41,6 +41,7 @@ const Project: NextPageWithLayout<ProjectProps> = ({ }; const components: NestedMDXComponents = { + CodeBlock: (props) => CodeBlock(props), Gallery: (props) => Gallery(props), Image: (props) => ResponsiveImage({ caption: props.caption, ...props }), Link: (props) => Link(props), diff --git a/src/styles/vendors/_prism.scss b/src/styles/vendors/_prism.scss index 2882835..7c05c9f 100644 --- a/src/styles/vendors/_prism.scss +++ b/src/styles/vendors/_prism.scss @@ -43,18 +43,6 @@ } .toolbar-item:nth-child(1) { - grid-column: 2; - grid-row: 1; - margin: 0 var(--spacing-2xs); - - @include mix.media("screen") { - @include mix.dimensions("2xs") { - order: 2; - } - } - } - - .toolbar-item:nth-child(2) { grid-column: 1; grid-row: 1 / 3; margin-right: auto; @@ -64,24 +52,18 @@ color: var(--color-primary-darker); font-size: var(--font-size-sm); font-weight: 600; + } - @include mix.media("screen") { - @include mix.dimensions("2xs") { - order: 1; - } - } + .toolbar-item:nth-child(2) { + grid-column: 2; + grid-row: 1; + margin: 0 var(--spacing-2xs); } .toolbar-item:nth-child(3) { grid-column: 2; grid-row: 2; margin: 0 var(--spacing-2xs); - - @include mix.media("screen") { - @include mix.dimensions("2xs") { - order: 3; - } - } } } diff --git a/src/ts/types/prism.ts b/src/ts/types/prism.ts new file mode 100644 index 0000000..663bc08 --- /dev/null +++ b/src/ts/types/prism.ts @@ -0,0 +1,51 @@ +export type PrismLanguages = + | 'apacheconf' + | 'bash' + | 'css' + | 'diff' + | 'docker' + | 'editorconfig' + | 'ejs' + | 'git' + | 'graphql' + | 'html' + | 'ignore' + | 'ini' + | 'javascript' + | 'jsdoc' + | 'json' + | 'jsx' + | 'makefile' + | 'markup' + | 'php' + | 'phpdoc' + | 'regex' + | 'scss' + | 'shell-session' + | 'smarty' + | 'tcl' + | 'toml' + | 'tsx' + | 'twig' + | 'yaml'; + +export type PrismDefaultPlugins = + | 'autoloader' + | 'color-scheme' + | 'copy-to-clipboard' + | 'match-braces' + | 'normalize-whitespace' + | 'show-language' + | 'toolbar'; + +export type PrismPlugins = + | 'command-line' + | 'diff-highlight' + | 'inline-color' + | 'line-highlight' + | 'line-numbers'; + +export type PrismProviderProps = { + language: PrismLanguages; + plugins: PrismPlugins[]; +}; diff --git a/src/utils/helpers/prism.ts b/src/utils/helpers/prism.ts index bc84c91..a5f5787 100644 --- a/src/utils/helpers/prism.ts +++ b/src/utils/helpers/prism.ts @@ -17,19 +17,18 @@ export const addPrismClasses = () => { const preTags = document.getElementsByTagName('pre'); Array.from(preTags).forEach((preTag) => { - if ( - isLanguageBlock(preTag.classList) && - !preTag.classList.contains('command-line') && - !preTag.classList.contains('language-diff') - ) { - preTag.classList.add('line-numbers', 'match-braces'); - } + if (!isLanguageBlock(preTag.classList)) return; + + preTag.classList.add('match-braces'); - if ( - preTag.classList.contains('command-line') && - preTag.classList.contains('filter-output') - ) { + if (preTag.classList.contains('filter-output')) { preTag.setAttribute('data-filter-output', '#output#'); } + + if (preTag.classList.contains('language-bash')) { + preTag.classList.add('command-line'); + } else if (!preTag.classList.contains('language-diff')) { + preTag.classList.add('line-numbers'); + } }); }; diff --git a/src/utils/providers/prism.tsx b/src/utils/providers/prism-theme.tsx index 7a4221d..2ed8454 100644 --- a/src/utils/providers/prism.tsx +++ b/src/utils/providers/prism-theme.tsx @@ -28,8 +28,12 @@ export type PrismThemeProviderProps = { export const PrismThemeContext = createContext<UsePrismThemeProps>({ themes: ['dark', 'light', 'system'], - setTheme: (_) => {}, - setCodeBlocks: (_) => {}, + setTheme: (_) => { + // This is intentional. + }, + setCodeBlocks: (_) => { + // This is intentional. + }, }); export const usePrismTheme = () => useContext(PrismThemeContext); |
