"use strict";

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = TutorialEditor;

var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));

var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));

var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));

var _react = _interopRequireWildcard(require("react"));

var _propTypes = _interopRequireDefault(require("prop-types"));

var _lodash = _interopRequireDefault(require("lodash"));

var _supportedLanguages = _interopRequireDefault(require("@readme/oas-to-snippet/src/supportedLanguages"));

var _components = require("../../../../components");

var _Method = _interopRequireDefault(require("../../../../components/Method"));

var _Menu = _interopRequireDefault(require("../../../../components/Menu"));

var _Divider = _interopRequireDefault(require("../../../../components/Menu/Divider"));

var _Header = _interopRequireDefault(require("../../../../components/Menu/Header"));

var _Item = _interopRequireDefault(require("../../../../components/Menu/Item"));

var ApiActions = _interopRequireWildcard(require("../../apiActions"));

var _useReadmeApi2 = _interopRequireDefault(require("../../../../../core/hooks/useReadmeApi"));

var _tutorials = require("../../proptypes/tutorials");

var _apiEndpoints = require("../../proptypes/apiEndpoints");

var _2 = require("../..");

// 3rd-Party Libraries
// Readme Libs
// Components
// Internals
// Constants
// Permissions
// Readme Libs
var syntaxHighlighter = typeof window !== 'undefined' ? require('@readme/syntax-highlighter/dist/index.js')["default"] : function () {}; // Style

var classes = {};
/* istanbul ignore next */

if (typeof window !== 'undefined' || typeof _COMPILED_ === 'undefined') classes = {
  "slate": "#384248",
  "blue": "#118CFD",
  "green": "#12CA93",
  "red": "#E95F6A",
  "yellow": "#F7C543",
  "purple": "#8470BE",
  "graphite": "#4F5A66",
  "shale": "#939EAE",
  "chalk": "#c6cbd3",
  "ivory": "#F0F0F0",
  "lightGray": "#F8F8F8",
  "white": "#FFF",
  "TutorialEditor-Nav": "_3K_jm-TutorialEditor-Nav",
  "TutorialEditor-Nav-Tab": "_2pc3x-TutorialEditor-Nav-Tab",
  "TutorialEditor-Nav-Tab_active": "_34eyE-TutorialEditor-Nav-Tab_active",
  "TutorialEditor-Nav-Plus": "_3iTeM-TutorialEditor-Nav-Plus",
  "TutorialEditor-Nav-Plus-ClearWrapper": "_1JWw6-TutorialEditor-Nav-Plus-ClearWrapper",
  "TutorialEditor-Nav-Menu": "_1D6XC-TutorialEditor-Nav-Menu",
  "TutorialEditor-Nav-Menu-List": "_1VhcI-TutorialEditor-Nav-Menu-List",
  "TutorialEditor-Nav-Menu-List_overflow": "_28d1i-TutorialEditor-Nav-Menu-List_overflow",
  "TutorialEditor-Nav-Menu-List_onboarding": "_18W5p-TutorialEditor-Nav-Menu-List_onboarding",
  "TutorialEditor-Nav-Menu-Method": "_39PB_-TutorialEditor-Nav-Menu-Method",
  "TutorialEditor-Nav-Menu-ReferenceGuide": "_20TLL-TutorialEditor-Nav-Menu-ReferenceGuide",
  "TutorialEditor-Nav-Menu-ReferenceGuide-Description": "_7W0Fb-TutorialEditor-Nav-Menu-ReferenceGuide-Description",
  "TutorialEditor-Nav-Menu-ReferenceGuide-Description-Button": "_3yKN--TutorialEditor-Nav-Menu-ReferenceGuide-Description-Button",
  "TutorialEditor-Nav-Menu-ReferenceGuide-Avatar": "_2_rvX-TutorialEditor-Nav-Menu-ReferenceGuide-Avatar",
  "TutorialEditor-Nav-Button": "JweRn-TutorialEditor-Nav-Button",
  "TutorialEditor-Nav-Button-Link-Icon": "_3OLcE-TutorialEditor-Nav-Button-Link-Icon",
  "TutorialEditor-Nav-Button-Text": "_1XGVc-TutorialEditor-Nav-Button-Text",
  "TutorialEditor-Nav-Menu-Text": "_38HJb-TutorialEditor-Nav-Menu-Text",
  "TutorialEditor-Controls": "_5li2B-TutorialEditor-Controls",
  "TutorialEditor-Controls-ControlWrapper": "_3MDg5-TutorialEditor-Controls-ControlWrapper",
  "TutorialEditor-Controls-ControlWrapper_select": "_3A-md-TutorialEditor-Controls-ControlWrapper_select",
  "TutorialEditor-Controls-ControlWrapper-Select": "_3wkmU-TutorialEditor-Controls-ControlWrapper-Select",
  "TutorialEditor-Controls-ControlWrapper-Input": "_3ONXt-TutorialEditor-Controls-ControlWrapper-Input",
  "TutorialEditor-Controls-ControlWrapper-Tooltip": "_2K4_M-TutorialEditor-Controls-ControlWrapper-Tooltip",
  "TutorialEditor-Controls-Delete": "_2Cjvx-TutorialEditor-Controls-Delete"
};

