diff options
| author | Armand Philippot <git@armandphilippot.com> | 2022-04-19 12:12:15 +0200 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2022-04-19 12:12:15 +0200 |
| commit | 362cf45bc520a68a1c1be20e1189ca2307577dde (patch) | |
| tree | d9a300e065001b9c95670cda8225fd55706d52a5 /src/utils | |
| parent | a4a406463d69f6901919d273e831dff22a838caf (diff) | |
chore: add a Code component
Diffstat (limited to 'src/utils')
| -rw-r--r-- | src/utils/hooks/use-prism-plugins.tsx | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/utils/hooks/use-prism-plugins.tsx b/src/utils/hooks/use-prism-plugins.tsx new file mode 100644 index 0000000..c4959ac --- /dev/null +++ b/src/utils/hooks/use-prism-plugins.tsx @@ -0,0 +1,115 @@ +import Prism from 'prismjs'; +import { useEffect, useMemo } from 'react'; +import { useIntl } from 'react-intl'; + +export type PrismPlugin = + | 'autoloader' + | 'color-scheme' + | 'command-line' + | 'copy-to-clipboard' + | 'diff-highlight' + | 'inline-color' + | 'line-highlight' + | 'line-numbers' + | 'match-braces' + | 'normalize-whitespace' + | 'show-language' + | 'toolbar'; + +/** + * Import and configure all given Prism plugins. + * + * @param {PrismPlugin[]} prismPlugins - The Prism plugins to activate. + */ +const loadPrismPlugins = async (prismPlugins: PrismPlugin[]) => { + 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( + 'usePrismPlugins: an error occurred while loading Prism plugins.' + ); + console.error(error); + } + } +}; + +/** + * Load both the given Prism plugins and the default plugins. + * + * @param {PrismPlugin[]} plugins - The Prism plugins to activate. + */ +const usePrismPlugins = (plugins: PrismPlugin[]) => { + const intl = useIntl(); + + const copyText = intl.formatMessage({ + defaultMessage: 'Copy', + description: 'usePrismPlugins: copy button text (not clicked)', + id: 'FIE/eC', + }); + const copiedText = intl.formatMessage({ + defaultMessage: 'Copied!', + description: 'usePrismPlugins: copy button text (clicked)', + id: 'MzLdEl', + }); + const errorText = intl.formatMessage({ + defaultMessage: 'Use Ctrl+c to copy', + description: 'usePrismPlugins: copy button error text', + id: '0XePFn', + }); + const darkTheme = intl.formatMessage({ + defaultMessage: 'Dark Theme 🌙', + description: 'usePrismPlugins: toggle dark theme button text', + id: 'jo9vr5', + }); + const lightTheme = intl.formatMessage({ + defaultMessage: 'Light Theme 🌞', + description: 'usePrismPlugins: toggle light theme button text', + id: '6EUEtH', + }); + + const attributes = { + '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, + }; + + const defaultPlugins: PrismPlugin[] = useMemo( + () => [ + 'toolbar', + 'autoloader', + 'show-language', + 'copy-to-clipboard', + 'color-scheme', + 'match-braces', + 'normalize-whitespace', + ], + [] + ); + + useEffect(() => { + loadPrismPlugins([...defaultPlugins, ...plugins]).then(() => { + Prism.highlightAll(); + }); + }, [defaultPlugins, plugins]); + + const defaultPluginsClasses = 'match-braces'; + const pluginsClasses = plugins.join(' '); + + return { + pluginsAttribute: attributes, + pluginsClassName: `${defaultPluginsClasses} ${pluginsClasses}`, + }; +}; + +export default usePrismPlugins; |
