FormidableLabs / prism-react-renderer

🖌️ Renders highlighted Prism output to React (+ theming & vendored Prism)
MIT License
1.88k stars 153 forks source link

Add types to languages #220

Closed andrecasal closed 9 months ago

andrecasal commented 1 year ago

Problem/suggestion

The documentation says that prism-react-renderer only supports a subset of the languages prism supports.

JavaScript is not part of that list. However, if you add it to the language prop, it will work.

It would be nice to add language types to improve the developer experience on this.

Context

I ran into this while building my CodeBlock component for the andrecasal/ui library.

import { Highlight } from 'prism-react-renderer'
import type { PrismTheme } from 'prism-react-renderer/dist/'

const cobalt2Theme: PrismTheme = {
    plain: {
        color: '#ffffff',
        backgroundColor: '#182E3F',
        fontWeight: '600',
    },
    styles: [
        // General purpose
        {
            types: ['keyword'],
            style: {
                color: '#F79028',
            },
        },
        {
            types: ['builtin'],
            style: {
                color: '#9DFE8D',
            },
        },
        {
            types: ['class-name'],
            style: {
                color: '#77FEB7',
            },
        },
        {
            types: ['function'],
            style: {
                color: '#FFBF2F',
            },
        },
        {
            types: ['boolean'],
            style: {
                color: '#FE5981',
            },
        },
        {
            types: ['number'],
            style: {
                color: '#FE5981',
            },
        },
        {
            types: ['string'],
            style: {
                color: '#9DFE8D',
            },
        },
        {
            types: ['char'],
            style: {
                color: '#9DFE8D',
            },
        },
        {
            types: ['symbol'], // For Smalltalk only
            style: {
                color: 'red',
            },
        },
        {
            types: ['regex'],
            style: {
                color: '#9DFE8D',
            },
        },
        {
            types: ['url'],
            style: {
                color: '#95FFFE',
            },
        },
        {
            types: ['operator'],
            style: {
                color: '#FE9327',
            },
        },
        {
            // The name of a variable. This token is intended to be used sparingly.
            // It's generally used on special variables (e.g. Less or Bash), not
            // general variables from imperative and procedural programming languages
            // (e.g. C, JavaScript, Python).
            types: ['variable'],
            style: {
                color: '#ffffff',
            },
        },
        {
            types: ['constant'],
            style: {
                color: '#ffffff',
            },
        },
        {
            types: ['property'],
            style: {
                color: '#9DFE8D',
            },
        },
        {
            types: ['punctuation'],
            style: {
                color: '#ffffff',
            },
        },
        {
            types: ['important'],
            style: {
                color: '#F79028',
            },
        },
        {
            types: ['comment'],
            style: {
                color: '#097DF9',
            },
        },
        // Markup languages
        {
            types: ['tag'],
            style: {
                color: '#95FFFE',
            },
        },
        {
            types: ['attr-name'],
            style: {
                color: '#FFBF2F',
            },
        },
        {
            types: ['attr-value'],
            style: {
                color: '#9DFE8D',
            },
        },
        {
            types: ['namespace'],
            style: {
                color: '#FFBF2F',
            },
        },
        {
            types: ['prolog'],
            style: {
                color: '#FFBF2F',
            },
        },
        {
            types: ['doctype'],
            style: {
                color: '#FFBF2F',
            },
        },
        {
            types: ['cdata'],
            style: {
                color: '#FFBF2F',
            },
        },
        {
            types: ['entity'],
            style: {
                color: '#FE5981',
            },
        },
        // Document-markup languages
        {
            types: ['bold'],
            style: {
                fontWeight: '900',
            },
        },
        {
            types: ['italic'],
            style: {
                fontStyle: 'italic',
            },
        },
        // Stylesheets
        {
            types: ['atrule'],
            style: {
                color: '#F79028',
            },
        },
        {
            types: ['selector'],
            style: {
                color: '#3AD900',
            },
        },
        // Diff (prism-react-renderer doesn't support this out-of-the-box)
        /* {
            types: ['inserted'],
            style: {
                color: '#FE5981',
            },
        },
        {
            types: ['deleted'],
            style: {
                color: '#9DFE8D',
            },
        }, */
        // Specific to prism-react-renderer
        /* {
            types: ['interpolation-punctuation'],
            style: {
                color: 'red',
            },
        },
        {
            types: ['template-punctuation'],
            style: {
                color: 'red',
            },
        }, */
    ],
}

type Language = 'jsx' | 'tsx' | 'swift' | 'kotlin' | 'objectivec' | 'js-extras' | 'reason' | 'rust' | 'graphql' | 'yaml' | 'go' | 'cpp' | 'markdown'

const CodeBlock = ({ code, language }: { code: string; language: Language }) => {
    return (
        <Highlight code={code} language={language} theme={cobalt2Theme}>
            {({ style, tokens, getLineProps, getTokenProps }) => (
                <pre className="font-code" style={style}>
                    {tokens.map((line, i) => (
                        <div key={i} {...getLineProps({ line })}>
                            <span>{i + 1}</span>
                            {line.map((token, key) => (
                                <span key={key} {...getTokenProps({ token })} />
                            ))}
                        </div>
                    ))}
                </pre>
            )}
        </Highlight>
    )
}

export { CodeBlock }
carbonrobot commented 9 months ago

The javascript language bundle is a dependency of the jsx language bundle. Since we use jsx, it will automatically pull in the javascript language as well.