All files / ts/components/misc code-block.tsx

100% Statements 29/29
100% Branches 21/21
100% Functions 5/5
100% Lines 27/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 99            32x 32x 32x   32x                                       32x       12x   12x     32x 11x     11x 10x       32x 4x           1x       32x 9x 9x 9x 9x 9x 18x 9x   9x     9x   9x                                           32x   32x  
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;
 
    // tslint:disable-next-line:strict-type-predicates
    if (typeof hljs === 'object' && typeof hljs.highlightBlock === 'function') {
      hljs.highlightBlock(this.element);
    }
  }
 
  public componentDidUpdate(prevProps: CodeBlockProps) {
    if (
      typeof hljs === 'object' &&
      // tslint:disable-next-line:strict-type-predicates
      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;