var LanguageDropdown = function LanguageDropdown(_ref) {
  var languageOpts = _ref.languageOpts,
      index = _ref.index,
      props = (0, _objectWithoutProperties2["default"])(_ref, ["languageOpts", "index"]);
  var maxTabCount = 4;
  var defaultLang = JSON.stringify({
    language: 'node-simple',
    highlightedSyntax: 'javascript'
  });

  var _useState = (0, _react.useState)(defaultLang),
      _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
      dropdownVal = _useState2[0],
      setVal = _useState2[1];

  var handleTabCreate = function handleTabCreate() {
    try {
      var _JSON$parse = JSON.parse(dropdownVal),
          language = _JSON$parse.language,
          highlightedSyntax = _JSON$parse.highlightedSyntax;

      if (language) {
        props.handleTabCreate({
          language: language,
          highlightedSyntax: highlightedSyntax
        });
        setVal(defaultLang);
      }
    } catch (e) {// Do nothing
    }
  };

  return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, index < maxTabCount && /*#__PURE__*/_react["default"].createElement(_components.Dropdown, {
    className: classes['TutorialEditor-Nav-Plus']
  }, /*#__PURE__*/_react["default"].createElement(_components.Button, {
    bem: {
      white_text: true
    }
  }, /*#__PURE__*/_react["default"].createElement("i", {
    className: "fa fa-plus-circle"
  })), /*#__PURE__*/_react["default"].createElement("div", {
    className: classes['TutorialEditor-Nav-Plus-ClearWrapper']
  }, /*#__PURE__*/_react["default"].createElement(_components.Box, {
    bem: [['pop']],
    style: {
      padding: 0
    }
  }, /*#__PURE__*/_react["default"].createElement(_Menu["default"], null, /*#__PURE__*/_react["default"].createElement(_Item["default"], {
    TagName: "div"
  }, /*#__PURE__*/_react["default"].createElement(_components.Select, {
    onChange: function onChange(e) {
      return setVal(e.target.value);
    },
    options: languageOpts,
    size: "sm",
    value: dropdownVal
  })), /*#__PURE__*/_react["default"].createElement(_Divider["default"], null), /*#__PURE__*/_react["default"].createElement(_Item["default"], {
    color: "blue",
    onClick: handleTabCreate
  }, "Create Tab"))))));
};

LanguageDropdown.propTypes = {
  handleTabCreate: _propTypes["default"].func,
  index: _propTypes["default"].number,
  languageOpts: _propTypes["default"].arrayOf(_propTypes["default"].shape({
    label: _propTypes["default"].string,
    value: _propTypes["default"].string
  }))
};

