Code Monkey home page Code Monkey logo

prism-react-renderer's Introduction

Prism React Renderer

A lean Prism highlighter component for React

Maintenance Status

Comes with everything to render Prismjs syntax highlighted code directly in React & React Native!

Introduction

Prism React Renderer powers syntax highlighting in the amazing Docusaurus framework and many others.

This library tokenises code using Prism and provides a small render-props-driven component to quickly render it out into React. This is why it even works with React Native! It's bundled with a modified version of Prism that won't pollute the global namespace and comes with a couple of common language syntaxes.

(There's also an escape-hatch to use your own Prism setup, just in case)

It also comes with its own VSCode-like theming format, which means by default you can easily drop in different themes, use the ones this library ships with, or create new ones programmatically on the fly.

(If you just want to use your Prism CSS-file themes, that's also no problem)

Table of Contents

Installation

This module is distributed via npm which is bundled with node and should be installed as one of your project's dependencies:

# npm
npm install --save prism-react-renderer
# yarn
yarn add prism-react-renderer
# pnpm
pnpm add prism-react-renderer

Prism React Renderer has a peer dependency on react

Usage

Prism React Renderer has a named export for the <Highlight /> component along with themes. To see Prism React Render in action with base styling check out packages/demo or run pnpm run start:demo from the root of this repository.

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 />)

Custom Language Support

By default prism-react-renderer only includes a base set of languages that Prism supports.

Note: Some languages (such as Javascript) are part of the bundle of other languages

Depending on your app's build system you may need to await the import or use require to ensure window.Prism exists before importing the custom languages. You can add support for more by including their definitions from the main prismjs package:

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")

Basic Props

This is the list of props that you should probably know about. There are some advanced props below as well.

Most of these advanced props are included in the defaultProps.

children

function({}) | required

This is called with an object. Read more about the properties of this object in the section "Children Function".

language

string | required

This is the language that your code will be highlighted as. You can see a list of all languages that are supported out of the box here. Not all languages are included and the list of languages that are currently is a little arbitrary. You can use the escape-hatch to use your own Prism setup, just in case, or add more languages to the bundled Prism.

code

string | required

This is the code that will be highlighted.

Advanced Props

theme

PrismTheme | optional; default is vsDark

If a theme is passed, it is used to generate style props which can be retrieved via the prop-getters which are described in "Children Function".

Read more about how to theme prism-react-renderer in the section "Theming".

prism

prism | optional; default is the vendored version

This is the Prismjs library itself. A vendored version of Prism is provided (and also exported) as part of this library. This vendored version doesn't pollute the global namespace, is slimmed down, and doesn't conflict with any installation of prismjs you might have.

If you're only using Prism.highlight you can choose to use prism-react-renderer's exported, vendored version of Prism instead.

But if you choose to use your own Prism setup, simply pass Prism as a prop:

// Whichever way you're retrieving Prism here:
import Prism from 'prismjs/components/prism-core';

<Highlight prism={Prism} {/* ... */} />

Children Function

This is where you render whatever you want to based on the output of <Highlight />. You use it like so:

const ui = (
  <Highlight>
    {highlight => (
      // use utilities and prop getters here, like highlight.className, highlight.getTokenProps, etc.
      <pre>{/* more jsx here */}</pre>
    )}
  </Highlight>
);

The properties of this highlight object can be split into two categories as indicated below:

state

These properties are the flat output of <Highlight />. They're generally "state" and are what you'd usually expect from a render-props-based API.

property type description
tokens Token[][] This is a doubly nested array of tokens. The outer array is for separate lines, the inner for tokens, so the actual content.
className string This is the class you should apply to your wrapping element, typically a <pre>

A "Token" is an object that represents a piece of content for Prism. It has a types property, which is an array of types that indicate the purpose and styling of a piece of text, and a content property, which is the actual text.

You'd typically iterate over tokens, rendering each line, and iterate over its items, rendering out each token, which is a piece of this line.

prop getters

See Kent C. Dodds' blog post about prop getters

These functions are used to apply props to the elements that you render. This gives you maximum flexibility to render what, when, and wherever you like.

You'd typically call these functions with some dictated input and add on all other props that it should pass through. It'll correctly override and modify the props that it returns to you, so passing props to it instead of adding them directly is advisable.

property type description
getLineProps function({}) returns the props you should apply to any list of tokens, i.e. the element that contains your tokens.
getTokenProps function({}) returns the props you should apply to the elements displaying tokens that you render.

getLineProps

You need to add a line property (type: Token[]) to the object you're passing to getLineProps.

This getter will return you props to spread onto your line elements (typically <div>s).

It will typically return a className (if you pass one it'll be appended), children, style (if you pass one it'll be merged). It also passes on all other props you pass to the input.

The className will always contain .token-line.

getTokenProps

You need to add a token property (type: Token) to the object you're passing to getTokenProps.

This getter will return you props to spread onto your token elements (typically <span>s).

It will typically return a className (if you pass one it'll be appended), children, style (if you pass one it'll be merged). It also passes on all other props you pass to the input.

The className will always contain .token. This also provides full compatibility with your old Prism CSS-file themes.

Utility Functions

useTokenize

(options: TokenizeOptions) => Token[][]

type TokenizeOptions = {
  prism: PrismLib
  code: string
  grammar?: PrismGrammar
  language: Language
}

This 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 your own custom component. It uses normalizeTokens internally to convert the tokens into a shape that can be rendered.

  • prism: PrismLib: the Prism library to use for tokenization. This can be the vendored version of Prism that is included with prism-react-renderer or a custom version of Prism that you have configured.

  • code: string: a string containing the code to tokenize.

  • grammar?: PrismGrammar: a Prism grammar object to use for tokenization. If this is omitted, the tokens will just be normalized. A grammar can be obtained from Prism.languages or by importing a language from prismjs/components/.

  • language: Language: the language to use for tokenization. This should be a language that Prism supports.

normalizeTokens

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

Takes an array of Prism’s tokens and groups them by line, converting strings into tokens. Tokens can become recursive in some cases which means that their types are concatenated. Plain-string tokens however are always of type plain.

  • PrismToken is an internal alias for Token exported by prismjs and is defined here.

  • Token is an internal object that represents a slice of tokenized content for Prism with three properties:

    • types: string[]: an array of types that indicate the purpose and styling of a piece of text
    • content: string: the content of the token
    • empty: boolean: a flag indicating whether the token is empty or not.

Theming

The defaultProps you'd typically apply in a basic use-case, contain a default theme. This theme is vsDark.

While all classNames are provided with <Highlight />, so that you could use your good old Prism CSS-file themes, you can also choose to use prism-react-renderer's themes like so:

import { Highlight, themes } from 'prism-react-renderer';

<Highlight theme={themes.dracula} {/* ... */} />

These themes are JSON-based and are heavily inspired by VSCode's theme format.

Their syntax, expressed in Flow looks like the following:

{
  plain: StyleObj,
  styles: Array<{
    types: string[],
    languages?: string[],
    style: StyleObj
  }>
}

The plain property provides a base style-object. This style object is directly used in the style props that you'll receive from the prop getters, if a theme prop has been passed to <Highlight />.

The styles property contains an array of definitions. Each definition contains a style property, that is also just a style object. These styles are limited by the types and languages properties.

The types properties is an array of token types that Prism outputs. The languages property limits styles to highlighted languages.

When converting a Prism CSS theme it's mostly just necessary to use classes as types and convert the declarations to object-style-syntax and put them on style.

Upgrade

If you are migrating from v1.x to v2.x, follow these steps

Change module imports

- 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">

Change theme imports

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

Check language support

By default prism-react-renderer only includes a base set of languages that Prism supports. Depending on your app's build system you may need to await the import or use require to ensure window.Prism exists before importing the custom languages.

See: https://github.com/FormidableLabs/prism-react-renderer#custom-language-support

Install prismjs (if not available yet):

# npm
npm install --save prismjs
# yarn
yarn add prismjs
# pnpm
pnpm add prismjs

Add language component

If the language is not already bundled in the above, you can add additional languages with the following code:

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")

LICENSE

MIT

Maintenance Status

Active: Nearform is actively working on this project, and we expect to continue work for the foreseeable future. Bug reports, feature requests and pull requests are welcome.

prism-react-renderer's People

Contributors

ahmadawais avatar boygirl avatar carbonrobot avatar carloskelly13 avatar chris-bateman avatar cpresler avatar deini avatar github-actions[bot] avatar gksander avatar harryzcy avatar inokawa avatar jonshort avatar jpdriver avatar karlhorky avatar kitten avatar manuelpuyol avatar mrousavy avatar narinluangrath avatar nluangrath-godaddy avatar petetnt avatar pomber avatar ryanmogk avatar ryuji-1to avatar satya164 avatar slorber avatar tombyrer avatar trevorblades avatar ustun-ed avatar wesbos avatar yakkomajuri avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

prism-react-renderer's Issues

New language support?

Hi, could you please show me how to construct a Prism object manually? I'm trying to get a few language supports that are not out of the box to the react package. Thanks.

Typescript error with import Prism from 'prism-react-renderer/prism';

Want to add java language following, but can't compile

import Prism from 'prism-react-renderer/prism';
(typeof global !== 'undefined' ? global : window).Prism = Prism;
require("prismjs/components/prism-java");

Could not find a declaration file for module 'prism-react-renderer/prism'. 'c:/Users/saula/ideaProjects/Javali/client/node_modules/prism-react-renderer/prism/index.cjs.js' implicitly has an 'any' type.ts(7016)

image

Aliases representing classes is not applied.

It seems there is an issue with aliases.
For example here is a rule:

    'delimiter': {
      pattern: /\?>|<\?(?:php|=)?/i,
      alias: 'important'
    },
    'variable': /\$+(?:\w+\b|(?={))/i,
    'package': {
      pattern: /(\\|namespace\s+|use\s+)[\w\\]+/,
      lookbehind: true,
      inside: {
        punctuation: /\\/
      }
    }
  });

