Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to highlight lines #26

Closed
alfieqashwa opened this issue Mar 1, 2019 · 8 comments
Closed

How to highlight lines #26

alfieqashwa opened this issue Mar 1, 2019 · 8 comments

Comments

@alfieqashwa
Copy link

alfieqashwa commented Mar 1, 2019

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.

@filoxo
Copy link

filoxo commented Mar 20, 2019

Here's how I managed to achieve line highlighting using prism-react-renderer in my gatsby-mdx blog.

filoxo/blog@3862bb4

@dimitrisnl
Copy link

dimitrisnl commented Mar 26, 2019

@filoxo Just note that your approach isn't working properly when there is a scrollbar

Screen Shot 2019-03-26 at 6 17 14 PM

I was looking for a way to solve this, and adding a wrapper element that overflows (div) before the pre element works great.

@filoxo
Copy link

filoxo commented Mar 27, 2019

@dimitrisnl I wouldn't say it isn't working properly. It's a known styling "inconvenience" that even Gatsby docs provide a solution for the overflow scroll styling. It's pretty minor when considering that it is only a visual help, and does nothing for accessibility or document semantics.

The solution is purely in the styling. You could add a wrapper element like you did, or you could allow the pre text to wrap (which React docs do https://reactjs.org/tutorial/tutorial.html#making-an-interactive-component ), or like me you could just not care about such a minor thing.

@kitten
Copy link
Collaborator

kitten commented Apr 26, 2019

I think there's been a sufficiently good answer and it's basically a UI problem on top of prism-react-renderer and not a library concern.

So there's a code sample, you can take it to StackOverflow, or we can open an issue to add more examples to the docs or repo 👍

@wwwebman
Copy link

wwwebman commented Apr 5, 2020

I migrated from gatsby-remark-prismjs and was searching for something backward compatible to highlight-* marks.

The working and simple solution would be:

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

const isHighlightedLine = (line, mark = '// highlight-next-line') =>
  line?.some((prevLine) => {
    return prevLine?.content === mark;
  });

export default ({ children, className }) => {
  const language = className.replace(/language-/, '');

  return (
    <Highlight {...defaultProps} code={children.trim()} language={language}>
      {({ className, style, tokens, getLineProps, getTokenProps }) => (
        <pre
          className={className}
          style={{ ...style }}
          data-language={language}
        >
          {tokens.map((line, i) => {
            const lineProps = getLineProps({ line, key: i });
            const classNameArr = [lineProps.className];

            if (isHighlightedLine(line)) {
              return null;
            }

            if (isHighlightedLine(tokens?.[i - 1])) {
              classNameArr.push('your-awesome-highlight-class');
            }

            const finalLineProps = {
              ...lineProps,
              className: classNameArr.join(' '),
            };

            return (
              <div key={i} {...finalLineProps}>
                {line.map((token, key) => (
                  <span key={key} {...getTokenProps({ token, key })} />
                ))}
              </div>
            );
          })}
        </pre>
      )}
    </Highlight>
  );
};

Usage (index.mdx):

#### Implementation

```jsx
// highlight-next-line
const Component = ({}) => null);
...

@maxcell
Copy link

maxcell commented Apr 30, 2020

Hey folks! Though this issue is closed, I just wanted to share that I ended up write up a synthesis of what folks have shared here! This particular feature for me was very important and I am glad to have it back <3. Thank you @filoxo for sharing your solution, I've made sure to credit you at the end https://prince.dev/blog/highlight-with-react

@EllisMin
Copy link

EllisMin commented May 15, 2020

In case anyone wants to use highlighting in gatsby.js with

// highlight-line: highlighting current line
// highlight-start & // highlight-end: highlighting lines between

I would like to share my solution

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

let highlightStart = false
const highlightClassName = "gatsby-highlight-code-line"

const highlightLine = (lineArray, lineProps) => {
  let shouldExclude = false

  lineArray.forEach((line, i) => {
    const content = line.content

    // Highlight lines with "// highlight-line"
    if (content.replace(/\s/g, "").includes("//highlight-line")) {
      lineProps.className = `${lineProps.className} ${highlightClassName}`
      line.content = content
        .replace("// highlight-line", "")
        .replace("//highlight-line", "")
    }

    // Stop highlighting
    if (
      !!highlightStart &&
      content.replace(/\s/g, "") === "//highlight-end"
    ) {
      highlightStart = false
      shouldExclude = true
    }

    // Start highlighting after "//highlight-start"
    if (
      content.replace(/\s/g, "") === "//highlight-start"
    ) {
      highlightStart = true
      shouldExclude = true
    }
  })

  // Highlight lines between //highlight-start & //highlight-end
  if (!!highlightStart) {
    lineProps.className = `${lineProps.className} ${highlightClassName}`
  }

  return shouldExclude
}

const Code = ({ codeString, language }) => {
  return (
    <Highlight {...defaultProps} code={codeString} language={language}>
      {({ className, style, tokens, getLineProps, getTokenProps }) => (
        <div className="gatsby-highlight" data-language={language}>
          <pre className={className} style={style}>
            {tokens.map((line, i) => {
              const lineProps = getLineProps({ line, key: i })
              const shouldExclude = highlightLine(line, lineProps)
              return !shouldExclude ? (
                <div {...lineProps} key={i}>
                  {line.map((token, key) => (
                    <span {...getTokenProps({ token, key })} />
                  ))}
                </div>
              ) : null
            })}
          </pre>
        </div>
      )}
    </Highlight>
  )
}

export default Code

@sahilrajput03
Copy link

sahilrajput03 commented Mar 26, 2021

If anybody wants to lookat live code of what @EllisMin suggested, take a look @ codesandbx example here .

The original codesandbox example was cloned from prism-react-renderer.

Thanks a lot @EllisMin .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants