Handles wrapping format strings around a selection
@param   {String} string         the entire string
@param   {Number[]}  selectionRange the starting and ending positions of the selection
@param   {String} symbol         the format string to use
@returns {Object} the new string, the updated selectionRange
function inlineHandler(string, selectionRange, symbol) {
  let newString = string;
  const newSelectionRange = [...selectionRange];
  // insertSymbols determines whether to add the symbol to either end of the selected text
  // Stat with assuming we will insert them (we will remove as necessary)
  const insertSymbols = [symbol, symbol];
  const symbolLength = symbol.length;
  const relevantPart = string.substring(selectionRange[0] - symbolLength, selectionRange[1] + symbolLength).trim();

  // First check that the symbol is in the string at all
  if (relevantPart.includes(symbol)) {
    // If it is, for each index in the selection range...
    newSelectionRange.forEach((selectionIndex, j) => {
      const isStartingIndex = j === 0;
      const isEndingIndex = j === 1;
      // If the symbol immediately precedes the selection index...
      if (newString.lastIndexOf(symbol, selectionIndex) === selectionIndex - symbolLength) {
        // First trim it
        newString = newString.substring(0, selectionIndex - symbolLength) + newString.substring(selectionIndex);

        // Then adjust the selection range,
        // If this is the starting index in the range, we will have to adjust both
        // starting and ending indices
        if (isStartingIndex) {
          newSelectionRange[0] -= symbolLength;
          newSelectionRange[1] -= symbolLength;
        }

        if (isEndingIndex && !insertSymbols[0]) {
          newSelectionRange[1] -= symbol.length;
        }

        // Finally, disallow the symbol at this end of the selection
        insertSymbols[j] = '';
      }

      // If the symbol immediately follows the selection index...
      if (newString.indexOf(symbol, selectionIndex) === selectionIndex) {
        // Trim it
        newString = newString.substring(0, selectionIndex) + newString.substring(selectionIndex + symbolLength);

        // Then adjust the selection range,
        // If this is the starting index in the range...
        if (isStartingIndex) {
          // If the starting and ending indices are NOT the same (selection length > 0)
          // Adjust the ending selection down
          if (newSelectionRange[0] !== newSelectionRange[1]) {
            newSelectionRange[1] -= symbolLength;
          }
          // If the starting and ending indices are the same (selection length = 0)
          // Adjust the starting selection down
          if (newSelectionRange[0] === newSelectionRange[1]) {
            newSelectionRange[0] -= symbolLength;
          }
        }

        // If this is the ending index and the range
        // AND we're inserting the symbol at the starting index,
        // Adjust the ending selection up
        if (isEndingIndex && insertSymbols[0]) {
          newSelectionRange[1] += symbolLength;
        }

        // Finally, disallow the symbol at this end of the selection
        insertSymbols[j] = '';
      }
    });
  }

  // Put it all together
  const value = newString.substring(0, newSelectionRange[0]) + insertSymbols[0] + newString.substring(newSelectionRange[0], newSelectionRange[1]) + insertSymbols[1] + newString.substring(newSelectionRange[1]);

  return {
    value,
    range: [newSelectionRange[0] + insertSymbols[0].length, newSelectionRange[1] + insertSymbols[1].length]
  };
}