var SnippetLanguageMenu = function SnippetLanguageMenu(_ref2) {
  var codeOptions = _ref2.codeOptions,
      languageOpts = _ref2.languageOpts,
      readOnly = _ref2.readOnly,
      setSelectedTab = _ref2.setSelectedTab,
      selectedTab = _ref2.selectedTab,
      props = (0, _objectWithoutProperties2["default"])(_ref2, ["codeOptions", "languageOpts", "readOnly", "setSelectedTab", "selectedTab"]);

  var handleTabCreate = function handleTabCreate(_ref3) {
    var language = _ref3.language,
        highlightedSyntax = _ref3.highlightedSyntax;
    // Basic scaffold for a new tab
    props.handleTabCreate({
      code: '',
      language: language,
      highlightedSyntax: highlightedSyntax,
      name: "".concat(language.charAt(0).toUpperCase()).concat(language.slice(1))
    });
  };

  var tutorialTabClasses = function tutorialTabClasses(index) {
    return [classes['TutorialEditor-Nav-Tab'], index === selectedTab && classes['TutorialEditor-Nav-Tab_active']].filter(function (e) {
      return e;
    }).join(' ');
  };

  return /*#__PURE__*/_react["default"].createElement(_components.Flex, null, codeOptions && codeOptions.map(function (opt, index) {
    return /*#__PURE__*/_react["default"].createElement(_components.Button, {
      key: index,
      bem: {
        white_text: true
      },
      className: "".concat(tutorialTabClasses(index)),
      onClick: function onClick() {
        return setSelectedTab(index);
      }
    }, opt.name);
  }), !readOnly && /*#__PURE__*/_react["default"].createElement(LanguageDropdown, {
    handleTabCreate: handleTabCreate,
    index: codeOptions.length - 1,
    languageOpts: languageOpts
  }));
};

SnippetLanguageMenu.propTypes = {
  codeOptions: _propTypes["default"].arrayOf(_tutorials.CodeOptionProp),
  handleTabCreate: _propTypes["default"].func,
  languageOpts: _propTypes["default"].arrayOf(_propTypes["default"].shape({
    label: _propTypes["default"].string,
    value: _propTypes["default"].string
  })),
  readOnly: _propTypes["default"].bool,
  selectedTab: _propTypes["default"].number,
  setSelectedTab: _propTypes["default"].func
};