The alias important is not applied. It means there is no class important for the <?php element.
However, in the official test it works:
screen-01-16-13
And it's relevant for all other aliases.

Enable HTTP syntax highlighting

Hi @kitten ,

I hope you don't mind tagging you as I'm not sure who maintains this repo. I've got a question would it be possible to have highlighting for HTTP? Ready to implement it myself and submit a PR, however don't want to waste effort as it isn't clear at the moment that my PR will be merged : )

Thanks.

Next.js MDX not applying default styles

Hello.

I followed what was described in #53 for some rust code I wanted to highlight. But, I am trying to do it in next.js, and am not seeing the styles from the prism docs being applied. Seeing some base style being applied via style attributes, is all.

<span class="token macro property" style="color: rgb(154, 134, 253);">format!</span>

Screen Shot 2020-08-14 at 4 29 46 PM

I am only interested in getting the default style working. Any guidance on what I might be missing?

Going deeper, here is my CodeBlock component

import React from "react";
import Highlight, { defaultProps } from "prism-react-renderer";

const CodeBlock = ({ children }) => {
  return (
    <Highlight {...defaultProps} code={children} language={"rust"}>
      {({ className, styles, tokens, getLineProps, getTokenProps }) => {
        return (
          <pre className={className} styles={styles}>
            <code className={className}>
              {tokens.map((line, i) => (
                <div key={i} {...getLineProps({ line, key: i })}>
                  {line.map((token, key) => (
                    <span key={key} {...getTokenProps({ token, key })} />
                  ))}
                </div>
              ))}
            </code>
          </pre>
        );
      }}
    </Highlight>
  );
};

