All files / ts/components code-block.tsx

100% Statements 26/26
100% Branches 21/21
100% Functions 5/5
100% Lines 23/23
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98            20x 20x 20x   20x                                       20x     12x     12x     20x 11x   11x 10x       20x 4x       1x       20x 27x 18x 9x           9x   9x   9x                                                 20x   20x  
interface IHighlightJS {
  highlightBlock(element: HTMLElement): void;
}
 
declare const hljs: void | IHighlightJS;
 
import * as classNames from 'classnames';
import * as React from 'react';
import { HTMLProps, PureComponent } from 'react';
import { ComponentProps } from '../types';
import { formatCode } from '../utils';
 
export interface CodeBlockProps extends ComponentProps, HTMLProps<HTMLElement> {
  /**
   * Code to display.
   */
  children?: string;
  /**
   * Language of the code to display e.g. "javascript".
   */
  language?: string;
  /**
   * Name of the code block e.g. "index.js".
   */
  codeBlockName?: string;
}
 
/**
 * Component to nicely highlight code inside a `pre` element.
 */
export class CodeBlock extends PureComponent<CodeBlockProps, {}> {
  public element: HTMLPreElement;
 
  public constructor (props: CodeBlockProps) {
    super(props);
 
    this.highlightBlock = this.highlightBlock.bind(this);
  }
 
  public highlightBlock (element: HTMLPreElement) {
    this.element = element;
 
    if (typeof hljs === 'object' && typeof hljs.highlightBlock === 'function') {
      hljs.highlightBlock(this.element);
    }
  }
 
  public componentDidUpdate (prevProps: CodeBlockProps) {
    if (
      typeof hljs === 'object' && typeof hljs.highlightBlock === 'function' &&
      prevProps.children !== this.props.children
    ) {
      hljs.highlightBlock(this.element);
    }
  }
 
  public render () {
    const {
      children,
      className,
      language,
      codeBlockName,
      component: Component = 'div',
      ...remainingProps
    } = this.props;
    const languageClassName = language && `language-${language}`;
 
    const content = typeof children === 'string' ? formatCode(children) : children;
 
    return (
      <Component {...remainingProps} className={classNames('code-block-wrapper', className)}>
        {
          typeof codeBlockName !== 'undefined' && (
            <div className="code-block-name">
              {
                typeof language !== 'undefined' && (
                  <div className="code-block-language">
                    {language}
                  </div>
                )
              }
              {codeBlockName}
            </div>
          )
        }
        <pre
          ref={this.highlightBlock}
          className={classNames('code-block', languageClassName)}
        >
          {content}
        </pre>
      </Component>
    );
  }
}
 
export default CodeBlock;