var EndpointSelector = function EndpointSelector(_ref4) {
  var baseUrl = _ref4.baseUrl,
      endpointOnboarding = _ref4.endpointOnboarding,
      endpoints = _ref4.endpoints,
      codeOptions = _ref4.codeOptions,
      selectedEndpoint = _ref4.selectedEndpoint,
      readOnly = _ref4.readOnly,
      requestDataRefresh = _ref4.requestDataRefresh,
      handleSnippetSelection = _ref4.handleSnippetSelection,
      clearSnippetSelection = _ref4.clearSnippetSelection;

  var _useReadmeApi = (0, _useReadmeApi2["default"])(baseUrl),
      response = _useReadmeApi.response,
      initRequest = _useReadmeApi.initRequest;

  (0, _react.useEffect)(function () {
    if (response.success) requestDataRefresh();
  }, [response]);
  return /*#__PURE__*/_react["default"].createElement(_components.Dropdown, {
    justify: "right",
    open: !endpointOnboarding && selectedEndpoint && !selectedEndpoint.title,
    sticky: !endpointOnboarding
  }, (!readOnly || selectedEndpoint && selectedEndpoint.title) && /*#__PURE__*/_react["default"].createElement(_components.Button, (0, _extends2["default"])({
    bem: {
      white_text: true
    },
    className: classes['TutorialEditor-Nav-Button'],
    title: selectedEndpoint && selectedEndpoint.title || ''
  }, readOnly && selectedEndpoint && selectedEndpoint.slug && {
    href: "".concat(baseUrl, "/reference-link/").concat(selectedEndpoint.slug),
    rel: 'noopener noreferrer',
    target: '_blank'
  }), selectedEndpoint && selectedEndpoint.method && /*#__PURE__*/_react["default"].createElement(_Method["default"], {
    type: selectedEndpoint.method.toLowerCase()
  }), /*#__PURE__*/_react["default"].createElement("span", {
    className: classes['TutorialEditor-Nav-Button-Text']
  }, selectedEndpoint && selectedEndpoint.title || 'Choose Endpoint'), !readOnly && /*#__PURE__*/_react["default"].createElement("i", {
    className: "fa fa-chevron-down"
  }), readOnly && selectedEndpoint && selectedEndpoint.slug && /*#__PURE__*/_react["default"].createElement("i", {
    className: ['fa fa-arrow-circle-up', classes['TutorialEditor-Nav-Button-Link-Icon']].join(' ')
  })), !readOnly && /*#__PURE__*/_react["default"].createElement(_components.Box, {
    bem: [['pop']],
    className: classes['TutorialEditor-Nav-Menu']
  }, !endpointOnboarding && selectedEndpoint && !selectedEndpoint.title && /*#__PURE__*/_react["default"].createElement("div", {
    className: classes['TutorialEditor-Nav-Menu-ReferenceGuide']
  }, /*#__PURE__*/_react["default"].createElement("span", {
    "aria-label": "finger pointing up",
    className: classes['TutorialEditor-Nav-Menu-ReferenceGuide-Avatar'],
    role: "img"
  }, "\u261D\uFE0F"), /*#__PURE__*/_react["default"].createElement("p", {
    className: classes['TutorialEditor-Nav-Menu-ReferenceGuide-Description']
  }, "Start from one of your API endpoints, or write a tutorial from scratch.", /*#__PURE__*/_react["default"].createElement("button", {
    className: classes['TutorialEditor-Nav-Menu-ReferenceGuide-Description-Button'],
    onClick: function onClick() {
      return ApiActions.updateOnboarding(initRequest, {
        endpoints: true
      });
    },
    type: "button"
  }, "Don\u2019t show again"))), /*#__PURE__*/_react["default"].createElement(_Menu["default"], {
    className: [classes['TutorialEditor-Nav-Menu-List'], !endpointOnboarding ? classes['TutorialEditor-Nav-Menu-List_onboarding'] : '', endpoints.length === 1 ? classes['TutorialEditor-Nav-Menu-List_overflow'] : ''].join(' ')
  }, selectedEndpoint && selectedEndpoint.title && /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement(_Header["default"], null, selectedEndpoint.title), /*#__PURE__*/_react["default"].createElement(_Item["default"], {
    color: "red",
    onClick: clearSnippetSelection
  }, "Clear Selection"), /*#__PURE__*/_react["default"].createElement(_Divider["default"], null)), endpoints && endpoints.length === 1 && endpoints.map(function (endpoint, index) {
    return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, {
      key: "tutorial-endpoint-group-".concat(index)
    }, /*#__PURE__*/_react["default"].createElement(_Header["default"], {
      title: endpoint.title
    }, endpoint.title), endpoint.children.map(function (child, idx) {
      return /*#__PURE__*/_react["default"].createElement(_Item["default"], {
        key: "tutorial-endpoint-opt-".concat(idx),
        onClick: function onClick() {
          return handleSnippetSelection({
            page: child,
            codeOptions: codeOptions
          });
        },
        title: child.title
      }, /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement(_Method["default"], {
        className: classes['TutorialEditor-Nav-Menu-Method'],
        type: child.api.method.toLowerCase(),
        width: 40
      }), /*#__PURE__*/_react["default"].createElement("span", {
        className: classes['TutorialEditor-Nav-Menu-Text']
      }, child.title)));
    }));
  }), endpoints && endpoints.length > 1 && /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement(_Header["default"], null, "API Definitions"), endpoints.map(function (endpoint, index) {
    return /*#__PURE__*/_react["default"].createElement(_Item["default"], {
      key: "tutorial-endpoint-group-".concat(index),
      openAt: "left",
      title: endpoint.title
    }, endpoint.title, /*#__PURE__*/_react["default"].createElement(_Menu["default"], null, /*#__PURE__*/_react["default"].createElement(_Header["default"], null, endpoint.title), endpoint.children.map(function (child, idx) {
      return /*#__PURE__*/_react["default"].createElement(_Item["default"], {
        key: "tutorial-endpoint-opt-".concat(idx),
        onClick: function onClick() {
          return handleSnippetSelection({
            page: child,
            codeOptions: codeOptions
          });
        },
        title: child.title
      }, /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement(_Method["default"], {
        className: classes['TutorialEditor-Nav-Menu-Method'],
        type: child.api.method.toLowerCase(),
        width: 40
      }), /*#__PURE__*/_react["default"].createElement("span", {
        className: classes['TutorialEditor-Nav-Menu-Text']
      }, child.title)));
    })));
  })))));
};