export default CodeBlock;

Here are the imports for my layout component that is taking care of rendering the MDX.

import React from "react";
import Prism from "prism-react-renderer/prism";
import { LayoutHeader } from "../components/Headers";
import HeadElement from "../components/HeadElement";
import { P, H1, H3 } from "../components/common";
import ConvertKitForm from "../components/ConvertKitForm";

(typeof global !== "undefined" ? global : window).Prism = Prism;

require("prismjs/components/prism-rust");

...component body...

Fix plain tokens not respecting cascading styles

Previously I incorrectly assumed that if a plain string token is nested inside other tokens, that the plain string should still be styled as plain.

(Not sure why I thought that...)

The correct behaviour if a plain string is encountered inside a tag for instance is to style it as a tag.

See: pomber/code-surfer#12

Minor version breaking change

See #41 for details.

Essentially a minor version was pushed live with breaking changes to production builds.

This should have been released as a major change so automated build tools wouldn't automatically update. It has caused all sorts of issues in our automated testing over the past week now, which is not acceptable, even for OSS.

Finer grained theme type selectors

Let's say I have three different punctuation tokens:
span.token.tag.spread.punctuation, span.token.tag.script.punctuation and span.token.tag.punctuation.

To get closer to a vscode dark+ theme, the first two tags are actually a different color than the last.

