prism-react-renderer

repository·master·Indexed 24 days ago

https://github.com/formidablelabs/prism-react-renderer

A lightweight syntax highlighting component for React and React Native. It uses Prism to tokenize code and provides a render-props API via the <Highlight /> component, giving developers full control over the rendering of highlighted code. It includes a set of built-in themes, the useTokenize hook for manual tokenization, and the normalizeTokens utility for processing Prism tokens.

Tokens
3.6K
Snippets
8
Records
21
Agent score
82%

What's inside prism-react-renderer

  1. How the Highlight children function works

    master

    The <Highlight /> component uses a render-props pattern. The function passed as children receives an object containing state and prop getters.

    State

    • tokens (Token[][]): A doubly nested array. The outer array represents lines, and the inner array contains Token objects. A Token has types (array of strings) and content (the text).
    • className (string): The CSS class to apply to the wrapping element (e.g., a <pre>).

    Prop Getters

    These functions return props that should be spread onto your elements to ensure correct styling and class names.

    • getLineProps({ line }): Returns props for a line element (typically a <div>). It includes a .token-line class and merges styles/classes.
    • getTokenProps({ token }): Returns props for a token element (typically a <span>). It includes a .token class and merges styles/classes.
  2. Set up local development

    master

    Local development requires Node 18.x and corepack enabled (corepack enable).

    Standard Workflow:

    1. Install dependencies: pnpm install
    2. Build the project: pnpm build
    3. Run tests: pnpm test

    Running the Demo:

    1. Build the project: pnpm build
    2. Start the demo: pnpm start:demo

    Hot Reloading (Watch Mode): To see changes reflected in the demo, run the build in watch mode in a separate terminal: pnpm build:watch

    $ pnpm install
    $ pnpm build
    $ pnpm test
    
    # To run demo
    $ pnpm build
    $ pnpm start:demo
    
    # In another terminal for hot reloading
    $ pnpm build:watch
  3. Migrate from v1.x to v2.x

    master

    If you are upgrading from version 1.x to 2.x, perform the following breaking changes:

    1. Update Module Imports Change the default import to a named import for Highlight and remove defaultProps usage.

    - import Highlight, { defaultProps } from "prism-react-renderer";
    + import { Highlight } from "prism-react-renderer"
    
    const Content = (
    -  <Highlight {...defaultProps} code={exampleCode} language="jsx">
    +  <Highlight code={exampleCode} language="jsx">

    2. Update Theme Imports Themes are now accessed via the themes property on the main export.

    - const theme = require('prism-react-renderer/themes/github')
    + const theme = require('prism-react-renderer').themes.github

    3. Handle Language Support By default, only a base set of languages is included. If you need custom languages, ensure window.Prism (or global.Prism) is available before importing them.

  4. Add custom language support

    master

    If a language is not bundled by default, you can add it by ensuring the Prism instance is attached to the global object and then dynamically importing the component from prismjs.

    Note: You may need to install prismjs first: npm install --save prismjs.

    import { Highlight, Prism } from "prism-react-renderer";
    
    (typeof global !== "undefined" ? global : window).Prism = Prism
    await import("prismjs/components/prism-applescript")
    /** or **/
    require("prismjs/components/prism-applescript")
  5. Apply built-in themes to `<Highlight />`

    master

    You can apply JSON-based themes (inspired by VSCode) to the <Highlight /> component using the theme prop. The library provides several built-in themes via the themes export.

    Theme Structure:

    export type PrismTheme = {
      plain: PrismThemeEntry
      styles: Array<{
        types: string[]
        style: PrismThemeEntry
        languages?: Language[]
      }>
    }
    • plain: Provides a base style object used for the style props in component getters.
    • styles: An array of definitions where types (token types) and languages (optional language limits) determine which style object is applied.
    import { Highlight, themes } from 'prism-react-renderer';
    
    <Highlight theme={themes.dracula} {/* ... */} />
  6. Basic usage of the Highlight component

    master

    Use the <Highlight /> component with a render-props pattern to render syntax-highlighted code. You must provide code and language props. You can use the themes object to apply built-in themes like themes.shadesOfPurple.

    import React from "react"
    import ReactDOM from "react-dom/client"
    import { Highlight, themes } from "prism-react-renderer"
    import styles from 'styles.module.css'
    
    const codeBlock = `
    const GroceryItem: React.FC<GroceryItemProps> = ({ item }) => {
      return (
        <div>
          <h2>{item.name}</h2>
          <p>Price: {item.price}</p>
          <p>Quantity: {item.quantity}</p>
        </div>
      );
    }
    `
    
    export const App = () => (
      <Highlight
        theme={themes.shadesOfPurple}
        code={codeBlock}
        language="tsx"
      >
        {({ className, style, tokens, getLineProps, getTokenProps }) => (
          <pre 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>
    )
    
    ReactDOM
      .createRoot(document.getElementById("root") as HTMLElement)
      .render(<App />)
  7. Use `normalizeTokens` to group Prism tokens

    master

    The normalizeTokens function takes an array of Prism's tokens and groups them by line, converting plain strings into tokens.

    Input: (tokens: (PrismToken | string)[]) => Token[][]

    Token Structure: A Token is an object representing a slice of tokenized content with three properties:

    • types: string[]: An array of types indicating purpose and styling.
    • content: string: The actual text content.
    • empty: boolean: A flag indicating if the token is empty.
  8. Use the Highlight component props

    master

    The <Highlight /> component accepts the following props:

    Required Props

    • code (string): The code string to be highlighted.
    • language (string): The language identifier (e.g., tsx, javascript).
    • children (function): A render function that receives the highlight state and prop getters.

    Optional Props

    • theme (PrismTheme): The theme to use for generating styles. Defaults to vsDark.
    • prism (prism): An instance of the Prismjs library. Use this if you want to use your own Prism setup instead of the bundled version.
  9. Use the `useTokenize` hook

    master

    The useTokenize hook is a React hook that tokenizes code using Prism. It returns an array of tokens that can be rendered using the built-in <Highlight /> component or a custom component. It uses normalizeTokens internally to convert tokens into a renderable shape.

    Options:

    • prism: PrismLib: The Prism library to use. You can use the vendored version included with prism-react-renderer or a custom configured version.
    • code: string: The code string to tokenize.
    • grammar?: PrismGrammar: An optional Prism grammar object. If omitted, tokens are just normalized. Grammars can be obtained from Prism.languages or by importing from prismjs/components/.
    • language: Language: The language to use for tokenization (must be supported by Prism).
    // Signature reference
    type TokenizeOptions = {
      prism: PrismLib
      code: string
      grammar?: PrismGrammar
      language: Language
    }
    
    // Returns
    (options: TokenizeOptions) => Token[][]
  10. Configure the Highlight component with RenderProps

    master

    The Highlight component uses a render prop pattern via the children property. The function provided to children receives a RenderProps object, which contains the processed tokens and helper functions to render lines and tokens with the correct styles and classes.

    Key properties in RenderProps:

    • tokens: A 2D array (Token[][]) representing lines and their constituent tokens.
    • getLineProps: A function that takes LineInputProps and returns LineOutputProps to apply styles to a line.
    • getTokenProps: A function that takes TokenInputProps and returns TokenOutputProps to apply styles to an individual token.
    • className: The base CSS class for the code block.
    • style: The base CSS style for the code block.