EndpointSelector.propTypes = {
  baseUrl: _propTypes["default"].string,
  clearSnippetSelection: _propTypes["default"].func,
  codeOptions: _propTypes["default"].arrayOf(_tutorials.CodeOptionProp),
  endpointOnboarding: _propTypes["default"].bool,
  endpoints: _propTypes["default"].arrayOf(_apiEndpoints.ApiEndpointProp),
  handleSnippetSelection: _propTypes["default"].func,
  readOnly: _propTypes["default"].bool,
  requestDataRefresh: _propTypes["default"].func,
  selectedEndpoint: _tutorials.EndpointProp
};

var TabControls = function TabControls(_ref5) {
  var codeOption = _ref5.codeOption,
      selectedLines = _ref5.selectedLines,
      languageOpts = _ref5.languageOpts,
      selectedTab = _ref5.selectedTab,
      isOnlyTab = _ref5.isOnlyTab,
      handleLineUpdate = _ref5.handleLineUpdate,
      handleTabUpdate = _ref5.handleTabUpdate,
      handleTabDelete = _ref5.handleTabDelete;
  var lineNumberRegex = /^[0-9,-]+$/;
  var maxLength = 20;

  var handleLineInput = function handleLineInput(event) {
    var value = event.target.value;

    if (!value || lineNumberRegex.test(value)) {
      handleLineUpdate(value);
    }
  };

  var handleNameInput = function handleNameInput(event, key) {
    var value = event.target.value;
    if (value.length >= maxLength) event.target.value = value.slice(0, maxLength);
    handleTabUpdate(event, key);
  };

  var language = codeOption.language,
      highlightedSyntax = codeOption.highlightedSyntax;
  return /*#__PURE__*/_react["default"].createElement("div", {
    className: classes['TutorialEditor-Controls']
  }, /*#__PURE__*/_react["default"].createElement("label", {
    className: [classes['TutorialEditor-Controls-ControlWrapper'], classes['TutorialEditor-Controls-ControlWrapper_select']].join(' ')
  }, /*#__PURE__*/_react["default"].createElement("span", null, "Language"), /*#__PURE__*/_react["default"].createElement("select", {
    className: classes['TutorialEditor-Controls-ControlWrapper-Select'],
    onChange: function onChange(e) {
      return handleTabUpdate(e, 'language');
    },
    value: JSON.stringify({
      language: language,
      highlightedSyntax: highlightedSyntax
    })
  }, languageOpts.map(function (_ref6, idx) {
    var value = _ref6.value,
        label = _ref6.label;
    return /*#__PURE__*/_react["default"].createElement("option", {
      key: "tab-control-language-".concat(idx),
      value: value
    }, label);
  }))), /*#__PURE__*/_react["default"].createElement("label", {
    className: classes['TutorialEditor-Controls-ControlWrapper']
  }, /*#__PURE__*/_react["default"].createElement("span", null, "Highlight"), /*#__PURE__*/_react["default"].createElement("input", {
    className: classes['TutorialEditor-Controls-ControlWrapper-Input'],
    onChange: handleLineInput,
    placeholder: "1,4,7-9",
    value: selectedLines
  }), /*#__PURE__*/_react["default"].createElement("i", {
    className: ['fa fa-question', classes['TutorialEditor-Controls-ControlWrapper-Tooltip']].join(' '),
    "data-tooltip": "Highlight multiple lines with commas and hyphens",
    "data-tooltip-position": "right"
  })), /*#__PURE__*/_react["default"].createElement("label", {
    className: classes['TutorialEditor-Controls-ControlWrapper']
  }, /*#__PURE__*/_react["default"].createElement("span", null, "Name"), /*#__PURE__*/_react["default"].createElement("input", {
    className: classes['TutorialEditor-Controls-ControlWrapper-Input'],
    maxLength: maxLength,
    onChange: function onChange(e) {
      return handleNameInput(e, 'name');
    },
    spellCheck: "false",
    value: codeOption.name
  })), /*#__PURE__*/_react["default"].createElement("button", {
    className: classes['TutorialEditor-Controls-Delete'],
    "data-tooltip": isOnlyTab ? 'Must have at least one tab' : '',
    "data-tooltip-position": "left",
    disabled: isOnlyTab,
    onClick: function onClick() {
      return handleTabDelete(selectedTab);
    },
    type: "button"
  }, "Delete Tab"));
};