As far as I can tell, the theme type only allows for styling all three as the same color

{
  types: ['punctuation'],
  style: {
    color: 'rgb(212, 212, 212)'
  }
}

Is there currently a way to select all three types individually in the theme?

edit: doesn't seem likely at the moment

const typeStyles = types.map(type => themeDict[type]);

an extra check if the token's entire classname list matches a type in the theme could get around this, so the theme would look like

{
  types: ['tag script punctuation',  'tag spread punctuation'],
  style: {
    color: 'rgb(212, 212, 212)'
  }
},
{
  types: ['tag punctuation'],
  style: {
    color: 'rgb(212, 212, 212)'
  }
}

Cannot read property 'languages' of undefined

I'm simply rendering a simple example:

<Highlight language="jsx">
  {highlight => <pre>/* your JSX here! */</pre>}
</Highlight>

and I get:

Screenshot 2019-03-14 at 12 49 31

Tried to install Prism on its own, but looking at the code it seems Prism is not even being imported.

Adding Out of the Box Languages

Howdy :) Thank you very much for this excellent package. I am creating a Gatsby MVP for a giant blog and using this package instead of the remark plugin sped up the rendering process.

We have a lot of languages that are not part of the out of the box list, such as Kotlin and C#. Could you please provide me some guidance on how to enable them?

https://github.com/FormidableLabs/prism-react-renderer/blob/master/src/vendor/prism/includeLangs.js

Thank you in advance for your time.

Add support for diff-highlight

Related to #2 and facebook/docusaurus#3318

Prism comes with a useful plugin: diff-highlight for combining syntax highlighting and diff highlighting.

Since prism-react-renderer does not support plugins, it would be interesting to reimplement this plugin directly in prism-react-renderer. This can increase quite significantly the readability of diffs.

Set line-height?

Hey there! Would this project be open to instituting a fixed line-height (maybe configurable?) to make rendering across different fonts / browsers more consistent? Not sure how out of date the information is, but I've been reading some articles that line-height: normal is not the same across browsers. I would also find this useful to be able to position elements relative to each line more consistently.

