render(): React.Node {
    const {
      block,
      children,
      contentState,
      decorator,
      decoratorKey,
      direction,
      leafSet,
      text,
    } = this.props;

    const blockKey = block.getKey();
    const leavesForLeafSet = leafSet.get('leaves');
    const DecoratorComponent = decorator.getComponentForKey(decoratorKey);
    const decoratorProps = decorator.getPropsForKey(decoratorKey);
    const decoratorOffsetKey = DraftOffsetKey.encode(
      blockKey,
      parseInt(decoratorKey, 10),
      0,
    );

    const decoratedText = text.slice(
      leavesForLeafSet.first().get('start'),
      leavesForLeafSet.last().get('end'),
    );

    // Resetting dir to the same value on a child node makes Chrome/Firefox
    // confused on cursor movement. See http://jsfiddle.net/d157kLck/3/
    const dir = UnicodeBidiDirection.getHTMLDirIfDifferent(
      UnicodeBidi.getDirection(decoratedText),
      direction,
    );

    return (
      <DecoratorComponent
        {...decoratorProps}
        contentState={contentState}
        decoratedText={decoratedText}
        dir={dir}
        key={decoratorOffsetKey}
        entityKey={block.getEntityAt(leafSet.get('start'))}
        offsetKey={decoratorOffsetKey}>
        {children}
      </DecoratorComponent>
    );
  }
 var leaves = leavesForLeafSet.map((leaf, jj) => {
   var offsetKey = DraftOffsetKey.encode(blockKey, ii, jj);
   var start = leaf.get('start');
   var end = leaf.get('end');
   return (
     <DraftEditorLeaf
       key={offsetKey}
       offsetKey={offsetKey}
       block={block}
       start={start}
       selection={hasSelection ? this.props.selection : undefined}
       forceSelection={this.props.forceSelection}
       text={text.slice(start, end)}
       styleSet={block.getInlineStyleAt(start)}
       customStyleMap={this.props.customStyleMap}
       customStyleFn={this.props.customStyleFn}
       isLast={ii === lastLeafSet && jj === lastLeaf}
     />
   );
 }).toArray();
 .map((leaf, jj) => {
   const offsetKey = DraftOffsetKey.encode(blockKey, ii, jj);
   const start = leaf.get('start');
   const end = leaf.get('end');
   return (
     <DraftEditorLeaf
       key={offsetKey}
       offsetKey={offsetKey}
       block={block}
       start={start}
       selection={hasSelection ? selection : null}
       forceSelection={forceSelection}
       text={text.slice(start, end)}
       styleSet={block.getInlineStyleAt(start)}
       customStyleMap={customStyleMap}
       customStyleFn={customStyleFn}
       isLast={decoratorKey === lastLeafSet && jj === lastLeaf}
     />
   );
 })
  render(): React.Element<any> {
    const {
      blockRenderMap,
      blockRendererFn,
      customStyleMap,
      editorState,
    } = this.props;

    const content = editorState.getCurrentContent();
    const selection = editorState.getSelection();
    const forceSelection = editorState.mustForceSelection();
    const decorator = editorState.getDecorator();
    const directionMap = nullthrows(editorState.getDirectionMap());

    const blocksAsArray = content.getBlocksAsArray();
    const blocks = [];
    let currentWrapperElement = null;
    let currentWrapperTemplate = null;
    let currentDepth = null;
    let currentWrappedBlocks;
    let block, key, blockType, child, childProps, wrapperTemplate;

    for (let ii = 0; ii < blocksAsArray.length; ii++) {
      block = blocksAsArray[ii];
      key = block.getKey();
      blockType = block.getType();

      const customRenderer = blockRendererFn(block);
      let CustomComponent, customProps, customEditable;
      if (customRenderer) {
        CustomComponent = customRenderer.component;
        customProps = customRenderer.props;
        customEditable = customRenderer.editable;
      }

      const direction = directionMap.get(key);
      const offsetKey = DraftOffsetKey.encode(key, 0, 0);
      const componentProps = {
        block,
        blockProps: customProps,
        customStyleMap,
        decorator,
        direction,
        forceSelection,
        key,
        offsetKey,
        selection,
        tree: editorState.getBlockTree(key),
      };

      // Block render map must have a configuration specified for this
      // block type.
      const configForType = nullthrows(blockRenderMap.get(blockType));

      wrapperTemplate = configForType.wrapper;

      const useNewWrapper = wrapperTemplate !== currentWrapperTemplate;

      const Element = (
        blockRenderMap.get(blockType).element ||
        blockRenderMap.get('unstyled').element
      );

      const depth = block.getDepth();
      let className = this.props.blockStyleFn(block);

      // List items are special snowflakes, since we handle nesting and
      // counters manually.
      if (Element === 'li') {
        const shouldResetCount = (
          useNewWrapper ||
          currentDepth === null ||
          depth > currentDepth
        );
        className = joinClasses(
          className,
          getListItemClasses(blockType, depth, shouldResetCount, direction)
        );
      }

      const Component = CustomComponent || DraftEditorBlock;
      childProps = {
        className,
        'data-block': true,
        'data-editor': this.props.editorKey,
        'data-offset-key': offsetKey,
        key,
      };
      if (customEditable !== undefined) {
        childProps = {
          ...childProps,
          contentEditable: customEditable,
          suppressContentEditableWarning: true,
        };
      }

      child = React.createElement(
        Element,
        childProps,
        <Component {...componentProps} />,
      );

      if (wrapperTemplate) {
        if (useNewWrapper) {
          currentWrappedBlocks = [];
          currentWrapperElement = React.cloneElement(
            wrapperTemplate,
            {
              key: key + '-wrap',
              'data-offset-key': offsetKey,
            },
            currentWrappedBlocks
          );
          currentWrapperTemplate = wrapperTemplate;
          blocks.push(currentWrapperElement);
        }
        currentDepth = block.getDepth();
        nullthrows(currentWrappedBlocks).push(child);
      } else {
        currentWrappedBlocks = null;
        currentWrapperElement = null;
        currentWrapperTemplate = null;
        currentDepth = null;
        blocks.push(child);
      }
    }

    return <div data-contents="true">{blocks}</div>;
  }
  render(): React.Node {
    const {
      blockRenderMap,
      blockRendererFn,
      blockStyleFn,
      customStyleMap,
      customStyleFn,
      editorState,
      editorKey,
      textDirectionality,
    } = this.props;

    const content = editorState.getCurrentContent();
    const selection = editorState.getSelection();
    const forceSelection = editorState.mustForceSelection();
    const decorator = editorState.getDecorator();
    const directionMap = nullthrows(editorState.getDirectionMap());

    const blocksAsArray = content.getBlocksAsArray();
    const rootBlock = blocksAsArray[0];
    const processedBlocks = [];

    let nodeBlock = rootBlock;

    while (nodeBlock) {
      const blockKey = nodeBlock.getKey();
      const blockProps = {
        blockRenderMap,
        blockRendererFn,
        blockStyleFn,
        contentState: content,
        customStyleFn,
        customStyleMap,
        decorator,
        editorKey,
        editorState,
        forceSelection,
        selection,
        block: nodeBlock,
        direction: textDirectionality
          ? textDirectionality
          : directionMap.get(blockKey),
        tree: editorState.getBlockTree(blockKey),
      };

      const configForType =
        blockRenderMap.get(nodeBlock.getType()) ||
        blockRenderMap.get('unstyled');
      const wrapperTemplate = configForType.wrapper;
      processedBlocks.push({
        block: <DraftEditorBlockNode key={blockKey} {...blockProps} />,
        wrapperTemplate,
        key: blockKey,
        offsetKey: DraftOffsetKey.encode(blockKey, 0, 0),
      });

      const nextBlockKey = nodeBlock.getNextSiblingKey();
      nodeBlock = nextBlockKey ? content.getBlockForKey(nextBlockKey) : null;
    }

    // Group contiguous runs of blocks that have the same wrapperTemplate
    const outputBlocks = [];
    for (let ii = 0; ii < processedBlocks.length; ) {
      const info: any = processedBlocks[ii];
      if (info.wrapperTemplate) {
        const blocks = [];
        do {
          blocks.push(processedBlocks[ii].block);
          ii++;
        } while (
          ii < processedBlocks.length &&
          processedBlocks[ii].wrapperTemplate === info.wrapperTemplate
        );
        const wrapperElement = React.cloneElement(
          info.wrapperTemplate,
          {
            key: info.key + '-wrap',
            'data-offset-key': info.offsetKey,
          },
          blocks,
        );
        outputBlocks.push(wrapperElement);
      } else {
        outputBlocks.push(info.block);
        ii++;
      }
    }

    return <div data-contents="true">{outputBlocks}</div>;
  }
    return this.props.tree.map((leafSet, ii) => {
      var leavesForLeafSet = leafSet.get('leaves');
      var lastLeaf = leavesForLeafSet.size - 1;
      var leaves = leavesForLeafSet.map((leaf, jj) => {
        var offsetKey = DraftOffsetKey.encode(blockKey, ii, jj);
        var start = leaf.get('start');
        var end = leaf.get('end');
        return (
          <DraftEditorLeaf
            key={offsetKey}
            offsetKey={offsetKey}
            block={block}
            start={start}
            selection={hasSelection ? this.props.selection : undefined}
            forceSelection={this.props.forceSelection}
            text={text.slice(start, end)}
            styleSet={block.getInlineStyleAt(start)}
            customStyleMap={this.props.customStyleMap}
            customStyleFn={this.props.customStyleFn}
            isLast={ii === lastLeafSet && jj === lastLeaf}
          />
        );
      }).toArray();

      var decoratorKey = leafSet.get('decoratorKey');
      if (decoratorKey == null) {
        return leaves;
      }

      if (!this.props.decorator) {
        return leaves;
      }

      var decorator = nullthrows(this.props.decorator);

      var DecoratorComponent = decorator.getComponentForKey(decoratorKey);
      if (!DecoratorComponent) {
        return leaves;
      }

      var decoratorProps = decorator.getPropsForKey(decoratorKey);
      var decoratorOffsetKey = DraftOffsetKey.encode(blockKey, ii, 0);
      var decoratedText = text.slice(
        leavesForLeafSet.first().get('start'),
        leavesForLeafSet.last().get('end'),
      );

      // Resetting dir to the same value on a child node makes Chrome/Firefox
      // confused on cursor movement. See http://jsfiddle.net/d157kLck/3/
      var dir = UnicodeBidiDirection.getHTMLDirIfDifferent(
        UnicodeBidi.getDirection(decoratedText),
        this.props.direction,
      );

      return (
        <DecoratorComponent
          {...decoratorProps}
          contentState={this.props.contentState}
          decoratedText={decoratedText}
          dir={dir}
          key={decoratorOffsetKey}
          entityKey={block.getEntityAt(leafSet.get('start'))}
          offsetKey={decoratorOffsetKey}>
          {leaves}
        </DecoratorComponent>
      );
    }).toArray();
  render(): React.Node {
    const {
      block,
      contentState,
      customStyleFn,
      customStyleMap,
      decorator,
      direction,
      forceSelection,
      hasSelection,
      selection,
      tree,
    } = this.props;

    const blockKey = block.getKey();
    const text = block.getText();
    const lastLeafSet = tree.size - 1;

    const children =
      this.props.children ||
      tree
        .map((leafSet, ii) => {
          const decoratorKey = leafSet.get('decoratorKey');
          const leavesForLeafSet = leafSet.get('leaves');
          const lastLeaf = leavesForLeafSet.size - 1;
          const Leaves = leavesForLeafSet
            .map((leaf, jj) => {
              const offsetKey = DraftOffsetKey.encode(blockKey, ii, jj);
              const start = leaf.get('start');
              const end = leaf.get('end');
              return (
                <DraftEditorLeaf
                  key={offsetKey}
                  offsetKey={offsetKey}
                  block={block}
                  start={start}
                  selection={hasSelection ? selection : null}
                  forceSelection={forceSelection}
                  text={text.slice(start, end)}
                  styleSet={block.getInlineStyleAt(start)}
                  customStyleMap={customStyleMap}
                  customStyleFn={customStyleFn}
                  isLast={decoratorKey === lastLeafSet && jj === lastLeaf}
                />
              );
            })
            .toArray();

          if (!decoratorKey || !decorator) {
            return Leaves;
          }

          return (
            <DraftEditorDecoratedLeaves
              block={block}
              children={Leaves}
              contentState={contentState}
              decorator={decorator}
              decoratorKey={decoratorKey}
              direction={direction}
              leafSet={leafSet}
              text={text}
              key={ii}
            />
          );
        })
        .toArray();

    return (
      <div
        data-offset-key={DraftOffsetKey.encode(blockKey, 0, 0)}
        className={cx({
          'public/DraftStyleDefault/block': true,
          'public/DraftStyleDefault/ltr': direction === 'LTR',
          'public/DraftStyleDefault/rtl': direction === 'RTL',
        })}>
        {children}
      </div>
    );
  }
  render(): React.Node {
    const {
      /* $FlowFixMe(>=0.53.0 site=www,mobile) This comment suppresses an error
       * when upgrading Flow's support for React. Common errors found when
       * upgrading Flow's React support are documented at
       * https://fburl.com/eq7bs81w */
      blockRenderMap,
      blockRendererFn,
      /* $FlowFixMe(>=0.53.0 site=www,mobile) This comment suppresses an error
       * when upgrading Flow's support for React. Common errors found when
       * upgrading Flow's React support are documented at
       * https://fburl.com/eq7bs81w */
      customStyleMap,
      /* $FlowFixMe(>=0.53.0 site=www,mobile) This comment suppresses an error
       * when upgrading Flow's support for React. Common errors found when
       * upgrading Flow's React support are documented at
       * https://fburl.com/eq7bs81w */
      customStyleFn,
      editorState,
    } = this.props;

    const content = editorState.getCurrentContent();
    const selection = editorState.getSelection();
    const forceSelection = editorState.mustForceSelection();
    const decorator = editorState.getDecorator();
    const directionMap = nullthrows(editorState.getDirectionMap());

    const blocksAsArray = content.getBlocksAsArray();
    const processedBlocks = [];
    let currentDepth = null;
    let lastWrapperTemplate = null;

    for (let ii = 0; ii < blocksAsArray.length; ii++) {
      const block = blocksAsArray[ii];
      const key = block.getKey();
      const blockType = block.getType();

      const customRenderer = blockRendererFn(block);
      let CustomComponent, customProps, customEditable;
      if (customRenderer) {
        CustomComponent = customRenderer.component;
        customProps = customRenderer.props;
        customEditable = customRenderer.editable;
      }

      const {textDirectionality} = this.props;
      const direction = textDirectionality
        ? textDirectionality
        : directionMap.get(key);
      const offsetKey = DraftOffsetKey.encode(key, 0, 0);
      const componentProps = {
        contentState: content,
        block,
        blockProps: customProps,
        customStyleMap,
        customStyleFn,
        decorator,
        direction,
        forceSelection,
        key,
        offsetKey,
        selection,
        tree: editorState.getBlockTree(key),
      };

      const configForType = blockRenderMap.get(blockType);
      const wrapperTemplate = configForType.wrapper;

      const Element = (
        configForType.element ||
        blockRenderMap.get('unstyled').element
      );

      const depth = block.getDepth();
      let className = this.props.blockStyleFn(block);

      // List items are special snowflakes, since we handle nesting and
      // counters manually.
      if (Element === 'li') {
        const shouldResetCount = (
          lastWrapperTemplate !== wrapperTemplate ||
          currentDepth === null ||
          depth > currentDepth
        );
        className = joinClasses(
          className,
          getListItemClasses(blockType, depth, shouldResetCount, direction),
        );
      }

      const Component = CustomComponent || DraftEditorBlock;
      let childProps = {
        className,
        'data-block': true,
        /* $FlowFixMe(>=0.53.0 site=www,mobile) This comment suppresses an
         * error when upgrading Flow's support for React. Common errors found
         * when upgrading Flow's React support are documented at
         * https://fburl.com/eq7bs81w */
        'data-editor': this.props.editorKey,
        'data-offset-key': offsetKey,
        key,
      };
      if (customEditable !== undefined) {
        childProps = {
          ...childProps,
          contentEditable: customEditable,
          suppressContentEditableWarning: true,
        };
      }

      const child = React.createElement(
        Element,
        childProps,
        /* $FlowFixMe(>=0.53.0 site=www,mobile) This comment suppresses an
         * error when upgrading Flow's support for React. Common errors found
         * when upgrading Flow's React support are documented at
         * https://fburl.com/eq7bs81w */
        <Component {...componentProps} />,
      );

      processedBlocks.push({
        block: child,
        wrapperTemplate,
        key,
        offsetKey,
      });

      if (wrapperTemplate) {
        currentDepth = block.getDepth();
      } else {
        currentDepth = null;
      }
      lastWrapperTemplate = wrapperTemplate;
    }

    // Group contiguous runs of blocks that have the same wrapperTemplate
    const outputBlocks = [];
    for (let ii = 0; ii < processedBlocks.length; ) {
      const info = processedBlocks[ii];
      if (info.wrapperTemplate) {
        const blocks = [];
        do {
          blocks.push(processedBlocks[ii].block);
          ii++;
        } while (
          ii < processedBlocks.length &&
          processedBlocks[ii].wrapperTemplate === info.wrapperTemplate
        );
        const wrapperElement = React.cloneElement(
          info.wrapperTemplate,
          {
            key: info.key + '-wrap',
            'data-offset-key': info.offsetKey,
          },
          blocks,
        );
        outputBlocks.push(wrapperElement);
      } else {
        outputBlocks.push(info.block);
        ii++;
      }
    }

    return <div data-contents="true">{outputBlocks}</div>;
  }
  render(): React.Element {
    const {blockRendererFn, customStyleMap, editorState} = this.props;
    const content = editorState.getCurrentContent();
    const selection = editorState.getSelection();
    const forceSelection = editorState.mustForceSelection();
    const decorator = editorState.getDecorator();
    const directionMap = nullthrows(editorState.getDirectionMap());

    const blocksAsArray = content.getBlocksAsArray();
    const blocks = [];
    let currentWrapperElement = null;
    let currentWrapperTemplate = null;
    let currentDepth = null;
    let currentWrappedBlocks;
    let block, key, blockType, child, wrapperTemplate;

    for (let ii = 0; ii < blocksAsArray.length; ii++) {
      block = blocksAsArray[ii];
      key = block.getKey();
      blockType = block.getType();

      const customRenderer = blockRendererFn(block);
      let CustomComponent, customProps;
      if (customRenderer) {
        CustomComponent = customRenderer.component;
        customProps = customRenderer.props;
      }

      const direction = directionMap.get(key);
      const offsetKey = DraftOffsetKey.encode(key, 0, 0);
      const componentProps = {
        block,
        blockProps: customProps,
        customStyleMap,
        decorator,
        direction,
        forceSelection,
        key,
        offsetKey,
        selection,
        tree: editorState.getBlockTree(key),
      };

      wrapperTemplate = getWrapperTemplateForBlockType(blockType);
      const useNewWrapper = wrapperTemplate !== currentWrapperTemplate;

      if (CustomComponent) {
        child = <CustomComponent {...componentProps} />;
      } else {
        const Element = getElementForBlockType(blockType);
        const depth = block.getDepth();
        let className = this.props.blockStyleFn(block);

        // List items are special snowflakes, since we handle nesting and
        // counters manually.
        if (Element === 'li') {
          const shouldResetCount = (
            useNewWrapper ||
            currentDepth === null ||
            depth > currentDepth
          );
          className = joinClasses(
            className,
            getListItemClasses(blockType, depth, shouldResetCount, direction)
          );
        }

        // $FlowFixMe: Support DOM elements in React.createElement
        child = React.createElement(
          Element,
          {
            className,
            'data-block': true,
            'data-editor': this.props.editorKey,
            'data-offset-key': offsetKey,
            key,
          },
          <DraftEditorBlock {...componentProps} />,
        );
      }

      if (wrapperTemplate) {
        if (useNewWrapper) {
          currentWrappedBlocks = [];
          currentWrapperElement = React.cloneElement(
            wrapperTemplate,
            {
              key: key + '-wrap',
              'data-offset-key': offsetKey,
            },
            currentWrappedBlocks
          );
          currentWrapperTemplate = wrapperTemplate;
          blocks.push(currentWrapperElement);
        }
        currentDepth = block.getDepth();
        nullthrows(currentWrappedBlocks).push(child);
      } else {
        currentWrappedBlocks = null;
        currentWrapperElement = null;
        currentWrapperTemplate = null;
        currentDepth = null;
        blocks.push(child);
      }
    }

    return <div data-contents="true">{blocks}</div>;
  }