TabControls.propTypes = {
  codeOption: _tutorials.CodeOptionProp,
  handleLineUpdate: _propTypes["default"].func,
  handleTabDelete: _propTypes["default"].func,
  handleTabUpdate: _propTypes["default"].func,
  isOnlyTab: _propTypes["default"].bool,
  languageOpts: _propTypes["default"].arrayOf(_propTypes["default"].shape({
    label: _propTypes["default"].string,
    value: _propTypes["default"].string
  })),
  selectedLines: _propTypes["default"].string,
  selectedTab: _propTypes["default"].number
};

function TutorialEditor(_ref7) {
  var baseUrl = _ref7.baseUrl,
      snippet = _ref7.snippet,
      endpointOnboarding = _ref7.endpointOnboarding,
      endpoints = _ref7.endpoints,
      lineNumbers = _ref7.lineNumbers,
      referenceEnabled = _ref7.referenceEnabled,
      requestDataRefresh = _ref7.requestDataRefresh,
      selectedTab = _ref7.selectedTab,
      setSelectedTab = _ref7.setSelectedTab,
      handleSnippetSelection = _ref7.handleSnippetSelection,
      clearSnippetSelection = _ref7.clearSnippetSelection,
      updateStep = _ref7.updateStep,
      updateSnippet = _ref7.updateSnippet,
      props = (0, _objectWithoutProperties2["default"])(_ref7, ["baseUrl", "snippet", "endpointOnboarding", "endpoints", "lineNumbers", "referenceEnabled", "requestDataRefresh", "selectedTab", "setSelectedTab", "handleSnippetSelection", "clearSnippetSelection", "updateStep", "updateSnippet"]);

  var _useState3 = (0, _react.useState)(null),
      _useState4 = (0, _slicedToArray2["default"])(_useState3, 2),
      editorInstance = _useState4[0],
      setEditorInstance = _useState4[1];

  var _useState5 = (0, _react.useState)([]),
      _useState6 = (0, _slicedToArray2["default"])(_useState5, 2),
      rangeOpts = _useState6[0],
      setRangeOpts = _useState6[1];

  var codeOptions = snippet.codeOptions,
      endpoint = snippet.endpoint;
  var languageOpts = Object.keys(_supportedLanguages["default"]).map(function (language) {
    var highlightedSyntax = _supportedLanguages["default"][language].highlight;
    return {
      value: JSON.stringify({
        language: language,
        highlightedSyntax: highlightedSyntax
      }),
      label: language
    };
  }); // Converting between human readable `1, 2-5` to codemirror selection syntax

  var spreadLineNumbers = function spreadLineNumbers(ranges) {
    return ranges.split(',').map(function (range) {
      var _range$split = range.split('-'),
          _range$split2 = (0, _slicedToArray2["default"])(_range$split, 2),
          anchor = _range$split2[0],
          head = _range$split2[1];

      var end = head || anchor ? parseInt(head || anchor, 10) : 0;
      var start = parseInt(anchor || 0, 10) - 1;
      return [{
        ch: 0,
        line: start
      }, {
        ch: 0,
        line: end
      }];
    });
  }; // Get the defined dimensions based on the first selected range
  // to programmatically scroll. This is necessary because codemirror likes to put
  // a margin buffer in their component


  var getEditorDimensions = function getEditorDimensions(editor, range, readOnly) {
    var editorHeight = readOnly ? editor.offsetHeight : editor.getWrapperElement().offsetHeight;
    var lineHeight = 15;

    var _range = (0, _slicedToArray2["default"])(range, 2),
        start = _range[0],
        end = _range[1];

    var rangeHeight = (end.line - start.line) * lineHeight;
    var editorCenter = start.line * lineHeight - editorHeight / 2 - lineHeight / 2; // if there’s a range greater than one line

    if (rangeHeight > 15) {
      editorCenter += rangeHeight / 2; // if the range is larger than the editor

      if (rangeHeight > editorHeight) editorCenter = start.line * lineHeight - lineHeight;
    }

    return {
      editorHeight: editorHeight,
      editorCenter: editorCenter
    };
  };

  var markEditorInstance = function markEditorInstance(editor, ranges) {
    // Clear existing style tags from our editor instance
    editor.getAllMarks().forEach(function (mark) {
      return mark.clear();
    }); // Mark new ranges with classname

    ranges.forEach(function (_ref8) {
      var _ref9 = (0, _slicedToArray2["default"])(_ref8, 2),
          anchor = _ref9[0],
          head = _ref9[1];

      return editor.getDoc().markText(anchor, head, {
        className: 'CodeEditor-Highlight',
        addToHistory: true
      });
    }); // Scroll to the first range so that code is in viewport

    var _getEditorDimensions = getEditorDimensions(editor, ranges[0]),
        editorHeight = _getEditorDimensions.editorHeight,
        editorCenter = _getEditorDimensions.editorCenter;

    editor.setSize('100%', editorHeight);
    editor.scrollTo(0, editorCenter);
  }; // Editor user interaction marking
  // Called when lineNumbers is updated (via input or step/tab change)


  (0, _react.useEffect)(function () {
    var newLines = lineNumbers[selectedTab];

    if (newLines) {
      var ranges = spreadLineNumbers(newLines);
      if (!editorInstance) setRangeOpts(ranges);
      if (editorInstance) setTimeout(function () {
        return markEditorInstance(editorInstance, ranges);
      });
    }
  }, [lineNumbers[selectedTab], snippet.codeOptions[selectedTab].code, snippet.codeOptions.endpoint, editorInstance]); // getCode() is called when two conditions are fulfilled:
  // 1. When a snippet is already selected and assigned to the tutorial and a new tab is created
  // 2. When we create a new step
  // getCode will retrieve a code string and place it within the tab's target index

  var getCode = function getCode(language, index) {
    var page = snippet.endpoint.page;
    var pages = endpoints.reduce(function (arr, val) {
      return arr.concat(val.children);
    }, []);
    var foundPage = pages.find(function (_ref10) {
      var _id = _ref10._id;
      return _id === page;
    });
    if (foundPage) props.getCode({
      page: foundPage,
      language: language,
      index: index
    });
  };

  var handleTabCreate = function handleTabCreate(codeOption) {
    lineNumbers.push('');
    updateStep({
      lineNumbers: lineNumbers
    });
    codeOptions.push(codeOption);
    updateSnippet({
      codeOptions: codeOptions
    });
    setSelectedTab(codeOptions.length - 1);
    getCode(codeOption.language, snippet.codeOptions.length - 1);
  };

  var handleTabUpdate = function handleTabUpdate(event, key) {
    var value = event.target.value;

    if (key === 'language') {
      var _JSON$parse2 = JSON.parse(value),
          language = _JSON$parse2.language,
          highlightedSyntax = _JSON$parse2.highlightedSyntax;

      codeOptions[selectedTab].language = language;
      codeOptions[selectedTab].highlightedSyntax = highlightedSyntax;
    } else {
      codeOptions[selectedTab][key] = value;
    }

    updateSnippet({
      codeOptions: codeOptions
    });
  };

  var handleTabDelete = function handleTabDelete(index) {
    lineNumbers.splice(index, 1);
    updateStep({
      lineNumbers: lineNumbers
    });
    codeOptions.splice(index, 1);
    updateSnippet({
      codeOptions: codeOptions
    });
    setSelectedTab(0);
  };

  var handleLineUpdate = function handleLineUpdate(value) {
    lineNumbers[selectedTab] = value;
    updateStep({
      lineNumbers: lineNumbers
    });
  };

  var handleCodeChange = function handleCodeChange(_ref11, code, readOnly) {
    var origin = _ref11.origin;

    if (['+input', 'paste', '+delete'].includes(origin) && !readOnly) {
      codeOptions[selectedTab].code = code;
      updateSnippet({
        codeOptions: codeOptions
      });
    }
  };

  var checkCodeChange = process.env.NODE_ENV === 'test' ? handleCodeChange : _lodash["default"].debounce(handleCodeChange, 300);

  var codeMirrorOpts = function codeMirrorOpts(readOnly) {
    if (readOnly) {
      if (typeof window !== 'undefined' && rangeOpts.length) {
        var readOnlyEditor = document.querySelector('.TutorialEditor-Nav + .CodeEditor');

        var _getEditorDimensions2 = getEditorDimensions(readOnlyEditor, rangeOpts[0], readOnly),
            editorCenter = _getEditorDimensions2.editorCenter;

        readOnlyEditor.scroll({
          top: editorCenter,
          left: 0,
          behavior: 'auto'
        });
      }

      return {
        highlightMode: true,
        tokenizeVariables: true,
        ranges: rangeOpts
      };
    }

    return {
      editable: true
    };
  };

  return /*#__PURE__*/_react["default"].createElement(_2.PermissionContext.Consumer, null, function (readOnly) {
    return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement(_components.Flex, {
      align: "center",
      className: ['TutorialEditor-Nav', classes['TutorialEditor-Nav']].join(' '),
      justify: "between",
      tag: "nav"
    }, /*#__PURE__*/_react["default"].createElement(SnippetLanguageMenu, {
      codeOptions: codeOptions,
      handleTabCreate: handleTabCreate,
      languageOpts: languageOpts,
      readOnly: readOnly,
      selectedTab: selectedTab,
      setSelectedTab: setSelectedTab
    }), referenceEnabled && (readOnly || endpoints.length > 0) && /*#__PURE__*/_react["default"].createElement(EndpointSelector, {
      baseUrl: baseUrl,
      clearSnippetSelection: clearSnippetSelection,
      codeOptions: snippet.codeOptions,
      endpointOnboarding: endpointOnboarding,
      endpoints: endpoints,
      handleSnippetSelection: handleSnippetSelection,
      readOnly: readOnly,
      requestDataRefresh: requestDataRefresh,
      selectedEndpoint: endpoint
    })), syntaxHighlighter(codeOptions[selectedTab].code, codeOptions[selectedTab].highlightedSyntax, codeMirrorOpts(readOnly), {
      autoScroll: true,
      className: "CodeEditor-Input ".concat(readOnly && 'CodeEditor-Input_readonly' || ''),
      editorDidMount: setEditorInstance,
      onChange: function onChange(editor, data, code) {
        return checkCodeChange(data, code, readOnly);
      }
    }), !readOnly && /*#__PURE__*/_react["default"].createElement(TabControls, {
      codeOption: codeOptions[selectedTab],
      handleLineUpdate: handleLineUpdate,
      handleTabDelete: handleTabDelete,
      handleTabUpdate: handleTabUpdate,
      isOnlyTab: codeOptions.length === 1,
      languageOpts: languageOpts,
      selectedLines: lineNumbers[selectedTab],
      selectedTab: selectedTab
    }));
  });
}

TutorialEditor.propTypes = {
  baseUrl: _propTypes["default"].string,
  clearSnippetSelection: _propTypes["default"].func,
  endpointOnboarding: _propTypes["default"].bool,
  endpoints: _propTypes["default"].arrayOf(_apiEndpoints.ApiEndpointProp),
  getCode: _propTypes["default"].func,
  handleSnippetSelection: _propTypes["default"].func,
  lineNumbers: _propTypes["default"].arrayOf(_propTypes["default"].string),
  referenceEnabled: _propTypes["default"].bool,
  requestDataRefresh: _propTypes["default"].func,
  selectedTab: _propTypes["default"].number,
  setSelectedTab: _propTypes["default"].func,
  snippet: _tutorials.StepSnippetProp,
  updateSnippet: _propTypes["default"].func,
  updateStep: _propTypes["default"].func
};