export function insertMarkdownText()

in app/assets/javascripts/lib/utils/text_markdown.js [434:593]


export function insertMarkdownText({
  textArea,
  text,
  tag,
  cursorOffset,
  blockTag,
  selected = '',
  wrap,
  select,
  editor,
}) {
  // If we aren't really inserting anything, let's just noop.
  // Let's check for `selected` too because there might be hidden logic that actually
  // is expected to run for this case.
  if (!tag && !blockTag && !selected) {
    return;
  }

  selected = selectSurroundingTags(textArea, tag) ?? selected;

  let removedLastNewLine = false;
  let removedFirstNewLine = false;
  let currentLineEmpty = false;
  const selectedLength = selected.length;
  const { selectionStart: textAreaSelectionStart, selectionEnd: textAreaSelectionEnd } =
    textArea || {};
  let editorSelectionStart;
  let editorSelectionEnd;
  let lastNewLine;
  let textToUpdate;
  selected = selected.toString();

  if (editor) {
    const selectionRange = getEditorSelectionRange(editor);

    editorSelectionStart = selectionRange.start;
    editorSelectionEnd = selectionRange.end;
  }

  // check for link pattern and selected text is an URL
  // if so fill in the url part instead of the text part of the pattern.
  if (tag === LINK_TAG_PATTERN) {
    if (isValidURL(selected)) {
      tag = '[text]({text})';
      select = 'text';
    }
  }

  // Remove the first newline
  if (selected.indexOf('\n') === 0) {
    removedFirstNewLine = true;
    selected = selected.replace(/\n+/, '');
  }

  // Remove the last newline
  if (textArea) {
    if (textArea.selectionEnd - textArea.selectionStart > selected.replace(/\n$/, '').length) {
      removedLastNewLine = true;
      selected = selected.replace(/\n$/, '');
    }
  } else if (editor) {
    if (editorSelectionStart.row !== editorSelectionEnd.row) {
      removedLastNewLine = true;
      selected = selected.replace(/\n$/, '');
    }
  }

  const selectedSplit = selected.split('\n');

  if (editor && !wrap) {
    lastNewLine = editor.getValue().split('\n')[editorSelectionStart.row];

    if (/^\s*$/.test(lastNewLine)) {
      currentLineEmpty = true;
    }
  } else if (textArea && !wrap) {
    lastNewLine = textArea.value.substr(0, textArea.selectionStart).lastIndexOf('\n');

    // Check whether the current line is empty or consists only of spaces(=handle as empty)
    if (/^\s*$/.test(textArea.value.substring(lastNewLine, textArea.selectionStart))) {
      currentLineEmpty = true;
    }
  }

  const isBeginning =
    (textArea && textArea.selectionStart === 0) ||
    (editor && editorSelectionStart.column === 0 && editorSelectionStart.row === 0);

  const startChar = !wrap && !currentLineEmpty && !isBeginning ? '\n' : '';
  const textPlaceholder = '{text}';

  const {
    shouldUseSelectedWithoutTags,
    removeTagFromLine,
    shouldRemoveTagFromLine,
    getSelectedWithoutTags,
    shouldPreserveTextAreaSelection,
  } = prepareInsertMarkdownText({ selected, tag, selectedSplit });

  const getSelectedWithTags = () => `${startChar}${tag}${selected}${wrap ? tag : ''}`;

  if (selectedSplit.length > 1 && (!wrap || (blockTag != null && blockTag !== ''))) {
    if (blockTag != null && blockTag !== '') {
      textToUpdate = editor
        ? editorBlockTagText(text, blockTag, selected, editor)
        : blockTagText(text, textArea, blockTag, selected);
    } else {
      textToUpdate = selectedSplit
        .map((line) => {
          if (tag.indexOf(textPlaceholder) > -1) {
            return tag.replace(textPlaceholder, line);
          }
          if (shouldRemoveTagFromLine(line)) {
            return removeTagFromLine(line);
          }
          return String(tag) + line;
        })
        .join('\n');
    }
  } else if (tag.indexOf(textPlaceholder) > -1) {
    textToUpdate = tag.replace(textPlaceholder, () =>
      selected.replace(/\\n/g, '\n').replace(/%br/g, '\\n'),
    );
  } else if (shouldUseSelectedWithoutTags) {
    textToUpdate = getSelectedWithoutTags();
  } else {
    textToUpdate = getSelectedWithTags();
  }

  if (removedFirstNewLine) {
    textToUpdate = `\n${textToUpdate}`;
  }

  if (removedLastNewLine) {
    textToUpdate += '\n';
  }

  if (editor) {
    editor.replaceSelectedText(textToUpdate, select);
  } else {
    insertText(textArea, textToUpdate);
  }

  if (shouldPreserveTextAreaSelection) {
    const offset = textToUpdate.length - selectedLength;
    textArea.setSelectionRange(textAreaSelectionStart, textAreaSelectionEnd + offset);
  } else {
    moveCursor({
      textArea,
      tag: tag.replace(textPlaceholder, selected),
      cursorOffset,
      positionBetweenTags: wrap && selected.length === 0,
      removedLastNewLine,
      select,
      editor,
      editorSelectionStart,
      editorSelectionEnd,
    });
  }
}