/**
   * Handling span
   *
   * @param cursor text cursor
   * @param blockEnd span search limit
   * @param elements current elements
   * @return is
   */
  private boolean handleSpan(TextCursor cursor, int blockEnd, ArrayList<MDText> elements) {
    if (mode != MODE_ONLY_LINKS) {
      int spanStart = findSpanStart(cursor, blockEnd);
      if (spanStart >= 0) {
        char span = cursor.text.charAt(spanStart);
        int spanEnd = findSpanEnd(cursor, spanStart, blockEnd, span);
        if (spanEnd >= 0) {
          handleUrls(cursor, spanStart, elements);

          MDText[] spanElements = handleSpans(cursor, spanEnd - 1);
          cursor.currentOffset = spanEnd;

          MDSpan spanElement =
              new MDSpan(span == '*' ? MDSpan.TYPE_BOLD : MDSpan.TYPE_ITALIC, spanElements);

          elements.add(spanElement);

          return true;
        }
      }
    }

    handleUrls(cursor, blockEnd, elements);

    return false;
  }
  /**
   * Outer parsing method: Processing code blocks first
   *
   * @param cursor text cursor
   * @param paragraphs current paragraphs
   * @return is code block found
   */
  private boolean handleCodeBlock(TextCursor cursor, ArrayList<MDSection> paragraphs) {
    if (mode != MODE_ONLY_LINKS) {
      int blockStart = findCodeBlockStart(cursor);
      if (blockStart >= 0) {
        int blockEnd = findCodeBlockEnd(cursor, blockStart);
        if (blockEnd >= 0) {
          // Adding Text Block if there are some elements before code block
          if (cursor.currentOffset < blockStart) {
            handleTextBlock(cursor, blockStart, paragraphs);
          }

          String codeContent = cursor.text.substring(cursor.currentOffset + 3, blockEnd - 3);
          cursor.currentOffset = blockEnd;
          paragraphs.add(new MDSection(new MDCode(codeContent)));
          return true;
        }
      }
    }

    // Adding remaining text blocks
    if (cursor.currentOffset < cursor.text.length()) {
      handleTextBlock(cursor, cursor.text.length(), paragraphs);
    }
    return false;
  }
  private boolean handleUrl(TextCursor cursor, int limit, ArrayList<MDText> elements) {
    Url url = findUrl(cursor, limit);
    if (url != null) {
      handleText(cursor, url.getStart(), elements);
      String title = cursor.text.substring(url.getStart() + 1, url.getMiddle());
      String urlVal = cursor.text.substring(url.getMiddle() + 2, url.getEnd());
      elements.add(new MDUrl(title, urlVal));
      cursor.currentOffset = url.getEnd() + 1;
      return true;
    }

    handleText(cursor, limit, elements);
    return false;
  }
 /**
  * Processing text blocks between code blocks
  *
  * @param cursor text cursor
  * @param blockEnd text block end
  * @param paragraphs current paragraphs
  */
 private void handleTextBlock(TextCursor cursor, int blockEnd, ArrayList<MDSection> paragraphs) {
   MDText[] spans = handleSpans(cursor, blockEnd);
   paragraphs.add(new MDSection(spans));
   cursor.currentOffset = blockEnd;
 }
 /**
  * Handling raw text block
  *
  * @param cursor text cursor
  * @param limit text end
  * @param elements current elements
  */
 private void handleText(TextCursor cursor, int limit, ArrayList<MDText> elements) {
   if (cursor.currentOffset < limit) {
     elements.add(new MDRawText(cursor.text.substring(cursor.currentOffset, limit)));
     cursor.currentOffset = limit + 1;
   }
 }