All files / packages/design-system/shared/components Doc.jsx

87.5% Statements 21/24
72.72% Branches 8/11
83.33% Functions 5/6
86.36% Lines 19/22

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 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120                          1x                                                   1x   23x                                                     1x   5x 5x                         1x 1x       11x     21x         5x 5x     2x 2x 2x     5x 5x 5x   1x                  
// Copyright (c) 2015-present, salesforce.com, inc. All rights reserved
// Licensed under BSD 3-Clause - see LICENSE.txt or git.io/sfdc-license
 
import cx from 'classnames';
import get from 'lodash.get';
import React from 'react';
 
import '../styles/doc.scss';
import { flattenElement, mapElement } from '../utils/react';
 
import Example from './Example';
import DocHeaderAnchor from './DocHeaderAnchor';
 
export const tags = [
  'p',
  'div',
  'a',
  'em',
  'strong',
  'ol',
  'ul',
  'li',
  'code',
  'blockquote',
  'pre',
  'tr',
  'td',
  'th',
  'table',
  'thead',
  'tbody',
  'h1',
  'h2',
  'h3',
  'h4',
  'h5',
  'h6'
];
 
export const factories = tags.reduce(
  (factories, type) =>
    Object.assign({}, factories, {
      [type]: (props, ...children) => {
        if (/h[1-6]/.test(type)) {
          children.push(
            React.createElement(
              DocHeaderAnchor,
              {
                id: props.id,
                type
              },
              null
            )
          );
        }
        return React.createElement(
          type,
          {
            ...props,
            className: cx('doc', props.className)
          },
          ...children
        );
      }
    }),
  {}
);
 
export const createTableOfContents = (() => {
  const createNode = (level, element) => {
    const { children, id } = element.props;
    return {
      children: [],
      id,
      level,
      title:
        typeof children === 'string'
          ? children
          : Array.isArray(children)
          ? children[0]
          : children
    };
  };
  return element => {
    let keyPath = [];
    let tree = {
      level: 0,
      children: []
    };
    flattenElement(mapElement(element, e => (e.type === Example ? null : e)))
      .filter(
        e =>
          /^h[1-6]/.test(String(e.type)) &&
          e.props.id &&
          e.props.className === 'doc'
      )
      .forEach(element => {
        let level = parseInt(element.type[1], 10);
        let levelLast = get(tree, keyPath.concat(['level']));
        if (level <= levelLast) {
          while (keyPath.length) {
            const heading = get(tree, keyPath);
            keyPath = keyPath.slice(0, -2);
            if (heading.level === level) break;
          }
        }
        const children = get(tree, keyPath.concat(['children']));
        children.push(createNode(level, element));
        keyPath.push('children', children.length - 1);
      });
    return tree;
  };
})();
 
export default class Doc extends React.Component {
  render() {
    return <div {...this.props} />;
  }
}