parse(cfiStr) {
    var cfi = {
      spinePos: -1,
      range: false,
      base: {},
      path: {},
      start: null,
      end: null
    };
    var baseComponent, pathComponent, range;

    if (typeof cfiStr !== "string") {
      return {
        spinePos: -1
      };
    }

    if (cfiStr.indexOf("epubcfi(") === 0 && cfiStr[cfiStr.length - 1] === ")") {
      // Remove intial epubcfi( and ending )
      cfiStr = cfiStr.slice(8, cfiStr.length - 1);
    }

    baseComponent = this.getChapterComponent(cfiStr); // Make sure this is a valid cfi or return

    if (!baseComponent) {
      return {
        spinePos: -1
      };
    }

    cfi.base = this.parseComponent(baseComponent);
    pathComponent = this.getPathComponent(cfiStr);
    cfi.path = this.parseComponent(pathComponent);
    range = this.getRange(cfiStr);

    if (range) {
      cfi.range = true;
      cfi.start = this.parseComponent(range[0]);
      cfi.end = this.parseComponent(range[1]);
    } // Get spine node position
    // cfi.spineSegment = cfi.base.steps[1];
    // Chapter segment is always the second step


    cfi.spinePos = cfi.base.steps[1].index;
    return cfi;
  }
Parse a cfi string to a CFI object representation
@param {string} cfiStr
@returns {object} cfi