```coffeescript
module.exports =
class OverlayManager
  constructor: (@container) ->
    @overlays = {}

  render: (props) ->
    {presenter, editor, overlayDecorations} = props
    lineHeight = presenter.getLineHeight()

    existingDecorations = null
    for markerId, {headPixelPosition, tailPixelPosition, decorations} of overlayDecorations
      for decoration in decorations
        pixelPosition =
          if decoration.position is 'tail' then tailPixelPosition else headPixelPosition

        @renderOverlay(editor, decoration, pixelPosition, lineHeight)

        existingDecorations ?= {}
        existingDecorations[decoration.id] = true

    for id, overlay of @overlays
      unless existingDecorations? and id of existingDecorations
        @container.removeChild(overlay)
        delete @overlays[id]

    return

  renderOverlay: (editor, decoration, pixelPosition, lineHeight) ->
    item = atom.views.getView(decoration.item)
    unless overlay = @overlays[decoration.id]
      overlay = @overlays[decoration.id] = document.createElement('atom-overlay')
      overlay.appendChild(item)
      @container.appendChild(overlay)

    itemWidth = item.offsetWidth
    itemHeight = item.offsetHeight

    left = pixelPosition.left
    if left + itemWidth - editor.getScrollLeft() > editor.getWidth() and left - itemWidth >= editor.getScrollLeft()
      left -= itemWidth

    top = pixelPosition.top + lineHeight
    if top + itemHeight - editor.getScrollTop() > editor.getHeight() and top - itemHeight - lineHeight >= editor.getScrollTop()
      top -= itemHeight + lineHeight

    overlay.style.top = top + 'px'
    overlay.style.left = left + 'px'
```

Use presenter for rendering overlay decorations
user
```coffeescript
module.exports =
class OverlayManager
  constructor: (@container) ->
    @overlayNodesById = {}

  render: (props) ->
    {presenter} = props

    for decorationId, {pixelPosition, item} of presenter.state.content.overlays
      @renderOverlay(presenter, decorationId, item, pixelPosition)

    for id, overlayNode of @overlayNodesById
      unless presenter.state.content.overlays.hasOwnProperty(id)
        overlayNode.remove()
        delete @overlayNodesById[id]

    return

  renderOverlay: (presenter, decorationId, item, pixelPosition) ->
    item = atom.views.getView(item)
    unless overlayNode = @overlayNodesById[decorationId]
      overlayNode = @overlayNodesById[decorationId] = document.createElement('atom-overlay')
      overlayNode.appendChild(item)
      @container.appendChild(overlayNode)

    itemWidth = item.offsetWidth
    itemHeight = item.offsetHeight


    {scrollTop} = presenter.state
    {scrollLeft} = presenter.state.content

    left = pixelPosition.left
    if left + itemWidth - scrollLeft > presenter.getClientWidth() and left - itemWidth >= scrollLeft
      left -= itemWidth

    top = pixelPosition.top + presenter.getLineHeight()
    if top + itemHeight - scrollTop > presenter.getClientHeight() and top - itemHeight - presenter.getLineHeight() >= scrollTop
      top -= itemHeight + presenter.getLineHeight()

    overlayNode.style.top = top + 'px'
    overlayNode.style.left = left + 'px'
```
assistant