Prism has made the decision to use line-height: 1.5 for all themes (Ref: PrismJS/prism#279). 1.5 seems a bit excessive, especially with the more minimal Menlo font-family, which is the default used by the default code-surfer configuration. Prism uses Consolas as the default when visiting the website on macOS, which both has a higher default line-height (with line-height: normal) and looks better like this.

Below is a comparison of the following:

  • yellow Header: the default Menlo with line-height: normal (which resolves to 1.2 in Chrome macOS)
  • orange Header: Prism's website, using Consolas and line-height: 1.5

Kapture 2019-05-20 at 12 20 37

For a further reference, HTML Boilerplate currently uses 1.4.

I am not actually all into this topic, so I may miss out on downsides or complexities involved in this.

cc @pomber

gatsby-plugin-mdx support?

I'm using gatsby-plugin-mdx with Gatsby and I'm also using gatsby-remark-prismjs for the code highlighting. I've seen it said that prism-react-renderer is more preferred than the remark plugin. If so, how can I use this? Because it's mdx, I don't know ahead of time what language the code would be in, but I'm most interested in dynamically changing the theme of the code on button click, such as on the PrismJS website.

Publish latest to NPM

I would like to use the GitHub theme that was added about a month ago, but it's not been published to NPM. The latest version on NPM is 0.1.6 and was published 3 months agoβ€”prior to the GitHub theme being added.

Many thanks for making such an awesome library!

Improve tokenization

As mentioned in #28 (comment), the tokenization and classes leave some things to be desired.

Would it fit the goals of this project to improve the support of the tokenization? I'm looking at this in terms of implementing more fully-featured themes, such as what I started in #28.

An example is this:

prism-react-renderer with Improved VS Code theme (#28)

screen shot 2019-03-04 at 17 58 24

screen shot 2019-03-04 at 17 58 36

VS Code
screen shot 2019-03-04 at 18 14 10

Would be nice to get a bit closer to VS Code's version (<, = and " punctuation highlighted differently).


Looking more in detail, I see that there are some limitations inherent in Prism, but maybe there could still be some improvements somehow, such as integration of Prism JS Extras: PrismJS/prism#1743


If improving tokenization is not easy or possible without changing Prism, one thing that could be easier to do would be to allow for changing the plain colors by language, so that the CSS plain could be the orange color instead of the light blue (which is more common throughout, which is why I opted to use it).

prism-react-renderer with Improved VS Code theme (#28)

css-after

VS Code

css-real-vs-code

Multiple files are not ESM and breaks ESM

  1. This line
    import theme from '../themes/duotoneDark'
    looks like ESM, but it's not because the entire themes directory use module.exports instead of transpiled exports.
  2. The prism vendor wrapper has the same issue:

This means that just importing prism-react-renderer is impossible (at least index and other files) in ESM in a browser.

Fix: Switch themes to esm exports and transpile to es same as all other code.

Add memoisation

About

I've been getting perf issues due to the highlight component doing calculations every render. Here's a brief example:

const MyComponent = () => {
  const { someCode } = useMyContext();

  return (
    <CodeHighlight language="json" code={someCode} />
  )
};


const CodeHighlight = (props) => (
    <Highlight {...defaultProps} {...props}>
      {({ className, style, tokens, getLineProps, getTokenProps }) => (
        <StyledCodeBlock
          className={className}
          style={{ ...style, backgroundColor: undefined, color: undefined }}
        >
          <code>
            {tokens.map((line, i) => (
              <div
                key={i}
                {...getLineProps({ line, key: i })}
                style={undefined}
              >
                {line.map((token, key) => (
                  <span
                    key={key}
                    {...getTokenProps({ token, key })}
                    style={undefined}
                  />
                ))}
              </div>
            ))}
          </code>
        </StyledCodeBlock>
      )}
    </Highlight>
);

The issue here is that these calculations are done every render regardless of whether the props have changed.

It looks like the Highlight component is completely stateless so wrapping it in memo will solve the problem.

As a temporary workaround for anyone with this issue, you can wrap the parent component (CodeHighlight in the example) in a memo.

Single empty line breaks are ignored

I'm rendering some markdown line so:

import auth from '@react-native-firebase/auth';
import database from '@react-native-firebase/database';
 
async function onCreateAccount() {
  // Get the users ID
  const uid = auth().currentUser.uid;
  // ..

The rendering works fine, however there is no line break happening between the imports/function:

image

It looks like the line token plain child is an empty string, rather than a string with a single space. I'm able to get around this by doing:

<code>
              {tokens.map((line, i) => {

                // Ensure blank lines/spaces drop onto a new line
                if (line.length === 1 && line[0].content === '') {
                  line[0].content = ' ';
                }

                return (
                  <div {...getLineProps({ line, key: i })}>
                    {line.map((token, key) => {

Not sure if it's a bug or something my end? There doesn't seem to be an issue when it's already within a line.

Adding new language, can't resolve component (?)

Likely an obvious mistake, but following what seems to work to many people doesn't work for me

(#53)

import Highlight, { defaultProps } from 'prism-react-renderer'
import Prism from 'prism-react-renderer/prism'
...
;(typeof global !== 'undefined' ? global : window).Prism = Prism
require('prismjs/components/prism-php')

Can't resolve 'prismjs/components/prism-php'

(but it does exist https://github.com/PrismJS/prism/blob/master/components/prism-php.js)

Pass react children instead of a code string

Is there any way to not use a string as a code block? Can the children I pass be converted automatically. When having multiple code blocks in a component having un-indent the code in the strings seems bad. to get the code blocks to look correct in the browser i have to do this:
Screen Shot 2019-07-25 at 8 02 23 PM

I would like to be able to just pass react components and have them converted automatically so I don't have to worry about indentation.
Screen Shot 2019-07-25 at 8 03 35 PM

Is this possible?

getTokenProps is returning a function instead of an object in style

When highlighting some reason code:

<Highlight {...defaultProps} code={`open Common;`} language="reason">

getTokenProps is returning a function instead of an object in style. So it fails when applying the props to an element:

Invariant Violation
The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + 'em'}} when using JSX.
    in span (created by Highlight)
    in div (created by Highlight)
    in pre (created by Highlight)
    in Highlight

Here is a CodeSandbox: https://codesandbox.io/s/9ql1rq3yw4

Unknown plugin "@babel/plugin-proposal-class-properties"

Hey, I am using your library with a react-native app with

"babel-cli": "6.24.0",
"react": "16.0.0",
"react-native": "^0.50.4",

And I get this error:

ReferenceError: Unknown plugin "@babel/plugin-proposal-class-properties" specified in "/home/circleci/rnapp/node_modules/prism-react-renderer/package.json" at 0, attempted to resolve relative to "/home/circleci/rnapp/node_modules/prism-react-renderer"
  
  at node_modules/babel-core/lib/transformation/file/options/option-manager.js:180:17
      at Array.map (<anonymous>)
  at Function.normalisePlugins (node_modules/babel-core/lib/transformation/file/options/option-manager.js:158:20)
  at OptionManager.mergeOptions (node_modules/babel-core/lib/transformation/file/options/option-manager.js:234:36)
  at OptionManager.init (node_modules/babel-core/lib/transformation/file/options/option-manager.js:368:12)
  at File.initOptions (node_modules/babel-core/lib/transformation/file/index.js:212:65)
  at new File (node_modules/babel-core/lib/transformation/file/index.js:135:24)
  at Pipeline.transform (node_modules/babel-core/lib/transformation/pipeline.js:46:16)

I also tried this this by updating babel-cli to 7.0.0 but I get the same error

Code block scroll bar

Are there plans to add scrollbar functionality in the foreseeable future (or is there an existing way to do this)? We're running into an issue with large blocks of code overflowing the component, and I'd prefer to have a scrollbar than to wrap the text.

Also, it appears that not all the in-line comments are being recognized. Do you have any insight into why this might be happening?

image

Thanks in advance! πŸ˜„

Render children using jsx syntax

In Highlight.js (and probably other parents), children is rendered by calling it as a function. This can cause a subtle but hard-to-find issue depending on user's code.

  1. If user passes a function component (using hooks) as child, that will fail
  2. There can be other subtle differences because of how react renders function component lazily now-a-days.

All of that can be solved by just rendering it as jsx, like <Children />. Then react will treat it as a proper component.

Backwards compat - Because normal functions will work just the same as pure function component, they will continue to work in the same way. It will not break existing userland code.

Add Flow types to the package

Hey,

I'm trying to use this module in a project where Flow is enabled, but I'm getting the following error:

Error ------------------------------------------------------------------------------------------------------------------
node_modules/prism-react-renderer/themes/vsDark.js:4:38

Cannot resolve module ../src/types.

     1| // @flow
     2| // Converted automatically using ./tools/themeFromVsCode
     3|
     4| /*:: import type { PrismTheme } from '../src/types' */
     5|
     6| var theme /*: PrismTheme */ = {
     7|   plain: {

The src/types folder isn't part of the NPM package.

Alex

How to display an object

For example, I have this object stored in variable

const object = {
   a: 'hello',
   b: 'world',
}

I want to display with Highlight, how do I do that? (I don't want to use JSON.stringify() because the result has "")

a11y: Failing color contrast in prism themes

Hey All,

This is related to: system-ui/theme-ui#564

I am using Theme-UI in some Gatsby projects. I installed Cypress for testing and cypress axe for accessibility testing. Turns out that some of the color contrasts on the prism themes are failing a11y checks. In most cases the color contrasts were meeting AA Large but because of the font size need to meet AA. I dug into a bit, you can see that in my above issue, originally made a PR for Theme-UI however didn't realize they are just auto-generating from your presets.

I would be happy to take it on, but don't know much about this project. Or how you would want a fix to look.

Document Line Numbers Snippet

Hey there!

Would be cool to add a small stub to the Readme to document adding line numbers either via either of the following methods:

Would the prism-react-renderer team be open to this?


CodeSandbox version

import React from 'react'
import styled from 'styled-components'
import Highlight, { defaultProps } from 'prism-react-renderer'
import theme from 'prism-react-renderer/themes/nightOwl'

const exampleCode = `
(function someDemo() {
  var test = "Hello World!";
  console.log(test);
})();

return () => <App />;
`.trim()

const LineNo = styled.span`
  display: inline-block;
  width: 2em;
  user-select: none;
  opacity: 0.3;
`

const Pre = styled.pre`
  text-align: left;
  margin: 1em 0;
  padding: 0.5em;

  & .token-line {
    line-height: 1.3em;
    height: 1.3em;
  }
`

const Basic = () => (
  <Highlight {...defaultProps} theme={theme} code={exampleCode} language="jsx">
    {({ className, style, tokens, getLineProps, getTokenProps }) => (
      <Pre className={className} style={style}>
        {tokens.map((line, i) => (
          <div {...getLineProps({ line, key: i })}>
            <LineNo>{i + 1}</LineNo>
            {line.map((token, key) => <span {...getTokenProps({ token, key })} />)}
          </div>
        ))}
      </Pre>
    )}
  </Highlight>
)

export default Basic

Please export type RenderProps in index.d.ts

I want to define the children in a separate function, so that I can use react hooks in the children component.

As shown in the code below, I need the type RenderProps.

type HighlightContentProps = RenderProps & {
  onLineCountChange?: (lineCount: number) => void
}

function HighlightContent(props: HighlightContentProps): React.ReactElement {
  const { tokens, getLineProps, getTokenProps, onLineCountChange } = props

  useEffect(() => {
    if (onLineCountChange != null) {
      onLineCountChange(tokens.length)
    }
  }, [tokens.length, onLineCountChange])

  return (
    <React.Fragment>
      { tokens.map((line, i) => (
        <Line { ...getLineProps({ line, key: i }) }>
          {
            line.map((token, key) => (
              <span { ...getTokenProps({ token, key }) } />
            ))
          }
        </Line>
      )) }
    </React.Fragment>
  )
}

export function CodeHighlight(props: CodeHighlightProps): React.ReactElement | null {
  const { lang, code, theme, onLineCountChange } = props

  return (
    <Highlight
      Prism={ Prism }
      code={ code }
      theme={ theme }
      language={ lang }
    >
      {
        props => (
          <HighlightContent
            { ...props }
            onLineCountChange={ onLineCountChange }
          />
        )
      }
    </Highlight>
  )
}

Add fallback for unsupported languages

Whenever I pass language using a prop instead of a straight up string, I get the error TypeError: Cannot read property 'rest' of undefined

Examples:

Working

<Highlight {...defaultProps} code={sample.code} language="jsx">
  {({ className, style, tokens, getLineProps, getTokenProps }) => (
    <pre className={className} style={style}>
      {tokens.map((line, i) => (
        <div {...getLineProps({ line, key: i })}>
          {line.map((token, key) => (
            <span {...getTokenProps({ token, key })} />
          ))}
        </div>
      ))}
    </pre>
  )}
</Highlight>

Broken

<Highlight {...defaultProps} code={sample.code} language={sample.language}>
  {({ className, style, tokens, getLineProps, getTokenProps }) => (
    <pre className={className} style={style}>
      {tokens.map((line, i) => (
        <div {...getLineProps({ line, key: i })}>
          {line.map((token, key) => (
            <span {...getTokenProps({ token, key })} />
          ))}
        </div>
      ))}
    </pre>
  )}
</Highlight>

Differences between Prism-React-Renderer and PrismJS?

I'm quite confused on what exactly the difference is between this library's vendored Prism and the source PrismJS implementation. From the README it sounds like prism-react-renderer is equivalent to Prism for the subset of supported languages, but when I use it I get very different results from source PrismJS on a language like Python:

Could someone please clarify what the differences are? Is it possible to use the source PrismJS styles, for a more complete syntax highlighting?

Source PrismJS:
Source PrismJS

Prism-React-Renderer:
Prism-React-Renderer

Prism plugins

Are Prism plugin supported? I guess not since they operate in DOM Nodes.

How to highlight lines

Hello, I'm using prism-react-renderer in .md and mdx using gatsbyjs. I can't find the documentation example how to add lines also highlight the line.

1.1.0 -> 1.1.1 breaks Python highlighting in Docusaurus

Hi,

Docusaurus (v2) uses this project for syntax highlighting.

https://v2.docusaurus.io/docs/theme-classic/#codeblock


Let's take this code:

@dataclass
class MySQLConfig:
    host: str = "localhost"
    port: int = 3306

@dataclass
class Config:
    db: MySQLConfig = MySQLConfig()
    verbose: bool = True

cfg_store = ConfigStore.instance()
cfg_store.store(name="config", node=MyConfig)

@hydra.main(config_name="config")
def my_app(cfg: MyConfig) -> None:
    # Python knows that the type of cfg.db is MySQLConfig without any additional hints
    print(f"Host: {cfg.db.host}, port: {cfg.db.port}")

if __name__ == "__main__":
    my_app()

When using:

  "resolutions": {
    "prism-react-renderer": "1.1.0"
  },

Python highlighting works fine for this code:

image


But when using newest version, highlighting is missing for things like decorators (or applied partially):

  "resolutions": {
    "prism-react-renderer": "1.1.1"
  },

image


@kitten as you proposed your help already here: facebook/docusaurus#2666 (comment) wonder if you can help me figure out what's happening.

The code does not seems to change much from 1.1.0 to 1.1.1 so I don't understand.

Anything I don't see in the commits?

Do you think this might affect other languages as Python, and that we should temporarily lock users to 1.1.0?

Changing the theme doesn't work

Theme is not updated when I change the theme prop.
Minimal repro: https://codesandbox.io/s/9415mzmr0w

My current workaround is changing the key of the Highlight component together with the theme prop, so the component is mounted again when the theme changes (line 26 in the linked codesandbox).

Sorry I didn't have time to debug it today.

Upgrade vendored version of prismjs

I was running into an issue where the TypeScript formatter was inserting extra newlines into the output of prism-react-renderer, and I found that if I used a newer version of prismjs the issue went away.

The issue looked like that the version of primjs bundled with prism-react-renderer will sometimes split a Windows-style line-ending across tokens, which causes the newline-regex in 'normalizeEmptyLines' to recognize it as two different newlines.

It might be worth fixing the the bug in 'normalizeEmptyLines', but a newer version of prismjs also seemed to not cause the issue in my specific case.

I'm working around the issue by normalizing newlines myself before sending it through formatting.

Themes shouldn't de-emphasise comments

All included themes I tried display comments in a faded colour. This is not great in a regular editor use case (since comments are usually important to understand what's going on), but it's doubly troublesome in a documentation setting, e.g. a blog or Docusaurus website (which uses the Palenight theme by default).

image

Ideally (in my humble opinion), comments would be in a colour that stands out from the background and the rest of the text, having enough contrast to at least meet the WCAG standards for accessible text.

(I'm not sure if the included themes are part of this project, but I couldn't find where they were from otherwise...)

About included languages ?

Hello,

First, thank you for this great work! πŸ‘

I'm getting started on a SSG NextJS project, and I was wondering what was the purpose of the limitation of included languages? I guess this is about bundle size and performances, but what about just using something like the babel-plugin-prismjs, instead of the method described here?

I'll be happy to discuss that!

Thx again

Integrate TypeScript typings

Hello!

I just added the package in a TS project but the typings are missing. Would you be interested in a PR or should I go on DefinitelyTyped to do one ?

"Cannot read length of undefined" due to parsing error

if (typeof content !== "string") {
stackIndex++;
typeArrStack.push(types);
tokenArrStack.push(content);
tokenArrIndexStack.push(0);
tokenArrSizeStack.push(content.length);
continue;
}

I'm looking into what part of my code is bad (presumably I have a preparser that converts unescaped HTML tags into React components), but there it ends up causing this error when content is undefined.

The highlighted code is this:

<pre><code class="language-javascript">
  import { ApiService } from 'core';
  const apolloClients = ApiService.generateApolloClients({
    apiKey: '<YOUR_API_KEY_HAS_NOT_BEEN_PROVISIONED>',
    deploymentConfigurationId: 'ABC123',
  });
</code></pre>

I think YOUR_API_KEY_HAS_NOT_BEEN_PROVISIONED is treated like an empty HTML tag. It'd probably be a good idea to somehow guard against parsing errors.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.